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

Change to use self-contained lld by default in rustup nightly artifacts breaks native linking #168

Closed
Nemo157 opened this issue May 17, 2024 · 7 comments · Fixed by #171
Closed
Labels
enhancement New feature or request

Comments

@Nemo157
Copy link

Nemo157 commented May 17, 2024

rust-lang/rust#71515 (comment) mentions that the next nightly will switch to using the self-contained lld by default instead of the system linker. Trying to do some pre-testing of this setup by manually enabling the new defaults in a project with a native dependency indicates that this causes issues with library loading (presumably something rpath related, but I've never dug into the details of how that is handled normally):

> cargo rustc -- -Clink-self-contained=+linker -Clinker-flavor=gnu-lld-cc
   Compiling u2f-touch-detector v0.1.0 (/home/nemo157/sources/u2f-touch-detector)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.58s

> $CARGO_HOME/target/shared/x86_64-unknown-linux-gnu/debug/u2f-touch-detector --help
/run/user/1000/cargo-home/target/shared/x86_64-unknown-linux-gnu/debug/u2f-touch-detector: error while loading shared libraries: libudev.so.1: cannot open shared object file: No such file or directory

The PR linked from the tracking issue mentions that the workaround will be to use -Zlinker-features=-lld.

@szlend
Copy link

szlend commented May 18, 2024

I assume we'll probably need to wrap rust-lld, similar to NixOS/nixpkgs#24744 (comment)

@Nemo157
Copy link
Author

Nemo157 commented May 20, 2024

Hmm, finally got round to testing it on the latest nightly and it seems like it's not active by default when installed via the overlay. I'm not sure why though, rustc --print target-spec-json -Z unstable-options | jq -r '.["link-self-contained"]' shows that it is enabled in the target-spec. Running RUSTC_LOG=rustc_codegen_ssa::back::link=info cargo rustc -- -Clink-arg=-Wl,-v with/without -Clink-self-contained=+linker shows that by default it's using GNU ld (GNU Binutils) 2.40 and only uses LLD 18.1.4 (compatible with GNU linkers) when explicitly requested.

@Nemo157
Copy link
Author

Nemo157 commented May 20, 2024

I found out why, I use cranelift as my codegen backend which disables default-active lld. Testing with that overridden successfully fails:

> CARGO_PROFILE_DEV_CODEGEN_BACKEND=llvm cargo run -- --help
   Compiling u2f-touch-detector v0.1.0 (/home/nemo157/sources/u2f-touch-detector)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.61s
     Running `/run/user/1000/cargo-home/target/shared/x86_64-unknown-linux-gnu/debug/u2f-touch-detector --help`
/run/user/1000/cargo-home/target/shared/x86_64-unknown-linux-gnu/debug/u2f-touch-detector: error while loading shared libraries: libudev.so.1: cannot open shared object file: No such file or directory

@Nemo157 Nemo157 changed the title Upcoming change to use self-contained lld by default in rustup nightly artifacts may break native linking Change to use self-contained lld by default in rustup nightly artifacts breaks native linking May 20, 2024
@Nemo157
Copy link
Author

Nemo157 commented May 20, 2024

I tried to figure out how to wrap the binaries, but bintools-wrapper is really not setup to wrap arbitrary binaries within a derivation, it wants something that looks at least somewhat like a bintools and wraps the whole thing.

@szlend
Copy link

szlend commented May 21, 2024

The wrap function is fairly simple, maybe worth vendoring it:

wrap() {
  local dst="$1"
  local wrapper="$2"
  export prog="$3"
  export use_response_file_by_default=${if isCCTools then "1" else "0"}
  substituteAll "$wrapper" "$out/bin/$dst"
  chmod +x "$out/bin/$dst"
}

You could then reference the ld wrapper like so:

mv $out/bin/rust-lld $out/bin/.rust-lld-unwrapped
wrap $out/bin/rust-lld \
  ${pkgs.path + /pkgs/build-support/bintools-wrapper/ld-wrapper.sh} \
  $out/bin/.rust-lld-unwrapped

Though there's a bunch of other things it expects substituted:

@coreutils_bin@
@suffixSalt@
coreutils_bin = lib.getBin coreutils; # pkgs.coreutils but probably unnecessary? 
suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config; # pkgs.stdenv.targetPlatform

Edit: Ah, this needs more bintools stuff in nix-support. Might be more difficult than I first thought.

@szlend
Copy link

szlend commented May 21, 2024

Alternatively, maybe we could extend stdenv.cc.bintools so it also includes and wraps rust-lld.

@oxalica
Copy link
Owner

oxalica commented May 29, 2024

The wrap function is fairly simple, maybe worth vendoring it:

Thanks for the investment of the ld-wrapper. I ends up copying part of the wrapper implementation to make it actually work. I created #171 and it works for me now. I'm looking for tests and feedback from people involving here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants