diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix index b54983986dbee..a573520ef9a80 100644 --- a/pkgs/build-support/bintools-wrapper/default.nix +++ b/pkgs/build-support/bintools-wrapper/default.nix @@ -8,6 +8,7 @@ { name ? "" , lib , stdenvNoCC +, stdenv ? stdenvNoCC , bintools ? null, libc ? null, coreutils ? null, shell ? stdenvNoCC.shell, gnugrep ? null , netbsd ? null, netbsdCross ? null , sharedLibraryLoader ? @@ -42,7 +43,6 @@ assert !(nativeLibc && noLibc); assert (noLibc || nativeLibc) == (libc == null); let - stdenv = stdenvNoCC; inherit (stdenv) hostPlatform targetPlatform; # Prefix for binaries. Customarily ends with a dash separator. @@ -94,6 +94,15 @@ let then import ../expand-response-params { inherit (buildPackages) stdenv; } else ""; + # We can install the link only if our compiler's host and target + # match GNU binutils' host and target. + gcc_lto_plugin_is_compatible = + (bintools.isGNU or false) + && stdenv.cc != null + && stdenv.cc.stdenv.hostPlatform == stdenv.hostPlatform + && stdenv.cc.stdenv.targetPlatform == stdenv.targetPlatform; + gcc_lto_plugin_path = "${stdenv.cc.cc}/libexec/gcc/${stdenv.targetPlatform.config}/${stdenv.cc.cc.version or "UNKNOWN"}/liblto_plugin.so"; + in stdenv.mkDerivation { @@ -137,6 +146,8 @@ stdenv.mkDerivation { installPhase = '' + runHook preInstall + mkdir -p $out/bin $out/nix-support wrap() { @@ -167,7 +178,7 @@ stdenv.mkDerivation { # Create symlinks for rest of the binaries. + '' - for binary in objdump objcopy size strings as ar nm gprof dwp c++filt addr2line ranlib readelf elfedit; do + for binary in objdump objcopy size strings as nm gprof dwp c++filt addr2line ranlib readelf elfedit; do if [ -e $ldPath/${targetPrefix}''${binary} ]; then ln -s $ldPath/${targetPrefix}''${binary} $out/bin/${targetPrefix}''${binary} fi @@ -187,6 +198,8 @@ stdenv.mkDerivation { [[ -e "$underlying" ]] || continue wrap ${targetPrefix}$variant ${./ld-wrapper.sh} $underlying done + + runHook postInstall ''; strictDeps = true; @@ -199,6 +212,25 @@ stdenv.mkDerivation { ./setup-hook.sh ]; + # Install linker plugin to make 'ar', 'ld' and friends auto-load + # linker plugin to handle LTO bytecode without explicit --plugin + # parameter. + # + # We can install the link only if our compiler's host and target + # match GNU binutils' host and target. + gnu_binutils_inject_plugin = lib.optionalString gcc_lto_plugin_is_compatible '' + if [ -d ${placeholder "out"}/lib/bfd-plugins ]; then + export BFD_PLUGINS_DIR="${placeholder "out"}/lib/bfd-plugins" + fi + ''; + + postInstall = lib.optionalString gcc_lto_plugin_is_compatible '' + if [ -e ${gcc_lto_plugin_path} ]; then + mkdir -p $out/lib/bfd-plugins + ln -s ${gcc_lto_plugin_path} $out/lib/bfd-plugins/ + fi + ''; + postFixup = ## ## General libc support @@ -209,6 +241,7 @@ stdenv.mkDerivation { echo "${libc_lib}" > $out/nix-support/orig-libc echo "${libc_dev}" > $out/nix-support/orig-libc-dev + '' ## @@ -306,6 +339,9 @@ stdenv.mkDerivation { + optionalString (bintools.isGNU or false) '' wrap ${targetPrefix}strip ${./gnu-binutils-strip-wrapper.sh} \ "${bintools_bin}/bin/${targetPrefix}strip" + # TODO: also wrap: size, rescoff, nm, dlltool, coffdump, addr2line, ranlib, maybe others? + wrap ${targetPrefix}ar ${./gnu-binutils-ar-wrapper.sh} \ + "${bintools_bin}/bin/${targetPrefix}ar" '' ### diff --git a/pkgs/build-support/bintools-wrapper/gnu-binutils-ar-wrapper.sh b/pkgs/build-support/bintools-wrapper/gnu-binutils-ar-wrapper.sh new file mode 100644 index 0000000000000..f631390f5897c --- /dev/null +++ b/pkgs/build-support/bintools-wrapper/gnu-binutils-ar-wrapper.sh @@ -0,0 +1,5 @@ +#! @shell@ +# shellcheck shell=bash + +@gnu_binutils_inject_plugin@ +exec @prog@ "$@" diff --git a/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh b/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh index 5b5136e3d14c0..6675579c9e659 100644 --- a/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh +++ b/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh @@ -1,4 +1,5 @@ #! @shell@ # shellcheck shell=bash +@gnu_binutils_inject_plugin@ exec @prog@ --enable-deterministic-archives "$@" diff --git a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh index 86a7416022010..dc015c0dd3980 100644 --- a/pkgs/build-support/bintools-wrapper/ld-wrapper.sh +++ b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh @@ -249,6 +249,7 @@ if (( "${NIX_DEBUG:-0}" >= 1 )); then fi PATH="$path_backup" +@gnu_binutils_inject_plugin@ # Old bash workaround, see above. @prog@ \ ${extraBefore+"${extraBefore[@]}"} \ diff --git a/pkgs/development/tools/misc/binutils/BFD_PLUGINS_DIR.patch b/pkgs/development/tools/misc/binutils/BFD_PLUGINS_DIR.patch new file mode 100644 index 0000000000000..8854cb67b1da6 --- /dev/null +++ b/pkgs/development/tools/misc/binutils/BFD_PLUGINS_DIR.patch @@ -0,0 +1,24 @@ +--- a/bfd/plugin.c ++++ b/bfd/plugin.c +@@ -490,9 +490,18 @@ build_plugin_list (bfd *abfd) + /* The intent was to search ${libdir}/bfd-plugins for plugins, but + unfortunately the original implementation wasn't precisely that + when configuring binutils using --libdir. Search in the proper +- path first, then the old one for backwards compatibility. */ +- static const char *path[] +- = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" }; ++ path first, then the old one for backwards compatibility. ++ ++ On top of that user is allowed to extend default search path with ++ BFD_PLUGINS_DIR environment variable. It's useful for cases when ++ modifying system directories is not feasible. ++ */ ++ const char *path[] = ++ { ++ getenv ("BFD_PLUGINS_DIR"), ++ LIBDIR "/bfd-plugins", ++ BINDIR "/../lib/bfd-plugins", ++ }; + struct stat last_st; + unsigned int i; + diff --git a/pkgs/development/tools/misc/binutils/default.nix b/pkgs/development/tools/misc/binutils/default.nix index fb891c67da40b..1aa717306d17e 100644 --- a/pkgs/development/tools/misc/binutils/default.nix +++ b/pkgs/development/tools/misc/binutils/default.nix @@ -85,6 +85,9 @@ stdenv.mkDerivation { # https://sourceware.org/PR29450 # Remove once 2.40 releases. ./gas-dwarf-zero-PR29451.patch + + # Add an extra path to look up gcc LTO plugin. Used by binutils wrapper. + ./BFD_PLUGINS_DIR.patch ] ++ lib.optional targetPlatform.isiOS ./support-ios.patch # This patch was suggested by Nick Clifton to fix