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

rust-toolchain affects which rustc version is used to execute a script #31

Closed
soenkehahn opened this issue Jul 29, 2021 · 6 comments
Closed
Assignees
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@soenkehahn
Copy link

If I have a script in a directory in my $PATH, say /usr/local/bin/foo, and it starts with #!/usr/bin/env rust-script and it has the executable flag set, then I can invoke that script from anywhere in my system with $ foo. And that usually works fine. When executing the script from a directory that has a rust-toolchain file in it, then -- to my surprise -- rust-script uses the rust toolchain version specified in the rust-toolchain file to execute the script. This feels like a bug to me, since the contents of a directory shouldn't affect what interpreter or compiler is used to run an executable in my $PATH.

An extreme example is this: If I put e.g. 1.10 into the rust-toolchain file, the rust script cannot be executed at all, since rust-script fails with error: Unknown flag: '--target-dir'.

I think I would expect rust-script to always use the default toolchain.

Is this an intended feature? Could this be changed?

@fornwall fornwall self-assigned this Jul 29, 2021
fornwall added a commit that referenced this issue Jul 29, 2021
By always specifying a cargo toolchain (the +${TOOLCHAIN} option) we
avoid being affected by rust-toolchain(.toml) files. Fixes #31.
@fornwall fornwall added the bug Something isn't working label Jul 29, 2021
fornwall added a commit that referenced this issue Jul 29, 2021
By always specifying a cargo toolchain (the +${TOOLCHAIN} option) we
avoid being affected by rust-toolchain(.toml) files. Fixes #31.
fornwall added a commit that referenced this issue Jul 29, 2021
By always specifying a cargo toolchain (the +${TOOLCHAIN} option) we
avoid being affected by rust-toolchain(.toml) files. Fixes #31.
@fornwall fornwall added the help wanted Extra attention is needed label Jul 29, 2021
@fornwall
Copy link
Owner

Thanks for reporting! I agree that rust-script should not be affected by a rust-toolchain file.

Resources:

One possible fix is as done in #32. It always specifies the toolchain option to cargo, by defaulting to +stable if no toolchain was specified by --toolchain-version (or a nightly toolchain implied by the --bench option).

However, this will fail if:

  • The cargo command being used is not a rustup proxy command (cargo being installed from another source than rustup).
  • There is no stable toolchain installed. This is the case in e.g. the official rust docker image, which has explicit versions installed instead.

One way to work around this would be to shell out to rustup, to try to detect if

  • rustup is installed: But rustup being installed might not mean that cargo is a rustup proxy command, so we should call cargo directly for that?
  • Check if stable toolchain is installed, and fall back to the default (rustup default) toolchain if not (or should be always use the default toolchain?).

Are there perhaps better ways?

@soenkehahn
Copy link
Author

Interesting. Thanks for the detailed explanation. To check whether my understanding is correct: the rustup proxies are the ones that are interpreting the +$TOOLCHAIN arguments, right? And then they're passing all other arguments to the executable they proxy? So a non-rustup-proxy version of cargo would choke on e.g. +stable?

One thing that I noticed is, that I can work around the issue by putting the following hashbang at the top of scripts: #!/usr/bin/env -S rust-script --toolchain-version stable. (Of course that only works when cargo is a rustup proxy.) But rust-script should ideally solve this without that.

What about this: Have rust-script not call cargo run. Instead, after creating the project in ~/.cache/rust-script/projects, it calls cargo build, using the project directory as the working directory for cargo build. After that, rust-script executes the built binary. This would mean that:

  1. No rust-toolchain file would be picked up from the directory from where the script is executed.
  2. If cargo is a rustup proxy, that proxy will pick whatever toolchain version is in effect in the ~/.cache/rust-script/projects/$HASH directory. In most cases this will just be the current default toolchain. But if users have a global RUSTUP_TOOLCHAIN environment variable, or a rust-toolchain file in their home directory, or a directory override for their home directory, then these settings would override the default toolchain.
  3. If cargo is not a rustup proxy, regardless of whether rustup is installed, it would just run.

Overall, that seems like fairly desirable behavior. It is a bigger change, and it would be somewhat daunting to do it without having good tests for a few different scenarios. Since I easily might have overlooked something.

cc: @casey

@fornwall
Copy link
Owner

Interesting. Thanks for the detailed explanation. To check whether my understanding is correct: the rustup proxies are the ones that are interpreting the +$TOOLCHAIN arguments, right? And then they're passing all other arguments to the executable they proxy? So a non-rustup-proxy version of cargo would choke on e.g. +stable?

Yes, exactly!

What about this: Have rust-script not call cargo run. Instead, after creating the project in ~/.cache/rust-script/projects, it calls cargo build, using the project directory as the working directory for cargo build. After that, rust-script executes the built binary.

I think this makes a lot of sense. Would also help with #30 (comment), where it's desired to show build progress for the initial build, but after that run it directly with no cargo output. Will experiment with the idea!

@Hecatron
Copy link

Hecatron commented Nov 29, 2021

Just to add I pretty much run into this problem while trying to run rust scripts
inside a directory setup for a custom toolchain (embedded esp / esp32 project).
Where it would default to using whatever toolchain was setup as an override in the source directory.

in my case I had a file setup called rust-toolchain.toml with the following in

[toolchain]
channel = "esp"

Adding "--toolchain-version stable" would allow it to compile.
Although I think it was still picking up other options from within .cargo/config.toml or perhaps Cargo.toml
as a basic hello world script wouldn't output anything if it was located inside the source directory where rust-toolchain.toml / .cargo directory was located

rust-script --toolchain-version stable test.rs

As a workaround so far I've been using cargo make's duckscript
https://github.com/sagiegurari/cargo-make#usage-task-command-script-task-exampleduckscript

Although looking ahead it'd be nice if I could implement scripts using stuff such as indicatif
https://github.com/mitsuhiko/indicatif
Or some form of menu system for setting up the config

@fornwall
Copy link
Owner

What about this: Have rust-script not call cargo run. Instead, after creating the project in ~/.cache/rust-script/projects, it calls cargo build, using the project directory as the working directory for cargo build. After that, rust-script executes the built binary.

Version 0.23.0 has just been released, and does it as described above, which should fix this issue - let me know if there are any problems!

@soenkehahn
Copy link
Author

Seems to work as expected for me. 🎉 Thanks a lot for working on rust-script!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants