rustup icon indicating copy to clipboard operation
rustup copied to clipboard

Populate more `env.*` files under `$CARGO_HOME` regardless of platform

Open mwisnicki opened this issue 1 year ago • 13 comments

Problem

It looks like $HOME/.cargo/env is not created on Windows. This breaks shell scripts that depend on it.

Steps

  1. Download and run rust-init.exe
  2. Check ~/.cargo/env existence

Possible Solution(s)

Just generate it like you do on Linux. It's useful for people using native bash on Windows.

Notes

No response

Rustup version

rustup 1.26.0 (5af9b9484 2023-04-05)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.75.0 (82e1608df 2023-12-21)`

Installed toolchains

Default host: x86_64-pc-windows-msvc
rustup home:  C:\Users\WDAGUtilityAccount\.rustup

stable-x86_64-pc-windows-msvc (default)
rustc 1.75.0 (82e1608df 2023-12-21)

mwisnicki avatar Jan 16 '24 00:01 mwisnicki

@rbtcollins do you think that'll be useful? I personally don't use Windows for development so I guess I can't decide by myself this time, sorry...

rami3l avatar Jan 16 '24 04:01 rami3l

I mostly work from a Git Bash prompt when I have to use Windows. Rustup appears to correctly set the PATH variable for Windows, so $HOME/.cargo/bin ends up in my path, anyway. I can't say this doesn't break other scripts that assume the env file(s) exist, however, just that it doesn't require extra steps to use it from a Git Bash/Mintty CLI.

That said, all the various checks the init scripts and/or rustup appear to go through to determine whether to create the env files makes the existence of the files unpredictable. I ran into similar issues trying to get Rust installed in a Docker container for a GitLab runner and found several other issues that complain about $HOME/.cargo/env not being created. Of course, I can manually add it to the PATH, but the effects of rustup-init and install steps differ more than necessary between environments.

It would be better if the installers had consistent effects, and users can use manual workarounds for special cases. The env files are not large or risky to install. Better to just install them unless explicitly told not to with / as a side-effect of a flag like --no-modify-path, or perhaps if the file already exists (unless it's assume it should never be modified, in which case, that's on the user).

There's even an open issue about the fact that Rustup unconditionally assumes the env file exists. So even the Rust (meta) toolchain assumes it's there.

bloodgain avatar Dec 11 '24 22:12 bloodgain

@bloodgain Thank for your detailed reply! I can see why this is probably causing a bad experience for Windows users now...

@ChrisDenton It looks like the user on Windows might be able to run the installer under pwsh or bash, and that will make it harder to determine what behavior can be considered "consistent". For example, will simply generating the script (without actually sourcing it) be okay, if somehow Rustup knows the user is running bash on Windows?

rami3l avatar Dec 12 '24 00:12 rami3l

So just so I understand it, the current state is we only install these scripts on Unix hosts (i.e. not Windows): https://github.com/rust-lang/rustup/blob/b2622d69cd8baf31e8652dfc7e0f720476289202/src/cli/self_update.rs#L826-L827

And on Unix hosts we attempt to detect which shells are installed and only add env files as necessary: https://github.com/rust-lang/rustup/blob/b2622d69cd8baf31e8652dfc7e0f720476289202/src/cli/self_update/shell.rs#L84-L88

The suggestion here is to always install the env files in cargo's directory? Or at least do so by default on all platforms.

ChrisDenton avatar Dec 12 '24 05:12 ChrisDenton

The suggestion here is to always install the env files in cargo's directory? Or at least do so by default on all platforms.

@ChrisDenton IMHO, following the spirit of current Unix support, it seems that a "consistent" implementation would be generating env for sh when it has detected signs of the current user actually using, say, bash.

However, it does look like there are many ways to install bash on Windows and it's hard to track them all, that's my primary concern now.

rami3l avatar Dec 12 '24 05:12 rami3l

Yeah. We could check the SHELL environment variable to see if /usr/bin/bash is the currently running shell. But detecting if any of msys2/cygwin/etc is installed somewhere on the system is more difficult (or even impossible without scanning every directory).

That said, the Unix code does assume that a POSIX shell always exists (by virtue of being Unix): https://github.com/rust-lang/rustup/blob/b2622d69cd8baf31e8652dfc7e0f720476289202/src/cli/self_update/shell.rs#L117-L119

While the same rationale does not apply to Windows, there also doesn't seem to be much downside to adding env.sh anyway?

ChrisDenton avatar Dec 12 '24 05:12 ChrisDenton

While the same rationale does not apply to Windows, there also doesn't seem to be much downside to adding env.sh anyway?

Yes, that's the direction I'm coming from. The shell used to install may not always be the shell used in all execution contexts. For example, I always use bash or zsh, but I have worked with legacy code that assumed csh was the execution env, which I managed by using scripts and aliases without giving up or rewriting my whole config.

Likewise, rustup-init.exe might be used to install, but the user will use a Bourne-derivative shell in practice.

Git Bash/Mintty works surprisingly well even with tools that were installed in the Windows context. In rare cases, I have to switch to Powershell for setup -- e.g. adding a JFrog server to the jf CLI tool -- but otherwise, it just works.

This is why most tools (that I'm familiar with) just go ahead and dump all the setup scripts in their usual directories.

Conda does this, for instance. It requires an extra step (manual or script) to set up the additional execution env, but at least the setup scripts are available if the user needs a different one. Otherwise, users have to go find it and copy the script somewhere before they can use it -- which sometimes means a non-standard location due to lack of write permissions -- or they have to duplicate the setup themselves.

bloodgain avatar Dec 13 '24 23:12 bloodgain

@bloodgain Thanks for your detailed explanation! Your point makes perfect sense.

@ChrisDenton @djc I think there is another place where the old Rustup is trying to be too smart and it's sometimes too hard for the user to instruct it to behave otherwise. The same thing can happen on Unix as well if, say, I suddenly decided to start using nu but that happens after my last rustup self update. In this case I'll definitely end up without any env.nu and have to manually populate that file from the repo (we shouldn't assume that I can find that file that easily in the first place):

https://github.com/rust-lang/rustup/blob/178c502bfab89b68d7e2f2fa681e07ccef295656/src/cli/self_update/env.nu#L1-L3

To conclude, my proposal for the next minor version is the follows:

  • Just populate the env.* files no matter what. As long as we don't inject the installation into the $PATH without permission, all should be fine. (Yes, even env.fish on Windows, although fish will probably never support Windows...)
  • The shell detection logic is here to stay, but only for $PATH modification purposes.
  • If something like the one described above happens, the user should be able to simply source the according env.* file without having to figure out how to replicate its effects in e.g. their *shrc.

rami3l avatar Dec 14 '24 02:12 rami3l

I see where you're going and it makes some sense, but at the same time as a user I would be a little annoyed if rustup sprayed a bunch of config files for shells I don't actually use all over the place? Maybe we should have some completion wizard thingy built-in that people can run and find the right points to advertise it (after install but maybe also if you run a shell for which no config is installed, or something)?

djc avatar Dec 16 '24 10:12 djc

I see where you're going and it makes some sense, but at the same time as a user I would be a little annoyed if rustup sprayed a bunch of config files for shells I don't actually use all over the place?

@djc That's what pip and opam are doing with their venv activation script IIRC.

rami3l avatar Dec 16 '24 10:12 rami3l

The suggestion of, e.g. rustup env nushell as a counterpart to rustup completions nushell sounds like a reasonable compromise? And it may be more discoverable that way.

We could additionally write all the env files to a rustup subdirectory so people can manually "install" them if they wish. That would avoid the issue of spraying config files all over the place.

ChrisDenton avatar Dec 16 '24 10:12 ChrisDenton

write all the env files to a rustup subdirectory

@ChrisDenton @djc To clarify, what I meant is that we already have $CARGO_HOME to populate our env.* files to, my apologies if I wasn't clear enough, and it should do little harm to just populate all these env.* files over there.

In other words, what gets scattered across the filesystem are the scripts that source these env.* files (and of course we will only add them on demand), not these files themselves.

So if the user wants to add another shell to the mix, manually sourcing the corresponding env.* file will do, and it's usually just a single line in their *shrc file. OTOH, if they want to source the env.* file automatically, rustup env <shell> would be perfect in terms of adding these sourcing scripts on demand.

rami3l avatar Dec 16 '24 12:12 rami3l

Ahh, yes, if this is about adding all the env.* files to $CARGO_HOME by default, that makes sense to me.

djc avatar Dec 18 '24 09:12 djc