diff options
Diffstat (limited to 'nixpkgs/pkgs/build-support/bintools-wrapper')
11 files changed, 1371 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/add-darwin-ldflags-before.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/add-darwin-ldflags-before.sh new file mode 100644 index 000000000000..75d9484846a8 --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/add-darwin-ldflags-before.sh @@ -0,0 +1,81 @@ +# Unconditionally adding in platform version flags will result in warnings that +# will be treated as errors by some packages. Add any missing flags here. + +# There are two things to be configured: the "platform version" (oldest +# supported version of macos, ios, etc), and the "sdk version". +# +# The modern way of configuring these is to use: +# -platform_version $platform $platform_version $sdk_version" +# +# The old way is still supported, and uses flags like: +# -${platform}_version_min $platform_version +# -sdk_version $sdk_version +# +# If both styles are specified ld will combine them. If multiple versions are +# specified for the same platform, ld will emit an error. +# +# The following adds flags for whichever properties have not already been +# provided. + +havePlatformVersionFlag= +haveDarwinSDKVersion= +haveDarwinPlatformVersion= + +# Roles will set by add-flags.sh, but add-flags.sh can be skipped when the +# cc-wrapper has added the linker flags. Both the cc-wrapper and the binutils +# wrapper mangle the same variable (MACOSX_DEPLOYMENT_TARGET), so if roles are +# empty due to being run through the cc-wrapper then the mangle here is a no-op +# and we still do the right thing. +# +# To be robust, make sure we always have the correct set of roles. +accumulateRoles + +mangleVarSingle @darwinMinVersionVariable@ ${role_suffixes[@]+"${role_suffixes[@]}"} + +n=0 +nParams=${#params[@]} +while (( n < nParams )); do + p=${params[n]} + case "$p" in + # the current platform + -@darwinPlatform@_version_min) + haveDarwinPlatformVersion=1 + ;; + + # legacy aliases + -macosx_version_min|-iphoneos_version_min|-iosmac_version_min|-uikitformac_version_min) + haveDarwinPlatformVersion=1 + ;; + + -sdk_version) + haveDarwinSDKVersion=1 + ;; + + -platform_version) + havePlatformVersionFlag=1 + + # If clang can't determine the sdk version it will pass 0.0.0. This + # has runtime effects so we override this to use the known sdk + # version. + if [ "${params[n+3]-}" = 0.0.0 ]; then + params[n+3]=@darwinSdkVersion@ + fi + ;; + esac + n=$((n + 1)) +done + +# If the caller has set -platform_version, trust they're doing the right thing. +# This will be the typical case for clang in nixpkgs. +if [ ! "$havePlatformVersionFlag" ]; then + if [ ! "$haveDarwinSDKVersion" ] && [ ! "$haveDarwinPlatformVersion" ]; then + # Nothing provided. Use the modern "-platform_version" to set both. + extraBefore+=(-platform_version @darwinPlatform@ "${@darwinMinVersionVariable@_@suffixSalt@:-@darwinMinVersion@}" @darwinSdkVersion@) + elif [ ! "$haveDarwinSDKVersion" ]; then + # Add missing sdk version + extraBefore+=(-sdk_version @darwinSdkVersion@) + elif [ ! "$haveDarwinPlatformVersion" ]; then + # Add missing platform version + extraBefore+=(-@darwinPlatform@_version_min "${@darwinMinVersionVariable@_@suffixSalt@:-@darwinMinVersion@}") + fi +fi diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/add-flags.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/add-flags.sh new file mode 100644 index 000000000000..3b94daba65d7 --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/add-flags.sh @@ -0,0 +1,37 @@ +# See cc-wrapper for comments. +var_templates_list=( + NIX_IGNORE_LD_THROUGH_GCC + NIX_LDFLAGS + NIX_LDFLAGS_BEFORE + NIX_DYNAMIC_LINKER + NIX_LDFLAGS_AFTER + NIX_LDFLAGS_HARDEN + NIX_HARDENING_ENABLE +) +var_templates_bool=( + NIX_SET_BUILD_ID + NIX_DONT_SET_RPATH +) + +accumulateRoles + +for var in "${var_templates_list[@]}"; do + mangleVarList "$var" ${role_suffixes[@]+"${role_suffixes[@]}"} +done +for var in "${var_templates_bool[@]}"; do + mangleVarBool "$var" ${role_suffixes[@]+"${role_suffixes[@]}"} +done + +if [ -e @out@/nix-support/libc-ldflags ]; then + NIX_LDFLAGS_@suffixSalt@+=" $(< @out@/nix-support/libc-ldflags)" +fi + +if [ -z "$NIX_DYNAMIC_LINKER_@suffixSalt@" ] && [ -e @out@/nix-support/ld-set-dynamic-linker ]; then + NIX_DYNAMIC_LINKER_@suffixSalt@="$(< @out@/nix-support/dynamic-linker)" +fi + +if [ -e @out@/nix-support/libc-ldflags-before ]; then + NIX_LDFLAGS_BEFORE_@suffixSalt@="$(< @out@/nix-support/libc-ldflags-before) $NIX_LDFLAGS_BEFORE_@suffixSalt@" +fi + +export NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@=1 diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/add-hardening.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/add-hardening.sh new file mode 100644 index 000000000000..db9553c3fc76 --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/add-hardening.sh @@ -0,0 +1,62 @@ +declare -a hardeningLDFlags=() + +declare -A hardeningEnableMap=() + +# Intentionally word-split in case 'NIX_HARDENING_ENABLE' is defined in Nix. The +# array expansion also prevents undefined variables from causing trouble with +# `set -u`. +for flag in ${NIX_HARDENING_ENABLE_@suffixSalt@-}; do + hardeningEnableMap["$flag"]=1 +done + +# Remove unsupported flags. +for flag in @hardening_unsupported_flags@; do + unset -v "hardeningEnableMap[$flag]" +done + +if (( "${NIX_DEBUG:-0}" >= 1 )); then + declare -a allHardeningFlags=(pie relro bindnow) + declare -A hardeningDisableMap=() + + # Determine which flags were effectively disabled so we can report below. + for flag in "${allHardeningFlags[@]}"; do + if [[ -z "${hardeningEnableMap[$flag]-}" ]]; then + hardeningDisableMap[$flag]=1 + fi + done + + printf 'HARDENING: disabled flags:' >&2 + (( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2 + echo >&2 + + if (( "${#hardeningEnableMap[@]}" )); then + echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; + fi +fi + +for flag in "${!hardeningEnableMap[@]}"; do + case $flag in + pie) + if [[ ! (" ${params[*]} " =~ " -shared " \ + || " ${params[*]} " =~ " -static " \ + || " ${params[*]} " =~ " -r " \ + || " ${params[*]} " =~ " -Ur " \ + || " ${params[*]} " =~ " -i ") ]]; then + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi + hardeningLDFlags+=('-pie') + fi + ;; + relro) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling relro >&2; fi + hardeningLDFlags+=('-z' 'relro') + ;; + bindnow) + if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling bindnow >&2; fi + hardeningLDFlags+=('-z' 'now') + ;; + *) + # Ignore unsupported. Checked in Nix that at least *some* + # tool supports each flag. + ;; + esac +done diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/darwin-install_name_tool-wrapper.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/darwin-install_name_tool-wrapper.sh new file mode 100755 index 000000000000..376a7abfe41c --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/darwin-install_name_tool-wrapper.sh @@ -0,0 +1,49 @@ +#! @shell@ +# shellcheck shell=bash + +set -eu -o pipefail +o posix +shopt -s nullglob + +if (( "${NIX_DEBUG:-0}" >= 7 )); then + set -x +fi + +source @signingUtils@ + +extraAfter=() +extraBefore=() +params=("$@") + +input= + +pprev= +prev= +for p in \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} +do + if [ "$pprev" != "-change" ] && [[ "$prev" != -* ]] && [[ "$p" != -* ]]; then + input="$p" + fi + pprev="$prev" + prev="$p" +done + +# Optionally print debug info. +if (( "${NIX_DEBUG:-0}" >= 1 )); then + # Old bash workaround, see above. + echo "extra flags before to @prog@:" >&2 + printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" ${params+"${params[@]}"} >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2 +fi + +@prog@ \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} + +sign "$input" diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/darwin-strip-wrapper.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/darwin-strip-wrapper.sh new file mode 100755 index 000000000000..a67699547a6f --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/darwin-strip-wrapper.sh @@ -0,0 +1,78 @@ +#! @shell@ +# shellcheck shell=bash + +set -eu -o pipefail +o posix +shopt -s nullglob + +if (( "${NIX_DEBUG:-0}" >= 7 )); then + set -x +fi + +source @signingUtils@ + +extraAfter=() +extraBefore=() +params=("$@") + +output= +inputs=() + +restAreFiles= +prev= +for p in \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} +do + if [ "$restAreFiles" ]; then + inputs+=("$p") + else + case "$prev" in + -s|-R|-d|-arch) + # Unrelated arguments with values + ;; + -o) + # Explicit output + output="$p" + ;; + *) + # Any other orgument either takes no value, or is a file. + if [[ "$p" != -* ]]; then + inputs+=("$p") + fi + ;; + esac + + if [ "$p" == - ]; then + restAreFiles=1 + fi + fi + + prev="$p" +done + +# Optionally print debug info. +if (( "${NIX_DEBUG:-0}" >= 1 )); then + # Old bash workaround, see above. + echo "extra flags before to @prog@:" >&2 + printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" ${params+"${params[@]}"} >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2 +fi + +@prog@ \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} + +if [ "$output" ]; then + # Single explicit output + signIfRequired "$output" +else + # Multiple inputs, rewritten in place + for input in "${inputs[@]}"; do + signIfRequired "$input" + done +fi diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix new file mode 100644 index 000000000000..2d75330f1c9e --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/default.nix @@ -0,0 +1,440 @@ +# The Nixpkgs CC is not directly usable, since it doesn't know where +# the C library and standard header files are. Therefore the compiler +# produced by that package cannot be installed directly in a user +# environment and used from the command line. So we use a wrapper +# script that sets up the right environment variables so that the +# compiler and the linker just "work". + +{ name ? "" +, lib +, stdenvNoCC +, runtimeShell +, bintools ? null, libc ? null, coreutils ? null, gnugrep ? null +, netbsd ? null +, sharedLibraryLoader ? + if libc == null then + null + else if stdenvNoCC.targetPlatform.isNetBSD then + if !(targetPackages ? netbsd) then + netbsd.ld_elf_so + else if libc != targetPackages.netbsd.headers then + targetPackages.netbsd.ld_elf_so + else + null + else + lib.getLib libc +, nativeTools, noLibc ? false, nativeLibc, nativePrefix ? "" +, propagateDoc ? bintools != null && bintools ? man +, extraPackages ? [], extraBuildCommands ? "" +, isGNU ? bintools.isGNU or false +, isLLVM ? bintools.isLLVM or false +, isCCTools ? bintools.isCCTools or false +, expand-response-params +, targetPackages ? {} +, useMacosReexportHack ? false +, wrapGas ? false + +# Note: the hardening flags are part of the bintools-wrapper, rather than +# the cc-wrapper, because a few of them are handled by the linker. +, defaultHardeningFlags ? [ + "bindnow" + "format" + "fortify" + "fortify3" + "pic" + "relro" + "stackprotector" + "strictoverflow" + ] ++ lib.optional (with stdenvNoCC; + # Musl-based platforms will keep "pie", other platforms will not. + # If you change this, make sure to update section `{#sec-hardening-in-nixpkgs}` + # in the nixpkgs manual to inform users about the defaults. + targetPlatform.libc == "musl" + # Except when: + # - static aarch64, where compilation works, but produces segfaulting dynamically linked binaries. + # - static armv7l, where compilation fails. + && !(targetPlatform.isAarch && targetPlatform.isStatic) + ) "pie" + +# Darwin code signing support utilities +, postLinkSignHook ? null, signingUtils ? null +}: + +assert propagateDoc -> bintools ? man; +assert nativeTools -> !propagateDoc && nativePrefix != ""; +assert !nativeTools -> bintools != null && coreutils != null && gnugrep != null; +assert !(nativeLibc && noLibc); +assert (noLibc || nativeLibc) == (libc == null); + +let + inherit (lib) + attrByPath + concatStringsSep + getBin + getDev + getLib + getName + getVersion + hasSuffix + optional + optionalAttrs + optionals + optionalString + platforms + removePrefix + replaceStrings + ; + + inherit (stdenvNoCC) hostPlatform targetPlatform; + + # Prefix for binaries. Customarily ends with a dash separator. + # + # TODO(@Ericson2314) Make unconditional, or optional but always true by + # default. + targetPrefix = optionalString (targetPlatform != hostPlatform) + (targetPlatform.config + "-"); + + bintoolsVersion = getVersion bintools; + bintoolsName = removePrefix targetPrefix (getName bintools); + + libc_bin = optionalString (libc != null) (getBin libc); + libc_dev = optionalString (libc != null) (getDev libc); + libc_lib = optionalString (libc != null) (getLib libc); + bintools_bin = optionalString (!nativeTools) (getBin bintools); + # The wrapper scripts use 'cat' and 'grep', so we may need coreutils. + coreutils_bin = optionalString (!nativeTools) (getBin coreutils); + + # See description in cc-wrapper. + suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config; + + # The dynamic linker has different names on different platforms. This is a + # shell glob that ought to match it. + dynamicLinker = + /**/ if sharedLibraryLoader == null then "" + else if targetPlatform.libc == "musl" then "${sharedLibraryLoader}/lib/ld-musl-*" + else if targetPlatform.libc == "uclibc" then "${sharedLibraryLoader}/lib/ld*-uClibc.so.1" + else if (targetPlatform.libc == "bionic" && targetPlatform.is32bit) then "/system/bin/linker" + else if (targetPlatform.libc == "bionic" && targetPlatform.is64bit) then "/system/bin/linker64" + else if targetPlatform.libc == "nblibc" then "${sharedLibraryLoader}/libexec/ld.elf_so" + else if targetPlatform.system == "i686-linux" then "${sharedLibraryLoader}/lib/ld-linux.so.2" + else if targetPlatform.system == "x86_64-linux" then "${sharedLibraryLoader}/lib/ld-linux-x86-64.so.2" + # ELFv1 (.1) or ELFv2 (.2) ABI + else if targetPlatform.isPower64 then "${sharedLibraryLoader}/lib/ld64.so.*" + # ARM with a wildcard, which can be "" or "-armhf". + else if (with targetPlatform; isAarch32 && isLinux) then "${sharedLibraryLoader}/lib/ld-linux*.so.3" + else if targetPlatform.system == "aarch64-linux" then "${sharedLibraryLoader}/lib/ld-linux-aarch64.so.1" + else if targetPlatform.system == "powerpc-linux" then "${sharedLibraryLoader}/lib/ld.so.1" + else if targetPlatform.isMips then "${sharedLibraryLoader}/lib/ld.so.1" + # `ld-linux-riscv{32,64}-<abi>.so.1` + else if targetPlatform.isRiscV then "${sharedLibraryLoader}/lib/ld-linux-riscv*.so.1" + else if targetPlatform.isLoongArch64 then "${sharedLibraryLoader}/lib/ld-linux-loongarch*.so.1" + else if targetPlatform.isDarwin then "/usr/lib/dyld" + else if targetPlatform.isFreeBSD then "${sharedLibraryLoader}/libexec/ld-elf.so.1" + else if hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" + else ""; + +in + +stdenvNoCC.mkDerivation { + pname = targetPrefix + + (if name != "" then name else "${bintoolsName}-wrapper"); + version = optionalString (bintools != null) bintoolsVersion; + + preferLocalBuild = true; + + outputs = [ "out" ] ++ optionals propagateDoc ([ "man" ] ++ optional (bintools ? info) "info"); + + passthru = { + inherit targetPrefix suffixSalt; + inherit bintools libc nativeTools nativeLibc nativePrefix isGNU isLLVM; + + emacsBufferSetup = pkgs: '' + ; We should handle propagation here too + (mapc + (lambda (arg) + (when (file-directory-p (concat arg "/lib")) + (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib"))) + (when (file-directory-p (concat arg "/lib64")) + (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib64")))) + '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) + ''; + + inherit defaultHardeningFlags; + }; + + dontBuild = true; + dontConfigure = true; + + enableParallelBuilding = true; + + unpackPhase = '' + src=$PWD + ''; + + installPhase = + '' + mkdir -p $out/bin $out/nix-support + + 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" + } + '' + + + (if nativeTools then '' + echo ${nativePrefix} > $out/nix-support/orig-bintools + + ldPath="${nativePrefix}/bin" + '' else '' + echo $bintools_bin > $out/nix-support/orig-bintools + + ldPath="${bintools_bin}/bin" + '' + + # Solaris needs an additional ld wrapper. + + optionalString (targetPlatform.isSunOS && nativePrefix != "") '' + ldPath="${nativePrefix}/bin" + exec="$ldPath/${targetPrefix}ld" + wrap ld-solaris ${./ld-solaris-wrapper.sh} + '') + + # If we are asked to wrap `gas` and this bintools has it, + # then symlink it (`as` will be symlinked next). + # This is mainly for the wrapped gnat-bootstrap on x86-64 Darwin, + # as it must have both the GNU assembler from cctools (installed as `gas`) + # and the Clang integrated assembler (installed as `as`). + # See pkgs/os-specific/darwin/binutils/default.nix for details. + + optionalString wrapGas '' + if [ -e $ldPath/${targetPrefix}gas ]; then + ln -s $ldPath/${targetPrefix}gas $out/bin/${targetPrefix}gas + fi + '' + + # 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 dlltool dllwrap windmc windres; do + if [ -e $ldPath/${targetPrefix}''${binary} ]; then + ln -s $ldPath/${targetPrefix}''${binary} $out/bin/${targetPrefix}''${binary} + fi + done + + '' + (if !useMacosReexportHack then '' + if [ -e ''${ld:-$ldPath/${targetPrefix}ld} ]; then + wrap ${targetPrefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${targetPrefix}ld} + fi + '' else '' + ldInner="${targetPrefix}ld-reexport-delegate" + wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${targetPrefix}ld} + wrap "${targetPrefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner" + unset ldInner + '') + '' + + for variant in $ldPath/${targetPrefix}ld.*; do + basename=$(basename "$variant") + wrap $basename ${./ld-wrapper.sh} $variant + done + ''; + + strictDeps = true; + depsTargetTargetPropagated = extraPackages; + + setupHooks = [ + ../setup-hooks/role.bash + ./setup-hook.sh + ]; + + postFixup = + ## + ## General libc support + ## + optionalString (libc != null) ('' + touch "$out/nix-support/libc-ldflags" + echo "-L${libc_lib}${libc.libdir or "/lib"}" >> $out/nix-support/libc-ldflags + + echo "${libc_lib}" > $out/nix-support/orig-libc + echo "${libc_dev}" > $out/nix-support/orig-libc-dev + '' + + ## + ## Dynamic linker support + ## + + optionalString (sharedLibraryLoader != null) '' + if [[ -z ''${dynamicLinker+x} ]]; then + echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2 + local dynamicLinker="${sharedLibraryLoader}/lib/ld*.so.?" + fi + '' + + # Expand globs to fill array of options + + '' + dynamicLinker=($dynamicLinker) + + case ''${#dynamicLinker[@]} in + 0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;; + 1) echo "Using dynamic linker: '$dynamicLinker'" >&2;; + *) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;; + esac + + if [ -n "''${dynamicLinker-}" ]; then + echo $dynamicLinker > $out/nix-support/dynamic-linker + + ${if targetPlatform.isDarwin then '' + printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook + '' else optionalString (sharedLibraryLoader != null) '' + if [ -e ${sharedLibraryLoader}/lib/32/ld-linux.so.2 ]; then + echo ${sharedLibraryLoader}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32 + fi + touch $out/nix-support/ld-set-dynamic-linker + ''} + fi + '') + + ## + ## User env support + ## + + # Propagate the underling unwrapped bintools so that if you + # install the wrapper, you get tools like objdump (same for any + # binaries of libc). + + optionalString (!nativeTools) '' + printWords ${bintools_bin} ${optionalString (libc != null) libc_bin} > $out/nix-support/propagated-user-env-packages + '' + + ## + ## Man page and info support + ## + + optionalString propagateDoc ('' + ln -s ${bintools.man} $man + '' + optionalString (bintools ? info) '' + ln -s ${bintools.info} $info + '') + + ## + ## Hardening support + ## + + # some linkers on some platforms don't support specific -z flags + + '' + export hardening_unsupported_flags="" + if [[ "$($ldPath/${targetPrefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then + hardening_unsupported_flags+=" bindnow" + fi + if [[ "$($ldPath/${targetPrefix}ld -z relro 2>&1 || true)" =~ un(recognized|known)\ option ]]; then + hardening_unsupported_flags+=" relro" + fi + '' + + + optionalString hostPlatform.isCygwin '' + hardening_unsupported_flags+=" pic" + '' + + + optionalString (targetPlatform.isAvr || targetPlatform.isWindows) '' + hardening_unsupported_flags+=" relro bindnow" + '' + + + optionalString (libc != null && targetPlatform.isAvr) '' + for isa in avr5 avr3 avr4 avr6 avr25 avr31 avr35 avr51 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack; do + echo "-L${getLib libc}/avr/lib/$isa" >> $out/nix-support/libc-cflags + done + '' + + + optionalString targetPlatform.isDarwin '' + echo "-arch ${targetPlatform.darwinArch}" >> $out/nix-support/libc-ldflags + '' + + ## + ## GNU specific extra strip flags + ## + + # TODO(@sternenseemann): make a generic strip wrapper? + + optionalString (bintools.isGNU or false) '' + wrap ${targetPrefix}strip ${./gnu-binutils-strip-wrapper.sh} \ + "${bintools_bin}/bin/${targetPrefix}strip" + '' + + ### + ### Remove certain timestamps from final binaries + ### + + optionalString (targetPlatform.isDarwin && !(bintools.isGNU or false)) '' + echo "export ZERO_AR_DATE=1" >> $out/nix-support/setup-hook + '' + + + '' + for flags in "$out/nix-support"/*flags*; do + substituteInPlace "$flags" --replace $'\n' ' ' + done + + substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh + substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh + substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash + '' + + ### + ### Ensure consistent LC_VERSION_MIN_MACOSX + ### + + optionalString targetPlatform.isDarwin ( + let + inherit (targetPlatform) + darwinPlatform darwinSdkVersion + darwinMinVersion darwinMinVersionVariable; + in '' + export darwinPlatform=${darwinPlatform} + export darwinMinVersion=${darwinMinVersion} + export darwinSdkVersion=${darwinSdkVersion} + export darwinMinVersionVariable=${darwinMinVersionVariable} + substituteAll ${./add-darwin-ldflags-before.sh} $out/nix-support/add-local-ldflags-before.sh + '' + ) + + ## + ## Code signing on Apple Silicon + ## + + optionalString (targetPlatform.isDarwin && targetPlatform.isAarch64) '' + echo 'source ${postLinkSignHook}' >> $out/nix-support/post-link-hook + + export signingUtils=${signingUtils} + + wrap \ + ${targetPrefix}install_name_tool \ + ${./darwin-install_name_tool-wrapper.sh} \ + "${bintools_bin}/bin/${targetPrefix}install_name_tool" + + wrap \ + ${targetPrefix}strip ${./darwin-strip-wrapper.sh} \ + "${bintools_bin}/bin/${targetPrefix}strip" + '' + + ## + ## Extra custom steps + ## + + extraBuildCommands; + + env = { + # for substitution in utils.bash + # TODO(@sternenseemann): invent something cleaner than passing in "" in case of absence + expandResponseParams = "${expand-response-params}/bin/expand-response-params"; + # TODO(@sternenseemann): rename env var via stdenv rebuild + shell = (getBin runtimeShell + runtimeShell.shellPath or ""); + gnugrep_bin = optionalString (!nativeTools) gnugrep; + wrapperName = "BINTOOLS_WRAPPER"; + inherit dynamicLinker targetPrefix suffixSalt coreutils_bin; + inherit bintools_bin libc_bin libc_dev libc_lib; + default_hardening_flags_str = builtins.toString defaultHardeningFlags; + }; + + meta = + let bintools_ = optionalAttrs (bintools != null) bintools; in + (optionalAttrs (bintools_ ? meta) (removeAttrs bintools.meta ["priority"])) // + { description = + attrByPath ["meta" "description"] "System binary utilities" bintools_ + + " (wrapper script)"; + priority = 10; + } // optionalAttrs useMacosReexportHack { + platforms = platforms.darwin; + }; +} diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh new file mode 100644 index 000000000000..5b5136e3d14c --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/gnu-binutils-strip-wrapper.sh @@ -0,0 +1,4 @@ +#! @shell@ +# shellcheck shell=bash + +exec @prog@ --enable-deterministic-archives "$@" diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh new file mode 100644 index 000000000000..5d81e34a047f --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh @@ -0,0 +1,29 @@ +#!@shell@ +set -eu -o pipefail +shopt -s nullglob + +if (( "${NIX_DEBUG:-0}" >= 7 )); then + set -x +fi + +declare -a args=("$@") +# I've also tried adding -z direct and -z lazyload, but it gave too many problems with C++ exceptions :'( +# Also made sure libgcc would not be lazy-loaded, as suggested here: https://www.illumos.org/issues/2534#note-3 +# but still no success. +declare -a argsBefore=(-z ignore) argsAfter=() + +# This loop makes sure all -L arguments are before -l arguments, or ld may complain it cannot find a library. +# GNU binutils does not have this problem: +# http://stackoverflow.com/questions/5817269/does-the-order-of-l-and-l-options-in-the-gnu-linker-matter +while (( $# )); do + case "${args[$i]}" in + -L) argsBefore+=("$1" "$2"); shift ;; + -L?*) argsBefore+=("$1") ;; + *) argsAfter+=("$1") ;; + esac + shift +done + +# Trace: +set -x +exec "@ld@" "${argsBefore[@]}" "${argsAfter[@]}" diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/ld-wrapper.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/ld-wrapper.sh new file mode 100644 index 000000000000..dcbe8a4c2494 --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/ld-wrapper.sh @@ -0,0 +1,273 @@ +#! @shell@ +set -eu -o pipefail +o posix +shopt -s nullglob + +if (( "${NIX_DEBUG:-0}" >= 7 )); then + set -x +fi + +path_backup="$PATH" + +# phase separation makes this look useless +# shellcheck disable=SC2157 +if [ -n "@coreutils_bin@" ]; then + PATH="@coreutils_bin@/bin" +fi + +source @out@/nix-support/utils.bash + +if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then + source @out@/nix-support/add-flags.sh +fi + + +# Optionally filter out paths not refering to the store. +expandResponseParams "$@" + +# NIX_LINK_TYPE is set if ld has been called through our cc wrapper. We take +# advantage of this to avoid both recalculating it, and also repeating other +# processing cc wrapper has already done. +if [[ -n "${NIX_LINK_TYPE_@suffixSalt@:-}" ]]; then + linkType=$NIX_LINK_TYPE_@suffixSalt@ +else + linkType=$(checkLinkType "${params[@]}") +fi + +if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}" + && ( -z "$NIX_IGNORE_LD_THROUGH_GCC_@suffixSalt@" || -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ) ]]; then + rest=() + nParams=${#params[@]} + declare -i n=0 + + while (( "$n" < "$nParams" )); do + p=${params[n]} + p2=${params[n+1]:-} # handle `p` being last one + if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then + skip "${p:2}" + elif [ "$p" = -L ] && badPath "$p2"; then + n+=1; skip "$p2" + elif [ "$p" = -rpath ] && badPath "$p2"; then + n+=1; skip "$p2" + elif [ "$p" = -dynamic-linker ] && badPath "$p2"; then + n+=1; skip "$p2" + elif [ "$p" = -syslibroot ] && [ $p2 == // ]; then + # When gcc is built on darwin --with-build-sysroot=/ + # produces '-syslibroot //' linker flag. It's a no-op, + # which does not introduce impurities. + n+=1; skip "$p2" + elif [ "${p:0:10}" = /LIBPATH:/ ] && badPath "${p:9}"; then + reject "${p:9}" + # We need to not match LINK.EXE-style flags like + # /NOLOGO or /LIBPATH:/nix/store/foo + elif [[ $p =~ ^/[^:]*/ ]] && badPath "$p"; then + reject "$p" + elif [ "${p:0:9}" = --sysroot ]; then + # Our ld is not built with sysroot support (Can we fix that?) + : + else + rest+=("$p") + fi + n+=1 + done + # Old bash empty array hack + params=(${rest+"${rest[@]}"}) +fi + + +source @out@/nix-support/add-hardening.sh + +extraAfter=() +extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"}) + +if [ -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ]; then + extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@)) + extraBefore+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@)) + + # By adding dynamic linker to extraBefore we allow the users set their + # own dynamic linker as NIX_LD_FLAGS will override earlier set flags + if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then + extraBefore+=("-dynamic-linker" "$NIX_DYNAMIC_LINKER_@suffixSalt@") + fi +fi + +extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_AFTER_@suffixSalt@)) + +# These flags *must not* be pulled up to -Wl, flags, so they can't go in +# add-flags.sh. They must always be set, so must not be disabled by +# NIX_LDFLAGS_SET. +if [ -e @out@/nix-support/add-local-ldflags-before.sh ]; then + source @out@/nix-support/add-local-ldflags-before.sh +fi + + +# Three tasks: +# +# 1. Find all -L... switches for rpath +# +# 2. Find relocatable flag for build id. +# +# 3. Choose 32-bit dynamic linker if needed +declare -a libDirs +declare -A libs +declare -i relocatable=0 link32=0 + +linkerOutput="a.out" + +if + [ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 ] \ + || [ "$NIX_SET_BUILD_ID_@suffixSalt@" = 1 ] \ + || [ -e @out@/nix-support/dynamic-linker-m32 ] +then + prev= + # Old bash thinks empty arrays are undefined, ugh. + for p in \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} + do + case "$prev" in + -L) + libDirs+=("$p") + ;; + -l) + libs["lib${p}.so"]=1 + ;; + -m) + # Presumably only the last `-m` flag has any effect. + case "$p" in + elf_i386) link32=1;; + *) link32=0;; + esac + ;; + -dynamic-linker | -plugin) + # Ignore this argument, or it will match *.so and be added to rpath. + ;; + *) + case "$p" in + -L/*) + libDirs+=("${p:2}") + ;; + -l?*) + libs["lib${p:2}.so"]=1 + ;; + "${NIX_STORE:-}"/*.so | "${NIX_STORE:-}"/*.so.*) + # This is a direct reference to a shared library. + libDirs+=("${p%/*}") + libs["${p##*/}"]=1 + ;; + -r | --relocatable | -i) + relocatable=1 + esac + ;; + esac + prev="$p" + done +fi + +# Determine linkerOutput +prev= +for p in \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} +do + case "$prev" in + -o) + # Informational for post-link-hook + linkerOutput="$p" + ;; + *) + ;; + esac + prev="$p" +done + +if [[ "$link32" == "1" && "$linkType" == dynamic && -e "@out@/nix-support/dynamic-linker-m32" ]]; then + # We have an alternate 32-bit linker and we're producing a 32-bit ELF, let's + # use it. + extraAfter+=( + '-dynamic-linker' + "$(< @out@/nix-support/dynamic-linker-m32)" + ) +fi + +# Add all used dynamic libraries to the rpath. +if [[ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 && "$linkType" != static-pie ]]; then + # 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. + # It's important to add the rpath in the order of -L..., so + # the link time chosen objects will be those of runtime linking. + declare -A rpaths + for dir in ${libDirs+"${libDirs[@]}"}; do + if [[ "$dir" =~ [/.][/.] ]] && dir2=$(readlink -f "$dir"); then + dir="$dir2" + fi + if [ -n "${rpaths[$dir]:-}" ] || [[ "$dir" != "${NIX_STORE:-}"/* ]]; then + # If the path is not in the store, don't add it to the rpath. + # This typically happens for libraries in /tmp that are later + # copied to $out/lib. If not, we're screwed. + continue + fi + for path in "$dir"/*; do + file="${path##*/}" + if [ "${libs[$file]:-}" ]; then + # This library may have been provided by a previous directory, + # but if that library file is inside an output of the current + # derivation, it can be deleted after this compilation and + # should be found in a later directory, so we add all + # directories that contain any of the libraries to rpath. + rpaths["$dir"]=1 + extraAfter+=(-rpath "$dir") + break + fi + done + done + +fi + +# This is outside the DONT_SET_RPATH branch because it's more targeted and we +# usually want it (on Darwin) even if DONT_SET_RPATH is set. +if [ -n "${NIX_COREFOUNDATION_RPATH:-}" ]; then + extraAfter+=(-rpath $NIX_COREFOUNDATION_RPATH) +fi + +# Only add --build-id if this is a final link. FIXME: should build gcc +# with --enable-linker-build-id instead? +# +# Note: `lld` interprets `--build-id` to mean `--build-id=fast`; GNU ld defaults +# to SHA1. +if [ "$NIX_SET_BUILD_ID_@suffixSalt@" = 1 ] && ! (( "$relocatable" )); then + extraAfter+=(--build-id="${NIX_BUILD_ID_STYLE:-sha1}") +fi + + +# Optionally print debug info. +if (( "${NIX_DEBUG:-0}" >= 1 )); then + # Old bash workaround, see above. + echo "extra flags before to @prog@:" >&2 + printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" ${params+"${params[@]}"} >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2 +fi + +PATH="$path_backup" +# Old bash workaround, see above. + +if (( "${NIX_LD_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then + @prog@ @<(printf "%q\n" \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"}) +else + @prog@ \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} +fi + +if [ -e "@out@/nix-support/post-link-hook" ]; then + source @out@/nix-support/post-link-hook +fi diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash b/nixpkgs/pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash new file mode 100644 index 000000000000..255071adf681 --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash @@ -0,0 +1,246 @@ +#! @shell@ + +set -eu -o pipefail + +# For cmd | while read; do ...; done +shopt -s lastpipe + +path_backup="$PATH" +if [ -n "@coreutils_bin@" ]; then + PATH="@coreutils_bin@/bin" +fi + +declare -ri recurThreshold=200 +declare -i overflowCount=0 + +declare -ar origArgs=("$@") + +# Throw away what we won't need +declare -a parentArgs=() + +while (( $# )); do + case "$1" in + -l) + echo "cctools LD does not support '-l foo'" >&2 + exit 1 + ;; + -lazy_library | -reexport_library | -upward_library | -weak_library) + overflowCount+=1 + shift 2 + ;; + -l* | *.so.* | *.dylib | -lazy-l* | -reexport-l* | -upward-l* | -weak-l*) + overflowCount+=1 + shift 1 + ;; + *.a | *.o) + shift 1 + ;; + -L | -F) + # Evidentally ld doesn't like using the child's RPATH, so it still + # needs these. + parentArgs+=("$1" "$2") + shift 2 + ;; + -L?* | -F?*) + parentArgs+=("$1") + shift 1 + ;; + -o) + outputName="$2" + parentArgs+=("$1" "$2") + shift 2 + ;; + -install_name | -dylib_install_name | -dynamic-linker | -plugin) + parentArgs+=("$1" "$2") + shift 2 + ;; + -rpath) + # Only an rpath to the child is needed, which we will add + shift 2 + ;; + *) + if [[ -f "$1" ]]; then + # Propabably a non-standard object file like Haskell's + # `.dyn_o`. Skip it like other inputs + : + else + parentArgs+=("$1") + fi + shift 1 + ;; + esac +done + + + +if (( "$overflowCount" <= "$recurThreshold" )); then + if [ -n "${NIX_DEBUG:-}" ]; then + echo "ld-wrapper: Only ${overflowCount} inputs counted while ${recurThreshold} is the ceiling, linking normally. " >&2 + fi + PATH="$path_backup" + exec @prog@ "${origArgs[@]}" +fi + + + +if [ -n "${NIX_DEBUG:-}" ]; then + echo "ld-wrapper: ${overflowCount} inputs counted when ${recurThreshold} is the ceiling, inspecting further. " >&2 +fi + +# Collect the normalized linker input +declare -a norm=() + +# Arguments are null-separated +@prog@ --dump-normalized-lib-args "${origArgs[@]}" | + while IFS= read -r -d '' input; do + norm+=("$input") + done + +declare -i leafCount=0 +declare lastLeaf='' +declare -a childrenInputs=() trailingInputs=() +while (( "${#norm[@]}" )); do + case "${norm[0]}" in + -lazy_library | -upward_library) + # TODO(@Ericson2314): Don't do that, but intersperse children + # between such args. + echo "ld-wrapper: Warning: Potentially changing link order" >&2 + trailingInputs+=("${norm[0]}" "${norm[1]}") + norm=("${norm[@]:2}") + ;; + -reexport_library | -weak_library) + childrenInputs+=("${norm[0]}" "${norm[1]}") + if [[ "${norm[1]}" != "$lastLeaf" ]]; then + leafCount+=1 + lastLeaf="${norm[1]}" + fi + norm=("${norm[@]:2}") + ;; + *.so | *.dylib) + childrenInputs+=(-reexport_library "${norm[0]}") + if [[ "${norm[0]}" != "$lastLeaf" ]]; then + leafCount+=1 + lastLeaf="${norm[0]}" + fi + norm=("${norm[@]:1}") + ;; + *.o | *.a) + # Don't delegate object files or static libs + parentArgs+=("${norm[0]}") + norm=("${norm[@]:1}") + ;; + *) + if [[ -f "${norm[0]}" ]]; then + # Propabably a non-standard object file. We'll let it by. + parentArgs+=("${norm[0]}") + norm=("${norm[@]:1}") + else + echo "ld-wrapper: Internal Error: Invalid normalized argument" >&2 + exit 255 + fi + ;; + esac +done + + + +if (( "$leafCount" <= "$recurThreshold" )); then + if [ -n "${NIX_DEBUG:-}" ]; then + echo "ld-wrapper: Only ${leafCount} *dynamic* inputs counted while ${recurThreshold} is the ceiling, linking normally. " >&2 + fi + PATH="$path_backup" + exec @prog@ "${origArgs[@]}" +fi + + + +if [ -n "${NIX_DEBUG:-}" ]; then + echo "ld-wrapper: ${leafCount} *dynamic* inputs counted when ${recurThreshold} is the ceiling, delegating to children. " >&2 +fi + +declare -r outputNameLibless=$( \ + if [[ -z "${outputName:+isUndefined}" ]]; then + echo unnamed + return 0; + fi + baseName=$(basename ${outputName}) + if [[ "$baseName" = lib* ]]; then + baseName="${baseName:3}" + fi + echo "$baseName") + +declare -ra children=( + "$outputNameLibless-reexport-delegate-0" + "$outputNameLibless-reexport-delegate-1" +) + +mkdir -p "$out/lib" + +symbolBloatObject=$outputNameLibless-symbol-hack.o +if [[ ! -f $symbolBloatObject ]]; then + # `-Q` means use GNU Assembler rather than Clang, avoiding an awkward + # dependency cycle. + printf '.private_extern _______child_hack_foo\nchild_hack_foo:\n' | + PATH="$PATH:@out@/bin" @targetPrefix@as -Q -- -o $symbolBloatObject +fi + +# Split inputs between children +declare -a child0Inputs=() child1Inputs=("${childrenInputs[@]}") +let "countFirstChild = $leafCount / 2" || true +lastLeaf='' +while (( "$countFirstChild" )); do + case "${child1Inputs[0]}" in + -reexport_library | -weak_library) + child0Inputs+=("${child1Inputs[0]}" "${child1Inputs[1]}") + if [[ "${child1Inputs[1]}" != "$lastLeaf" ]]; then + let countFirstChild-=1 || true + lastLeaf="${child1Inputs[1]}" + fi + child1Inputs=("${child1Inputs[@]:2}") + ;; + *.so | *.dylib) + child0Inputs+=(-reexport_library "${child1Inputs[0]}") + if [[ "${child1Inputs[0]}" != "$lastLeaf" ]]; then + let countFirstChild-=1 || true + lastLeaf="${child1Inputs[1]}" + fi + child1Inputs=("${child1Inputs[@]:2}") + ;; + *) + echo "ld-wrapper: Internal Error: Invalid delegated input" >&2 + exit -1 + ;; + esac +done + + +# First half of libs +@out@/bin/@targetPrefix@ld \ + -macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \ + -o "$out/lib/lib${children[0]}.dylib" \ + -install_name "$out/lib/lib${children[0]}.dylib" \ + "$symbolBloatObject" "${child0Inputs[@]}" "${trailingInputs[@]}" + +# Second half of libs +@out@/bin/@targetPrefix@ld \ + -macosx_version_min $MACOSX_DEPLOYMENT_TARGET -arch x86_64 -dylib \ + -o "$out/lib/lib${children[1]}.dylib" \ + -install_name "$out/lib/lib${children[1]}.dylib" \ + "$symbolBloatObject" "${child1Inputs[@]}" "${trailingInputs[@]}" + +parentArgs+=("-L$out/lib" -rpath "$out/lib") +if [[ $outputName != *reexport-delegate* ]]; then + parentArgs+=("-l${children[0]}" "-l${children[1]}") +else + parentArgs+=("-reexport-l${children[0]}" "-reexport-l${children[1]}") +fi + +parentArgs+=("${trailingInputs[@]}") + +if [ -n "${NIX_DEBUG:-}" ]; then + echo "flags using delegated children to @prog@:" >&2 + printf " %q\n" "${parentArgs[@]}" >&2 +fi + +PATH="$path_backup" +exec @prog@ "${parentArgs[@]}" diff --git a/nixpkgs/pkgs/build-support/bintools-wrapper/setup-hook.sh b/nixpkgs/pkgs/build-support/bintools-wrapper/setup-hook.sh new file mode 100644 index 000000000000..c146cbea80e4 --- /dev/null +++ b/nixpkgs/pkgs/build-support/bintools-wrapper/setup-hook.sh @@ -0,0 +1,72 @@ +# Binutils Wrapper hygiene +# +# See comments in cc-wrapper's setup hook. This works exactly the same way. + +# Skip setup hook if we're neither a build-time dep, nor, temporarily, doing a +# native compile. +# +# TODO(@Ericson2314): No native exception +[[ -z ${strictDeps-} ]] || (( "$hostOffset" < 0 )) || return 0 + +bintoolsWrapper_addLDVars () { + # See ../setup-hooks/role.bash + local role_post + getHostRoleEnvHook + + if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then + export NIX_LDFLAGS${role_post}+=" -L$1/lib64" + fi + + if [[ -d "$1/lib" ]]; then + # Don't add the /lib directory if it actually doesn't contain any libraries. For instance, + # Python and Haskell packages often only have directories like $out/lib/ghc-8.4.3/ or + # $out/lib/python3.6/, so having them in LDFLAGS just makes the linker search unnecessary + # directories and bloats the size of the environment variable space. + local -a glob=( $1/lib/lib* ) + if [ "${#glob[*]}" -gt 0 ]; then + export NIX_LDFLAGS${role_post}+=" -L$1/lib" + fi + fi +} + +# See ../setup-hooks/role.bash +getTargetRole +getTargetRoleWrapper + +addEnvHooks "$targetOffset" bintoolsWrapper_addLDVars + +# shellcheck disable=SC2157 +if [ -n "@bintools_bin@" ]; then + addToSearchPath _PATH @bintools_bin@/bin +fi + +# shellcheck disable=SC2157 +if [ -n "@libc_bin@" ]; then + addToSearchPath _PATH @libc_bin@/bin +fi + +# shellcheck disable=SC2157 +if [ -n "@coreutils_bin@" ]; then + addToSearchPath _PATH @coreutils_bin@/bin +fi + +# Export tool environment variables so various build systems use the right ones. + +export NIX_BINTOOLS${role_post}=@out@ + +for cmd in \ + ar as ld nm objcopy objdump readelf ranlib strip strings size windres +do + if + PATH=$_PATH type -p "@targetPrefix@${cmd}" > /dev/null + then + export "${cmd^^}${role_post}=@targetPrefix@${cmd}"; + fi +done + +# If unset, assume the default hardening flags. +: ${NIX_HARDENING_ENABLE="@default_hardening_flags_str@"} +export NIX_HARDENING_ENABLE + +# No local scope in sourced file +unset -v role_post cmd upper_case |