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

LLD linker does not have required nixpkgs wrapper script and flags #24744

Open
nh2 opened this issue Apr 8, 2017 · 27 comments
Open

LLD linker does not have required nixpkgs wrapper script and flags #24744

nh2 opened this issue Apr 8, 2017 · 27 comments
Labels
6.topic: haskell 6.topic: llvm/clang Issues related to llvmPackages, clangStdenv and related

Comments

@nh2
Copy link
Contributor

nh2 commented Apr 8, 2017

Currently using the lld linker in nix doesn't work correctly.

Executables that it produces have entries in lld being not found (rpaths are missing).

That's because ld and gold have wrappers that do the following:

# Second, for each directory in the library search path (-L...),

 # First, find all -L... switches.

    # Second, for each directory in the library search path (-L...),
    # see if it contains a dynamic library used by a -l... flag.  If
    # so, add the directory to the rpath.

But lld currently doesn't have such a wrapper.

(I found this via See also #24692 (comment).)

Also this type of patch or setting to --enable-new-dtags will likely be needed, and potentially other changes nixpkgs makes to ld and gold.

@domenkozar
Copy link
Member

This would be a nice addition to speed up Haskell builds by reducing time in linking phase.

@taktoa
Copy link
Member

taktoa commented Jun 6, 2017

As part of my work this summer on speeding up Nix Haskell builds for Awake Networks, I'm interested in tackling this issue (and upstreaming a fix). Does it just amount to adding something similar to the code snippet below to pkgs/build-support/cc-wrapper/default.nix (around line 180)?

      if [ -e ${binutils_bin}/bin/ld.gold ]; then
        wrap ld.gold ${./ld-wrapper.sh} ${binutils_bin}/bin/ld.gold
      fi

or should I be modifying the lld package itself to use the ld-wrapper.sh script?
Also, if someone could cook up an example Nix expression that should build iff I have correctly wrapped lld, that would be quite useful in implementing a fix for this.

@nh2
Copy link
Contributor Author

nh2 commented Jun 6, 2017

@taktoa I can't answer conclusively, but I suspect it won't be as trivial as using the exiting scripts.

The right approach is likely to first do a proper reads through all things nixpkgs does to ld or gold, and then check which of those have to be done to lld as well.

For example, I know that lld searches through some default paths. We probably want to patch them out, or pass flags so that it doesn't do that.

@domenkozar
Copy link
Member

@taktoa we're interested in this project at https://github.com/input-output-hk as well - maybe we could have quick chat and join some forces :)

we invested a bit of time into parallel GC and general GHC option tuning for scaling the compilation into multiple cores: https://github.com/input-output-hk/iohk-nixops/pull/49/files

Indeed linking takes a hell lot of time, but buildTarget fix in Cabal master will help a lot, limiting what executables are built for the given package.

@domenkozar
Copy link
Member

@taktoa for this particular change, I'd talk to @vcunat or @wkennington

@vcunat
Copy link
Member

vcunat commented Jun 6, 2017

Assuming the relevant linker options have the same syntax, I'd expect that the same wrapping approach should work. The way cc-wrapper is written now, I'd suggest to first try adding an option that makes it include ld.lld. (And maybe an option to make it the default ld, though I don't know if that's the standard way to exchange linkers.)

@matthewbauer
Copy link
Member

I have now added the lldClang stdenv. We could expose this better as needed if people want lld to be installable. Otherwise, without anything actionable I think this can be closed?

for instance, you can run llvm linker:

with import <nixpkgs> { system = "x86_64-linux"; };
let stdenv' = overrideCC stdenv llvmPackages_8.lldClang;
in stdenv'.mkDerivation {
  name = "test";
  buildCommand = ''
  cc ${./test.c} -o test
  ./test
  '';
}

Also install lld using:

nix-env -iA nixpkgs.llvmPackages_8.lldClang.bintools

@nh2
Copy link
Contributor Author

nh2 commented May 1, 2019

Otherwise, without anything actionable I think this can be closed?

@matthewbauer The actionable part from the issue description was:

Executables that it produces have entries in lld being not found (rpaths are missing).
But lld currently doesn't have such a wrapper [that fixes the rpaths].

Concretely, we want to be able to:

  • Use a nix-provided lld in nix-build and nix-shell to link executables, also on non-NixOS platforms like Ubuntu
    • nix-shell support means it should work without sandbox, without lld picking up some global paths that it has hardcoded; it should be patched or wrapped to not do that, like binutils ld is
  • Use lld for general nix builds of specific or all packages (lddClang sounds like it does exactly that)

If your lldClang env fixes all those points, then this can be closed; if it does not fix/wrap/patch lld so that the nix-shell-on-Ubuntu use case works, then we still have to do that.

@domenkozar
Copy link
Member

Can't easily override stdenv in haskell #66267, but could be checked by overriding it in nixpkgs and see if darwin builds.

orivej-nixos pushed a commit that referenced this issue Mar 3, 2020
lld buildInput is still needed for the library.

Related: #24744
@stale
Copy link

stale bot commented Jun 2, 2020

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 2, 2020
@tobim
Copy link
Contributor

tobim commented Jun 11, 2020

I discovered that the following can be used for incremental development:

{ pkgs ? import <nixpkgs> {} }:
let
  bintools_lld = pkgs.wrapBintoolsWith {
    bintools = pkgs.llvmPackages_10.bintools;
  };
in pkgs.mkShell {
  buildInputs = [ pkgs.stdenv bintools_lld ];
  hardeningDisable = [ "fortify" ];
  NIX_CFLAGS_LINK = "-fuse-ld=lld";
}

It would be great if there was an easier way to achieve that, but I'm unsure of what would be a good way to expose lld.

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 11, 2020
@orivej
Copy link
Contributor

orivej commented Jun 11, 2020

You could use nixpkgs.llvmPackages_10.lldClang.bintools instead of bintools_lld, this makes it pretty simple.

@stale
Copy link

stale bot commented Dec 9, 2020

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Dec 9, 2020
@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/rust-c-link-time-optimization/13276/1

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label May 26, 2021
@PanAeon
Copy link
Contributor

PanAeon commented Oct 9, 2021

Using llvmPackages.bintools fixes similar issue for me.

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/how-rpath-works-or-doesnt-on-nixos/18182/1

@matklad
Copy link
Member

matklad commented Mar 15, 2022

Let me restate the solution more clearly:

There are two packages that provide LLD in nixpkgs: pkgs.lld and pkgs.llvmPackages.bintools. The former is unwrapped, and doesn't, eg, set rpath. The latter is wrapped, and just works. So, the following fixed the issue I was having with compiling Rust code:

matklad/config@440b1e2

@tobim
Copy link
Contributor

tobim commented Mar 15, 2022

That raises the question whether pkgs.lld should also provide a wrapped lld so the next person doesn't have to go through the same journey. I'm not sure whether the unwrapped version actually provides any value.

@happysalada
Copy link
Contributor

How did you make it work in the end exactly ?
On ubuntu I tried the following

  • having RUSTFLAGS="-Clink-arg=-fuse-ld=lld" (not inside the cargo config, but as an env var).
  • As a build input, I added llvmPackages.bintools . I still ran into some linker errors.
    Just wondering if you have more knowledge on this.

@matklad
Copy link
Member

matklad commented Mar 29, 2022

@happysalada https://matklad.github.io/2022/03/14/rpath-or-why-lld-doesnt-work-on-nixos.html includes some notes on debugging. Useful things:

  • Compare working and broken linkers
  • readelf -d target/debug/examples/my-binary | rg PATH to get the actual RPATH
  • cat (which ld.lld) to check if it's actually a script
  • check which C compiler is used as a linker. For me right now, cc is clang

@happysalada
Copy link
Contributor

for me adding lld_13 to the list of buildInputs did the trick. It makes lld work on darwin as well.

Thanks again for the help!

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/using-mold-as-linker-prevents-libraries-from-being-found/18530/2

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/using-mold-as-linker-prevents-libraries-from-being-found/18530/3

@tobim tobim mentioned this issue May 11, 2022
15 tasks
@gabyx
Copy link
Contributor

gabyx commented Feb 5, 2024

I used the following to make lld work:

 # Define settings
  # Toolchain.
  gccVersion = "13";
  gccPkg = pkgs."gcc${gccVersion}";

  llvmVersion = "17";
  llvmPkgs = pkgs."llvmPackages_${llvmVersion}";

  clangStdEnv = pkgs.stdenvAdapters.overrideCC llvmPkgs.stdenv (
    llvmPkgs.clang.override {
      bintools = llvmPkgs.bintools;
      gccForLibs = gccPkg.cc; # This is the unwrapped gcc.
    }
  ); 
  

  clangStdEnv.mkDerivation( ... )

@szlend
Copy link
Member

szlend commented May 4, 2024

Here's a wrapped bintools that's cross-platform and includes lld (tested on linux and darwin):

{ clangStdenv, lld, path }:

clangStdenv.cc.bintools.override {
  extraBuildCommands = ''
    for ld in $(find ${lld}/bin -name "ld*" -printf "%f\n"); do
      wrap ${clangStdenv.cc.bintools.targetPrefix}$ld \
           ${path + /pkgs/build-support/bintools-wrapper/ld-wrapper.sh} \
           ${lld}/bin/$ld
    done
  '';
}

@domenkozar
Copy link
Member

@szlend however on linux it shouldn't be using clangStdenv?

@szlend
Copy link
Member

szlend commented May 10, 2024

@szlend however on linux it shouldn't be using clangStdenv?

Yeah. For my use case I wanted to use clang on all platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: haskell 6.topic: llvm/clang Issues related to llvmPackages, clangStdenv and related
Projects
None yet
Development

No branches or pull requests