Rustup on linux, absolute path in ld.lld script

At risk of describing a niche unsupported workflow (xkcd: Workflow)...

TL;DR
The rustup file for ld.lld on linux seems to reference an absolute path to ~/.rustup which causes problems when ~/.rustup is mounted to a different path (read-only, for a different user).
Why is the "path of the current file" needed in the ld.lld script that rustup creates?


Additional background:
I've had success so far using rustup inside in a container on my NixOS linux machine by mounting my main user's /home/main/.rustup folder as readonly inside the container as /home/unprivileged/.rustup.

After updating my toolchain from ~1.89 to rustc 1.91.0-beta.1 (1bffa2300 2025-09-15), I started having an issue where the unprivileged user's compiles fail, trying to access a path inside /home/main/.rustup.

From my initial look, it seems like this might not be the fault of cursed NixOS shenanigans, or even the read-only mount, but rather because the path /home/main/.rustup is hard-coded inside the rustup folder that isn't valid inside the VM.

The cc linker, when invoked using the /home/unprivileged/.rustup read-only install, is trying to access a script in /home/main/.rustup

Error: no such file: gcc-ld-unwrapped/ld.lld
[unprivileged@my_vm]$ echo $HOME
/home/unprivileged

[unprivileged@my_vm]$ rustup which cargo
/home/unprivileged/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/bin/cargo

[unprivileged@my_vm]$ cargo check

error: linking with `cc` failed: exit status: 1
  |
  = note:  "cc" "-m64" "/tmp/rustc7Tk7FZ/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,libcfg_if-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,liblibc-*,librustc_std_workspace_core-*,liballoc-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/tmp/rustc7Tk7FZ/raw-dylibs" "-B<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld" "-fuse-ld=lld" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/ned/git/ai-dev/soundbox-iii/target/debug/build/icu_normalizer_data-b2ada45b3903a87c/build_script_build-b2ada45b3903a87c" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs"
  = note: some arguments are omitted. use `--verbose` to show all linker arguments
  = note: /nix/store/pwrvyffzg8hzvi4d864q8bmjr7vfaxqz-rustup-1.27.1/nix-support/ld-wrapper.sh: line 270: /home/main/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld-unwrapped/ld.lld: No such file or directory
          collect2: error: ld returned 127 exit status

Looking into the file, it contains a line defining PROG with the path to the current file.
Contents of /home/main/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld/ld.lld:

#!/usr/bin/env bash
set -eu -o pipefail +o posix
shopt -s nullglob
export PROG="/home/main/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld-unwrapped/ld.lld"
"/nix/store/pwrvyffzg8hzvi4d864q8bmjr7vfaxqz-rustup-1.27.1/nix-support/ld-wrapper.sh" $@


That's a lot of background... my actual question:

Do you know why this file has to record a path to itself?

I don't know much about linkers (seems the default recently changed to lld on x86_64 linux?), but some searching showed that lld is better than the older default?

As a workaround, it works if I mount /home/main/.rustup read-only inside the container too, so that /home/unprivileged/.rustup/ tools can access those hard-coded paths at /home/main/.rustup (with just a small amount of extra read-only clutter).
I thought about changing this file to use /home/${USER}/.rustup instead, but it seems odd to modify a file that rustup will overwrite on the next update.

NixOS has patched rustup to add this wrapper: nixpkgs/pkgs/development/tools/rust/rustup/0001-dynamically-patchelf-binaries.patch at a1f79a1770d05af18111fbbe2a3ab2c42c0f6cd0 · NixOS/nixpkgs · GitHub You will have to ask them.

Thanks! I'll ask on a NixOS forum.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.