Debug `/nix/store/*-rustup-1.24.3/bin/` symlinks unrunnable

Running nix shell nixpkgs#rustup enters a shell with /nix/store/*-rustup-1.24.3/bin/ on $PATH. The bin/ contains a binary, a script, and symlinks

dr-xr-xr-x 2 root root   15 Dec 31  1969 ./
dr-xr-xr-x 4 root root    4 Dec 31  1969 ../
-r-xr-xr-x 1 root root 8.3M Dec 31  1969 .rustup-wrapped*
lrwxrwxrwx 1 root root    6 Dec 31  1969 cargo -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 cargo-clippy -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 cargo-fmt -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 cargo-miri -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 clippy-driver -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 rls -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 rust-gdb -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 rust-lldb -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 rustc -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 rustdoc -> rustup*
lrwxrwxrwx 1 root root    6 Dec 31  1969 rustfmt -> rustup*
-r-xr-xr-x 1 root root  532 Dec 31  1969 rustup*

Executing rustup --version (the script) behaves (mostly) as expected. Executing rustc --version returns the error

error: command failed: 'rustc': No such file or directory (os error 2)

which I think is bash’s way of saying “I have no idea how to execute such a thing.” Or, maybe it is suggesting that a shared library is missing when it tries to execute through one of the symlinks.

How can I diagnose and fix what is going wrong?

A bit more fun…

Running nix shell nixpkgs#rustc creates a working environment where rustc --version can run.

Running nix shell nixpkgs#rustc nixpkgs#rustup creates an environment where rustc fails to run.

Running nix shell nixpkgs#rustup nixpkgs#rustc creates an environment where rustc and rustup can run.

It seems like nixpkgs#rustup shadows nixpkgs#rustc. Likely it does so for some of its other symlinks; although nixpkgs#cargo always seems to work.

What OS are you on?

With nix shell nixpkgs#rustup, what does which rustc output? I believe nixpkgs’s rustc ends up in the same nix store path as its rustup.

1 Like

@rgoulter, thanks for considering my problem.

All this is on nixOS. OS config pulls from nixos-22.05 with some userland installs pulling from nixpkgs-unstable. Trying different commits of nixpkgs did not change the misbehavior.

I think I may have inadvertently fixed my problem by removing/rebuilding $RUSTUP_HOME and $CARGO_HOME.

When running in a new shell I get this output

eric@farm:~$ nix shell nixpkgs#rustup
eric@farm:~$ rustup --version
rustup 1.24.3 (1980-01-01)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
eric@farm:~$ rustc --version
error: no override and no default toolchain set
eric@farm:~$ which rustc

That output seems reasonable to me.

When running in a rust project where rust-toolchain populates $RUSTC_VERSION and rustup has run at least once, I also see reasonable results.

I suspect that I had some bad binaries in $RUSTUP_HOME and $CARGO_HOME from when I was exploring use of buildFHSUserEnv to build the project. Possibly I should keep $RUSTUP_HOME and $CARGO_HOME local to the project until I know better how to ensure consistent usage across projects. Or, maybe I’ll get mkShell working well enough that I won’t be creating more problems for myself.

I’m new enough to nixOS and rust that mixing the two has been very painful. Several times I’ve considered abandoning one or the other, but I keep coming back to try to make it work as I get more experience with nix subtleties.

Nothing is going wrong; rustup is behaving as intended. This is unrelated to nix, you’re misunderstanding rustup itself.

See, those symlinks there are symlinks to rustup. Since it supports managing multiple toolchains, rustup has some clever logic to figure out which binary is intended to be called in a specific situation, and then calls it. I.e., using rustc will actually run rustup, and rustup will then find whichever rustc you configured it to run and run that.

You clearly don’t have a toolchain installed yet. Use rustup to install your toolchain and it will work - well, hopefully, assuming you don’t have problems with dynamic linkers.

This is also why your projects work when properly set up. Once you have a toolchain configured, well, rustup will work.

The shadowing you observe is just that; depending on whether rustup or rustc is added to $PATH first, you either get rustup’s fake rustc or the one from the nix package. In the former case, there is no rustup toolchain installed yet, so you get an error. In the latter, you call the rustc installed by nix, which succeeds.