Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] A way to use pwsh.exe (PowershellCore) on Windows by default instead of cmd.exe #677

Closed
frederikhors opened this issue Jul 31, 2022 · 26 comments
Assignees
Milestone

Comments

@frederikhors
Copy link

frederikhors commented Jul 31, 2022

I'm using Windows and the new Powershell Core (pwsh.exe and not powershell.exe).

It would be amazing to be able to use pwsh.exe instead of cmd.exe by default:

[tasks.windows_start]
script_runner = "@shell-pwsh" # or differently
script = "cargo watch -x run"

[tasks.start]
windows_alias = "windows_start"
@sagiegurari
Copy link
Owner

you can use that runner today by pointing to that exe. you can't change defaults but that might break other makefiles you are importing (like the core makefiles)

@frederikhors
Copy link
Author

I can use that runner only if I use this config:

[tasks.windows_start]
script_runner = "pwsh"
script_extension = "ps1" # If I remove this line it doesn't work!
script = "echo hello"

[tasks.start]
windows_alias = "windows_start"

@sagiegurari
Copy link
Owner

yes exactly!
so you can do something like this to reuse the definition:

[tasks.powershell]
private = true # do not call it directly
script_runner = "pwsh"
script_extension = "ps1"

[tasks.print_hello]
extend = "powershell"
script = "echo hello"

[tasks.something-else]
extend = "powershell"
script = "echo whatever...."

however, if you want multi platform, you can add the .windows like this:

[tasks.print_hello]
script = "echo hello from non windows"

[tasks.print_hello.windows]
extend = "powershell"
script = "echo hello from windows"

also if you want to have some automatic handling without doing extend, you can write a custom cargo-make plugin:
https://github.com/sagiegurari/cargo-make#usage-plugins

@frederikhors
Copy link
Author

Thanks.

It may work, but I feel it could be done better. Each time the script starts it must create a temporary .ps1 file. I don't think that's the fairest thing in the world.

A way to directly call pwsh.exe with the command would really be much better.

@sagiegurari
Copy link
Owner

you can use the command and args if possible. meaning put in command pwsh and in args the script (if powershell supports that...)

@frederikhors
Copy link
Author

you can use the command and args if possible. meaning put in command pwsh and in args the script (if powershell supports that...)

I'll try now.

Anyway, I'm having this error trying with this code:

[tasks.powershell]
private = true
script_runner = "pwsh"
script_extension = "ps1"

[tasks.print_hello]
script = "echo hello from non windows"

[tasks.print_hello.windows]
extend = "powershell"
script = "echo hello from windows"

[config]
skip_core_tasks = true
skip_git_env_info = true
skip_rust_env_info = true
skip_crate_env_info = true
default_to_workspace = false
makers print_hello

[cargo-make] INFO - makers 0.35.15
[cargo-make] INFO - Build File: Makefile.toml
[cargo-make] INFO - Task: print_hello
[cargo-make] INFO - Profile: development
[cargo-make] ERROR - Task print_hello is private
[cargo-make] WARN - Build Failed.

Why?

@frederikhors
Copy link
Author

So I can confirm this works on Windows:

pwsh.exe -C "echo hello from windows"

Is there a way to use this?

I tried with:

[tasks.print_hello.windows]
extend = "pwsh"
args = ["echo hello from windows"]

[tasks.pwsh]
command = "pwsh.exe -C"

but I get an error:

Invalid task: print_hello, contains multiple actions.

@frederikhors
Copy link
Author

Ok the problem was I was using script in [tasks.print_hello].

The error now is this:

[cargo-make] INFO - makers 0.35.15
[cargo-make] INFO - Build File: Makefile.toml
[cargo-make] INFO - Task: print_hello
[cargo-make] INFO - Profile: development
[cargo-make] INFO - Execute Command: "pwsh.exe -C" "echo hello from windows"
[cargo-make] ERROR - Error while executing command, error: Error {
    kind: NotFound,
    message: "program not found",
}
[cargo-make] WARN - Build Failed.

with:

[tasks.print_hello]
args = ["echo hello from non windows"]

[tasks.print_hello.windows]
extend = "pwsh"
args = ["echo hello from windows"]

[tasks.pwsh]
command = "pwsh.exe -C"

Why?

@sagiegurari
Copy link
Owner

[tasks.print_hello.windows]
command = "pwsh.exe"
args = ["-C", "echo hello from windows"]

@sagiegurari
Copy link
Owner

@frederikhors please check my answer and feel free to reopen if not solved

@frederikhors
Copy link
Author

args = ["-C", "echo hello from windows"]

If I use this I need to repeat "-C" on each command, it's very awful.

It would be AWESOME, really, to have in Makefile.toml (or in the global config file) something like:

[config]
windows_shell = ["pwsh.exe", "-NoLogo", "-Command"]

Like Justfile does.

I cannot re-open this if you close it.

Please, please, please create this config for us.

We tried A LOT of libraries like this and Makers is THE BEST of all.

If you add this it will be the NON PLUS ULTRA.

PLEASE. 🙏

@sagiegurari sagiegurari reopened this Aug 7, 2022
@sagiegurari
Copy link
Owner

let me think of some solution here...

@frederikhors
Copy link
Author

Since you are thinking, it would also be very useful to have a way to pass a list of commands as if it were a script but by running each command by itself, without using the syntax of args. Example:

[tasks.backup]
args = '''
  echo Starting backup
  command 1
  command 2
  command 3
  echo Done backup
'''

@sagiegurari
Copy link
Owner

that feels like a script instead

[tasks.backup]
script_runner = "pwsh"
script_extension = "ps1"
script = '''
  echo Starting backup
  command 1
  command 2
  command 3
  echo Done backup
'''

@sagiegurari
Copy link
Owner

@frederikhors so I improved the cargo-make plugin system to enable users to create tasks on the fly and run them.
plugins are a way for users to take over how tasks are executed from cargo-make and run custom code.
see more at: https://github.com/sagiegurari/cargo-make/tree/0.35.16#usage-plugins

so i created a powershell plugin:
https://github.com/sagiegurari/cargo-make/tree/0.35.16#usage-plugins-plugin-example-powershell
to enable you to replace cmd with powershell and all you have to do in the task is put
plugin="powershell"

naturally that plugin code is not inside cargo-make so you do have to put it in your makefile (as the example i linked to shows).
since makefiles can load external makefiles from http or whatever you want, you can have one makefile with all your plugins (or just this one) and have your different projects, load that makefile and have access to the plugin.

in order to test it, please use the dev 0.35.16 branch and tell me if it works well for you.
I do not have windows to test on, so I can't be certain.

@sagiegurari
Copy link
Owner

by the way, with plugins, you can expand mine to support a list of commands as you wanted. but you will have to implement that.

@sagiegurari sagiegurari added this to the 0.35.16 milestone Aug 8, 2022
@sagiegurari
Copy link
Owner

@frederikhors this is now released so you can use the official cargo-make version with this plugin code
feel free to open new issues around this subject if needed.

@frederikhors
Copy link
Author

Thank you very much.

Unfortunately now with plugins it has become really complex, even just to understand.

I cannot present this solution to the team.

Thank you very much also for your speed.

I had something much simpler in mind, like justfile does.

Thanks again.

@sagiegurari
Copy link
Owner

than maybe i didn't explain it well, since it simplifies your work.

i'm not sure if its 1 project or multiple or a workspace, but it supports all very easily.
lets assume you have a workspace with many crates and root makefile at the top

Makefile.toml
plugins.toml

crate1->Makefile.toml
crate2->...
...
  1. in plugins toml file you put the code i wrote and thats it. no one looks at this file anymore.
  2. in workspace root toml file put
extends = "plugins.toml"
  1. in each crate toml file you put
[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true

see https://github.com/sagiegurari/cargo-make#usage-workspace-extend explanation about that.

than when you define tasks in the crate makefile just do

[tasks.task1]
plugin = "powershell"
args = ["echo whatever..."]

Lets say you have multiple projects of standalone crates....
you can have a standalone project with the plugins.toml as before and thats it.
in each project, add a init script to load that external plugins file, just git pull it to your local repo to some ignored path (so you won't check it in)

[config]
load_script = "git clone git@mygitserver:user/project.git /home/myuser/common"

see more at: https://github.com/sagiegurari/cargo-make#usage-load-scripts
and extend.
This actually allows you to put things in standalone repo to share anything you want with all other repos.
that concept is also explained in this repo that has lots of non rust tasks:
https://github.com/sagiegurari/cargo-make-tasks/

lets say you have only one standalone repo and thats it.
put the code in plugins.toml as before and add extend. thats it. no need to touch that file and no one will see all that code.

@frederikhors
Copy link
Author

Ok. Thanks again.

But for a moment imagine if everything you are telling me can be solved without plugins and without all this with a simple line:

[config]
windows_shell = ["pwsh.exe", "-NoLogo", "-Command"]

[tasks.hello]
cmd = "echo hello from NON windows"

[tasks.hello.windows]
cmd = "echo hello from windows"

Great, right?

@sagiegurari
Copy link
Owner

and how would some tasks use powershell and some use something else? i'm not sure i get it?

@frederikhors
Copy link
Author

With the example I wrote above I want Makers to execute all commands in pwsh.exe when it comes to Windows.

I don't want to use cmd.exe at all.

@sagiegurari
Copy link
Owner

but its not cmd. i'm not sure i get it.
lets say you have this

[tasks.build]
command = "cargo"
args = ["build"]

[tasks.pwsh]
args = ["echo hello powershell"]

what would tell it to use powershell capability in pwsh task and ignore it and call cargo in the cargo build task?
also, the tasks.build one does not call cmd.exe at all. it calls cargo.
maybe i'm not explaining what the difference between command+args compared to script good enough?

@sagiegurari
Copy link
Owner

@frederikhors maybe just is using cmd to call commands. thats similar to what cargo-make does with scripts.
for 'command+args' cargo-make calls the provided executable directly.

@frederikhors
Copy link
Author

Ok. Let's recape. I know the difference between script and single command with args. In this post I was asking for a feature to call many commands in one task only without using script. But it's another question. Forget it.

What I need is a way to use Makers on Windows/Linux with the same Makefile.toml file committed in my git project.

What I need too is to NOT use cmd.exe on Windows only because you choose it but to specify another shell, like Justfile does (read the comment above).

Is there a way to choose my shell for my commands using a config like Justfile?

I do not like the plugin way you did: it's too complex for such a "simple" thing.

@sagiegurari
Copy link
Owner

ok, but I don't use cmd.exe for commands at all, only for scripts :)
and there you can replace it by specifying the script runner (you did it).
and commands, have nothing to do with cmd.exe.
thats why i'm so confused of what your expectations are.

i gave the plugin solution as it is the way for users to expand on what cargo-make doesn't give out of the box by putting a reusable piece of code that they can 'call/use' in tasks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants