diff --git a/doc/stdenv.xml b/doc/stdenv.xml index ee3403c196a47..91c659408c4bb 100644 --- a/doc/stdenv.xml +++ b/doc/stdenv.xml @@ -1358,36 +1358,67 @@ someVar=$(stripHash $name) - CC Wrapper + Bintools Wrapper - CC Wrapper wraps a C toolchain for a bunch of miscellaneous purposes. - Specifically, a C compiler (GCC or Clang), Binutils (or the CCTools + binutils mashup when targetting Darwin), and a C standard library (glibc or Darwin's libSystem) are all fed in, and dependency finding, hardening (see below), and purity checks for each are handled by CC Wrapper. - Packages typically depend on only CC Wrapper, instead of those 3 inputs directly. + Bintools Wrapper wraps the binary utilities for a bunch of miscellaneous purposes. + These are GNU Binutils when targetting Linux, and a mix of cctools and GNU binutils for Darwin. + [The "Bintools" name is supposed to be a compromise between "Binutils" and "cctools" not denoting any specific implementation.] + Specifically, the underlying bintools package, and a C standard library (glibc or Darwin's libSystem, just for the dynamic loader) are all fed in, and dependency finding, hardening (see below), and purity checks for each are handled by Bintools Wrapper. + Packages typically depend on CC Wrapper, which in turn (at run time) depends on Bintools Wrapper. - Dependency finding is undoubtedly the main task of CC wrapper. + Bintools Wrapper was only just recently split off from CC Wrapper, so the division of labor is still being worked out. + For example, it shouldn't care about about the C standard library, but just take a derivation with the dynamic loader (which happens to be the glibc on linux). + Dependency finding however is a task both wrappers will continue to need to share, and probably the most important to understand. It is currently accomplished by collecting directories of host-platform dependencies (i.e. buildInputs and nativeBuildInputs) in environment variables. - CC wrapper's setup hook causes any include subdirectory of such a dependency to be added to NIX_CFLAGS_COMPILE, and any lib and lib64 subdirectories to NIX_LDFLAGS. - The setup hook itself contains some lengthy comments describing the exact convoluted mechanism by which this is accomplished. + Bintools Wrapper's setup hook causes any lib and lib64 subdirectories to be added to NIX_LDFLAGS. + Since CC Wrapper and Bintools Wrapper use the same strategy, most of the Bintools Wrapper code is sparsely commented and refers to CC Wrapper. + But CC Wrapper's code, by contrast, has quite lengthy comments. + Bintools Wrapper merely cites those, rather than repeating them, to avoid falling out of sync. A final task of the setup hook is defining a number of standard environment variables to tell build systems which executables full-fill which purpose. - They are defined to just be the base name of the tools, under the assumption that CC Wrapper's binaries will be on the path. + They are defined to just be the base name of the tools, under the assumption that Bintools Wrapper's binaries will be on the path. Firstly, this helps poorly-written packages, e.g. ones that look for just gcc when CC isn't defined yet clang is to be used. - Secondly, this helps packages not get confused when cross-compiling, in which case multiple CC wrappers may be simultaneous in use (targeting different platforms). - BUILD_- and TARGET_-prefixed versions of the normal environment variable are defined for the additional CC Wrappers, properly disambiguating them. + Secondly, this helps packages not get confused when cross-compiling, in which case multiple Bintools Wrappers may simultaneously be in use. + + Each wrapper targets a single platform, so if binaries for multiple platforms are needed, the underlying binaries must be wrapped multiple times. + As this is a property of the wrapper itself, the multiple wrappings are needed whether or not the same underlying binaries can target multiple platforms. + + BUILD_- and TARGET_-prefixed versions of the normal environment variable are defined for the additional Bintools Wrappers, properly disambiguating them. - A problem with this final task is that CC Wrapper is honest and defines LD as ld. + A problem with this final task is that Bintools Wrapper is honest and defines LD as ld. Most packages, however, firstly use the C compiler for linking, secondly use LD anyways, defining it as the C compiler, and thirdly, only so define LD when it is undefined as a fallback. - This triple-threat means CC Wrapper will break those packages, as LD is already defined as the actually linker which the package won't override yet doesn't want to use. + This triple-threat means Bintools Wrapper will break those packages, as LD is already defined as the actual linker which the package won't override yet doesn't want to use. The workaround is to define, just for the problematic package, LD as the C compiler. A good way to do this would be preConfigure = "LD=$CC". + + CC Wrapper + + + CC Wrapper wraps a C toolchain for a bunch of miscellaneous purposes. + Specifically, a C compiler (GCC or Clang), wrapped binary tools, and a C standard library (glibc or Darwin's libSystem, just for the dynamic loader) are all fed in, and dependency finding, hardening (see below), and purity checks for each are handled by CC Wrapper. + Packages typically depend on CC Wrapper, which in turn (at run time) depends on Bintools Wrapper. + + + Dependency finding is undoubtedly the main task of CC Wrapper. + This works just like Bintools Wrapper, except that any include subdirectory of any relevant dependency is added to NIX_CFLAGS_COMPILE. + The setup hook itself contains some lengthy comments describing the exact convoluted mechanism by which this is accomplished. + + + CC Wrapper also like Bintools Wrapper defines standard environment variables with the names of the tools it wraps, for the same reasons described above. + Importantly, while it includes a cc symlink to the c compiler for portability, the CC will be defined using the compiler's "real name" (i.e. gcc or clang). + This helps lousy build systems that inspect on the name of the compiler rather than run it. + + + + Perl Adds the lib/site_perl subdirectory diff --git a/pkgs/build-support/bintools-wrapper/add-flags.sh b/pkgs/build-support/bintools-wrapper/add-flags.sh new file mode 100644 index 0000000000000..7d118d20fc682 --- /dev/null +++ b/pkgs/build-support/bintools-wrapper/add-flags.sh @@ -0,0 +1,40 @@ +# See cc-wrapper for comments. +var_templates_list=( + NIX+IGNORE_LD_THROUGH_GCC + NIX+LDFLAGS + NIX+LDFLAGS_BEFORE + NIX+LDFLAGS_AFTER + NIX+LDFLAGS_HARDEN +) +var_templates_bool=( + NIX+SET_BUILD_ID + NIX+DONT_SET_RPATH +) + +declare -a role_infixes=() +if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_BUILD:-}" ]; then + role_infixes+=(_BUILD_) +fi +if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_HOST:-}" ]; then + role_infixes+=(_) +fi +if [ "${NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_TARGET:-}" ]; then + role_infixes+=(_TARGET_) +fi + +for var in "${var_templates_list[@]}"; do + mangleVarList "$var" "${role_infixes[@]}" +done +for var in "${var_templates_bool[@]}"; do + mangleVarBool "$var" "${role_infixes[@]}" +done + +if [ -e @out@/nix-support/libc-ldflags ]; then + NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)" +fi + +if [ -e @out@/nix-support/libc-ldflags-before ]; then + NIX_@infixSalt@_LDFLAGS_BEFORE="$(< @out@/nix-support/libc-ldflags-before) $NIX_@infixSalt@_LDFLAGS_BEFORE" +fi + +export NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET=1 diff --git a/pkgs/build-support/bintools-wrapper/add-hardening.sh b/pkgs/build-support/bintools-wrapper/add-hardening.sh new file mode 100644 index 0000000000000..5282d17fce27f --- /dev/null +++ b/pkgs/build-support/bintools-wrapper/add-hardening.sh @@ -0,0 +1,53 @@ +hardeningFlags=(relro bindnow) +# Intentionally word-split in case 'hardeningEnable' is defined in +# Nix. Also, our bootstrap tools version of bash is old enough that +# undefined arrays trip `set -u`. +if [[ -v hardeningEnable[@] ]]; then + hardeningFlags+=(${hardeningEnable[@]}) +fi +hardeningLDFlags=() + +declare -A hardeningDisableMap + +# Intentionally word-split in case 'hardeningDisable' is defined in Nix. +for flag in ${hardeningDisable[@]:-IGNORED_KEY} @hardening_unsupported_flags@ +do + hardeningDisableMap[$flag]=1 +done + +if (( "${NIX_DEBUG:-0}" >= 1 )); then + printf 'HARDENING: disabled flags:' >&2 + (( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2 + echo >&2 +fi + +if [[ -z "${hardeningDisableMap[all]:-}" ]]; then + if (( "${NIX_DEBUG:-0}" >= 1 )); then + echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; + fi + for flag in "${hardeningFlags[@]}" + do + if [[ -z "${hardeningDisableMap[$flag]:-}" ]]; then + case $flag in + pie) + if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; 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 + fi + done +fi diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix new file mode 100644 index 0000000000000..0dcae204824d5 --- /dev/null +++ b/pkgs/build-support/bintools-wrapper/default.nix @@ -0,0 +1,292 @@ +# 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 ? "", stdenvNoCC, nativeTools, noLibc ? false, nativeLibc, nativePrefix ? "" +, bintools ? null, libc ? null +, coreutils ? null, shell ? stdenvNoCC.shell, gnugrep ? null +, extraPackages ? [], extraBuildCommands ? "" +, buildPackages ? {} +, useMacosReexportHack ? false +}: + +with stdenvNoCC.lib; + +assert nativeTools -> nativePrefix != ""; +assert !nativeTools -> + bintools != null && coreutils != null && gnugrep != null; +assert !(nativeLibc && noLibc); +assert (noLibc || nativeLibc) == (libc == null); + +let + stdenv = stdenvNoCC; + inherit (stdenv) hostPlatform targetPlatform; + + # Prefix for binaries. Customarily ends with a dash separator. + # + # TODO(@Ericson2314) Make unconditional, or optional but always true by + # default. + targetPrefix = stdenv.lib.optionalString (targetPlatform != hostPlatform) + (targetPlatform.config + "-"); + + bintoolsVersion = (builtins.parseDrvName bintools.name).version; + bintoolsName = (builtins.parseDrvName bintools.name).name; + + libc_bin = if libc == null then null else getBin libc; + libc_dev = if libc == null then null else getDev libc; + libc_lib = if libc == null then null else getLib libc; + bintools_bin = if nativeTools then "" else getBin bintools; + # The wrapper scripts use 'cat' and 'grep', so we may need coreutils. + coreutils_bin = if nativeTools then "" else getBin coreutils; + + dashlessTarget = stdenv.lib.replaceStrings ["-"] ["_"] targetPlatform.config; + + # See description in cc-wrapper. + infixSalt = dashlessTarget; + + # The dynamic linker has different names on different platforms. This is a + # shell glob that ought to match it. + dynamicLinker = + /**/ if libc == null then null + else if targetPlatform.system == "i686-linux" then "${libc_lib}/lib/ld-linux.so.2" + else if targetPlatform.system == "x86_64-linux" then "${libc_lib}/lib/ld-linux-x86-64.so.2" + # ARM with a wildcard, which can be "" or "-armhf". + else if (with targetPlatform; isArm && isLinux) then "${libc_lib}/lib/ld-linux*.so.3" + else if targetPlatform.system == "aarch64-linux" then "${libc_lib}/lib/ld-linux-aarch64.so.1" + else if targetPlatform.system == "powerpc-linux" then "${libc_lib}/lib/ld.so.1" + else if targetPlatform.system == "mips64el-linux" then "${libc_lib}/lib/ld.so.1" + else if targetPlatform.isDarwin then "/usr/lib/dyld" + else if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" + else null; + + expand-response-params = + if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null" + then import ../expand-response-params { inherit (buildPackages) stdenv; } + else ""; + +in + +stdenv.mkDerivation { + name = targetPrefix + + (if name != "" then name else "${bintoolsName}-wrapper") + + (stdenv.lib.optionalString (bintools != null && bintoolsVersion != "") "-${bintoolsVersion}"); + + preferLocalBuild = true; + + inherit bintools_bin libc_bin libc_dev libc_lib coreutils_bin; + shell = getBin shell + shell.shellPath or ""; + gnugrep_bin = if nativeTools then "" else gnugrep; + + inherit targetPrefix infixSalt; + + outputs = [ "out" "info" "man" ]; + + passthru = { + inherit bintools libc nativeTools nativeLibc nativePrefix; + + emacsBufferSetup = pkgs: '' + ; We should handle propagation here too + (mapc + (lambda (arg) + (when (file-directory-p (concat arg "/lib")) + (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib"))) + (when (file-directory-p (concat arg "/lib64")) + (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64")))) + '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) + ''; + }; + + dontBuild = true; + dontConfigure = true; + + unpackPhase = '' + src=$PWD + ''; + + installPhase = + '' + set -u + + mkdir -p $out/bin {$out,$info,$man}/nix-support + + wrap() { + local dst="$1" + local wrapper="$2" + export prog="$3" + set +u + substituteAll "$wrapper" "$out/bin/$dst" + set -u + 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" + '' + + + optionalString (targetPlatform.isSunOS && nativePrefix != "") '' + # Solaris needs an additional ld wrapper. + ldPath="${nativePrefix}/bin" + exec="$ldPath/${targetPrefix}ld" + wrap ld-solaris ${./ld-solaris-wrapper.sh} + '') + + + '' + # Create a symlink to as (the assembler). + if [ -e $ldPath/${targetPrefix}as ]; then + ln -s $ldPath/${targetPrefix}as $out/bin/${targetPrefix}as + fi + + '' + (if !useMacosReexportHack then '' + wrap ${targetPrefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${targetPrefix}ld} + '' 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 ld.gold ld.bfd ld.lld; do + local underlying=$ldPath/${targetPrefix}$variant + [[ -e "$underlying" ]] || continue + wrap ${targetPrefix}$variant ${./ld-wrapper.sh} $underlying + done + + set +u + ''; + + propagatedBuildInputs = extraPackages; + + setupHook = ./setup-hook.sh; + + postFixup = + '' + set -u + '' + + + optionalString (libc != null) ('' + ## + ## General libc support + ## + + echo "-L${libc_lib}/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 + ## + + 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="${libc_lib}/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 '' + if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then + echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32 + fi + + local ldflagsBefore=(-dynamic-linker "$dynamicLinker") + '') + '' + fi + + # The dynamic linker is passed in `ldflagsBefore' to allow + # explicit overrides of the dynamic linker by callers to ld + # (the *last* value counts, so ours should come first). + printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before + '') + + + optionalString (!nativeTools) '' + + ## + ## User env support + ## + + # Propagate the underling unwrapped bintools so that if you + # install the wrapper, you get tools like objdump, the manpages, + # etc. as well (same for any binaries of libc). + printWords ${bintools_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages + + ## + ## Man page and info support + ## + + printWords ${bintools.info or ""} \ + >> $info/nix-support/propagated-build-inputs + printWords ${bintools.man or ""} \ + >> $man/nix-support/propagated-build-inputs + '' + + + '' + + ## + ## 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" + '' + + + '' + set +u + substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh + substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh + substituteAll ${../cc-wrapper/utils.sh} $out/nix-support/utils.sh + + ## + ## Extra custom steps + ## + + '' + + extraBuildCommands; + + inherit dynamicLinker expand-response-params; + + # for substitution in utils.sh + expandResponseParams = "${expand-response-params}/bin/expand-response-params"; + + meta = + let bintools_ = if bintools != null then bintools else {}; in + (if bintools_ ? meta then removeAttrs bintools.meta ["priority"] else {}) // + { description = + stdenv.lib.attrByPath ["meta" "description"] "System binary utilities" bintools_ + + " (wrapper script)"; + } // optionalAttrs useMacosReexportHack { + platforms = stdenv.lib.platforms.darwin; + }; +} diff --git a/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh old mode 100755 new mode 100644 similarity index 100% rename from pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh rename to pkgs/build-support/bintools-wrapper/ld-solaris-wrapper.sh diff --git a/pkgs/build-support/cc-wrapper/ld-wrapper.sh b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh similarity index 98% rename from pkgs/build-support/cc-wrapper/ld-wrapper.sh rename to pkgs/build-support/bintools-wrapper/ld-wrapper.sh index ef618f9a86d40..136621d27af55 100644 --- a/pkgs/build-support/cc-wrapper/ld-wrapper.sh +++ b/pkgs/build-support/bintools-wrapper/ld-wrapper.sh @@ -14,12 +14,12 @@ if [ -n "@coreutils_bin@" ]; then PATH="@coreutils_bin@/bin" fi -if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then +source @out@/nix-support/utils.sh + +if [ -z "${NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then source @out@/nix-support/add-flags.sh fi -source @out@/nix-support/utils.sh - # Optionally filter out paths not refering to the store. expandResponseParams "$@" diff --git a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash b/pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash similarity index 95% rename from pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash rename to pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash index 205035453332a..a0c4e9edfcdbc 100644 --- a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash +++ b/pkgs/build-support/bintools-wrapper/macos-sierra-reexport-hack.bash @@ -81,8 +81,10 @@ else symbolBloatObject=$outputNameLibless-symbol-hack.o if [[ ! -e $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' \ - | @targetPrefix@as -- -o $symbolBloatObject + | @targetPrefix@as -Q -- -o $symbolBloatObject fi # first half of libs diff --git a/pkgs/build-support/bintools-wrapper/setup-hook.sh b/pkgs/build-support/bintools-wrapper/setup-hook.sh new file mode 100644 index 0000000000000..43f79ec59200f --- /dev/null +++ b/pkgs/build-support/bintools-wrapper/setup-hook.sh @@ -0,0 +1,67 @@ +# Binutils Wrapper hygiene +# +# See comments in cc-wrapper's setup hook. This works exactly the same way. + +bintoolsWrapper_addLDVars () { + case $depOffset in + -1) local role='BUILD_' ;; + 0) local role='' ;; + 1) local role='TARGET_' ;; + *) echo "bintools-wrapper: Error: Cannot be used with $depOffset-offset deps, " >2; + return 1 ;; + esac + + if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then + export NIX_${role}LDFLAGS+=" -L$1/lib64" + fi + + if [[ -d "$1/lib" ]]; then + export NIX_${role}LDFLAGS+=" -L$1/lib" + fi +} + +if [ -n "${crossConfig:-}" ]; then + export NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_BUILD=1 + role_pre='BUILD_' + role_post='_FOR_BUILD' +else + export NIX_BINTOOLS_WRAPPER_@infixSalt@_TARGET_HOST=1 + role_pre="" + role_post='' +fi + +envHooks+=(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_${role_pre}BINTOOLS=@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 + upper_case="$(echo "$cmd" | tr "[:lower:]" "[:upper:]")" + export "${role_pre}${upper_case}=@targetPrefix@${cmd}"; + export "${upper_case}${role_post}=@targetPrefix@${cmd}"; + fi +done + +# No local scope in sourced file +unset -v role_pre role_post cmd upper_case diff --git a/pkgs/build-support/cc-wrapper/add-flags.sh b/pkgs/build-support/cc-wrapper/add-flags.sh index 39633fce69a81..d8b42244607ad 100644 --- a/pkgs/build-support/cc-wrapper/add-flags.sh +++ b/pkgs/build-support/cc-wrapper/add-flags.sh @@ -4,19 +4,14 @@ # that case, it is cheaper/better to not repeat this step and let the forked # wrapped binary just inherit the work of the forker's wrapper script. -var_templates=( +var_templates_list=( NIX+CFLAGS_COMPILE NIX+CFLAGS_LINK NIX+CXXSTDLIB_COMPILE NIX+CXXSTDLIB_LINK NIX+GNATFLAGS_COMPILE - NIX+IGNORE_LD_THROUGH_GCC - NIX+LDFLAGS - NIX+LDFLAGS_BEFORE - NIX+LDFLAGS_AFTER - - NIX+SET_BUILD_ID - NIX+DONT_SET_RPATH +) +var_templates_bool=( NIX+ENFORCE_NO_NATIVE ) @@ -35,17 +30,11 @@ fi # We need to mangle names for hygiene, but also take parameters/overrides # from the environment. -for var in "${var_templates[@]}"; do - outputVar="${var/+/_@infixSalt@_}" - export ${outputVar}+='' - # For each role we serve, we accumulate the input parameters into our own - # cc-wrapper-derivation-specific environment variables. - for infix in "${role_infixes[@]}"; do - inputVar="${var/+/${infix}}" - if [ -v "$inputVar" ]; then - export ${outputVar}+="${!outputVar:+ }${!inputVar}" - fi - done +for var in "${var_templates_list[@]}"; do + mangleVarList "$var" "${role_infixes[@]}" +done +for var in "${var_templates_bool[@]}"; do + mangleVarBool "$var" "${role_infixes[@]}" done # `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld. @@ -66,17 +55,9 @@ if [ -e @out@/nix-support/gnat-cflags ]; then NIX_@infixSalt@_GNATFLAGS_COMPILE="$(< @out@/nix-support/gnat-cflags) $NIX_@infixSalt@_GNATFLAGS_COMPILE" fi -if [ -e @out@/nix-support/libc-ldflags ]; then - NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)" -fi - if [ -e @out@/nix-support/cc-ldflags ]; then NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/cc-ldflags)" fi -if [ -e @out@/nix-support/libc-ldflags-before ]; then - NIX_@infixSalt@_LDFLAGS_BEFORE="$(< @out@/nix-support/libc-ldflags-before) $NIX_@infixSalt@_LDFLAGS_BEFORE" -fi - # That way forked processes will not extend these environment variables again. export NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET=1 diff --git a/pkgs/build-support/cc-wrapper/add-hardening.sh b/pkgs/build-support/cc-wrapper/add-hardening.sh index b0e39e455ffc5..a35ff3cb42609 100644 --- a/pkgs/build-support/cc-wrapper/add-hardening.sh +++ b/pkgs/build-support/cc-wrapper/add-hardening.sh @@ -6,7 +6,6 @@ if [[ -v hardeningEnable[@] ]]; then hardeningFlags+=(${hardeningEnable[@]}) fi hardeningCFlags=() -hardeningLDFlags=() declare -A hardeningDisableMap @@ -44,7 +43,6 @@ if [[ -z "${hardeningDisableMap[all]:-}" ]]; then if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling LDFlags -pie >&2; fi hardeningCFlags+=('-pie') - hardeningLDFlags+=('-pie') fi ;; pic) @@ -59,14 +57,6 @@ if [[ -z "${hardeningDisableMap[all]:-}" ]]; then if (( "${NIX_DEBUG:-0}" >= 1 )); then echo HARDENING: enabling format >&2; fi hardeningCFlags+=('-Wformat' '-Wformat-security' '-Werror=format-security') ;; - 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. diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh index d2cdbf6ce0cca..c2e6c1406358f 100644 --- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh @@ -15,12 +15,18 @@ if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin" fi +source @out@/nix-support/utils.sh + +# Flirting with a layer violation here. +if [ -z "${NIX_BINTOOLS_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then + source @bintools@/nix-support/add-flags.sh +fi + +# Put this one second so libc ldflags take priority. if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then source @out@/nix-support/add-flags.sh fi -source @out@/nix-support/utils.sh - # Parse command line options and set several variables. # For instance, figure out if linker flags should be passed. @@ -59,7 +65,8 @@ while (( "$n" < "$nParams" )); do cppInclude=0 elif [ "$p" = -nostdinc++ ]; then cppInclude=0 - elif [ "${p:0:1}" != - ]; then + elif [[ "$p" != -?* ]]; then + # A dash alone signifies standard input; it is not a flag nonFlagArgs=1 fi n+=1 diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index b809591fbc82e..5978d8665d094 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -6,18 +6,17 @@ # compiler and the linker just "work". { name ? "", stdenvNoCC, nativeTools, noLibc ? false, nativeLibc, nativePrefix ? "" -, cc ? null, libc ? null, binutils ? null, coreutils ? null, shell ? stdenvNoCC.shell +, cc ? null, libc ? null, bintools, coreutils ? null, shell ? stdenvNoCC.shell , zlib ? null, extraPackages ? [], extraBuildCommands ? "" , isGNU ? false, isClang ? cc.isClang or false, gnugrep ? null , buildPackages ? {} -, useMacosReexportHack ? false }: with stdenvNoCC.lib; assert nativeTools -> nativePrefix != ""; assert !nativeTools -> - cc != null && binutils != null && coreutils != null && gnugrep != null; + cc != null && coreutils != null && gnugrep != null; assert !(nativeLibc && noLibc); assert (noLibc || nativeLibc) == (libc == null); @@ -42,7 +41,6 @@ let libc_dev = if libc == null then null else getDev libc; libc_lib = if libc == null then null else getLib libc; cc_solib = getLib cc; - binutils_bin = if nativeTools then "" else getBin binutils; # The wrapper scripts use 'cat' and 'grep', so we may need coreutils. coreutils_bin = if nativeTools then "" else getBin coreutils; @@ -58,21 +56,6 @@ let # unstable implementation detail, however. infixSalt = dashlessTarget; - # The dynamic linker has different names on different platforms. This is a - # shell glob that ought to match it. - dynamicLinker = - /**/ if libc == null then null - else if targetPlatform.system == "i686-linux" then "${libc_lib}/lib/ld-linux.so.2" - else if targetPlatform.system == "x86_64-linux" then "${libc_lib}/lib/ld-linux-x86-64.so.2" - # ARM with a wildcard, which can be "" or "-armhf". - else if (with targetPlatform; isArm && isLinux) then "${libc_lib}/lib/ld-linux*.so.3" - else if targetPlatform.system == "aarch64-linux" then "${libc_lib}/lib/ld-linux-aarch64.so.1" - else if targetPlatform.system == "powerpc-linux" then "${libc_lib}/lib/ld.so.1" - else if targetPlatform.system == "mips64el-linux" then "${libc_lib}/lib/ld.so.1" - else if targetPlatform.isDarwin then "/usr/lib/dyld" - else if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" - else null; - expand-response-params = if buildPackages.stdenv.cc or null != null && buildPackages.stdenv.cc != "/dev/null" then import ../expand-response-params { inherit (buildPackages) stdenv; } @@ -80,6 +63,14 @@ let in +# Ensure bintools matches +assert libc_bin == bintools.libc_bin; +assert libc_dev == bintools.libc_dev; +assert libc_lib == bintools.libc_lib; +assert nativeTools == bintools.nativeTools; +assert nativeLibc == bintools.nativeLibc; +assert nativePrefix == bintools.nativePrefix; + stdenv.mkDerivation { name = targetPrefix + (if name != "" then name else "${ccName}-wrapper") @@ -87,8 +78,8 @@ stdenv.mkDerivation { preferLocalBuild = true; - inherit cc libc_bin libc_dev libc_lib binutils_bin coreutils_bin; - shell = getBin shell + shell.shellPath or ""; + inherit cc libc_bin libc_dev libc_lib bintools coreutils_bin; + shell = getBin shell + stdenv.lib.optionalString (stdenv ? shellPath) stdenv.shellPath; gnugrep_bin = if nativeTools then "" else gnugrep; inherit targetPrefix infixSalt; @@ -98,20 +89,18 @@ stdenv.mkDerivation { passthru = { # "cc" is the generic name for a C compiler, but there is no one for package # providing the linker and related tools. The two we use now are GNU - # Binutils, and Apple's "cctools"; "binutils" as an attempt to find an + # Binutils, and Apple's "cctools"; "bintools" as an attempt to find an # unused middle-ground name that evokes both. - bintools = binutils_bin; + inherit bintools; inherit libc nativeTools nativeLibc nativePrefix isGNU isClang default_cxx_stdlib_compile; emacsBufferSetup = pkgs: '' ; We should handle propagation here too - (mapc (lambda (arg) - (when (file-directory-p (concat arg "/include")) - (setenv "NIX_${infixSalt}_CFLAGS_COMPILE" (concat (getenv "NIX_${infixSalt}_CFLAGS_COMPILE") " -isystem " arg "/include"))) - (when (file-directory-p (concat arg "/lib")) - (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib"))) - (when (file-directory-p (concat arg "/lib64")) - (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64")))) '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) + (mapc + (lambda (arg) + (when (file-directory-p (concat arg "/include")) + (setenv "NIX_${infixSalt}_CFLAGS_COMPILE" (concat (getenv "NIX_${infixSalt}_CFLAGS_COMPILE") " -isystem " arg "/include")))) + '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) ''; }; @@ -141,45 +130,18 @@ stdenv.mkDerivation { echo ${if targetPlatform.isDarwin then cc else nativePrefix} > $out/nix-support/orig-cc ccPath="${if targetPlatform.isDarwin then cc else nativePrefix}/bin" - ldPath="${nativePrefix}/bin" '' else '' echo $cc > $out/nix-support/orig-cc ccPath="${cc}/bin" - ldPath="${binutils_bin}/bin" - '' - - + optionalString (targetPlatform.isSunOS && nativePrefix != "") '' - # Solaris needs an additional ld wrapper. - ldPath="${nativePrefix}/bin" - exec="$ldPath/${targetPrefix}ld" - wrap ld-solaris ${./ld-solaris-wrapper.sh} '') + '' - # Create a symlink to as (the assembler). This is useful when a - # cc-wrapper is installed in a user environment, as it ensures that - # the right assembler is called. - if [ -e $ldPath/${targetPrefix}as ]; then - ln -s $ldPath/${targetPrefix}as $out/bin/${targetPrefix}as - fi - - '' + (if !useMacosReexportHack then '' - wrap ${targetPrefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${targetPrefix}ld} - '' 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 - '') + '' - - if [ -e ${binutils_bin}/bin/${targetPrefix}ld.gold ]; then - wrap ${targetPrefix}ld.gold ${./ld-wrapper.sh} ${binutils_bin}/bin/${targetPrefix}ld.gold - fi - - if [ -e ${binutils_bin}/bin/ld.bfd ]; then - wrap ${targetPrefix}ld.bfd ${./ld-wrapper.sh} ${binutils_bin}/bin/${targetPrefix}ld.bfd - fi + # Create symlinks to everything in the bintools wrapper. + for bbin in $bintools/bin/*; do + mkdir -p "$out/bin" + ln -s "$bbin" "$out/bin/$(basename $bbin)" + done # We export environment variables pointing to the wrapped nonstandard # cmds, lest some lousy configure script use those to guess compiler @@ -239,16 +201,28 @@ stdenv.mkDerivation { ln -s $ccPath/${targetPrefix}ghdl $out/bin/${targetPrefix}ghdl ''; - propagatedBuildInputs = extraPackages; + propagatedBuildInputs = [ bintools ] ++ extraPackages; setupHook = ./setup-hook.sh; postFixup = '' set -u + + # Backwards compatability for packages expecting this file, e.g. with + # `$NIX_CC/nix-support/dynamic-linker`. + # + # TODO(@Ericson2314): Remove this after stable release and force + # everyone to refer to bintools-wrapper directly. + if [[ -f "$bintools/nix-support/dynamic-linker" ]]; then + ln -s "$bintools/nix-support/dynamic-linker" "$out/nix-support" + fi + if [[ -f "$bintools/nix-support/dynamic-linker-m32" ]]; then + ln -s "$bintools/nix-support/dynamic-linker-m32" "$out/nix-support" + fi '' - + optionalString (libc != null) ('' + + optionalString (libc != null) '' ## ## General libc support ## @@ -266,48 +240,9 @@ stdenv.mkDerivation { # another -idirafter is necessary to add that directory again. echo "-B${libc_lib}/lib/ -idirafter ${libc_dev}/include ${optionalString isGNU "-idirafter ${cc}/lib/gcc/*/*/include-fixed"}" > $out/nix-support/libc-cflags - echo "-L${libc_lib}/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 - ## - - 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="${libc_lib}/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 '' - if [ -e ${libc_lib}/lib/32/ld-linux.so.2 ]; then - echo ${libc_lib}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32 - fi - - local ldflagsBefore=(-dynamic-linker "$dynamicLinker") - '') + '' - fi - - # The dynamic linker is passed in `ldflagsBefore' to allow - # explicit overrides of the dynamic linker by callers to gcc/ld - # (the *last* value counts, so ours should come first). - printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before - '') + '' + optionalString (!nativeTools) '' @@ -348,7 +283,6 @@ stdenv.mkDerivation { # Propagate the wrapped cc so that if you install the wrapper, # you get tools like gcov, the manpages, etc. as well (including # for binutils and Glibc). - printWords ${cc} ${binutils_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages printWords ${cc.man or ""} > $man/nix-support/propagated-user-env-packages '' @@ -358,14 +292,7 @@ stdenv.mkDerivation { ## 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 '' @@ -384,7 +311,7 @@ stdenv.mkDerivation { '' + extraBuildCommands; - inherit dynamicLinker expand-response-params; + inherit expand-response-params; # for substitution in utils.sh expandResponseParams = "${expand-response-params}/bin/expand-response-params"; @@ -395,7 +322,5 @@ stdenv.mkDerivation { { description = stdenv.lib.attrByPath ["meta" "description"] "System C compiler" cc_ + " (wrapper script)"; - } // optionalAttrs useMacosReexportHack { - platforms = stdenv.lib.platforms.darwin; }; } diff --git a/pkgs/build-support/cc-wrapper/gnat-wrapper.sh b/pkgs/build-support/cc-wrapper/gnat-wrapper.sh index 7a0eb28be6368..a86c9fe4ada4c 100644 --- a/pkgs/build-support/cc-wrapper/gnat-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/gnat-wrapper.sh @@ -17,12 +17,12 @@ if [ -n "@coreutils_bin@" ]; then PATH="@coreutils_bin@/bin" fi +source @out@/nix-support/utils.sh + if [ -z "${NIX_@infixSalt@_GNAT_WRAPPER_FLAGS_SET:-}" ]; then source @out@/nix-support/add-flags.sh fi -source @out@/nix-support/utils.sh - # Figure out if linker flags should be passed. GCC prints annoying # warnings when they are not needed. @@ -36,10 +36,6 @@ for i in "$@"; do dontLink=1 elif [ "${i:0:1}" != - ]; then nonFlagArgs=1 - elif [ "$i" = -m32 ]; then - if [ -e @out@/nix-support/dynamic-linker-m32 ]; then - NIX_@infixSalt@_LDFLAGS+=" -dynamic-linker $(< @out@/nix-support/dynamic-linker-m32)" - fi fi done diff --git a/pkgs/build-support/cc-wrapper/setup-hook.sh b/pkgs/build-support/cc-wrapper/setup-hook.sh index 7822b7f84d006..a922193ad2e7d 100644 --- a/pkgs/build-support/cc-wrapper/setup-hook.sh +++ b/pkgs/build-support/cc-wrapper/setup-hook.sh @@ -74,14 +74,6 @@ ccWrapper_addCVars () { export NIX_${role}CFLAGS_COMPILE+=" ${ccIncludeFlag:--isystem} $1/include" fi - if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then - export NIX_${role}LDFLAGS+=" -L$1/lib64" - fi - - if [[ -d "$1/lib" ]]; then - export NIX_${role}LDFLAGS+=" -L$1/lib" - fi - if [[ -d "$1/Library/Frameworks" ]]; then export NIX_${role}CFLAGS_COMPILE+=" -F$1/Library/Frameworks" fi @@ -118,11 +110,6 @@ if [ -n "@cc@" ]; then addToSearchPath _PATH @cc@/bin fi -# shellcheck disable=SC2157 -if [ -n "@binutils_bin@" ]; then - addToSearchPath _PATH @binutils_bin@/bin -fi - # shellcheck disable=SC2157 if [ -n "@libc_bin@" ]; then addToSearchPath _PATH @libc_bin@/bin @@ -142,17 +129,5 @@ export ${role_pre}CXX=@named_cxx@ export CC${role_post}=@named_cc@ export CXX${role_post}=@named_cxx@ -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 - upper_case="$(echo "$cmd" | tr "[:lower:]" "[:upper:]")" - export "${role_pre}${upper_case}=@targetPrefix@${cmd}"; - export "${upper_case}${role_post}=@targetPrefix@${cmd}"; - fi -done - # No local scope in sourced file -unset -v role_pre role_post cmd upper_case +unset -v role_pre role_post diff --git a/pkgs/build-support/cc-wrapper/utils.sh b/pkgs/build-support/cc-wrapper/utils.sh index c43c2e12d74a4..4b2b13809181e 100644 --- a/pkgs/build-support/cc-wrapper/utils.sh +++ b/pkgs/build-support/cc-wrapper/utils.sh @@ -1,3 +1,35 @@ +mangleVarList() { + local var="$1" + shift + local -a role_infixes=("$@") + + local outputVar="${var/+/_@infixSalt@_}" + declare -gx ${outputVar}+='' + # For each role we serve, we accumulate the input parameters into our own + # cc-wrapper-derivation-specific environment variables. + for infix in "${role_infixes[@]}"; do + local inputVar="${var/+/${infix}}" + if [ -v "$inputVar" ]; then + export ${outputVar}+="${!outputVar:+ }${!inputVar}" + fi + done +} + +mangleVarBool() { + local var="$1" + shift + local -a role_infixes=("$@") + + local outputVar="${var/+/_@infixSalt@_}" + declare -gxi ${outputVar}+=0 + for infix in "${role_infixes[@]}"; do + local inputVar="${var/+/${infix}}" + if [ -v "$inputVar" ]; then + let "${outputVar} |= ${!inputVar}" + fi + done +} + skip () { if (( "${NIX_DEBUG:-0}" >= 1 )); then echo "skipping impure path $1" >&2 diff --git a/pkgs/build-support/setup-hooks/separate-debug-info.sh b/pkgs/build-support/setup-hooks/separate-debug-info.sh index c90d2cd520136..19dbb10d18e72 100644 --- a/pkgs/build-support/setup-hooks/separate-debug-info.sh +++ b/pkgs/build-support/setup-hooks/separate-debug-info.sh @@ -19,7 +19,7 @@ _separateDebugInfo() { if ! isELF "$i"; then continue; fi # Extract the Build ID. FIXME: there's probably a cleaner way. - local id="$(readelf -n "$i" | sed 's/.*Build ID: \([0-9a-f]*\).*/\1/; t; d')" + local id="$($READELF -n "$i" | sed 's/.*Build ID: \([0-9a-f]*\).*/\1/; t; d')" if [ "${#id}" != 40 ]; then echo "could not find build ID of $i, skipping" >&2 continue @@ -28,8 +28,8 @@ _separateDebugInfo() { # Extract the debug info. header "separating debug info from $i (build ID $id)" mkdir -p "$dst/${id:0:2}" - objcopy --only-keep-debug "$i" "$dst/${id:0:2}/${id:2}.debug" - strip --strip-debug "$i" + $OBJCOPY --only-keep-debug "$i" "$dst/${id:0:2}/${id:2}.debug" + $STRIP --strip-debug "$i" # Also a create a symlink .debug. ln -sfn ".build-id/${id:0:2}/${id:2}.debug" "$dst/../$(basename "$i")" diff --git a/pkgs/build-support/setup-hooks/strip.sh b/pkgs/build-support/setup-hooks/strip.sh index 0bf37e10d8703..a33968ca18dea 100644 --- a/pkgs/build-support/setup-hooks/strip.sh +++ b/pkgs/build-support/setup-hooks/strip.sh @@ -30,7 +30,7 @@ stripDirs() { if [ -n "${dirs}" ]; then header "stripping (with flags $stripFlags) in$dirs" - find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} strip $commonStripFlags $stripFlags 2>/dev/null || true + find $dirs -type f -print0 | xargs -0 ${xargsFlags:--r} $STRIP $commonStripFlags $stripFlags 2>/dev/null || true stopNest fi } diff --git a/pkgs/build-support/setup-hooks/win-dll-link.sh b/pkgs/build-support/setup-hooks/win-dll-link.sh index 9658b9f82595c..6130f32bef86c 100644 --- a/pkgs/build-support/setup-hooks/win-dll-link.sh +++ b/pkgs/build-support/setup-hooks/win-dll-link.sh @@ -25,7 +25,7 @@ _linkDLLs() { linkCount=0 # Iterate over any DLL that we depend on. local dll - for dll in $(objdump -p *.{exe,dll} | sed -n 's/.*DLL Name: \(.*\)/\1/p' | sort -u); do + for dll in $($OBJDUMP -p *.{exe,dll} | sed -n 's/.*DLL Name: \(.*\)/\1/p' | sort -u); do if [ -e "./$dll" ]; then continue; fi # Locate the DLL - it should be an *executable* file on $DLLPATH. local dllPath="$(PATH="$DLLPATH" type -P "$dll")" diff --git a/pkgs/development/compilers/emscripten-fastcomp/default.nix b/pkgs/development/compilers/emscripten-fastcomp/default.nix index 5d952073740ed..490dace2faaf9 100644 --- a/pkgs/development/compilers/emscripten-fastcomp/default.nix +++ b/pkgs/development/compilers/emscripten-fastcomp/default.nix @@ -1,4 +1,4 @@ -{ newScope, stdenv, wrapCC, wrapCCWith, symlinkJoin }: +{ newScope, stdenv, binutils-raw, wrapCCWith, symlinkJoin }: let callPackage = newScope (self // {inherit stdenv;}); @@ -6,6 +6,8 @@ let emscriptenfastcomp-unwrapped = callPackage ./emscripten-fastcomp.nix {}; emscriptenfastcomp-wrapped = wrapCCWith { cc = self.emscriptenfastcomp-unwrapped; + # Never want Apple's cctools for WASM target + bintools = binutils-raw; libc = stdenv.cc.libc; extraBuildCommands = '' # hardening flags break WASM support diff --git a/pkgs/development/compilers/gcc/4.5/default.nix b/pkgs/development/compilers/gcc/4.5/default.nix index b41d22f4f5398..b4ae867d5859d 100644 --- a/pkgs/development/compilers/gcc/4.5/default.nix +++ b/pkgs/development/compilers/gcc/4.5/default.nix @@ -356,6 +356,7 @@ stdenv.mkDerivation ({ dontStrip = true; }; + NIX_BUILD_BINTOOLS = buildPackages.stdenv.cc.bintools; NIX_BUILD_CC = buildPackages.stdenv.cc; # Needed for the cross compilation to work diff --git a/pkgs/development/compilers/gcc/4.8/default.nix b/pkgs/development/compilers/gcc/4.8/default.nix index 8713c174d5a6a..4efac1b26c340 100644 --- a/pkgs/development/compilers/gcc/4.8/default.nix +++ b/pkgs/development/compilers/gcc/4.8/default.nix @@ -444,6 +444,7 @@ stdenv.mkDerivation ({ buildFlags = ""; }; + NIX_BUILD_BINTOOLS = buildPackages.stdenv.cc.bintools; NIX_BUILD_CC = buildPackages.stdenv.cc; # Needed for the cross compilation to work diff --git a/pkgs/development/compilers/gcc/4.9/default.nix b/pkgs/development/compilers/gcc/4.9/default.nix index c338f9c641ee6..fb4218a0edea8 100644 --- a/pkgs/development/compilers/gcc/4.9/default.nix +++ b/pkgs/development/compilers/gcc/4.9/default.nix @@ -442,6 +442,7 @@ stdenv.mkDerivation ({ buildFlags = ""; }; + NIX_BUILD_BINTOOLS = buildPackages.stdenv.cc.bintools; NIX_BUILD_CC = buildPackages.stdenv.cc; # Needed for the cross compilation to work diff --git a/pkgs/development/compilers/gcc/5/default.nix b/pkgs/development/compilers/gcc/5/default.nix index 552e827ec366b..b4399ef72f199 100644 --- a/pkgs/development/compilers/gcc/5/default.nix +++ b/pkgs/development/compilers/gcc/5/default.nix @@ -451,6 +451,7 @@ stdenv.mkDerivation ({ buildFlags = ""; }; + NIX_BUILD_BINTOOLS = buildPackages.stdenv.cc.bintools; NIX_BUILD_CC = buildPackages.stdenv.cc; # Needed for the cross compilation to work diff --git a/pkgs/development/compilers/gcc/6/default.nix b/pkgs/development/compilers/gcc/6/default.nix index fbc4900260675..d923092168abd 100644 --- a/pkgs/development/compilers/gcc/6/default.nix +++ b/pkgs/development/compilers/gcc/6/default.nix @@ -452,6 +452,7 @@ stdenv.mkDerivation ({ buildFlags = ""; }; + NIX_BUILD_BINTOOLS = buildPackages.stdenv.cc.bintools; NIX_BUILD_CC = buildPackages.stdenv.cc; # Needed for the cross compilation to work diff --git a/pkgs/development/compilers/gcc/7/default.nix b/pkgs/development/compilers/gcc/7/default.nix index 032a20271ee05..c9daf813e6f80 100644 --- a/pkgs/development/compilers/gcc/7/default.nix +++ b/pkgs/development/compilers/gcc/7/default.nix @@ -446,6 +446,7 @@ stdenv.mkDerivation ({ buildFlags = ""; }; + NIX_BUILD_BINTOOLS = buildPackages.stdenv.cc.bintools; NIX_BUILD_CC = buildPackages.stdenv.cc; # Needed for the cross compilation to work diff --git a/pkgs/development/compilers/gcc/builder.sh b/pkgs/development/compilers/gcc/builder.sh index 0765daee4534b..1796c83385e54 100644 --- a/pkgs/development/compilers/gcc/builder.sh +++ b/pkgs/development/compilers/gcc/builder.sh @@ -28,37 +28,55 @@ if test "$noSysDirs" = "1"; then EXTRA_BUILD_FLAGS EXTRA_FLAGS EXTRA_TARGET_FLAGS \ EXTRA_BUILD_LDFLAGS EXTRA_TARGET_LDFLAGS + # Extract flags from Bintools Wrappers + for pre in 'BUILD_' ''; do + curBintools="NIX_${pre}BINTOOLS" + + declare -a extraLDFlags=() + if [[ -e "${!curBintools}/nix-support/orig-libc" ]]; then + # Figure out what extra flags when linking to pass to the gcc + # compilers being generated to make sure that they use our libc. + extraLDFlags=($(< "${!curBintools}/nix-support/libc-ldflags") $(< "${!curBintools}/nix-support/libc-ldflags-before" || true)) + + # The path to the Libc binaries such as `crti.o'. + libc_libdir="$(< "${!curBintools}/nix-support/orig-libc")/lib" + else + # Hack: support impure environments. + extraLDFlags=("-L/usr/lib64" "-L/usr/lib") + libc_libdir="/usr/lib" + fi + extraLDFlags=("-L$libc_libdir" "-rpath" "$libc_libdir" + "${extraLDFlags[@]}") + for i in "${extraLDFlags[@]}"; do + declare EXTRA_${pre}LDFLAGS+=" -Wl,$i" + done + done + + # Extract flags from CC Wrappers for pre in 'BUILD_' ''; do curCC="NIX_${pre}CC" curFIXINC="NIX_${pre}FIXINC_DUMMY" - declare -a extraFlags=() extraLDFlags=() + declare -a extraFlags=() if [[ -e "${!curCC}/nix-support/orig-libc" ]]; then - # Figure out what extra flags to pass to the gcc compilers being - # generated to make sure that they use our glibc. - extraFlags=($(cat "${!curCC}/nix-support/libc-cflags")) - extraLDFlags=($(cat "${!curCC}/nix-support/libc-ldflags") $(cat "${!curCC}/nix-support/libc-ldflags-before" || true)) + # Figure out what extra compiling flags to pass to the gcc compilers + # being generated to make sure that they use our libc. + extraFlags=($(< "${!curCC}/nix-support/libc-cflags")) - # The path to the Glibc binaries such as `crti.o'. - glibc_libdir="$(cat "${!curCC}/nix-support/orig-libc")/lib" - glibc_devdir="$(cat "${!curCC}/nix-support/orig-libc-dev")" + # The path to the Libc headers + libc_devdir="$(< "${!curCC}/nix-support/orig-libc-dev")" # Use *real* header files, otherwise a limits.h is generated that - # does not include Glibc's limits.h (notably missing SSIZE_MAX, + # does not include Libc's limits.h (notably missing SSIZE_MAX, # which breaks the build). - declare NIX_${pre}FIXINC_DUMMY="$glibc_devdir/include" + declare NIX_${pre}FIXINC_DUMMY="$libc_devdir/include" else # Hack: support impure environments. extraFlags=("-isystem" "/usr/include") - extraLDFlags=("-L/usr/lib64" "-L/usr/lib") - glibc_libdir="/usr/lib" declare NIX_${pre}FIXINC_DUMMY=/usr/include fi - extraFlags=("-I${!curFIXINC}" - "${extraFlags[@]}") - extraLDFlags=("-L$glibc_libdir" "-rpath" "$glibc_libdir" - "${extraLDFlags[@]}") + extraFlags=("-I${!curFIXINC}" "${extraFlags[@]}") # BOOT_CFLAGS defaults to `-g -O2'; since we override it below, make # sure to explictly add them so that files compiled with the bootstrap @@ -72,9 +90,6 @@ if test "$noSysDirs" = "1"; then fi declare EXTRA_${pre}FLAGS="${extraFlags[*]}" - for i in "${extraLDFlags[@]}"; do - declare EXTRA_${pre}LDFLAGS+=" -Wl,$i" - done done if test -z "${targetConfig-}"; then diff --git a/pkgs/development/compilers/gcc/snapshot/default.nix b/pkgs/development/compilers/gcc/snapshot/default.nix index f2f8eeb09a5ec..9d1bdc08133de 100644 --- a/pkgs/development/compilers/gcc/snapshot/default.nix +++ b/pkgs/development/compilers/gcc/snapshot/default.nix @@ -433,6 +433,7 @@ stdenv.mkDerivation ({ buildFlags = ""; }; + NIX_BUILD_BINTOOLS = buildPackages.stdenv.cc.bintools; NIX_BUILD_CC = buildPackages.stdenv.cc; # Needed for the cross compilation to work diff --git a/pkgs/development/compilers/llvm/3.7/default.nix b/pkgs/development/compilers/llvm/3.7/default.nix index 432443e1a89a1..35af978216c61 100644 --- a/pkgs/development/compilers/llvm/3.7/default.nix +++ b/pkgs/development/compilers/llvm/3.7/default.nix @@ -30,14 +30,14 @@ let libstdcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ libstdcxxHook ]; }; libcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ self.libcxx self.libcxxabi ]; }; diff --git a/pkgs/development/compilers/llvm/3.8/default.nix b/pkgs/development/compilers/llvm/3.8/default.nix index 453d2c1f04b47..bd79db012a636 100644 --- a/pkgs/development/compilers/llvm/3.8/default.nix +++ b/pkgs/development/compilers/llvm/3.8/default.nix @@ -27,14 +27,14 @@ let libstdcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ libstdcxxHook ]; }; libcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ self.libcxx self.libcxxabi ]; }; diff --git a/pkgs/development/compilers/llvm/3.9/default.nix b/pkgs/development/compilers/llvm/3.9/default.nix index 755b417c78d4d..5ce51bc9c1222 100644 --- a/pkgs/development/compilers/llvm/3.9/default.nix +++ b/pkgs/development/compilers/llvm/3.9/default.nix @@ -27,14 +27,14 @@ let libstdcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ libstdcxxHook ]; }; libcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ self.libcxx self.libcxxabi ]; }; diff --git a/pkgs/development/compilers/llvm/4/default.nix b/pkgs/development/compilers/llvm/4/default.nix index 25bb008567f7a..fa61a6c22e71b 100644 --- a/pkgs/development/compilers/llvm/4/default.nix +++ b/pkgs/development/compilers/llvm/4/default.nix @@ -42,14 +42,14 @@ let libstdcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ libstdcxxHook ]; }; libcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ self.libcxx self.libcxxabi ]; }; diff --git a/pkgs/development/compilers/llvm/5/default.nix b/pkgs/development/compilers/llvm/5/default.nix index 1d5cc0e504b71..9891f3090ac1c 100644 --- a/pkgs/development/compilers/llvm/5/default.nix +++ b/pkgs/development/compilers/llvm/5/default.nix @@ -42,14 +42,14 @@ let libstdcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ libstdcxxHook ]; }; libcxxClang = ccWrapperFun { cc = self.clang-unwrapped; /* FIXME is this right? */ - inherit (stdenv.cc) libc nativeTools nativeLibc; + inherit (stdenv.cc) bintools libc nativeTools nativeLibc; extraPackages = [ self.libcxx self.libcxxabi ]; }; diff --git a/pkgs/development/compilers/llvm/multi.nix b/pkgs/development/compilers/llvm/multi.nix index 0fa0eb3404d8f..b4f2f8f9d6f6f 100644 --- a/pkgs/development/compilers/llvm/multi.nix +++ b/pkgs/development/compilers/llvm/multi.nix @@ -36,6 +36,10 @@ let # Most of the magic is done by setting the --gcc-toolchain option below libc = gcc_multi_sysroot; + bintools = clang.bintools.override { + libc = gcc_multi_sysroot; + }; + extraBuildCommands = '' sed -e '$a --gcc-toolchain=${gcc_multi_sysroot}' -i $out/nix-support/libc-cflags ''; diff --git a/pkgs/development/libraries/libbfd/default.nix b/pkgs/development/libraries/libbfd/default.nix index 700c5a928e554..5bcf243155b0e 100644 --- a/pkgs/development/libraries/libbfd/default.nix +++ b/pkgs/development/libraries/libbfd/default.nix @@ -5,11 +5,11 @@ stdenv.mkDerivation rec { name = "libbfd-${version}"; - inherit (binutils-raw) version src; + inherit (binutils-raw.bintools) version src; outputs = [ "out" "dev" ]; - patches = binutils-raw.patches ++ [ + patches = binutils-raw.bintools.patches ++ [ ../../tools/misc/binutils/build-components-separately.patch ]; diff --git a/pkgs/development/libraries/libopcodes/default.nix b/pkgs/development/libraries/libopcodes/default.nix index f3e12db398194..7ffc40f149462 100644 --- a/pkgs/development/libraries/libopcodes/default.nix +++ b/pkgs/development/libraries/libopcodes/default.nix @@ -5,11 +5,11 @@ stdenv.mkDerivation rec { name = "libopcodes-${version}"; - inherit (binutils-raw) version src; + inherit (binutils-raw.bintools) version src; outputs = [ "out" "dev" ]; - patches = binutils-raw.patches ++ [ + patches = binutils-raw.bintools.patches ++ [ ../../tools/misc/binutils/build-components-separately.patch ]; diff --git a/pkgs/development/libraries/libstdc++5/default.nix b/pkgs/development/libraries/libstdc++5/default.nix index baea981ca4a18..5c0e7c9bdfa4f 100644 --- a/pkgs/development/libraries/libstdc++5/default.nix +++ b/pkgs/development/libraries/libstdc++5/default.nix @@ -64,7 +64,7 @@ stdenv.mkDerivation rec { # being generated to make sure that they use our glibc. EXTRA_FLAGS="-I$NIX_FIXINC_DUMMY $(cat $NIX_CC/nix-support/libc-cflags) -O2" - extraLDFlags="-L$glibc_libdir -rpath $glibc_libdir $(cat $NIX_CC/nix-support/libc-ldflags) $(cat $NIX_CC/nix-support/libc-ldflags-before)" + extraLDFlags="-L$glibc_libdir -rpath $glibc_libdir $(cat $NIX_BINTOOLS/nix-support/libc-ldflags) $(cat $NIX_BINTOOLS/nix-support/libc-ldflags-before)" for i in $extraLDFlags; do EXTRA_FLAGS="$EXTRA_FLAGS -Wl,$i" done diff --git a/pkgs/development/tools/misc/binutils/default.nix b/pkgs/development/tools/misc/binutils/default.nix index 519d5c722af8d..7628e37ae1cdb 100644 --- a/pkgs/development/tools/misc/binutils/default.nix +++ b/pkgs/development/tools/misc/binutils/default.nix @@ -55,7 +55,7 @@ stdenv.mkDerivation rec { ./disambiguate-arm-targets.patch ]; - outputs = [ "out" "info" ]; + outputs = [ "out" "info" "man" ]; nativeBuildInputs = [ bison buildPackages.stdenv.cc ]; buildInputs = [ zlib ]; diff --git a/pkgs/os-specific/darwin/binutils/default.nix b/pkgs/os-specific/darwin/binutils/default.nix index 613606b50358a..1fff4915da3c8 100644 --- a/pkgs/os-specific/darwin/binutils/default.nix +++ b/pkgs/os-specific/darwin/binutils/default.nix @@ -17,10 +17,11 @@ in # TODO loop over targetPrefixed binaries too stdenv.mkDerivation { name = "${targetPrefix}cctools-binutils-darwin"; + outputs = [ "out" "info" "man" ]; buildCommand = '' mkdir -p $out/bin $out/include - ln -s ${binutils-raw.out}/bin/${targetPrefix}c++filt $out/bin/${targetPrefix}c++filt + ln -s ${binutils-raw.bintools.out}/bin/${targetPrefix}c++filt $out/bin/${targetPrefix}c++filt # We specifically need: # - ld: binutils doesn't provide it on darwin @@ -37,10 +38,16 @@ stdenv.mkDerivation { ln -sf "${cctools}/bin/$i" "$out/bin/$i" done - # FIXME: this will give us incorrect man pages for bits of cctools - ln -s ${binutils-raw.out}/share $out/share + ln -s ${binutils-raw.bintools.out}/share $out/share ln -s ${cctools}/libexec $out/libexec + + mkdir -p "$info/nix-support" "$man/nix-support" + printWords ${binutils-raw.bintools.info} \ + >> $info/nix-support/propagated-build-inputs + # FIXME: cctools missing man pages + printWords ${binutils-raw.bintools.man} \ + >> $man/nix-support/propagated-build-inputs ''; passthru = { diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 89c903b04a048..d202186c29b24 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -60,10 +60,40 @@ in rec { extraBuildInputs, allowedRequisites ? null}: let + buildPackages = lib.optionalAttrs (last ? stdenv) { + inherit (last) stdenv; + }; + + coreutils = { name = "coreutils-9.9.9"; outPath = bootstrapTools; }; + gnugrep = { name = "gnugrep-9.9.9"; outPath = bootstrapTools; }; + + bintools = import ../../build-support/bintools-wrapper { + inherit shell; + inherit (last) stdenvNoCC; + + nativeTools = false; + nativeLibc = false; + inherit buildPackages coreutils gnugrep; + libc = last.pkgs.darwin.Libsystem; + bintools = { name = "binutils-9.9.9"; outPath = bootstrapTools; }; + }; + + cc = if isNull last then "/dev/null" else import ../../build-support/cc-wrapper { + inherit shell; + inherit (last) stdenvNoCC; + + nativeTools = false; + nativeLibc = false; + inherit buildPackages coreutils gnugrep bintools; + libc = last.pkgs.darwin.Libsystem; + isClang = true; + cc = { name = "clang-9.9.9"; outPath = bootstrapTools; }; + }; + thisStdenv = import ../generic { inherit config shell extraNativeBuildInputs extraBuildInputs; allowedRequisites = if allowedRequisites == null then null else allowedRequisites ++ [ - thisStdenv.cc.expand-response-params + cc.expand-response-params cc.bintools ]; name = "stdenv-darwin-boot-${toString step}"; @@ -72,24 +102,9 @@ in rec { hostPlatform = localSystem; targetPlatform = localSystem; - cc = if isNull last then "/dev/null" else import ../../build-support/cc-wrapper { - inherit shell; - inherit (last) stdenvNoCC; - - nativeTools = false; - nativeLibc = false; - buildPackages = lib.optionalAttrs (last ? stdenv) { - inherit (last) stdenv; - }; - libc = last.pkgs.darwin.Libsystem; - isClang = true; - cc = { name = "clang-9.9.9"; outPath = bootstrapTools; }; - binutils = { name = "binutils-9.9.9"; outPath = bootstrapTools; }; - coreutils = { name = "coreutils-9.9.9"; outPath = bootstrapTools; }; - gnugrep = { name = "gnugrep-9.9.9"; outPath = bootstrapTools; }; - }; + inherit cc; - preHook = stage0.stdenv.lib.optionalString (shell == "${bootstrapTools}/bin/bash") '' + preHook = lib.optionalString (shell == "${bootstrapTools}/bin/bash") '' # Don't patch #!/interpreter because it leads to retained # dependencies on the bootstrapTools in the final stdenv. dontPatchShebangs=1 @@ -328,9 +343,10 @@ in rec { buildPackages = { inherit (prevStage) stdenv; }; - inherit (pkgs) coreutils binutils gnugrep; - cc = pkgs.llvmPackages.clang-unwrapped; - libc = pkgs.darwin.Libsystem; + inherit (pkgs) coreutils gnugrep; + cc = pkgs.llvmPackages.clang-unwrapped; + bintools = pkgs.darwin.binutils; + libc = pkgs.darwin.Libsystem; }; extraNativeBuildInputs = []; @@ -349,8 +365,8 @@ in rec { xz.out xz.bin libcxx libcxxabi gmp.out gnumake findutils bzip2.out bzip2.bin llvmPackages.llvm llvmPackages.llvm.lib zlib.out zlib.dev libffi.out coreutils ed diffutils gnutar gzip ncurses.out ncurses.dev ncurses.man gnused bash gawk - gnugrep llvmPackages.clang-unwrapped patch pcre.out binutils-raw.out - binutils gettext + gnugrep llvmPackages.clang-unwrapped patch pcre.out gettext + binutils-raw.bintools binutils binutils.bintools cc.expand-response-params ]) ++ (with pkgs.darwin; [ dyld Libsystem CF cctools ICU libiconv locale diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index a114ab609e6cf..858323e5cc566 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -80,9 +80,10 @@ let inherit (prevStage) stdenv; }; cc = prevStage.gcc-unwrapped; + bintools = prevStage.binutils; isGNU = true; libc = prevStage.glibc; - inherit (prevStage) binutils coreutils gnugrep; + inherit (prevStage) coreutils gnugrep; name = name; stdenvNoCC = prevStage.ccWrapperStdenv; }; @@ -143,7 +144,15 @@ in ''; }; gcc-unwrapped = bootstrapTools; - binutils = bootstrapTools; + binutils = import ../../build-support/bintools-wrapper { + nativeTools = false; + nativeLibc = false; + buildPackages = { }; + libc = self.glibc; + inherit (self) stdenvNoCC coreutils gnugrep; + bintools = bootstrapTools; + name = "bootstrap-binutils-wrapper"; + }; coreutils = bootstrapTools; gnugrep = bootstrapTools; }; @@ -165,7 +174,7 @@ in # Rebuild binutils to use from stage2 onwards. overrides = self: super: { - binutils = super.binutils.override { gold = false; }; + binutils = super.binutils_nogold; inherit (prevStage) ccWrapperStdenv glibc gcc-unwrapped coreutils gnugrep; @@ -188,9 +197,14 @@ in overrides = self: super: { inherit (prevStage) ccWrapperStdenv - binutils gcc-unwrapped coreutils gnugrep + gcc-unwrapped coreutils gnugrep perl paxctl gnum4 bison; # This also contains the full, dynamically linked, final Glibc. + binutils = prevStage.binutils.override { + # Rewrap the binutils with the new glibc, so both the next + # stage's wrappers use it. + libc = self.glibc; + }; }; }) @@ -235,6 +249,15 @@ in # other purposes (binutils and top-level pkgs) too. inherit (prevStage) gettext gnum4 bison gmp perl glibc zlib linuxHeaders; + binutils = super.binutils.override { + # Don't use stdenv's shell but our own + shell = self.bash + "/bin/bash"; + # Build expand-response-params with last stage like below + buildPackages = { + inherit (prevStage) stdenv; + }; + }; + gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) { nativeTools = false; nativeLibc = false; @@ -243,8 +266,9 @@ in inherit (prevStage) stdenv; }; cc = prevStage.gcc-unwrapped; + bintools = self.binutils; libc = self.glibc; - inherit (self) stdenvNoCC binutils coreutils gnugrep; + inherit (self) stdenvNoCC coreutils gnugrep; name = ""; shell = self.bash + "/bin/bash"; }; @@ -299,8 +323,8 @@ in allowedRequisites = with prevStage; with lib; # Simple executable tools concatMap (p: [ (getBin p) (getLib p) ]) - [ gzip bzip2 xz bash binutils coreutils diffutils findutils gawk - gnumake gnused gnutar gnugrep gnupatch patchelf ed paxctl + [ gzip bzip2 xz bash binutils.bintools coreutils diffutils findutils + gawk gnumake gnused gnutar gnugrep gnupatch patchelf ed paxctl ] # Library dependencies ++ map getLib ( @@ -310,7 +334,7 @@ in # More complicated cases ++ [ glibc.out glibc.dev glibc.bin/*propagated from .dev*/ linuxHeaders - gcc gcc.cc gcc.cc.lib gcc.expand-response-params + binutils gcc gcc.cc gcc.cc.lib gcc.expand-response-params ] ++ lib.optionals localSystem.isAarch64 [ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ]; @@ -322,7 +346,7 @@ in attr acl paxctl zlib pcre; } // lib.optionalAttrs (super.targetPlatform == localSystem) { # Need to get rid of these when cross-compiling. - inherit (prevStage) binutils; + inherit (prevStage) binutils binutils-raw; gcc = cc; }; }; diff --git a/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix b/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix index 8a1f7445b30b4..8aaf4993108b4 100644 --- a/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix +++ b/pkgs/stdenv/linux/make-bootstrap-tools-cross.nix @@ -177,7 +177,7 @@ rec { # Copy binutils. for i in as ld ar ranlib nm strip readelf objdump; do - cp ${binutils.out}/bin/$i $out/bin + cp ${binutils.bintools.out}/bin/$i $out/bin done chmod -R u+w $out diff --git a/pkgs/stdenv/linux/make-bootstrap-tools.nix b/pkgs/stdenv/linux/make-bootstrap-tools.nix index 52eea41bdbd76..15be64a22a925 100644 --- a/pkgs/stdenv/linux/make-bootstrap-tools.nix +++ b/pkgs/stdenv/linux/make-bootstrap-tools.nix @@ -126,7 +126,7 @@ rec { # Copy binutils. for i in as ld ar ranlib nm strip readelf objdump; do - cp ${binutils.out}/bin/$i $out/bin + cp ${binutils.bintools.out}/bin/$i $out/bin done chmod -R u+w $out diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 6dd631ac9aa8e..5b27052fb040b 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -5485,7 +5485,9 @@ with pkgs; clang-sierraHack = clang.override { name = "clang-wrapper-with-reexport-hack"; - useMacosReexportHack = true; + bintools = clang.bintools.override { + useMacosReexportHack = true; + }; }; clang_5 = llvmPackages_5.clang; @@ -5514,7 +5516,7 @@ with pkgs; cc = build; isClang = true; inherit stdenvNoCC; - libc = glibc; + inherit (targetPackages.stdenv.cc) bintools libc; extraPackages = [ libcxx libcxxabi ]; nativeTools = false; nativeLibc = false; @@ -5586,18 +5588,23 @@ with pkgs; }; wrapCCMulti = cc: - if system == "x86_64-linux" then lowPrio (wrapCCWith { + if system == "x86_64-linux" then let + # Binutils with glibc multi + bintools = cc.bintools.override { + libc = glibc_multi; + }; + in lowPrio (wrapCCWith { cc = cc.cc.override { stdenv = overrideCC stdenv (wrapCCWith { cc = cc.cc; + inherit bintools; libc = glibc_multi; }); profiledCompiler = false; enableMultilib = true; }; - libc = glibc_multi; - + inherit bintools; extraBuildCommands = '' echo "dontMoveLib64=1" >> $out/nix-support/setup-hook ''; @@ -5643,6 +5650,10 @@ with pkgs; if targetPlatform.libc == "msvcrt" then targetPackages.windows.mingw_w64_headers else if targetPlatform.libc == "libSystem" then darwin.xcode else null; + binutils1 = wrapBintoolsWith { + bintools = binutils-unwrapped; + libc = libcCross1; + }; in wrapCCWith { name = "gcc-cross-wrapper"; cc = gccFun { @@ -5656,8 +5667,10 @@ with pkgs; crossStageStatic = true; langCC = false; libcCross = libcCross1; + targetPackages.stdenv.cc.bintools = binutils1; enableShared = false; }; + bintools = binutils1; libc = libcCross1; }; @@ -5666,6 +5679,7 @@ with pkgs; name = "gcc-cross-wrapper"; cc = gccCrossStageStatic.gcc; libc = windows.mingw_headers2; + inherit binutils; }; gcc45 = lowPrio (wrapCC (callPackage ../development/compilers/gcc/4.5 { @@ -6437,7 +6451,8 @@ with pkgs; wla-dx = callPackage ../development/compilers/wla-dx { }; - wrapCCWith = { name ? "", cc, libc, extraBuildCommands ? "" }: ccWrapperFun rec { + wrapCCWith = { name ? "", cc, bintools, libc, extraBuildCommands ? "" }: + ccWrapperFun rec { nativeTools = targetPlatform == hostPlatform && stdenv.cc.nativeTools or false; nativeLibc = targetPlatform == hostPlatform && stdenv.cc.nativeLibc or false; nativePrefix = stdenv.cc.nativePrefix or ""; @@ -6446,14 +6461,20 @@ with pkgs; isGNU = cc.isGNU or false; isClang = cc.isClang or false; - inherit name cc libc extraBuildCommands; + inherit name cc bintools libc extraBuildCommands; }; ccWrapperFun = callPackage ../build-support/cc-wrapper; + bintoolsWrapperFun = callPackage ../build-support/bintools-wrapper; wrapCC = cc: wrapCCWith { name = lib.optionalString (targetPlatform != hostPlatform) "gcc-cross-wrapper"; inherit cc; + # This should be the only bintools runtime dep with this sort of logic. The + # Others should instead delegate to the next stage's choice with + # `targetPackages.stdenv.cc.bintools`. This one is different just to + # provide the default choice, avoiding infinite recursion. + bintools = if targetPlatform.isDarwin then darwin.binutils else binutils; libc = if targetPlatform != hostPlatform then libcCross else stdenv.cc.libc; }; # legacy version, used for gnat bootstrapping @@ -6465,6 +6486,17 @@ with pkgs; libc = glibc; }; + wrapBintoolsWith = { bintools, libc }: bintoolsWrapperFun { + nativeTools = targetPlatform == hostPlatform && stdenv.cc.nativeTools or false; + nativeLibc = targetPlatform == hostPlatform && stdenv.cc.nativeLibc or false; + nativePrefix = stdenv.cc.nativePrefix or ""; + + noLibc = (libc == null); + + inherit bintools libc; + extraBuildCommands = ""; + }; + # prolog yap = callPackage ../development/compilers/yap { }; @@ -7046,13 +7078,19 @@ with pkgs; then darwin.binutils else binutils-raw; - binutils-raw = callPackage ../development/tools/misc/binutils { + binutils-unwrapped = callPackage ../development/tools/misc/binutils { # FHS sys dirs presumably only have stuff for the build platform noSysDirs = (targetPlatform != buildPlatform) || noSysDirs; }; + binutils-raw = wrapBintoolsWith { + libc = if targetPlatform != hostPlatform then libcCross else stdenv.cc.libc; + bintools = binutils-unwrapped; + }; binutils_nogold = lowPrio (binutils-raw.override { - gold = false; + bintools = binutils-raw.bintools.override { + gold = false; + }; }); bison2 = callPackage ../development/tools/parsing/bison/2.x.nix { }; diff --git a/pkgs/top-level/darwin-packages.nix b/pkgs/top-level/darwin-packages.nix index 30f50c56db74a..7540a47ef6d52 100644 --- a/pkgs/top-level/darwin-packages.nix +++ b/pkgs/top-level/darwin-packages.nix @@ -10,8 +10,14 @@ in apple_sdk = callPackage ../os-specific/darwin/apple-sdk { }; - binutils = callPackage ../os-specific/darwin/binutils { - inherit (darwin) cctools; + binutils = pkgs.wrapBintoolsWith { + libc = + if pkgs.targetPlatform != pkgs.hostPlatform + then pkgs.libcCross + else pkgs.stdenv.cc.libc; + bintools = callPackage ../os-specific/darwin/binutils { + inherit (darwin) cctools; + }; }; cctools = callPackage ../os-specific/darwin/cctools/port.nix {