diff options
author | Vladimír Čunát <vcunat@gmail.com> | 2017-08-12 10:09:41 +0200 |
---|---|---|
committer | Vladimír Čunát <vcunat@gmail.com> | 2017-08-12 10:09:41 +0200 |
commit | 6899c7fdb989ce02f877ce5c0490a20ac4a64bf0 (patch) | |
tree | 68a2e9b25d3b4f0d0a70343b38d10bdc0111f20d /pkgs/build-support | |
parent | 9bcee1051a94d6ba2be64a19665f017542122b83 (diff) | |
parent | e207d1f04ad262f53e387e9e3956a2a9c421a66a (diff) | |
download | nixlib-6899c7fdb989ce02f877ce5c0490a20ac4a64bf0.tar nixlib-6899c7fdb989ce02f877ce5c0490a20ac4a64bf0.tar.gz nixlib-6899c7fdb989ce02f877ce5c0490a20ac4a64bf0.tar.bz2 nixlib-6899c7fdb989ce02f877ce5c0490a20ac4a64bf0.tar.lz nixlib-6899c7fdb989ce02f877ce5c0490a20ac4a64bf0.tar.xz nixlib-6899c7fdb989ce02f877ce5c0490a20ac4a64bf0.tar.zst nixlib-6899c7fdb989ce02f877ce5c0490a20ac4a64bf0.zip |
Merge branch 'master' into gcc-6
Diffstat (limited to 'pkgs/build-support')
24 files changed, 810 insertions, 483 deletions
diff --git a/pkgs/build-support/cc-wrapper/add-flags.sh b/pkgs/build-support/cc-wrapper/add-flags.sh index 5634c82aa285..4d28ba08d103 100644 --- a/pkgs/build-support/cc-wrapper/add-flags.sh +++ b/pkgs/build-support/cc-wrapper/add-flags.sh @@ -1,28 +1,88 @@ +# N.B. It may be a surprise that the derivation-specific variables are exported, +# since this is just sourced by the wrapped binaries---the end consumers. This +# is because one wrapper binary may invoke another (e.g. cc invoking ld). In +# 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=( + NIX_CC_WRAPPER+START_HOOK + NIX_CC_WRAPPER+EXEC_HOOK + NIX_LD_WRAPPER+START_HOOK + NIX_LD_WRAPPER+EXEC_HOOK + + 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+LDFLAGS_HARDEN + + NIX+SET_BUILD_ID + NIX+DONT_SET_RPATH + NIX+ENFORCE_NO_NATIVE +) + +# Accumulate infixes for taking in the right input parameters. See setup-hook +# for details. +declare -a role_infixes=() +if [ "${NIX_CC_WRAPPER_@infixSalt@_TARGET_BUILD:-}" ]; then + role_infixes+=(_BUILD_) +fi +if [ "${NIX_CC_WRAPPER_@infixSalt@_TARGET_HOST:-}" ]; then + role_infixes+=(_) +fi +if [ "${NIX_CC_WRAPPER_@infixSalt@_TARGET_TARGET:-}" ]; then + role_infixes+=(_TARGET_) +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 +done + # `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld. -export NIX_CFLAGS_COMPILE="-B@out@/bin/ $NIX_CFLAGS_COMPILE" +NIX_@infixSalt@_CFLAGS_COMPILE="-B@out@/bin/ $NIX_@infixSalt@_CFLAGS_COMPILE" + +# Export and assign separately in order that a failing $(..) will fail +# the script. if [ -e @out@/nix-support/libc-cflags ]; then - export NIX_CFLAGS_COMPILE="$(cat @out@/nix-support/libc-cflags) $NIX_CFLAGS_COMPILE" + NIX_@infixSalt@_CFLAGS_COMPILE="$(< @out@/nix-support/libc-cflags) $NIX_@infixSalt@_CFLAGS_COMPILE" fi if [ -e @out@/nix-support/cc-cflags ]; then - export NIX_CFLAGS_COMPILE="$(cat @out@/nix-support/cc-cflags) $NIX_CFLAGS_COMPILE" + NIX_@infixSalt@_CFLAGS_COMPILE="$(< @out@/nix-support/cc-cflags) $NIX_@infixSalt@_CFLAGS_COMPILE" fi if [ -e @out@/nix-support/gnat-cflags ]; then - export NIX_GNATFLAGS_COMPILE="$(cat @out@/nix-support/gnat-cflags) $NIX_GNATFLAGS_COMPILE" + NIX_@infixSalt@_GNATFLAGS_COMPILE="$(< @out@/nix-support/gnat-cflags) $NIX_@infixSalt@_GNATFLAGS_COMPILE" fi if [ -e @out@/nix-support/libc-ldflags ]; then - export NIX_LDFLAGS+=" $(cat @out@/nix-support/libc-ldflags)" + NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)" fi if [ -e @out@/nix-support/cc-ldflags ]; then - export NIX_LDFLAGS+=" $(cat @out@/nix-support/cc-ldflags)" + NIX_@infixSalt@_LDFLAGS+=" $(< @out@/nix-support/cc-ldflags)" fi if [ -e @out@/nix-support/libc-ldflags-before ]; then - export NIX_LDFLAGS_BEFORE="$(cat @out@/nix-support/libc-ldflags-before) $NIX_LDFLAGS_BEFORE" + NIX_@infixSalt@_LDFLAGS_BEFORE="$(< @out@/nix-support/libc-ldflags-before) $NIX_@infixSalt@_LDFLAGS_BEFORE" fi -export NIX_CC_WRAPPER_FLAGS_SET=1 +# 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 b98833b3513b..aa8eb720486c 100644 --- a/pkgs/build-support/cc-wrapper/add-hardening.sh +++ b/pkgs/build-support/cc-wrapper/add-hardening.sh @@ -1,53 +1,69 @@ hardeningFlags=(fortify stackprotector pic strictoverflow format relro bindnow) -hardeningFlags+=("${hardeningEnable[@]}") +# 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 hardeningCFlags=() hardeningLDFlags=() -hardeningDisable=${hardeningDisable:-""} -hardeningDisable+=" @hardening_unsupported_flags@" +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 [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: Value of '$hardeningDisable': $hardeningDisable >&2; fi +if [[ -n "${NIX_DEBUG:-}" ]]; then + printf 'HARDENING: disabled flags:' >&2 + (( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2 + echo >&2 +fi -if [[ ! $hardeningDisable =~ "all" ]]; then - if [[ -n "$NIX_DEBUG" ]]; then echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; fi +if [[ -z "${hardeningDisableMap[all]:-}" ]]; then + if [[ -n "${NIX_DEBUG:-}" ]]; then + echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; + fi for flag in "${hardeningFlags[@]}" do - if [[ ! "${hardeningDisable}" =~ "$flag" ]]; then + if [[ -z "${hardeningDisableMap[$flag]:-}" ]]; then case $flag in fortify) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling fortify >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling fortify >&2; fi hardeningCFlags+=('-O2' '-D_FORTIFY_SOURCE=2') ;; stackprotector) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling stackprotector >&2; fi - hardeningCFlags+=('-fstack-protector-strong' '--param ssp-buffer-size=4') + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling stackprotector >&2; fi + hardeningCFlags+=('-fstack-protector-strong' '--param' 'ssp-buffer-size=4') ;; pie) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling CFlags -fPIE >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling CFlags -fPIE >&2; fi hardeningCFlags+=('-fPIE') if [[ ! ("$*" =~ " -shared " || "$*" =~ " -static ") ]]; then - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling LDFlags -pie >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling LDFlags -pie >&2; fi hardeningLDFlags+=('-pie') fi ;; pic) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling pic >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling pic >&2; fi hardeningCFlags+=('-fPIC') ;; strictoverflow) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling strictoverflow >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling strictoverflow >&2; fi hardeningCFlags+=('-fno-strict-overflow') ;; format) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling format >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling format >&2; fi hardeningCFlags+=('-Wformat' '-Wformat-security' '-Werror=format-security') ;; relro) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling relro >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling relro >&2; fi hardeningLDFlags+=('-z' 'relro') ;; bindnow) - if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling bindnow >&2; fi + if [[ -n "${NIX_DEBUG:-}" ]]; then echo HARDENING: enabling bindnow >&2; fi hardeningLDFlags+=('-z' 'now') ;; *) diff --git a/pkgs/build-support/cc-wrapper/cc-wrapper.sh b/pkgs/build-support/cc-wrapper/cc-wrapper.sh index 3ccdc34db5b2..e5a3a5818519 100644 --- a/pkgs/build-support/cc-wrapper/cc-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/cc-wrapper.sh @@ -1,17 +1,24 @@ -#! @shell@ -e +#! @shell@ +set -eu -o pipefail +shopt -s nullglob + path_backup="$PATH" -if [ -n "@coreutils_bin@" ]; then - PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin" -fi -if [ -n "$NIX_CC_WRAPPER_START_HOOK" ]; then - source "$NIX_CC_WRAPPER_START_HOOK" +# That @-vars are substituted separately from bash evaluation makes +# shellcheck think this, and others like it, are useless conditionals. +# shellcheck disable=SC2157 +if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then + PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin" fi -if [ -z "$NIX_CC_WRAPPER_FLAGS_SET" ]; then +if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then source @out@/nix-support/add-flags.sh fi +if [ -n "$NIX_CC_WRAPPER_@infixSalt@_START_HOOK" ]; then + source "$NIX_CC_WRAPPER_@infixSalt@_START_HOOK" +fi + source @out@/nix-support/utils.sh @@ -19,16 +26,17 @@ source @out@/nix-support/utils.sh # For instance, figure out if linker flags should be passed. # GCC prints annoying warnings when they are not needed. dontLink=0 -getVersion=0 nonFlagArgs=0 +# shellcheck disable=SC2193 [[ "@prog@" = *++ ]] && isCpp=1 || isCpp=0 cppInclude=1 expandResponseParams "$@" -n=0 -while [ $n -lt ${#params[*]} ]; do +declare -i n=0 +nParams=${#params[@]} +while [ "$n" -lt "$nParams" ]; do p=${params[n]} - p2=${params[$((n+1))]} + p2=${params[n+1]:-} # handle `p` being last one if [ "$p" = -c ]; then dontLink=1 elif [ "$p" = -S ]; then @@ -55,10 +63,10 @@ while [ $n -lt ${#params[*]} ]; do nonFlagArgs=1 elif [ "$p" = -m32 ]; then if [ -e @out@/nix-support/dynamic-linker-m32 ]; then - NIX_LDFLAGS="$NIX_LDFLAGS -dynamic-linker $(cat @out@/nix-support/dynamic-linker-m32)" + NIX_@infixSalt@_LDFLAGS+=" -dynamic-linker $(< @out@/nix-support/dynamic-linker-m32)" fi fi - n=$((n + 1)) + n+=1 done # If we pass a flag like -Wl, then gcc will call the linker unless it @@ -71,39 +79,40 @@ if [ "$nonFlagArgs" = 0 ]; then fi # Optionally filter out paths not refering to the store. -if [ "$NIX_ENFORCE_PURITY" = 1 -a -n "$NIX_STORE" ]; then +if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then rest=() - n=0 - while [ $n -lt ${#params[*]} ]; do + nParams=${#params[@]} + declare -i n=0 + while [ "$n" -lt "$nParams" ]; do p=${params[n]} - p2=${params[$((n+1))]} + p2=${params[n+1]:-} # handle `p` being last one if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then - skip $p + skip "${p:2}" elif [ "$p" = -L ] && badPath "$p2"; then - n=$((n + 1)); skip $p2 + n+=1; skip "$p2" elif [ "${p:0:3}" = -I/ ] && badPath "${p:2}"; then - skip $p + skip "${p:2}" elif [ "$p" = -I ] && badPath "$p2"; then - n=$((n + 1)); skip $p2 + n+=1; skip "$p2" elif [ "$p" = -isystem ] && badPath "$p2"; then - n=$((n + 1)); skip $p2 + n+=1; skip "$p2" else rest+=("$p") fi - n=$((n + 1)) + n+=1 done params=("${rest[@]}") fi # Clear march/mtune=native -- they bring impurity. -if [ "$NIX_ENFORCE_NO_NATIVE" = 1 ]; then +if [ "$NIX_@infixSalt@_ENFORCE_NO_NATIVE" = 1 ]; then rest=() - for i in "${params[@]}"; do - if [[ "$i" = -m*=native ]]; then - skip $i + for p in "${params[@]}"; do + if [[ "$p" = -m*=native ]]; then + skip "$p" else - rest+=("$i") + rest+=("$p") fi done params=("${rest[@]}") @@ -111,37 +120,36 @@ fi if [[ "$isCpp" = 1 ]]; then if [[ "$cppInclude" = 1 ]]; then - NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE ${NIX_CXXSTDLIB_COMPILE-@default_cxx_stdlib_compile@}" + NIX_@infixSalt@_CFLAGS_COMPILE+=" ${NIX_@infixSalt@_CXXSTDLIB_COMPILE-@default_cxx_stdlib_compile@}" fi - NIX_CFLAGS_LINK="$NIX_CFLAGS_LINK $NIX_CXXSTDLIB_LINK" + NIX_@infixSalt@_CFLAGS_LINK+=" $NIX_@infixSalt@_CXXSTDLIB_LINK" fi -LD=@ldPath@/ld source @out@/nix-support/add-hardening.sh # Add the flags for the C compiler proper. -extraAfter=($NIX_CFLAGS_COMPILE ${hardeningCFlags[@]}) +extraAfter=($NIX_@infixSalt@_CFLAGS_COMPILE "${hardeningCFlags[@]}") extraBefore=() if [ "$dontLink" != 1 ]; then # Add the flags that should only be passed to the compiler when # linking. - extraAfter+=($NIX_CFLAGS_LINK ${hardeningLDFlags[@]}) + extraAfter+=($NIX_@infixSalt@_CFLAGS_LINK "${hardeningLDFlags[@]}") # Add the flags that should be passed to the linker (and prevent - # `ld-wrapper' from adding NIX_LDFLAGS again). - for i in $NIX_LDFLAGS_BEFORE; do - extraBefore=(${extraBefore[@]} "-Wl,$i") + # `ld-wrapper' from adding NIX_@infixSalt@_LDFLAGS again). + for i in $NIX_@infixSalt@_LDFLAGS_BEFORE; do + extraBefore+=("-Wl,$i") done - for i in $NIX_LDFLAGS; do + for i in $NIX_@infixSalt@_LDFLAGS; do if [ "${i:0:3}" = -L/ ]; then extraAfter+=("$i") else extraAfter+=("-Wl,$i") fi done - export NIX_LDFLAGS_SET=1 + export NIX_@infixSalt@_LDFLAGS_SET=1 fi # As a very special hack, if the arguments are just `-v', then don't @@ -154,24 +162,21 @@ if [ "$*" = -v ]; then fi # Optionally print debug info. -if [ -n "$NIX_DEBUG" ]; then - echo "original flags to @prog@:" >&2 - for i in "${params[@]}"; do - echo " $i" >&2 - done - echo "extraBefore flags to @prog@:" >&2 - for i in ${extraBefore[@]}; do - echo " $i" >&2 - done - echo "extraAfter flags to @prog@:" >&2 - for i in ${extraAfter[@]}; do - echo " $i" >&2 - done +if [ -n "${NIX_DEBUG:-}" ]; then + set +u # Old bash workaround, see ld-wrapper for explanation. + echo "extra flags before to @prog@:" >&2 + printf " %q\n" "${extraBefore[@]}" >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" "${params[@]}" >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" "${extraAfter[@]}" >&2 + set -u fi -if [ -n "$NIX_CC_WRAPPER_EXEC_HOOK" ]; then - source "$NIX_CC_WRAPPER_EXEC_HOOK" +if [ -n "$NIX_CC_WRAPPER_@infixSalt@_EXEC_HOOK" ]; then + source "$NIX_CC_WRAPPER_@infixSalt@_EXEC_HOOK" fi PATH="$path_backup" -exec @prog@ ${extraBefore[@]} "${params[@]}" "${extraAfter[@]}" +set +u # Old bash workaround, see above. +exec @prog@ "${extraBefore[@]}" "${params[@]}" "${extraAfter[@]}" diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 7df9615653f9..502362514ebc 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -12,6 +12,7 @@ , isGNU ? false, isClang ? cc.isClang or false, gnugrep ? null , buildPackages ? {}, hostPlatform, targetPlatform , runCommand ? null +, useMacosReexportHack ? false }: with stdenv.lib; @@ -52,75 +53,28 @@ let "-isystem $(echo -n ${cc.gcc}/include/c++/*) -isystem $(echo -n ${cc.gcc}/include/c++/*)/$(${cc.gcc}/bin/gcc -dumpmachine)"; dashlessTarget = stdenv.lib.replaceStrings ["-"] ["_"] targetPlatform.config; - # TODO(@Ericson2314) Make unconditional - infixSalt = stdenv.lib.optionalString (targetPlatform != hostPlatform) dashlessTarget; - infixSalt_ = stdenv.lib.optionalString (targetPlatform != hostPlatform) (dashlessTarget + "_"); - _infixSalt = stdenv.lib.optionalString (targetPlatform != hostPlatform) ("_" + dashlessTarget); - - # We want to prefix all NIX_ flags with the target triple - preWrap = textFile: - # TODO: Do even when not cross on next mass-rebuild - # TODO: use @target_tripple@ for consistency - if targetPlatform == hostPlatform - then textFile - else runCommand "sed-nix-env-vars" {} ('' - cp --no-preserve=mode ${textFile} $out - - sed -i $out \ - -e 's^NIX_^NIX_${infixSalt_}^g' \ - -e 's^addCVars^addCVars${_infixSalt}^g' \ - -e 's^\[ -z "\$crossConfig" \]^\[\[ "${builtins.toString (targetPlatform != hostPlatform)}" || -z "$crossConfig" \]\]^g' - - '' + stdenv.lib.optionalString (textFile == ./setup-hook.sh) '' - cat << 'EOF' >> $out - for CMD in ar as nm objcopy ranlib strip strings size ld windres - do - # which is not part of stdenv, but compgen will do for now - if - PATH=$_PATH type -p ${prefix}$CMD > /dev/null - then - export ''$(echo "$CMD" | tr "[:lower:]" "[:upper:]")=${prefix}''${CMD}; - fi - done - EOF - - sed -i $out -e 's_envHooks_crossEnvHooks_g' - '' + '' - - # NIX_ things which we don't both use and define, we revert them - #asymmetric=$( - # for pre in "" "\\$" - # do - # grep -E -ho $pre'NIX_[a-zA-Z_]*' ./* | sed 's/\$//' | sort | uniq - # done | sort | uniq -c | sort -nr | sed -n 's/^1 NIX_//gp') - - # hard-code for now - asymmetric=("CXXSTDLIB_COMPILE" "CC") - - # The ([^a-zA-Z_]|$) bussiness is to ensure environment variables that - # begin with `NIX_CC` don't also get blacklisted. - for var in "''${asymmetric[@]}" - do - sed -i $out -E -e "s~NIX_${infixSalt_}$var([^a-zA-Z_]|$)~NIX_$var\1~g" - done - ''); - - # The dynamic linker has different names on different platforms. + + # The "infix salt" is a arbitrary string added in the middle of env vars + # defined by cc-wrapper's hooks so that multiple cc-wrappers can be used + # without interfering. For the moment, it is defined as the target triple, + # adjusted to be a valid bash identifier. This should be considered an + # 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 !nativeLibc then - (if targetPlatform.system == "i686-linux" then "ld-linux.so.2" else - if targetPlatform.system == "x86_64-linux" then "ld-linux-x86-64.so.2" else - # ARM with a wildcard, which can be "" or "-armhf". - if targetPlatform.isArm32 then "ld-linux*.so.3" else - if targetPlatform.system == "aarch64-linux" then "ld-linux-aarch64.so.1" else - if targetPlatform.system == "powerpc-linux" then "ld.so.1" else - if targetPlatform.system == "mips64el-linux" then "ld.so.1" else - if targetPlatform.system == "x86_64-darwin" then "/usr/lib/dyld" else - if stdenv.lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" else - builtins.trace - "Don't know the name of the dynamic linker for platform ${targetPlatform.config}, so guessing instead." - null) - else ""; + /**/ 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 targetPlatform.isArm32 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.system == "x86_64-darwin" 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 buildPackages.stdenv.mkDerivation { @@ -147,21 +101,24 @@ stdenv.mkDerivation { inherit cc shell libc_bin libc_dev libc_lib binutils_bin coreutils_bin; gnugrep_bin = if nativeTools then "" else gnugrep; + binPrefix = prefix; + inherit infixSalt; + outputs = [ "out" "man" ]; passthru = { inherit libc nativeTools nativeLibc nativePrefix isGNU isClang default_cxx_stdlib_compile - prefix infixSalt infixSalt_ _infixSalt; + prefix; 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"))) + (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"))) + (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)})) + (setenv "NIX_${infixSalt}_LDFLAGS" (concat (getenv "NIX_${infixSalt}_LDFLAGS") " -L" arg "/lib64")))) '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) ''; }; @@ -178,39 +135,39 @@ stdenv.mkDerivation { } '' - # TODO(@Ericson2314): Unify logic next hash break - + optionalString (libc != null) (if (targetPlatform.isDarwin) then '' - echo $dynamicLinker > $out/nix-support/dynamic-linker + + optionalString (libc != null) ('' + if [[ -z ''${dynamicLinker+x} ]]; then + echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2 + dynamicLinker="${libc_lib}/lib/ld*.so.?" + fi - echo "export LD_DYLD_PATH=\"$dynamicLinker\"" >> $out/nix-support/setup-hook - '' else if dynamicLinker != null then '' - dynamicLinker="${libc_lib}/lib/$dynamicLinker" - echo $dynamicLinker > $out/nix-support/dynamic-linker + # Expand globs to fill array of options + dynamicLinker=($dynamicLinker) - 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 + 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 - # 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). - echo "-dynamic-linker" $dynamicLinker > $out/nix-support/libc-ldflags-before - '' else '' - dynamicLinker=`eval 'echo $libc/lib/ld*.so.?'` 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 - ldflagsBefore="-dynamic-linker $dlinker" + 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). - echo "$ldflagsBefore" > $out/nix-support/libc-ldflags-before + printWords "''${ldflagsBefore[@]}" > $out/nix-support/libc-ldflags-before '') + optionalString (libc != null) '' @@ -278,17 +235,17 @@ 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). - echo ${cc} ${binutils_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages - echo ${cc.man or ""} > $man/nix-support/propagated-user-env-packages + 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 - echo ${toString extraPackages} > $out/nix-support/propagated-native-build-inputs + printWords ${toString extraPackages} > $out/nix-support/propagated-native-build-inputs '' + optionalString (targetPlatform.isSunOS && nativePrefix != "") '' # Solaris needs an additional ld wrapper. ldPath="${nativePrefix}/bin" exec="$ldPath/${prefix}ld" - wrap ld-solaris ${preWrap ./ld-solaris-wrapper.sh} + wrap ld-solaris ${./ld-solaris-wrapper.sh} '') + '' @@ -299,64 +256,75 @@ stdenv.mkDerivation { ln -s $ldPath/${prefix}as $out/bin/${prefix}as fi - wrap ${prefix}ld ${preWrap ./ld-wrapper.sh} ''${ld:-$ldPath/${prefix}ld} + '' + (if !useMacosReexportHack then '' + wrap ${prefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${prefix}ld} + '' else '' + ldInner="${prefix}ld-reexport-delegate" + wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${prefix}ld} + wrap "${prefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner" + unset ldInner + '') + '' if [ -e ${binutils_bin}/bin/${prefix}ld.gold ]; then - wrap ${prefix}ld.gold ${preWrap ./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.gold + wrap ${prefix}ld.gold ${./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.gold fi if [ -e ${binutils_bin}/bin/ld.bfd ]; then - wrap ${prefix}ld.bfd ${preWrap ./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.bfd + wrap ${prefix}ld.bfd ${./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.bfd fi - export real_cc=${prefix}cc - export real_cxx=${prefix}c++ + # We export environment variables pointing to the wrapped nonstandard + # cmds, lest some lousy configure script use those to guess compiler + # version. + export named_cc=${prefix}cc + export named_cxx=${prefix}c++ + export default_cxx_stdlib_compile="${default_cxx_stdlib_compile}" if [ -e $ccPath/${prefix}gcc ]; then - wrap ${prefix}gcc ${preWrap ./cc-wrapper.sh} $ccPath/${prefix}gcc + wrap ${prefix}gcc ${./cc-wrapper.sh} $ccPath/${prefix}gcc ln -s ${prefix}gcc $out/bin/${prefix}cc - export real_cc=${prefix}gcc - export real_cxx=${prefix}g++ + export named_cc=${prefix}gcc + export named_cxx=${prefix}g++ elif [ -e $ccPath/clang ]; then - wrap ${prefix}clang ${preWrap ./cc-wrapper.sh} $ccPath/clang + wrap ${prefix}clang ${./cc-wrapper.sh} $ccPath/clang ln -s ${prefix}clang $out/bin/${prefix}cc - export real_cc=clang - export real_cxx=clang++ + export named_cc=${prefix}clang + export named_cxx=${prefix}clang++ fi if [ -e $ccPath/${prefix}g++ ]; then - wrap ${prefix}g++ ${preWrap ./cc-wrapper.sh} $ccPath/${prefix}g++ + wrap ${prefix}g++ ${./cc-wrapper.sh} $ccPath/${prefix}g++ ln -s ${prefix}g++ $out/bin/${prefix}c++ elif [ -e $ccPath/clang++ ]; then - wrap ${prefix}clang++ ${preWrap ./cc-wrapper.sh} $ccPath/clang++ + wrap ${prefix}clang++ ${./cc-wrapper.sh} $ccPath/clang++ ln -s ${prefix}clang++ $out/bin/${prefix}c++ fi if [ -e $ccPath/cpp ]; then - wrap ${prefix}cpp ${preWrap ./cc-wrapper.sh} $ccPath/cpp + wrap ${prefix}cpp ${./cc-wrapper.sh} $ccPath/cpp fi '' + optionalString cc.langFortran or false '' - wrap ${prefix}gfortran ${preWrap ./cc-wrapper.sh} $ccPath/${prefix}gfortran + wrap ${prefix}gfortran ${./cc-wrapper.sh} $ccPath/${prefix}gfortran ln -sv ${prefix}gfortran $out/bin/${prefix}g77 ln -sv ${prefix}gfortran $out/bin/${prefix}f77 '' + optionalString cc.langJava or false '' - wrap ${prefix}gcj ${preWrap ./cc-wrapper.sh} $ccPath/${prefix}gcj + wrap ${prefix}gcj ${./cc-wrapper.sh} $ccPath/${prefix}gcj '' + optionalString cc.langGo or false '' - wrap ${prefix}gccgo ${preWrap ./cc-wrapper.sh} $ccPath/${prefix}gccgo + wrap ${prefix}gccgo ${./cc-wrapper.sh} $ccPath/${prefix}gccgo '' + optionalString cc.langAda or false '' - wrap ${prefix}gnatgcc ${preWrap ./cc-wrapper.sh} $ccPath/${prefix}gnatgcc - wrap ${prefix}gnatmake ${preWrap ./gnat-wrapper.sh} $ccPath/${prefix}gnatmake - wrap ${prefix}gnatbind ${preWrap ./gnat-wrapper.sh} $ccPath/${prefix}gnatbind - wrap ${prefix}gnatlink ${preWrap ./gnatlink-wrapper.sh} $ccPath/${prefix}gnatlink + wrap ${prefix}gnatgcc ${./cc-wrapper.sh} $ccPath/${prefix}gnatgcc + wrap ${prefix}gnatmake ${./gnat-wrapper.sh} $ccPath/${prefix}gnatmake + wrap ${prefix}gnatbind ${./gnat-wrapper.sh} $ccPath/${prefix}gnatbind + wrap ${prefix}gnatlink ${./gnatlink-wrapper.sh} $ccPath/${prefix}gnatlink '' + optionalString cc.langVhdl or false '' @@ -364,7 +332,7 @@ stdenv.mkDerivation { '' + '' - substituteAll ${preWrap ./setup-hook.sh} $out/nix-support/setup-hook.tmp + substituteAll ${./setup-hook.sh} $out/nix-support/setup-hook.tmp cat $out/nix-support/setup-hook.tmp >> $out/nix-support/setup-hook rm $out/nix-support/setup-hook.tmp @@ -383,9 +351,9 @@ stdenv.mkDerivation { '' + '' - substituteAll ${preWrap ./add-flags.sh} $out/nix-support/add-flags.sh - substituteAll ${preWrap ./add-hardening.sh} $out/nix-support/add-hardening.sh - substituteAll ${preWrap ./utils.sh} $out/nix-support/utils.sh + substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh + substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh + substituteAll ${./utils.sh} $out/nix-support/utils.sh '' + extraBuildCommands; @@ -403,5 +371,7 @@ 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 0d74527dd8ad..1a09f4841098 100644 --- a/pkgs/build-support/cc-wrapper/gnat-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/gnat-wrapper.sh @@ -1,15 +1,24 @@ -#! @shell@ -e +#! @shell@ +set -eu -o pipefail +shopt -s nullglob + +# N.B. Gnat is not used during bootstrapping, so we don't need to +# worry about the old bash empty array `set -u` workarounds. + path_backup="$PATH" + +# phase separation makes this look useless +# shellcheck disable=SC2157 if [ -n "@coreutils_bin@" ]; then - PATH="@coreutils_bin@/bin" + PATH="@coreutils_bin@/bin" fi -if [ -n "$NIX_GNAT_WRAPPER_START_HOOK" ]; then - source "$NIX_GNAT_WRAPPER_START_HOOK" +if [ -z "${NIX_@infixSalt@_GNAT_WRAPPER_FLAGS_SET:-}" ]; then + source @out@/nix-support/add-flags.sh fi -if [ -z "$NIX_GNAT_WRAPPER_FLAGS_SET" ]; then - source @out@/nix-support/add-flags.sh +if [ -n "$NIX_@infixSalt@_GNAT_WRAPPER_START_HOOK" ]; then + source "$NIX_@infixSalt@_GNAT_WRAPPER_START_HOOK" fi source @out@/nix-support/utils.sh @@ -18,7 +27,6 @@ source @out@/nix-support/utils.sh # Figure out if linker flags should be passed. GCC prints annoying # warnings when they are not needed. dontLink=0 -getVersion=0 nonFlagArgs=0 for i in "$@"; do @@ -30,7 +38,7 @@ for i in "$@"; do nonFlagArgs=1 elif [ "$i" = -m32 ]; then if [ -e @out@/nix-support/dynamic-linker-m32 ]; then - NIX_LDFLAGS="$NIX_LDFLAGS -dynamic-linker $(cat @out@/nix-support/dynamic-linker-m32)" + NIX_@infixSalt@_LDFLAGS+=" -dynamic-linker $(< @out@/nix-support/dynamic-linker-m32)" fi fi done @@ -47,37 +55,33 @@ fi # Optionally filter out paths not refering to the store. params=("$@") -if [ "$NIX_ENFORCE_PURITY" = 1 -a -n "$NIX_STORE" ]; then +if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then rest=() - n=0 - while [ $n -lt ${#params[*]} ]; do - p=${params[n]} - p2=${params[$((n+1))]} + for p in "${params[@]}"; do if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then - skip $p + skip "${p:2}" elif [ "${p:0:3}" = -I/ ] && badPath "${p:2}"; then - skip $p + skip "${p:2}" elif [ "${p:0:4}" = -aI/ ] && badPath "${p:3}"; then - skip $p + skip "${p:2}" elif [ "${p:0:4}" = -aO/ ] && badPath "${p:3}"; then - skip $p + skip "${p:2}" else rest+=("$p") fi - n=$((n + 1)) done params=("${rest[@]}") fi # Clear march/mtune=native -- they bring impurity. -if [ "$NIX_ENFORCE_NO_NATIVE" = 1 ]; then +if [ "$NIX_@infixSalt@_ENFORCE_NO_NATIVE" = 1 ]; then rest=() - for i in "${params[@]}"; do - if [[ "$i" = -m*=native ]]; then - skip $i + for p in "${params[@]}"; do + if [[ "$p" = -m*=native ]]; then + skip "$p" else - rest+=("$i") + rest+=("$p") fi done params=("${rest[@]}") @@ -85,38 +89,42 @@ fi # Add the flags for the GNAT compiler proper. -extraAfter=($NIX_GNATFLAGS_COMPILE) +extraAfter=($NIX_@infixSalt@_GNATFLAGS_COMPILE) extraBefore=() -if [ "`basename $0`x" = "gnatmakex" ]; then - extraBefore=("--GNATBIND=@out@/bin/gnatbind --GNATLINK=@out@/bin/gnatlink ") +if [ "$(basename "$0")x" = "gnatmakex" ]; then + extraBefore=("--GNATBIND=@out@/bin/gnatbind" "--GNATLINK=@out@/bin/gnatlink ") fi -# Add the flags that should be passed to the linker (and prevent -# `ld-wrapper' from adding NIX_LDFLAGS again). -#for i in $NIX_LDFLAGS_BEFORE; do -# extraBefore=(${extraBefore[@]} "-largs $i") -#done +#if [ "$dontLink" != 1 ]; then +# # Add the flags that should be passed to the linker (and prevent +# # `ld-wrapper' from adding NIX_@infixSalt@_LDFLAGS again). +# for i in $NIX_@infixSalt@_LDFLAGS_BEFORE; do +# extraBefore+=("-largs" "$i") +# done +# for i in $NIX_@infixSalt@_LDFLAGS; do +# if [ "${i:0:3}" = -L/ ]; then +# extraAfter+=("$i") +# else +# extraAfter+=("-largs" "$i") +# fi +# done +# export NIX_@infixSalt@_LDFLAGS_SET=1 +#fi # Optionally print debug info. -if [ -n "$NIX_DEBUG" ]; then - echo "original flags to @prog@:" >&2 - for i in "${params[@]}"; do - echo " $i" >&2 - done - echo "extraBefore flags to @prog@:" >&2 - for i in ${extraBefore[@]}; do - echo " $i" >&2 - done - echo "extraAfter flags to @prog@:" >&2 - for i in ${extraAfter[@]}; do - echo " $i" >&2 - done +if [ -n "${NIX_DEBUG:-}" ]; then + echo "extra flags before to @prog@:" >&2 + printf " %q\n" "${extraBefore[@]}" >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" "${params[@]}" >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" "${extraAfter[@]}" >&2 fi -if [ -n "$NIX_GNAT_WRAPPER_EXEC_HOOK" ]; then - source "$NIX_GNAT_WRAPPER_EXEC_HOOK" +if [ -n "$NIX_@infixSalt@_GNAT_WRAPPER_EXEC_HOOK" ]; then + source "$NIX_@infixSalt@_GNAT_WRAPPER_EXEC_HOOK" fi PATH="$path_backup" -exec @prog@ ${extraBefore[@]} "${params[@]}" ${extraAfter[@]} +exec @prog@ "${extraBefore[@]}" "${params[@]}" "${extraAfter[@]}" diff --git a/pkgs/build-support/cc-wrapper/gnatlink-wrapper.sh b/pkgs/build-support/cc-wrapper/gnatlink-wrapper.sh index c9958dbbb413..ee973d3270f9 100644 --- a/pkgs/build-support/cc-wrapper/gnatlink-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/gnatlink-wrapper.sh @@ -1,33 +1,40 @@ -#! @shell@ -e +#! @shell@ +set -eu -o pipefail +shopt -s nullglob + +# N.B. Gnat is not used during bootstrapping, so we don't need to +# worry about the old bash empty array `set -u` workarounds. # Add the flags for the GNAT compiler proper. -extraAfter="--GCC=@out@/bin/gcc" +extraAfter=("--GCC=@out@/bin/gcc") extraBefore=() -# Add the flags that should be passed to the linker (and prevent -# `ld-wrapper' from adding NIX_LDFLAGS again). -#for i in $NIX_LDFLAGS_BEFORE; do -# extraBefore=(${extraBefore[@]} "-largs $i") +## Add the flags that should be passed to the linker (and prevent +## `ld-wrapper' from adding NIX_@infixSalt@_LDFLAGS again). +#for i in $NIX_@infixSalt@_LDFLAGS_BEFORE; do +# extraBefore+=("-largs" "$i") +#done +#for i in $NIX_@infixSalt@_LDFLAGS; do +# if [ "${i:0:3}" = -L/ ]; then +# extraAfter+=("$i") +# else +# extraAfter+=("-largs" "$i") +# fi #done +#export NIX_@infixSalt@_LDFLAGS_SET=1 # Optionally print debug info. -if [ -n "$NIX_DEBUG" ]; then - echo "original flags to @prog@:" >&2 - for i in "$@"; do - echo " $i" >&2 - done - echo "extraBefore flags to @prog@:" >&2 - for i in ${extraBefore[@]}; do - echo " $i" >&2 - done - echo "extraAfter flags to @prog@:" >&2 - for i in ${extraAfter[@]}; do - echo " $i" >&2 - done +if [ -n "${NIX_DEBUG:-}" ]; then + echo "extra flags before to @prog@:" >&2 + printf " %q\n" "${extraBefore[@]}" >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" "$@" >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" "${extraAfter[@]}" >&2 fi -if [ -n "$NIX_GNAT_WRAPPER_EXEC_HOOK" ]; then - source "$NIX_GNAT_WRAPPER_EXEC_HOOK" +if [ -n "$NIX_@infixSalt@_GNAT_WRAPPER_EXEC_HOOK" ]; then + source "$NIX_@infixSalt@_GNAT_WRAPPER_EXEC_HOOK" fi -exec @prog@ ${extraBefore[@]} "$@" ${extraAfter[@]} +exec @prog@ "${extraBefore[@]}" "$@" "${extraAfter[@]}" diff --git a/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh b/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh index 263ea5408e9a..72c999ff8bc8 100755 --- a/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/ld-solaris-wrapper.sh @@ -1,40 +1,25 @@ #!@shell@ +set -eu -o pipefail +shopt -s nullglob -set -e -set -u - +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. -cmd="@ld@ -z ignore" - -args=("$@"); +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 -i=0; -while [[ $i -lt $# ]]; do +while (( $# )); do case "${args[$i]}" in - -L) cmd="$cmd ${args[$i]} ${args[($i+1)]}"; i=($i+1); ;; - -L*) cmd="$cmd ${args[$i]}" ;; - *) ;; + -L) argsBefore+=("$1" "$2"); shift ;; + -L?*) argsBefore+=("$1") ;; + *) argsAfter+=("$1") ;; esac - i=($i+1); -done - -i=0; -while [[ $i -lt $# ]]; do - case "${args[$i]}" in - -L) i=($i+1); ;; - -L*) ;; - *) cmd="$cmd ${args[$i]}" ;; - esac - i=($i+1); + shift done # Trace: set -x -exec $cmd - -exit 0 +exec "@ld@" "${argsBefore[@]}" "${argsAfter[@]}" diff --git a/pkgs/build-support/cc-wrapper/ld-wrapper.sh b/pkgs/build-support/cc-wrapper/ld-wrapper.sh index 056cfa920535..d0a1d5a0ddb7 100644 --- a/pkgs/build-support/cc-wrapper/ld-wrapper.sh +++ b/pkgs/build-support/cc-wrapper/ld-wrapper.sh @@ -1,15 +1,21 @@ -#! @shell@ -e +#! @shell@ +set -eu -o pipefail +shopt -s nullglob + path_backup="$PATH" + +# phase separation makes this look useless +# shellcheck disable=SC2157 if [ -n "@coreutils_bin@" ]; then - PATH="@coreutils_bin@/bin" + PATH="@coreutils_bin@/bin" fi -if [ -n "$NIX_LD_WRAPPER_START_HOOK" ]; then - source "$NIX_LD_WRAPPER_START_HOOK" +if [ -z "${NIX_CC_WRAPPER_@infixSalt@_FLAGS_SET:-}" ]; then + source @out@/nix-support/add-flags.sh fi -if [ -z "$NIX_CC_WRAPPER_FLAGS_SET" ]; then - source @out@/nix-support/add-flags.sh +if [ -n "$NIX_LD_WRAPPER_@infixSalt@_START_HOOK" ]; then + source "$NIX_LD_WRAPPER_@infixSalt@_START_HOOK" fi source @out@/nix-support/utils.sh @@ -17,21 +23,22 @@ source @out@/nix-support/utils.sh # Optionally filter out paths not refering to the store. expandResponseParams "$@" -if [ "$NIX_ENFORCE_PURITY" = 1 -a -n "$NIX_STORE" \ - -a \( -z "$NIX_IGNORE_LD_THROUGH_GCC" -o -z "$NIX_LDFLAGS_SET" \) ]; then +if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}" + && ( -z "$NIX_@infixSalt@_IGNORE_LD_THROUGH_GCC" || -z "${NIX_@infixSalt@_LDFLAGS_SET:-}" ) ]]; then rest=() - n=0 - while [ $n -lt ${#params[*]} ]; do + nParams=${#params[@]} + declare -i n=0 + while [ "$n" -lt "$nParams" ]; do p=${params[n]} - p2=${params[$((n+1))]} + p2=${params[n+1]:-} # handle `p` being last one if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then - skip $p + skip "${p:2}" elif [ "$p" = -L ] && badPath "$p2"; then - n=$((n + 1)); skip $p2 + n+=1; skip "$p2" elif [ "$p" = -rpath ] && badPath "$p2"; then - n=$((n + 1)); skip $p2 + n+=1; skip "$p2" elif [ "$p" = -dynamic-linker ] && badPath "$p2"; then - n=$((n + 1)); skip $p2 + n+=1; skip "$p2" elif [ "${p:0:1}" = / ] && badPath "$p"; then # We cannot skip this; barf. echo "impure path \`$p' used in link" >&2 @@ -40,149 +47,128 @@ if [ "$NIX_ENFORCE_PURITY" = 1 -a -n "$NIX_STORE" \ # Our ld is not built with sysroot support (Can we fix that?) : else - rest=("${rest[@]}" "$p") + rest+=("$p") fi - n=$((n + 1)) + n+=1 done params=("${rest[@]}") fi -LD=@prog@ source @out@/nix-support/add-hardening.sh -extra=(${hardeningLDFlags[@]}) +extraAfter=("${hardeningLDFlags[@]}") extraBefore=() -if [ -z "$NIX_LDFLAGS_SET" ]; then - extra+=($NIX_LDFLAGS) - extraBefore+=($NIX_LDFLAGS_BEFORE) +if [ -z "${NIX_@infixSalt@_LDFLAGS_SET:-}" ]; then + extraAfter+=($NIX_@infixSalt@_LDFLAGS) + extraBefore+=($NIX_@infixSalt@_LDFLAGS_BEFORE) fi -extra+=($NIX_LDFLAGS_AFTER $NIX_LDFLAGS_HARDEN) - - -# Add all used dynamic libraries to the rpath. -if [ "$NIX_DONT_SET_RPATH" != 1 ]; then - - libPath="" - addToLibPath() { - local path="$1" - if [ "${path:0:1}" != / ]; then return 0; fi - case "$path" in - *..*|*./*|*/.*|*//*) - local path2 - if path2=$(readlink -f "$path"); then - path="$path2" - fi +extraAfter+=($NIX_@infixSalt@_LDFLAGS_AFTER $NIX_@infixSalt@_LDFLAGS_HARDEN) + +declare -a libDirs +declare -A libs +relocatable= + +# Find all -L... switches for rpath, and relocatable flags for build id. +if [ "$NIX_@infixSalt@_DONT_SET_RPATH" != 1 ] || [ "$NIX_@infixSalt@_SET_BUILD_ID" = 1 ]; then + prev= + # Old bash thinks empty arrays are undefined, ugh, so temporarily disable + # `set -u`. + set +u + for p in "${extraBefore[@]}" "${params[@]}" "${extraAfter[@]}"; do + set -u + case "$prev" in + -L) + libDirs+=("$p") + ;; + -l) + libs["lib${p}.so"]=1 + ;; + -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 - case $libPath in - *\ $path\ *) return 0 ;; - esac - libPath="$libPath $path " - } - - addToRPath() { - # 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. - if [ "${1:0:${#NIX_STORE}}" != "$NIX_STORE" ]; then return 0; fi - case $rpath in - *\ $1\ *) return 0 ;; - esac - rpath="$rpath $1 " - } - - libs="" - addToLibs() { - libs="$libs $1" - } - - rpath="" - - # First, find all -L... switches. - allParams=("${params[@]}" ${extra[@]}) - n=0 - while [ $n -lt ${#allParams[*]} ]; do - p=${allParams[n]} - p2=${allParams[$((n+1))]} - if [ "${p:0:3}" = -L/ ]; then - addToLibPath ${p:2} - elif [ "$p" = -L ]; then - addToLibPath ${p2} - n=$((n + 1)) - elif [ "$p" = -l ]; then - addToLibs ${p2} - n=$((n + 1)) - elif [ "${p:0:2}" = -l ]; then - addToLibs ${p:2} - elif [ "$p" = -dynamic-linker ]; then - # Ignore the dynamic linker argument, or it - # will get into the next 'elif'. We don't want - # the dynamic linker path rpath to go always first. - n=$((n + 1)) - elif [[ "$p" =~ ^[^-].*\.so($|\.) ]]; then - # This is a direct reference to a shared library, so add - # its directory to the rpath. - path="$(dirname "$p")"; - addToRPath "${path}" - fi - n=$((n + 1)) + prev="$p" done +fi + - # Second, for each directory in the library search path (-L...), +# Add all used dynamic libraries to the rpath. +if [ "$NIX_@infixSalt@_DONT_SET_RPATH" != 1 ]; 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. - - for i in $libPath; do - for j in $libs; do - if [ -f "$i/lib$j.so" ]; then - addToRPath $i + declare -A rpaths + for dir in "${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 - - - # Finally, add `-rpath' switches. - for i in $rpath; do - extra+=(-rpath $i) - done fi # Only add --build-id if this is a final link. FIXME: should build gcc # with --enable-linker-build-id instead? -if [ "$NIX_SET_BUILD_ID" = 1 ]; then - for p in "${params[@]}"; do - if [ "$p" = "-r" -o "$p" = "--relocatable" -o "$p" = "-i" ]; then - relocatable=1 - break - fi - done - if [ -z "$relocatable" ]; then - extra+=(--build-id) - fi +if [ "$NIX_@infixSalt@_SET_BUILD_ID" = 1 ] && [ ! "$relocatable" ]; then + extraAfter+=(--build-id) fi # Optionally print debug info. -if [ -n "$NIX_DEBUG" ]; then - echo "original flags to @prog@:" >&2 - for i in "${params[@]}"; do - echo " $i" >&2 - done - echo "extra flags to @prog@:" >&2 - for i in ${extra[@]}; do - echo " $i" >&2 - done +if [ -n "${NIX_DEBUG:-}" ]; then + set +u # Old bash workaround, see above. + echo "extra flags before to @prog@:" >&2 + printf " %q\n" "${extraBefore[@]}" >&2 + echo "original flags to @prog@:" >&2 + printf " %q\n" "${params[@]}" >&2 + echo "extra flags after to @prog@:" >&2 + printf " %q\n" "${extraAfter[@]}" >&2 + set -u fi -if [ -n "$NIX_LD_WRAPPER_EXEC_HOOK" ]; then - source "$NIX_LD_WRAPPER_EXEC_HOOK" +if [ -n "$NIX_LD_WRAPPER_@infixSalt@_EXEC_HOOK" ]; then + source "$NIX_LD_WRAPPER_@infixSalt@_EXEC_HOOK" fi PATH="$path_backup" -exec @prog@ ${extraBefore[@]} "${params[@]}" ${extra[@]} +set +u # Old bash workaround, see above. +exec @prog@ "${extraBefore[@]}" "${params[@]}" "${extraAfter[@]}" diff --git a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash new file mode 100644 index 000000000000..b7aa7ea5c092 --- /dev/null +++ b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash @@ -0,0 +1,106 @@ +#! @shell@ + +set -eu -o pipefail + +path_backup="$PATH" +if [ -n "@coreutils_bin@" ]; then + PATH="@coreutils_bin@/bin" +fi + +declare -r recurThreshold=300 + +declare overflowCount=0 +for ((n=0; n < $#; ++n)); do + case "${!n}" in + -l*) let overflowCount+=1 ;; + -reexport-l*) let overflowCount+=1 ;; + *) ;; + esac +done + +declare -a allArgs=() + +if (( "$overflowCount" <= "$recurThreshold" )); then + allArgs=("$@") +else + declare -a childrenLookup=() childrenLink=() + + while (( $# )); do + case "$1" in + -L/*) + childrenLookup+=("$1") + allArgs+=("$1") + ;; + -L) + echo "cctools LD does not support '-L foo' or '-l foo'" >&2 + exit 1 + ;; + -l) + echo "cctools LD does not support '-L foo' or '-l foo'" >&2 + exit 1 + ;; + -lazy_library | -lazy_framework | -lto_library) + # We aren't linking any "azy_library", "to_library", etc. + allArgs+=("$1") + ;; + -lazy-l | -weak-l) allArgs+=("$1") ;; + # We can't so easily prevent header issues from these. + -lSystem) allArgs+=("$1") ;; + # Special case as indirection seems like a bad idea for something + # so fundamental. Can be removed for simplicity. + -l?* | -reexport-l?*) childrenLink+=("$1") ;; + *) allArgs+=("$1") ;; + esac + + shift + done + + declare n=0 + while (( $n < "${#childrenLink[@]}" )); do + if [[ "${childrenLink[n]}" = -l* ]]; then + childrenLink[n]="-reexport${childrenLink[n]}" + fi + let ++n + done + unset n + + declare -r outputNameLibless=$(basename $( \ + if [[ -z "${outputName:+isUndefined}" ]]; then + echo unnamed + elif [[ "${outputName:0:3}" = lib ]]; then + echo "${outputName:3}" + else + echo "${outputName}" + fi)) + declare -ra children=("$outputNameLibless-reexport-delegate-0" \ + "$outputNameLibless-reexport-delegate-1") + + mkdir -p "$out/lib" + + PATH="$PATH:@out@/bin" + + symbolBloatObject=$outputNameLibless-symbol-hack.o + if [[ ! -e $symbolBloatObject ]]; then + printf '.private_extern _______child_hack_foo\nchild_hack_foo:\n' \ + | @binPrefix@as -- -o $symbolBloatObject + fi + + # first half of libs + @binPrefix@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" \ + "${childrenLookup[@]}" "$symbolBloatObject" \ + "${childrenLink[@]:0:$((${#childrenLink[@]} / 2 ))}" + + # second half of libs + @binPrefix@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" \ + "${childrenLookup[@]}" "$symbolBloatObject" \ + "${childrenLink[@]:$((${#childrenLink[@]} / 2 ))}" + + allArgs+=("-L$out/lib" "-l${children[0]}" "-l${children[1]}") +fi + +PATH="$path_backup" +exec @prog@ "${allArgs[@]}" diff --git a/pkgs/build-support/cc-wrapper/setup-hook.sh b/pkgs/build-support/cc-wrapper/setup-hook.sh index f4f7ab181d3e..c6abd6281d26 100644 --- a/pkgs/build-support/cc-wrapper/setup-hook.sh +++ b/pkgs/build-support/cc-wrapper/setup-hook.sh @@ -1,47 +1,153 @@ -export NIX_CC=@out@ +# CC Wrapper hygiene +# +# For at least cross compilation, we need to depend on multiple cc-wrappers at +# once---specifically up to one per sort of dependency. This follows from having +# different tools targeting different platforms, and different flags for those +# tools. For example: +# +# # Flags for compiling (whether or not linking) C code for the... +# NIX_BUILD_CFLAGS_COMPILE # ...build platform +# NIX_CFLAGS_COMPILE # ...host platform +# NIX_TARGET_CFLAGS_COMPILE # ...target platform +# +# Notice that these platforms are the 3 *relative* to the package using +# cc-wrapper, not absolute like `x86_64-pc-linux-gnu`. +# +# The simplest solution would be to have separate cc-wrappers per (3 intended +# use-cases * n absolute concrete platforms). For the use-case axis, we would +# @-splice in 'BUILD_' '' 'TARGET_' to use the write environment variables when +# building the cc-wrapper, and likewise prefix the binaries' names so they didn't +# clobber each other on the PATH. But the need for 3x cc-wrappers, along with +# non-standard name prefixes, is annoying and liable to break packages' build +# systems. +# +# Instead, we opt to have just one cc-wrapper per absolute platform. Matching +# convention, the binaries' names can just be prefixed with their target +# platform. On the other hand, that means packages will depend on not just +# multiple cc-wrappers, but the exact same cc-wrapper derivation multiple ways. +# That means the exact same cc-wrapper derivation must be able to avoid +# conflicting with itself, despite the fact that `setup-hook.sh`, the `addCvars` +# function, and `add-flags.sh` are all communicating with each other with +# environment variables. Yuck. +# +# The basic strategy is: +# +# - Everyone exclusively *adds information* to relative-platform-specific +# environment variables, like `NIX_TARGET_CFLAGS_COMPILE`, to communicate +# with the wrapped binaries. +# +# - The wrapped binaries will exclusively *read* cc-wrapper-derivation-specific +# environment variables distinguished with with `infixSalt`, like +# `NIX_@infixSalt@_CFLAGS_COMPILE`. +# +# - `add-flags`, beyond its old task of reading extra flags stuck inside the +# cc-wrapper derivation, will convert the relative-platform-specific +# variables to cc-wrapper-derivation-specific variables. This conversion is +# the only time all but one of the cc-wrapper-derivation-specific variables +# are set. +# +# This ensures the flow of information is exclusive from +# relative-platform-specific variables to cc-wrapper-derivation-specific +# variables. This allows us to support the general case of a many--many relation +# between relative platforms and cc-wrapper derivations. +# +# For more details, read the individual files where the mechanisms used to +# accomplish this will be individually documented. -addCVars () { - if [ -d $1/include ]; then - export NIX_CFLAGS_COMPILE+=" ${ccIncludeFlag:--isystem} $1/include" + +# It's fine that any other cc-wrapper will redefine this. Bash functions close +# over no state, and there's no @-substitutions within, so any redefined +# function is guaranteed to be exactly the same. +ccWrapper_addCVars () { + # The `depOffset` describes how the platforms of the dependencies are slid + # relative to the depending package. It is brought into scope of the + # environment hook defined as the role of the dependency being applied. + case $depOffset in + -1) local role='BUILD_' ;; + 0) local role='' ;; + 1) local role='TARGET_' ;; + *) echo "cc-wrapper: Error: Cannot be used with $depOffset-offset deps, " >2; + return 1 ;; + esac + + if [[ -d "$1/include" ]]; then + export NIX_${role}CFLAGS_COMPILE+=" ${ccIncludeFlag:--isystem} $1/include" fi - if [ -d $1/lib64 -a ! -L $1/lib64 ]; then - export NIX_LDFLAGS+=" -L$1/lib64" + if [[ -d "$1/lib64" && ! -L "$1/lib64" ]]; then + export NIX_${role}LDFLAGS+=" -L$1/lib64" fi - if [ -d $1/lib ]; then - export NIX_LDFLAGS+=" -L$1/lib" + if [[ -d "$1/lib" ]]; then + export NIX_${role}LDFLAGS+=" -L$1/lib" fi - if test -d $1/Library/Frameworks; then - export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -F$1/Library/Frameworks" + if [[ -d "$1/Library/Frameworks" ]]; then + export NIX_${role}CFLAGS_COMPILE+=" -F$1/Library/Frameworks" fi } -envHooks+=(addCVars) +# Since the same cc-wrapper derivation can be depend on in multiple ways, we +# need to accumulate *each* role (i.e. target platform relative the depending +# derivation) in which the cc-wrapper derivation is used. +# `NIX_CC_WRAPPER_@infixSalt@_TARGET_*` tracks this (needs to be an exported env +# var so can't use fancier data structures). +# +# We also need to worry about what role is being added on *this* invocation of +# setup-hook, which `role` tracks. +if [ -n "${crossConfig:-}" ]; then + export NIX_CC_WRAPPER_@infixSalt@_TARGET_BUILD=1 + role="BUILD_" +else + export NIX_CC_WRAPPER_@infixSalt@_TARGET_HOST=1 + role="" +fi + +# Eventually the exact sort of env-hook we create will depend on the role. This +# is because based on what relative platform we are targeting, we use different +# dependencies. +envHooks+=(ccWrapper_addCVars) -# Note: these come *after* $out in the PATH (see setup.sh). +# Note 1: these come *after* $out in the PATH (see setup.sh). +# Note 2: phase separation makes this look useless to shellcheck. +# shellcheck disable=SC2157 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 fi +# shellcheck disable=SC2157 if [ -n "@coreutils_bin@" ]; then addToSearchPath _PATH @coreutils_bin@/bin fi -if [ -z "$crossConfig" ]; then - export CC=@real_cc@ - export CXX=@real_cxx@ -else - export BUILD_CC=@real_cc@ - export BUILD_CXX=@real_cxx@ -fi +# Export tool environment variables so various build systems use the right ones. + +export NIX_${role}CC=@out@ + +export ${role}CC=@named_cc@ +export ${role}CXX=@named_cxx@ + +for CMD in \ + cpp \ + ar as nm objcopy ranlib strip strings size ld windres +do + if + PATH=$_PATH type -p "@binPrefix@$CMD" > /dev/null + then + export "${role}$(echo "$CMD" | tr "[:lower:]" "[:upper:]")=@binPrefix@${CMD}"; + fi +done + +# No local scope in sourced file +unset role diff --git a/pkgs/build-support/cc-wrapper/utils.sh b/pkgs/build-support/cc-wrapper/utils.sh index 87e48da9c8d5..5a70c2d9ccf3 100644 --- a/pkgs/build-support/cc-wrapper/utils.sh +++ b/pkgs/build-support/cc-wrapper/utils.sh @@ -1,5 +1,5 @@ skip () { - if [ -n "$NIX_DEBUG" ]; then + if [ -n "${NIX_DEBUG:-}" ]; then echo "skipping impure path $1" >&2 fi } @@ -24,11 +24,15 @@ badPath() { } expandResponseParams() { - params=("$@") + declare -g params=("$@") local arg for arg in "$@"; do if [[ "$arg" == @* ]]; then + # phase separation makes this look useless + # shellcheck disable=SC2157 if [ -n "@expandResponseParams@" ]; then + # params is used by caller + #shellcheck disable=SC2034 readarray -d '' params < <("@expandResponseParams@" "$@") return 0 else diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index 506ef7837a2e..17d7f2da035c 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -6,6 +6,7 @@ findutils, go, jshon, + jq, lib, pkgs, pigz, @@ -408,9 +409,10 @@ rec { contents runAsRoot diskSize extraCommands; }; result = runCommand "docker-image-${baseName}.tar.gz" { - buildInputs = [ jshon pigz coreutils findutils ]; - imageName = name; - imageTag = tag; + buildInputs = [ jshon pigz coreutils findutils jq ]; + # Image name and tag must be lowercase + imageName = lib.toLower name; + imageTag = lib.toLower tag; inherit fromImage baseJson; layerClosure = writeReferencesToFile layer; passthru.buildArgs = args; @@ -434,6 +436,9 @@ rec { if [[ -n "$fromImage" ]]; then echo "Unpacking base image..." tar -C image -xpf "$fromImage" + # Do not import the base image configuration and manifest + chmod a+w image image/*.json + rm -f image/*.json if [[ -z "$fromImageName" ]]; then fromImageName=$(jshon -k < image/repositories|head -n1) @@ -492,6 +497,24 @@ rec { # Use the temp folder we've been working on to create a new image. mv temp image/$layerID + # Create image json and image manifest + imageJson=$(cat ${baseJson} | jq ". + {\"rootfs\": {\"diff_ids\": [], \"type\": \"layers\"}}") + manifestJson=$(jq -n "[{\"RepoTags\":[\"$imageName:$imageTag\"]}]") + currentID=$layerID + while [[ -n "$currentID" ]]; do + layerChecksum=$(sha256sum image/$currentID/layer.tar | cut -d ' ' -f1) + imageJson=$(echo "$imageJson" | jq ".history |= [{\"created\": \"${created}\"}] + .") + imageJson=$(echo "$imageJson" | jq ".rootfs.diff_ids |= [\"sha256:$layerChecksum\"] + .") + manifestJson=$(echo "$manifestJson" | jq ".[0].Layers |= [\"$currentID/layer.tar\"] + .") + + currentID=$(cat image/$currentID/json | (jshon -e parent -u 2>/dev/null || true)) + done + + imageJsonChecksum=$(echo "$imageJson" | sha256sum | cut -d ' ' -f1) + echo "$imageJson" > "image/$imageJsonChecksum.json" + manifestJson=$(echo "$manifestJson" | jq ".[0].Config = \"$imageJsonChecksum.json\"") + echo "$manifestJson" > image/manifest.json + # Store the json under the name image/repositories. jshon -n object \ -n object -s "$layerID" -i "$imageTag" \ @@ -501,7 +524,7 @@ rec { chmod -R a-w image echo "Cooking the image..." - tar -C image --mtime="@$SOURCE_DATE_EPOCH" --owner=0 --group=0 -c . | pigz -nT > $out + tar -C image --mtime="@$SOURCE_DATE_EPOCH" --owner=0 --group=0 --xform s:'./':: -c . | pigz -nT > $out echo "Finished." ''; diff --git a/pkgs/build-support/emacs/wrapper.nix b/pkgs/build-support/emacs/wrapper.nix index e41b1fd6a215..bd733f1b9baf 100644 --- a/pkgs/build-support/emacs/wrapper.nix +++ b/pkgs/build-support/emacs/wrapper.nix @@ -80,7 +80,8 @@ stdenv.mkDerivation { linkPath "$1" "share/emacs/site-lisp" "share/emacs/site-lisp" } - for pkg in $requires; do + # Iterate over the array of inputs (avoiding nix's own interpolation) + for pkg in "''${requires[@]}"; do linkEmacsPackage $pkg done diff --git a/pkgs/build-support/fetchbower/default.nix b/pkgs/build-support/fetchbower/default.nix index 835fbec6bf0e..dd0bac49cb6d 100644 --- a/pkgs/build-support/fetchbower/default.nix +++ b/pkgs/build-support/fetchbower/default.nix @@ -7,8 +7,10 @@ let ver = if builtins.length components == 1 then version else hash; in ver; + bowerName = name: lib.replaceStrings ["/"] ["-"] name; + fetchbower = name: version: target: outputHash: stdenv.mkDerivation { - name = "${name}-${bowerVersion version}"; + name = "${bowerName name}-${bowerVersion version}"; SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; buildCommand = '' fetch-bower --quiet --out=$PWD/out "${name}" "${target}" "${version}" diff --git a/pkgs/build-support/fetchpatch/default.nix b/pkgs/build-support/fetchpatch/default.nix index a6ddf132cd5b..a9bfac320fb8 100644 --- a/pkgs/build-support/fetchpatch/default.nix +++ b/pkgs/build-support/fetchpatch/default.nix @@ -5,7 +5,7 @@ # stripLen acts as the -p parameter when applying a patch. { lib, fetchurl, patchutils }: -{ stripLen ? 0, addPrefixes ? false, ... }@args: +{ stripLen ? 0, addPrefixes ? false, excludes ? [], ... }@args: fetchurl ({ postFetch = '' @@ -21,7 +21,10 @@ fetchurl ({ --addnewprefix=b/ \ ''} \ --clean "$out" > "$tmpfile" - mv "$tmpfile" "$out" + ${patchutils}/bin/filterdiff \ + -p1 \ + ${builtins.toString (builtins.map (x: "-x ${x}") excludes)} \ + "$tmpfile" > "$out" ${args.postFetch or ""} ''; -} // builtins.removeAttrs args ["stripLen" "addPrefixes"]) +} // builtins.removeAttrs args ["stripLen" "addPrefixes" "excludes"]) diff --git a/pkgs/build-support/fetchurl/boot.nix b/pkgs/build-support/fetchurl/boot.nix index 722fd2566ef3..bd71f93c5291 100644 --- a/pkgs/build-support/fetchurl/boot.nix +++ b/pkgs/build-support/fetchurl/boot.nix @@ -5,10 +5,11 @@ let mirrors = import ./mirrors.nix; in { url ? builtins.head urls , urls ? [] , sha256 +, name ? baseNameOf (toString url) }: import <nix/fetchurl.nix> { - inherit system sha256; + inherit system sha256 name; url = # Handle mirror:// URIs. Since <nix/fetchurl.nix> currently diff --git a/pkgs/build-support/fetchurl/builder.sh b/pkgs/build-support/fetchurl/builder.sh index c4fd18e46caf..7c2bdf260b4e 100644 --- a/pkgs/build-support/fetchurl/builder.sh +++ b/pkgs/build-support/fetchurl/builder.sh @@ -39,7 +39,6 @@ tryDownload() { curlexit=$?; fi done - stopNest } @@ -51,7 +50,6 @@ finish() { fi runHook postFetch - stopNest exit 0 } diff --git a/pkgs/build-support/gcc-wrapper-old/builder.sh b/pkgs/build-support/gcc-wrapper-old/builder.sh index a8e8a370ec0d..22e32814927e 100644 --- a/pkgs/build-support/gcc-wrapper-old/builder.sh +++ b/pkgs/build-support/gcc-wrapper-old/builder.sh @@ -211,5 +211,5 @@ cp -p $utils $out/nix-support/utils.sh # tools like gcov, the manpages, etc. as well (including for binutils # and Glibc). if test -z "$nativeTools"; then - echo $gcc $binutils $libc $libc_bin > $out/nix-support/propagated-user-env-packages + printWords $gcc $binutils $libc $libc_bin > $out/nix-support/propagated-user-env-packages fi diff --git a/pkgs/build-support/setup-hooks/die.sh b/pkgs/build-support/setup-hooks/die.sh new file mode 100644 index 000000000000..0db41e030f4c --- /dev/null +++ b/pkgs/build-support/setup-hooks/die.sh @@ -0,0 +1,21 @@ +# Exit with backtrace and error message +# +# Usage: die "Error message" +die() { + # Let us be a little sloppy with errors, because otherwise the final + # invocation of `caller` below will cause the script to exit. + set +e + + # Print our error message + printf "\nBuilder called die: %b\n" "$*" + printf "Backtrace:\n" + + # Print a backtrace. + local frame=0 + while caller $frame; do + ((frame++)); + done + printf "\n" + + exit 1 +} diff --git a/pkgs/build-support/setup-hooks/make-wrapper.sh b/pkgs/build-support/setup-hooks/make-wrapper.sh index eebde886a884..cde28fbbcaf1 100644 --- a/pkgs/build-support/setup-hooks/make-wrapper.sh +++ b/pkgs/build-support/setup-hooks/make-wrapper.sh @@ -1,3 +1,12 @@ +# Assert that FILE exists and is executable +# +# assertExecutable FILE +assertExecutable() { + local file="$1" + [[ -f "${file}" && -x "${file}" ]] || \ + die "Cannot wrap ${file} because it is not an executable file" +} + # construct an executable file that wraps the actual executable # makeWrapper EXECUTABLE ARGS @@ -24,6 +33,8 @@ makeWrapper() { local params varName value command separator n fileNames local argv0 flagsBefore flags + assertExecutable "${original}" + mkdir -p "$(dirname "$wrapper")" echo "#! $SHELL -e" > "$wrapper" @@ -32,26 +43,20 @@ makeWrapper() { for ((n = 2; n < ${#params[*]}; n += 1)); do p="${params[$n]}" - if test "$p" = "--set"; then + if [[ "$p" == "--set" ]]; then varName="${params[$((n + 1))]}" value="${params[$((n + 2))]}" n=$((n + 2)) echo "export $varName=\"$value\"" >> "$wrapper" - fi - - if test "$p" = "--unset"; then + elif [[ "$p" == "--unset" ]]; then varName="${params[$((n + 1))]}" n=$((n + 1)) echo "unset $varName" >> "$wrapper" - fi - - if test "$p" = "--run"; then + elif [[ "$p" == "--run" ]]; then command="${params[$((n + 1))]}" n=$((n + 1)) echo "$command" >> "$wrapper" - fi - - if test "$p" = "--suffix" -o "$p" = "--prefix"; then + elif [[ ("$p" == "--suffix") || ("$p" == "--prefix") ]]; then varName="${params[$((n + 1))]}" separator="${params[$((n + 2))]}" value="${params[$((n + 3))]}" @@ -63,9 +68,7 @@ makeWrapper() { echo "export $varName=$value\${$varName:+$separator}\$$varName" >> "$wrapper" fi fi - fi - - if test "$p" = "--suffix-each"; then + elif [[ "$p" == "--suffix-each" ]]; then varName="${params[$((n + 1))]}" separator="${params[$((n + 2))]}" values="${params[$((n + 3))]}" @@ -73,9 +76,7 @@ makeWrapper() { for value in $values; do echo "export $varName=\$$varName\${$varName:+$separator}$value" >> "$wrapper" done - fi - - if test "$p" = "--suffix-contents" -o "$p" = "--prefix-contents"; then + elif [[ ("$p" == "--suffix-contents") || ("$p" == "--prefix-contents") ]]; then varName="${params[$((n + 1))]}" separator="${params[$((n + 2))]}" fileNames="${params[$((n + 3))]}" @@ -87,17 +88,15 @@ makeWrapper() { echo "export $varName=$(cat "$fileName")\${$varName:+$separator}\$$varName" >> "$wrapper" fi done - fi - - if test "$p" = "--add-flags"; then + elif [[ "$p" == "--add-flags" ]]; then flags="${params[$((n + 1))]}" n=$((n + 1)) flagsBefore="$flagsBefore $flags" - fi - - if test "$p" = "--argv0"; then + elif [[ "$p" == "--argv0" ]]; then argv0="${params[$((n + 1))]}" n=$((n + 1)) + else + die "makeWrapper doesn't understand the arg $p" fi done @@ -131,6 +130,9 @@ filterExisting() { wrapProgram() { local prog="$1" local hidden + + assertExecutable "${prog}" + hidden="$(dirname "$prog")/.$(basename "$prog")"-wrapped while [ -e "$hidden" ]; do hidden="${hidden}_" @@ -138,5 +140,5 @@ wrapProgram() { mv "$prog" "$hidden" # Silence warning about unexpanded $0: # shellcheck disable=SC2016 - makeWrapper "$hidden" "$prog" --argv0 '$0' "$@" + makeWrapper "$hidden" "$prog" --argv0 '$0' "${@:2}" } diff --git a/pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh b/pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh new file mode 100644 index 000000000000..2fd2a2d6da6f --- /dev/null +++ b/pkgs/build-support/setup-hooks/setup-debug-info-dirs.sh @@ -0,0 +1,5 @@ +setupDebugInfoDirs () { + addToSearchPath NIX_DEBUG_INFO_DIRS $1/lib/debug +} + +envHooks+=(setupDebugInfoDirs) diff --git a/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh b/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh index 9891128a6231..79b8d5b73fa1 100644 --- a/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh +++ b/pkgs/build-support/setup-hooks/wrap-gapps-hook.sh @@ -39,7 +39,7 @@ wrapGAppsHook() { targetDirs=( "${prefix}/bin" "${prefix}/libexec" ) for targetDir in "${targetDirs[@]}"; do if [[ -d "${targetDir}" ]]; then - find "${targetDir}" -type f -executable -print0 \ + find -L "${targetDir}" -type f -executable -print0 \ | while IFS= read -r -d '' file; do echo "Wrapping program ${file}" wrapProgram "${file}" "${gappsWrapperArgs[@]}" diff --git a/pkgs/build-support/trivial-builders.nix b/pkgs/build-support/trivial-builders.nix index 4debd9636396..14553c33e039 100644 --- a/pkgs/build-support/trivial-builders.nix +++ b/pkgs/build-support/trivial-builders.nix @@ -26,6 +26,7 @@ rec { , text , executable ? false # run chmod +x ? , destination ? "" # relative path appended to $out eg "/bin/foo" + , checkPhase ? "" # syntax checks, e.g. for scripts }: runCommand name { inherit text executable; @@ -44,6 +45,8 @@ rec { echo -n "$text" > "$n" fi + ${checkPhase} + (test -n "$executable" && chmod +x "$n") || true ''; @@ -54,6 +57,20 @@ rec { writeScript = name: text: writeTextFile {inherit name text; executable = true;}; writeScriptBin = name: text: writeTextFile {inherit name text; executable = true; destination = "/bin/${name}";}; + # Create a Shell script, check its syntax + writeShellScriptBin = name : text : + writeTextFile { + inherit name; + executable = true; + destination = "/bin/${name}"; + text = '' + #!${stdenv.shell} + ${text} + ''; + checkPhase = '' + ${stdenv.shell} -n $out + ''; + }; # Create a forest of symlinks to the files in `paths'. symlinkJoin = @@ -84,7 +101,7 @@ rec { mkdir -p $out/nix-support cp ${script} $out/nix-support/setup-hook '' + lib.optionalString (deps != []) '' - echo ${toString deps} > $out/nix-support/propagated-native-build-inputs + printWords ${toString deps} > $out/nix-support/propagated-native-build-inputs '' + lib.optionalString (substitutions != {}) '' substituteAll ${script} $out/nix-support/setup-hook ''); diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix index d5cfc419fc72..d886e9a56fa4 100644 --- a/pkgs/build-support/vm/default.nix +++ b/pkgs/build-support/vm/default.nix @@ -750,6 +750,7 @@ rec { { name, fullName, size ? 4096, urlPrefix , packagesList ? "", packagesLists ? [packagesList] , packages, extraPackages ? [], postInstall ? "" + , extraDebs ? [] , QEMU_OPTS ? "", memSize ? 512 }: let @@ -760,7 +761,7 @@ rec { in (fillDiskWithDebs { inherit name fullName size postInstall QEMU_OPTS memSize; - debs = import expr {inherit fetchurl;}; + debs = import expr {inherit fetchurl;} ++ extraDebs; }) // {inherit expr;}; @@ -1954,22 +1955,22 @@ rec { }; debian8i386 = { - name = "debian-8.8-jessie-i386"; - fullName = "Debian 8.8 Jessie (i386)"; + name = "debian-8.9-jessie-i386"; + fullName = "Debian 8.9 Jessie (i386)"; packagesList = fetchurl { url = mirror://debian/dists/jessie/main/binary-i386/Packages.xz; - sha256 = "79dbf81e9698913c577333f47f5a56be78529fba265ec492880e8c369c478b58"; + sha256 = "3c78bdf3b693f2f37737c52d6a7718b3a545956f2a853da79f04a2d15541e811"; }; urlPrefix = mirror://debian; packages = commonDebianPackages; }; debian8x86_64 = { - name = "debian-8.8-jessie-amd64"; - fullName = "Debian 8.8 Jessie (amd64)"; + name = "debian-8.9-jessie-amd64"; + fullName = "Debian 8.9 Jessie (amd64)"; packagesList = fetchurl { url = mirror://debian/dists/jessie/main/binary-amd64/Packages.xz; - sha256 = "845fc80c9934d8c0f78ada6455c81c331a3359ef15c4c036b47e742fb1bb99c6"; + sha256 = "0605589ae7a63c690f37bd2567dc12e02a2eb279d9dc200a7310072ad3593e53"; }; urlPrefix = mirror://debian; packages = commonDebianPackages; |