From 0c37778c2c17fb40407f6432ff009cd7ae5b17b1 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 17 Jul 2017 23:36:17 -0400 Subject: [PATCH 01/10] cc-wrapper: WIP linking hack for mac OS Probably best to override Haskell packages set, or anything else linking a lot of libraries, with this. --- pkgs/build-support/cc-wrapper/default.nix | 20 ++- .../macos-sierra-reexport-hack.patch | 140 ++++++++++++++++++ pkgs/stdenv/darwin/default.nix | 2 +- pkgs/test/macos-sierra-shared/default.nix | 43 ++++++ pkgs/top-level/all-packages.nix | 6 + 5 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.patch create mode 100644 pkgs/test/macos-sierra-shared/default.nix diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 676fbd006881..c178204f9fb5 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; @@ -295,7 +296,20 @@ stdenv.mkDerivation { ln -s $ldPath/${prefix}as $out/bin/${prefix}as fi - wrap ${prefix}ld ${preWrap ./ld-wrapper.sh} ''${ld:-$ldPath/${prefix}ld} + wrap ${prefix}ld ${if !useMacosReexportHack + then preWrap ./ld-wrapper.sh + else stdenv.mkDerivation { + name = "patched-ld-wrapper-src"; + patches = [ ./macos-sierra-reexport-hack.patch ]; + unpackPhase = '' + src=$PWD + cp ${./ld-wrapper.sh} ld-wrapper.sh + ''; + buildPhase = ""; + installPhase = '' + cp ld-wrapper.sh $out + ''; + }} ''${ld:-$ldPath/${prefix}ld} if [ -e ${binutils_bin}/bin/${prefix}ld.gold ]; then wrap ${prefix}ld.gold ${preWrap ./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.gold @@ -399,5 +413,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/macos-sierra-reexport-hack.patch b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.patch new file mode 100644 index 000000000000..031c5640f541 --- /dev/null +++ b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.patch @@ -0,0 +1,140 @@ +--- a/ld-wrapper.sh ++++ b/ld-wrapper.sh +@@ -101,35 +101,115 @@ if [ "$NIX_DONT_SET_RPATH" != 1 ]; then + rpath="" + + # First, find all -L... switches. +- allParams=("${params[@]}" ${extra[@]}) ++ declare -ar allParams=("${extraBefore[@]}" "${params[@]}" "${extra[@]}") ++ declare -a allParamsPost=() childrenLookup=() childrenLink=() ++ ++ declare -r recurThreshold=300 ++ ++ declare overflowCount=0 ++ for p in "${allParams[@]}"; do ++ case "$p" in ++ -o) ++ declare -r outputName="$p2" ++ ;; ++ (-l*) ++ let overflowCount+=1 ++ ;; ++ *) ;; ++ esac ++ done ++ ++ if (( "$overflowCount" > "$recurThreshold" )); then ++ declare -r linkIndirect="1" ++ else ++ declare -r linkIndirect="" ++ fi ++ ++ function append_Ls() { ++ if [[ -n "$linkIndirect" ]]; then ++ childrenLookup+=("$@") ++ fi ++ allParamsPost+=("$@") ++ } ++ ++ function append_ls() { ++ local p ++ if (( $# == 2 )); then p="$2"; else p="${1:2}"; fi ++ if [[ -n "$linkIndirect" && "$p" != "-lto_library" && "$p" != "-lSystem" ]]; then ++ childrenLink+=("$@") ++ else ++ allParamsPost+=("$@") ++ fi ++ } ++ + n=0 + while [ $n -lt ${#allParams[*]} ]; do + p=${allParams[n]} + p2=${allParams[$((n+1))]} ++ + if [ "${p:0:3}" = -L/ ]; then + addToLibPath ${p:2} ++ append_Ls "$p" + elif [ "$p" = -L ]; then + addToLibPath ${p2} ++ append_Ls "$p" "$p2" + n=$((n + 1)) + elif [ "$p" = -l ]; then + addToLibs ${p2} ++ append_ls "$p" "$p2" + n=$((n + 1)) + elif [ "${p:0:2}" = -l ]; then + addToLibs ${p:2} ++ append_ls "$p" + 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. ++ allParamsPost+=("$p" "$p2") + 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}" ++ allParamsPost+=("$p") ++ else ++ allParamsPost+=("$p") + fi ++ + n=$((n + 1)) + done + ++ if [[ "$linkIndirect" ]]; then ++ while (( $n < "${#childrenLink[@]}" )); do ++ childrenLink[n]="-reexport${childrenLink[n]}" ++ done ++ declare -r outputNameLibless=$(basename $( ++ if [[ "${outputName:0:3}" = lib ]]; then ++ echo "${outputName:3}" ++ else ++ echo "${outputName:-unnamed}" ++ fi)) ++ declare -ra children=("$outputNameLibless-reexport-delegate-0" \ ++ "$outputNameLibless-reexport-delegate-1") ++ ++ mkdir -p "$out/lib" ++ ++ # first half of libs ++ "$0" -dylib -o "$out/lib/lib${children[0]}.dylib" \ ++ -install_name "$out/lib/lib${children[0]}.dylib" \ ++ "${childrenLookup[@]}" \ ++ "${childrenLink[@]::$((${#childrenLink[@]} / 2 ))}" ++ ++ # second half of libs ++ "$0" -dylib -o "$out/lib/lib${children[1]}.dylib" \ ++ -install_name "$out/lib/lib${children[1]}.dylib" \ ++ "${childrenLookup[@]}" \ ++ "${childrenLink[@]:$((${#childrenLink[@]} / 2 ))}" ++ ++ allParamsPost+=("-L$out/lib" "-l${children[0]}" "-l${children[1]}") ++ fi ++ + # Second, for each directory in the library search path (-L...), + # see if it contains a dynamic library used by a -l... flag. If + # so, add the directory to the rpath. +@@ -170,12 +243,8 @@ 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 "flags to @prog@:" >&2 ++ for i in "${allParamsPost[@]}"; do + echo " $i" >&2 + done + fi +@@ -185,4 +254,4 @@ if [ -n "$NIX_LD_WRAPPER_EXEC_HOOK" ]; then + fi + + PATH="$path_backup" +-exec @prog@ ${extraBefore[@]} "${params[@]}" ${extra[@]} ++exec @prog@ "${allParamsPost[@]}" diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index f6d9bcac5104..ed114fa740c8 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -297,7 +297,7 @@ in rec { initialPath = import ../common-path.nix { inherit pkgs; }; shell = "${pkgs.bash}/bin/bash"; - cc = import ../../build-support/cc-wrapper { + cc = lib.callPackageWith {} ../../build-support/cc-wrapper { inherit (pkgs) stdenv; inherit shell; nativeTools = false; diff --git a/pkgs/test/macos-sierra-shared/default.nix b/pkgs/test/macos-sierra-shared/default.nix new file mode 100644 index 000000000000..8d7b9fc93842 --- /dev/null +++ b/pkgs/test/macos-sierra-shared/default.nix @@ -0,0 +1,43 @@ +{ lib, clangStdenv, clang-sierraHack-stdenv }: + +let + makeBigExe = stdenv: prefix: rec { + + sillyLibs = lib.genList (i: stdenv.mkDerivation rec { + name = "${prefix}-fluff-${toString i}"; + unpackPhase = '' + src=$PWD + echo 'int asdf${toString i}(void) { return ${toString i}; }' > ${name}.c + ''; + buildPhase = '' + $CC -shared ${name}.c -o lib${name}.dylib -Wl,-install_name,$out/lib/lib${name}.dylib + ''; + installPhase = '' + mkdir -p "$out/lib" + mv lib${name}.dylib "$out/lib" + ''; + }) 500 + ; + + finalExe = stdenv.mkDerivation rec { + name = "${prefix}-final-asdf"; + unpackPhase = '' + src=$PWD + echo 'int main(int argc, char **argv) { return argc; }' > main.c; + ''; + buildPhase = '' + $CC main.c ${toString (map (x: "-l${x.name}") sillyLibs)} -o asdf + ''; + buildInputs = sillyLibs; + installPhase = '' + mkdir -p "$out/bin" + mv asdf "$out/bin" + ''; + }; + + }; + +in { + good = makeBigExe clang-sierraHack-stdenv "good"; + bad = makeBigExe clangStdenv "bad"; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 7c26ba7c8263..85573b10321b 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -5162,6 +5162,11 @@ with pkgs; clang = llvmPackages.clang; + clang-sierraHack = clang.override { + name = "clang-wrapper-with-reexport-hack"; + useMacosReexportHack = true; + }; + clang_4 = llvmPackages_4.clang; clang_39 = llvmPackages_39.clang; clang_38 = llvmPackages_38.clang; @@ -5189,6 +5194,7 @@ with pkgs; #Use this instead of stdenv to build with clang clangStdenv = if stdenv.isDarwin then stdenv else lowPrio llvmPackages.stdenv; + clang-sierraHack-stdenv = overrideCC stdenv clang-sierraHack; libcxxStdenv = lowPrio llvmPackages.libcxxStdenv; clean = callPackage ../development/compilers/clean { }; From 9242c8b331a3571debb04b6485b0783386371838 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Fri, 21 Jul 2017 13:29:47 -0400 Subject: [PATCH 02/10] cc-wrapper: Use two scripts instead of patch --- pkgs/build-support/cc-wrapper/default.nix | 22 +-- .../macos-sierra-reexport-hack.bash | 95 ++++++++++++ .../macos-sierra-reexport-hack.patch | 140 ------------------ 3 files changed, 103 insertions(+), 154 deletions(-) create mode 100644 pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash delete mode 100644 pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.patch diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index c178204f9fb5..371db540b0ab 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -296,20 +296,14 @@ stdenv.mkDerivation { ln -s $ldPath/${prefix}as $out/bin/${prefix}as fi - wrap ${prefix}ld ${if !useMacosReexportHack - then preWrap ./ld-wrapper.sh - else stdenv.mkDerivation { - name = "patched-ld-wrapper-src"; - patches = [ ./macos-sierra-reexport-hack.patch ]; - unpackPhase = '' - src=$PWD - cp ${./ld-wrapper.sh} ld-wrapper.sh - ''; - buildPhase = ""; - installPhase = '' - cp ld-wrapper.sh $out - ''; - }} ''${ld:-$ldPath/${prefix}ld} + '' + (if !useMacosReexportHack then '' + wrap ${prefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${prefix}ld} + '' else '' + export ldWrapper="$out/bin/${prefix}ld" innerLd="${prefix}ld-reexport-delegate" + wrap "$innerLd" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${prefix}ld} + wrap "${prefix}ld" ${./ld-wrapper.sh} "$out/bin/$innerLd" + unset ldWrapper + '') + '' if [ -e ${binutils_bin}/bin/${prefix}ld.gold ]; then wrap ${prefix}ld.gold ${preWrap ./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.gold 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..548be0c4dd45 --- /dev/null +++ b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash @@ -0,0 +1,95 @@ +#! @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 + ;; + -lto_library) allArgs+=("$1") ;; + # We aren't linking any "to_library" + -lSystem) allArgs+=("$1") ;; + # Special case as indirection seems like a bad idea for something + # so fundamental. Can be removed for simplicity. + -l?*) childrenLink+=("$1") ;; + -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" + + # first half of libs + @ldWrapper@ -macosx_version_min 10.10 -arch x86_64 -dylib \ + -o "$out/lib/lib${children[0]}.dylib" \ + -install_name "$out/lib/lib${children[0]}.dylib" \ + "${childrenLookup[@]}" \ + "${childrenLink[@]:0:$((${#childrenLink[@]} / 2 ))}" + + # second half of libs + @ldWrapper@ -macosx_version_min 10.10 -arch x86_64 -dylib \ + -o "$out/lib/lib${children[1]}.dylib" \ + -install_name "$out/lib/lib${children[1]}.dylib" \ + "${childrenLookup[@]}" \ + "${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/macos-sierra-reexport-hack.patch b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.patch deleted file mode 100644 index 031c5640f541..000000000000 --- a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.patch +++ /dev/null @@ -1,140 +0,0 @@ ---- a/ld-wrapper.sh -+++ b/ld-wrapper.sh -@@ -101,35 +101,115 @@ if [ "$NIX_DONT_SET_RPATH" != 1 ]; then - rpath="" - - # First, find all -L... switches. -- allParams=("${params[@]}" ${extra[@]}) -+ declare -ar allParams=("${extraBefore[@]}" "${params[@]}" "${extra[@]}") -+ declare -a allParamsPost=() childrenLookup=() childrenLink=() -+ -+ declare -r recurThreshold=300 -+ -+ declare overflowCount=0 -+ for p in "${allParams[@]}"; do -+ case "$p" in -+ -o) -+ declare -r outputName="$p2" -+ ;; -+ (-l*) -+ let overflowCount+=1 -+ ;; -+ *) ;; -+ esac -+ done -+ -+ if (( "$overflowCount" > "$recurThreshold" )); then -+ declare -r linkIndirect="1" -+ else -+ declare -r linkIndirect="" -+ fi -+ -+ function append_Ls() { -+ if [[ -n "$linkIndirect" ]]; then -+ childrenLookup+=("$@") -+ fi -+ allParamsPost+=("$@") -+ } -+ -+ function append_ls() { -+ local p -+ if (( $# == 2 )); then p="$2"; else p="${1:2}"; fi -+ if [[ -n "$linkIndirect" && "$p" != "-lto_library" && "$p" != "-lSystem" ]]; then -+ childrenLink+=("$@") -+ else -+ allParamsPost+=("$@") -+ fi -+ } -+ - n=0 - while [ $n -lt ${#allParams[*]} ]; do - p=${allParams[n]} - p2=${allParams[$((n+1))]} -+ - if [ "${p:0:3}" = -L/ ]; then - addToLibPath ${p:2} -+ append_Ls "$p" - elif [ "$p" = -L ]; then - addToLibPath ${p2} -+ append_Ls "$p" "$p2" - n=$((n + 1)) - elif [ "$p" = -l ]; then - addToLibs ${p2} -+ append_ls "$p" "$p2" - n=$((n + 1)) - elif [ "${p:0:2}" = -l ]; then - addToLibs ${p:2} -+ append_ls "$p" - 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. -+ allParamsPost+=("$p" "$p2") - 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}" -+ allParamsPost+=("$p") -+ else -+ allParamsPost+=("$p") - fi -+ - n=$((n + 1)) - done - -+ if [[ "$linkIndirect" ]]; then -+ while (( $n < "${#childrenLink[@]}" )); do -+ childrenLink[n]="-reexport${childrenLink[n]}" -+ done -+ declare -r outputNameLibless=$(basename $( -+ if [[ "${outputName:0:3}" = lib ]]; then -+ echo "${outputName:3}" -+ else -+ echo "${outputName:-unnamed}" -+ fi)) -+ declare -ra children=("$outputNameLibless-reexport-delegate-0" \ -+ "$outputNameLibless-reexport-delegate-1") -+ -+ mkdir -p "$out/lib" -+ -+ # first half of libs -+ "$0" -dylib -o "$out/lib/lib${children[0]}.dylib" \ -+ -install_name "$out/lib/lib${children[0]}.dylib" \ -+ "${childrenLookup[@]}" \ -+ "${childrenLink[@]::$((${#childrenLink[@]} / 2 ))}" -+ -+ # second half of libs -+ "$0" -dylib -o "$out/lib/lib${children[1]}.dylib" \ -+ -install_name "$out/lib/lib${children[1]}.dylib" \ -+ "${childrenLookup[@]}" \ -+ "${childrenLink[@]:$((${#childrenLink[@]} / 2 ))}" -+ -+ allParamsPost+=("-L$out/lib" "-l${children[0]}" "-l${children[1]}") -+ fi -+ - # Second, for each directory in the library search path (-L...), - # see if it contains a dynamic library used by a -l... flag. If - # so, add the directory to the rpath. -@@ -170,12 +243,8 @@ 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 "flags to @prog@:" >&2 -+ for i in "${allParamsPost[@]}"; do - echo " $i" >&2 - done - fi -@@ -185,4 +254,4 @@ if [ -n "$NIX_LD_WRAPPER_EXEC_HOOK" ]; then - fi - - PATH="$path_backup" --exec @prog@ ${extraBefore[@]} "${params[@]}" ${extra[@]} -+exec @prog@ "${allParamsPost[@]}" From 1cd74ac70a69f60b826b20d2e31644f2a2be98ea Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 26 Jul 2017 20:26:57 -0400 Subject: [PATCH 03/10] cc-wrapper: Make sure symbol tables of child delegators is not empty As described in https://github.com/NixOS/nixpkgs/issues/18461, MacOS no longer accepts dylibs which only reexport other dylibs, because their symbol tables are empty. To get around this, we define an object file with a single "private extern" symbol, which hopefully won't clobber anything. --- pkgs/build-support/cc-wrapper/default.nix | 9 +++++---- .../cc-wrapper/macos-sierra-reexport-hack.bash | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 371db540b0ab..43cf3b1cafeb 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -299,10 +299,11 @@ stdenv.mkDerivation { '' + (if !useMacosReexportHack then '' wrap ${prefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${prefix}ld} '' else '' - export ldWrapper="$out/bin/${prefix}ld" innerLd="${prefix}ld-reexport-delegate" - wrap "$innerLd" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${prefix}ld} - wrap "${prefix}ld" ${./ld-wrapper.sh} "$out/bin/$innerLd" - unset ldWrapper + export binPrefix=${prefix} + 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 diff --git a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash index 548be0c4dd45..ae920e4fdad1 100644 --- a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash +++ b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash @@ -74,18 +74,26 @@ else 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 - @ldWrapper@ -macosx_version_min 10.10 -arch x86_64 -dylib \ + @binPrefix@ld -macosx_version_min 10.10 -arch x86_64 -dylib \ -o "$out/lib/lib${children[0]}.dylib" \ -install_name "$out/lib/lib${children[0]}.dylib" \ - "${childrenLookup[@]}" \ + "${childrenLookup[@]}" "$symbolBloatObject" \ "${childrenLink[@]:0:$((${#childrenLink[@]} / 2 ))}" # second half of libs - @ldWrapper@ -macosx_version_min 10.10 -arch x86_64 -dylib \ + @binPrefix@ld -macosx_version_min 10.10 -arch x86_64 -dylib \ -o "$out/lib/lib${children[1]}.dylib" \ -install_name "$out/lib/lib${children[1]}.dylib" \ - "${childrenLookup[@]}" \ + "${childrenLookup[@]}" "$symbolBloatObject" \ "${childrenLink[@]:$((${#childrenLink[@]} / 2 ))}" allArgs+=("-L$out/lib" "-l${children[0]}" "-l${children[1]}") From f671b85fb2c082819ea419ea5b0f5914bc6f26b3 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 26 Jul 2017 23:28:36 -0400 Subject: [PATCH 04/10] cc-wrapper: Beef up sierra tests to actually use functions --- pkgs/test/macos-sierra-shared/default.nix | 34 +++++++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/pkgs/test/macos-sierra-shared/default.nix b/pkgs/test/macos-sierra-shared/default.nix index 8d7b9fc93842..ebcf6c62c608 100644 --- a/pkgs/test/macos-sierra-shared/default.nix +++ b/pkgs/test/macos-sierra-shared/default.nix @@ -3,30 +3,52 @@ let makeBigExe = stdenv: prefix: rec { + count = 500; + sillyLibs = lib.genList (i: stdenv.mkDerivation rec { name = "${prefix}-fluff-${toString i}"; unpackPhase = '' src=$PWD - echo 'int asdf${toString i}(void) { return ${toString i}; }' > ${name}.c + cat << 'EOF' > ${name}.c + unsigned int asdf_${toString i}(void) { + return ${toString i}; + } + EOF ''; buildPhase = '' - $CC -shared ${name}.c -o lib${name}.dylib -Wl,-install_name,$out/lib/lib${name}.dylib + $CC -std=c99 -shared ${name}.c -o lib${name}.dylib -Wl,-install_name,$out/lib/lib${name}.dylib ''; installPhase = '' mkdir -p "$out/lib" mv lib${name}.dylib "$out/lib" ''; - }) 500 - ; + }) count; finalExe = stdenv.mkDerivation rec { name = "${prefix}-final-asdf"; unpackPhase = '' src=$PWD - echo 'int main(int argc, char **argv) { return argc; }' > main.c; + cat << 'EOF' > main.cxx + + #include + + ${toString (lib.genList (i: "extern unsigned int asdf_${toString i}(void); ") count)} + + unsigned int (*funs[])(void) = { + ${toString (lib.genList (i: "asdf_${toString i},") count)} + }; + + int main(int argc, char **argv) { + unsigned int i = 0; + for (auto f : funs) { + assert(f() == i++); + } + return 0; + } + EOF ''; buildPhase = '' - $CC main.c ${toString (map (x: "-l${x.name}") sillyLibs)} -o asdf + $CC -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o asdf ''; buildInputs = sillyLibs; installPhase = '' From 539dcb8e2760ee6cab990ce929a586b050496520 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 27 Jul 2017 14:15:10 -0400 Subject: [PATCH 05/10] cc-wrapper-test: Forgot to `extern "C"` now that main is C++ --- pkgs/test/macos-sierra-shared/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test/macos-sierra-shared/default.nix b/pkgs/test/macos-sierra-shared/default.nix index ebcf6c62c608..2d52a02affa0 100644 --- a/pkgs/test/macos-sierra-shared/default.nix +++ b/pkgs/test/macos-sierra-shared/default.nix @@ -32,7 +32,7 @@ let #include - ${toString (lib.genList (i: "extern unsigned int asdf_${toString i}(void); ") count)} + ${toString (lib.genList (i: "extern \"C\" unsigned int asdf_${toString i}(void); ") count)} unsigned int (*funs[])(void) = { ${toString (lib.genList (i: "asdf_${toString i},") count)} From a9dd855894d426ecc1e32b1b8b72a9db7f8ed913 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 27 Jul 2017 14:37:24 -0400 Subject: [PATCH 06/10] cc-wrapper-test: Don't use assert --- pkgs/test/macos-sierra-shared/default.nix | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pkgs/test/macos-sierra-shared/default.nix b/pkgs/test/macos-sierra-shared/default.nix index 2d52a02affa0..e96fdb34c05f 100644 --- a/pkgs/test/macos-sierra-shared/default.nix +++ b/pkgs/test/macos-sierra-shared/default.nix @@ -30,7 +30,8 @@ let src=$PWD cat << 'EOF' > main.cxx - #include + #include + #include ${toString (lib.genList (i: "extern \"C\" unsigned int asdf_${toString i}(void); ") count)} @@ -39,11 +40,15 @@ let }; int main(int argc, char **argv) { + bool ret; unsigned int i = 0; for (auto f : funs) { - assert(f() == i++); + if (f() != i++) { + std::cerr << "Failed to get expected response from function #" << i << std::endl; + return EXIT_FAILURE; + } } - return 0; + return EXIT_SUCCESS; } EOF ''; From eeed1814dc84121f81fc6214a26f1adffc41581c Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 27 Jul 2017 15:36:51 -0400 Subject: [PATCH 07/10] cc-wrapper-test: Use `$CXX` else the C++ std lib won't be on the include path --- pkgs/test/macos-sierra-shared/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test/macos-sierra-shared/default.nix b/pkgs/test/macos-sierra-shared/default.nix index e96fdb34c05f..690d09414fbd 100644 --- a/pkgs/test/macos-sierra-shared/default.nix +++ b/pkgs/test/macos-sierra-shared/default.nix @@ -53,7 +53,7 @@ let EOF ''; buildPhase = '' - $CC -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o asdf + $CXX -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o asdf ''; buildInputs = sillyLibs; installPhase = '' From 14e05c30e85f0e8bd8f51b49a2ea622df7172ec2 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 31 Jul 2017 21:02:20 -0400 Subject: [PATCH 08/10] macos-sierra-shared: Make live code and add to nascent Darwin channel Also add appropriate `meta.platforms = ...` to each derivation. --- pkgs/test/macos-sierra-shared/default.nix | 27 +++++++++++++++++++---- pkgs/top-level/all-packages.nix | 5 +++++ pkgs/top-level/release.nix | 1 + 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/pkgs/test/macos-sierra-shared/default.nix b/pkgs/test/macos-sierra-shared/default.nix index 690d09414fbd..51e8ae53736c 100644 --- a/pkgs/test/macos-sierra-shared/default.nix +++ b/pkgs/test/macos-sierra-shared/default.nix @@ -1,4 +1,4 @@ -{ lib, clangStdenv, clang-sierraHack-stdenv }: +{ lib, clangStdenv, clang-sierraHack-stdenv, stdenvNoCC }: let makeBigExe = stdenv: prefix: rec { @@ -22,6 +22,7 @@ let mkdir -p "$out/lib" mv lib${name}.dylib "$out/lib" ''; + meta.platforms = lib.platforms.darwin; }) count; finalExe = stdenv.mkDerivation rec { @@ -53,18 +54,36 @@ let EOF ''; buildPhase = '' - $CXX -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o asdf + $CXX -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o ${prefix}-asdf ''; buildInputs = sillyLibs; installPhase = '' mkdir -p "$out/bin" - mv asdf "$out/bin" + mv ${prefix}-asdf "$out/bin" ''; + meta.platforms = lib.platforms.darwin; }; }; -in { good = makeBigExe clang-sierraHack-stdenv "good"; + bad = makeBigExe clangStdenv "bad"; + +in stdenvNoCC.mkDerivation { + name = "macos-sierra-shared-test"; + buildInputs = [ good.finalExe bad.finalExe ]; + # TODO(@Ericson2314): Be impure or require exact MacOS version of builder? + buildCommand = '' + if bad-asdf + then echo "bad-asdf can succeed on non-sierra, OK" >&2 + else echo "bad-asdf should fail on sierra, OK" >&2 + fi + + # Must succeed on all supported MacOS versions + good-asdf + + touch $out + ''; + meta.platforms = lib.platforms.darwin; } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 85573b10321b..a1d83e314584 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -19223,4 +19223,9 @@ with pkgs; undaemonize = callPackage ../tools/system/undaemonize {}; houdini = callPackage ../applications/misc/houdini {}; + + # No `recurseIntoAttrs` because there's no need to nix-env these. + tests = { + macOSSierraShared = callPackage ../test/macos-sierra-shared {}; + }; } diff --git a/pkgs/top-level/release.nix b/pkgs/top-level/release.nix index be57b40fca64..0c7c67a0d03b 100644 --- a/pkgs/top-level/release.nix +++ b/pkgs/top-level/release.nix @@ -42,6 +42,7 @@ let jobs.python.x86_64-darwin jobs.rustc.x86_64-darwin jobs.go.x86_64-darwin + jobs.tests.macOSSierraShared ]; }; From 2e61d8b71cb2f24fd71bb811f8a504451366f2e2 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 1 Aug 2017 16:31:38 -0400 Subject: [PATCH 09/10] cc-wrapper: Handle more -l.... gotchas --- .../cc-wrapper/macos-sierra-reexport-hack.bash | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash index ae920e4fdad1..9829179a97c4 100644 --- a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash +++ b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash @@ -39,14 +39,17 @@ else echo "cctools LD does not support '-L foo' or '-l foo'" >&2 exit 1 ;; - -lto_library) allArgs+=("$1") ;; - # We aren't linking any "to_library" - -lSystem) allArgs+=("$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?*) childrenLink+=("$1") ;; - -reexport-l?*) childrenLink+=("$1") ;; - *) allArgs+=("$1") ;; + -l?* | -reexport-l?*) childrenLink+=("$1") ;; + *) allArgs+=("$1") ;; esac shift From cd6c452ade3a309050f56c36c27d41b0abb0eef7 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 1 Aug 2017 16:31:38 -0400 Subject: [PATCH 10/10] cc-wrapper: Don't hardcode MacOS min version for delegates --- pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash index 9829179a97c4..b7aa7ea5c092 100644 --- a/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash +++ b/pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash @@ -86,14 +86,14 @@ else fi # first half of libs - @binPrefix@ld -macosx_version_min 10.10 -arch x86_64 -dylib \ + @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 10.10 -arch x86_64 -dylib \ + @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" \