about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2017-08-03 17:25:30 -0400
committerJohn Ericson <John.Ericson@Obsidian.Systems>2017-08-03 17:25:30 -0400
commit8ba6012dfdc1214f5df7dc90955973be3f7562e3 (patch)
tree8a29c257fa64cbad9c370144817030a88eeb5bc2
parent264d6641ecc7c0bea4ae0758a43c446fe52b4cd3 (diff)
parentcd6c452ade3a309050f56c36c27d41b0abb0eef7 (diff)
downloadnixlib-8ba6012dfdc1214f5df7dc90955973be3f7562e3.tar
nixlib-8ba6012dfdc1214f5df7dc90955973be3f7562e3.tar.gz
nixlib-8ba6012dfdc1214f5df7dc90955973be3f7562e3.tar.bz2
nixlib-8ba6012dfdc1214f5df7dc90955973be3f7562e3.tar.lz
nixlib-8ba6012dfdc1214f5df7dc90955973be3f7562e3.tar.xz
nixlib-8ba6012dfdc1214f5df7dc90955973be3f7562e3.tar.zst
nixlib-8ba6012dfdc1214f5df7dc90955973be3f7562e3.zip
Merge PR #27536
-rw-r--r--pkgs/build-support/cc-wrapper/default.nix15
-rw-r--r--pkgs/build-support/cc-wrapper/macos-sierra-reexport-hack.bash106
-rw-r--r--pkgs/stdenv/darwin/default.nix2
-rw-r--r--pkgs/test/macos-sierra-shared/default.nix89
-rw-r--r--pkgs/top-level/all-packages.nix11
-rw-r--r--pkgs/top-level/release.nix1
6 files changed, 221 insertions, 3 deletions
diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix
index 09d1d4cd681a..e0cc1fc26696 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;
@@ -278,7 +279,15 @@ 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 ''
+      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
         wrap ${prefix}ld.gold ${preWrap ./ld-wrapper.sh} ${binutils_bin}/bin/${prefix}ld.gold
@@ -386,5 +395,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.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/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix
index cac33a1bebb2..74dcf2f009b3 100644
--- a/pkgs/stdenv/darwin/default.nix
+++ b/pkgs/stdenv/darwin/default.nix
@@ -305,7 +305,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..51e8ae53736c
--- /dev/null
+++ b/pkgs/test/macos-sierra-shared/default.nix
@@ -0,0 +1,89 @@
+{ lib, clangStdenv, clang-sierraHack-stdenv, stdenvNoCC }:
+
+let
+  makeBigExe = stdenv: prefix: rec {
+
+    count = 500;
+
+    sillyLibs = lib.genList (i: stdenv.mkDerivation rec {
+      name = "${prefix}-fluff-${toString i}";
+      unpackPhase = ''
+        src=$PWD
+        cat << 'EOF' > ${name}.c
+        unsigned int asdf_${toString i}(void) {
+          return ${toString i};
+        }
+        EOF
+      '';
+      buildPhase = ''
+        $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"
+      '';
+      meta.platforms = lib.platforms.darwin;
+    }) count;
+
+    finalExe = stdenv.mkDerivation rec {
+      name = "${prefix}-final-asdf";
+      unpackPhase = ''
+        src=$PWD
+        cat << 'EOF' > main.cxx
+
+        #include <cstdlib>
+        #include <iostream>
+
+        ${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)}
+        };
+
+        int main(int argc, char **argv) {
+          bool ret;
+          unsigned int i = 0;
+          for (auto f : funs) {
+            if (f() != i++) {
+              std::cerr << "Failed to get expected response from function #" << i << std::endl;
+              return EXIT_FAILURE;
+            }
+          }
+          return EXIT_SUCCESS;
+        }
+        EOF
+      '';
+      buildPhase = ''
+        $CXX -std=c++11 main.cxx ${toString (map (x: "-l${x.name}") sillyLibs)} -o ${prefix}-asdf
+      '';
+      buildInputs = sillyLibs;
+      installPhase = ''
+        mkdir -p "$out/bin"
+        mv ${prefix}-asdf "$out/bin"
+      '';
+      meta.platforms = lib.platforms.darwin;
+    };
+
+  };
+
+  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 eb59deba7e82..103906a39d05 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -5184,6 +5184,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;
@@ -5211,6 +5216,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 { };
@@ -19254,4 +19260,9 @@ with pkgs;
   houdini = callPackage ../applications/misc/houdini {};
 
   xtermcontrol = callPackage ../applications/misc/xtermcontrol {};
+
+  # 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
             ];
         };