summary refs log tree commit diff
path: root/pkgs/stdenv
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/stdenv')
-rw-r--r--pkgs/stdenv/adapters.nix184
-rw-r--r--pkgs/stdenv/darwin/default.nix58
-rw-r--r--pkgs/stdenv/generic/default-builder.sh4
-rw-r--r--pkgs/stdenv/generic/setup.sh17
4 files changed, 225 insertions, 38 deletions
diff --git a/pkgs/stdenv/adapters.nix b/pkgs/stdenv/adapters.nix
index f7d7053c77a..dd298719071 100644
--- a/pkgs/stdenv/adapters.nix
+++ b/pkgs/stdenv/adapters.nix
@@ -42,6 +42,50 @@ rec {
     stdenv.override (prev: { allowedRequisites = null; extraBuildInputs = (prev.extraBuildInputs or []) ++ pkgs; });
 
 
+  # Override the libc++ dynamic library used in the stdenv to use the one from the platform’s
+  # default stdenv. This allows building packages and linking dependencies with different
+  # compiler versions while still using the same libc++ implementation for compatibility.
+  #
+  # Note that this adapter still uses the headers from the new stdenv’s libc++. This is necessary
+  # because older compilers may not be able to parse the headers from the default stdenv’s libc++.
+  overrideLibcxx = stdenv:
+    assert stdenv.cc.libcxx != null;
+    let
+      llvmLibcxxVersion = lib.getVersion llvmLibcxx;
+      stdenvLibcxxVersion = lib.getVersion stdenvLibcxx;
+
+      stdenvLibcxx = pkgs.stdenv.cc.libcxx;
+      stdenvCxxabi = pkgs.stdenv.cc.libcxx.cxxabi;
+
+      llvmLibcxx = stdenv.cc.libcxx;
+      llvmCxxabi = stdenv.cc.libcxx.cxxabi;
+
+      libcxx = pkgs.runCommand "${stdenvLibcxx.name}-${llvmLibcxxVersion}" {
+        outputs = [ "out" "dev" ];
+        inherit cxxabi;
+        isLLVM = true;
+      } ''
+        mkdir -p "$dev/nix-support"
+        ln -s '${stdenvLibcxx}' "$out"
+        echo '${stdenvLibcxx}' > "$dev/nix-support/propagated-build-inputs"
+        ln -s '${lib.getDev llvmLibcxx}/include' "$dev/include"
+      '';
+
+      cxxabi = pkgs.runCommand "${stdenvCxxabi.name}-${llvmLibcxxVersion}" {
+        outputs = [ "out" "dev" ];
+        inherit (stdenvCxxabi) libName;
+      } ''
+        mkdir -p "$dev/nix-support"
+        ln -s '${stdenvCxxabi}' "$out"
+        echo '${stdenvCxxabi}' > "$dev/nix-support/propagated-build-inputs"
+        ln -s '${lib.getDev llvmCxxabi}/include' "$dev/include"
+      '';
+    in
+    overrideCC stdenv (stdenv.cc.override {
+      inherit libcxx;
+      extraPackages = [ cxxabi pkgs.pkgsTargetTarget."llvmPackages_${lib.versions.major llvmLibcxxVersion}".compiler-rt ];
+    });
+
   # Override the setup script of stdenv.  Useful for testing new
   # versions of the setup script without causing a rebuild of
   # everything.
@@ -60,12 +104,13 @@ rec {
       mkDerivationFromStdenv = withOldMkDerivation old (stdenv: mkDerivationSuper: args:
       if stdenv.hostPlatform.isDarwin
       then throw "Cannot build fully static binaries on Darwin/macOS"
-      else (mkDerivationSuper args).overrideAttrs(finalAttrs: {
-        NIX_CFLAGS_LINK = toString (finalAttrs.NIX_CFLAGS_LINK or "") + " -static";
-      } // lib.optionalAttrs (!(finalAttrs.dontAddStaticConfigureFlags or false)) {
-        configureFlags = (finalAttrs.configureFlags or []) ++ [
-            "--disable-shared" # brrr...
-          ];
+      else (mkDerivationSuper args).overrideAttrs (args: {
+        NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -static";
+      } // lib.optionalAttrs (!(args.dontAddStaticConfigureFlags or false)) {
+        configureFlags = (args.configureFlags or []) ++ [
+          "--disable-shared" # brrr...
+        ];
+        cmakeFlags = (args.cmakeFlags or []) ++ ["-DCMAKE_SKIP_INSTALL_RPATH=On"];
       }));
     } // lib.optionalAttrs (stdenv0.hostPlatform.libc == "glibc") {
       extraBuildInputs = (old.extraBuildInputs or []) ++ [
@@ -245,4 +290,131 @@ rec {
         env = (args.env or {}) // { NIX_CFLAGS_COMPILE = toString (args.env.NIX_CFLAGS_COMPILE or "") + " ${toString compilerFlags}"; };
       });
     });
+
+  # Overriding the SDK changes the Darwin SDK used to build the package, which:
+  # * Ensures that the compiler and bintools have the correct Libsystem version; and
+  # * Replaces any SDK references with those in the SDK corresponding to the requested SDK version.
+  #
+  # `sdkVersion` can be any of the following:
+  # * A version string indicating the requested SDK version; or
+  # * An attrset consisting of either or both of the following fields: darwinSdkVersion and darwinMinVersion.
+  overrideSDK = stdenv: sdkVersion:
+    let
+      inherit (
+        { inherit (stdenv.hostPlatform) darwinMinVersion darwinSdkVersion; }
+        // (if lib.isAttrs sdkVersion then sdkVersion else { darwinSdkVersion = sdkVersion; })
+      ) darwinMinVersion darwinSdkVersion;
+
+      sdk = pkgs.darwin."apple_sdk_${lib.replaceStrings [ "." ] [ "_" ] darwinSdkVersion}";
+      # TODO: Make this unconditional after #229210 has been merged,
+      # and the 10.12 SDK is updated to follow the new structure.
+      Libsystem = if darwinSdkVersion == "10.12" then pkgs.darwin.Libsystem else sdk.Libsystem;
+
+      replacePropagatedFrameworks = pkg:
+        let
+          propagatedInputs = pkg.propagatedBuildInputs;
+          mappedInputs = map mapPackageToSDK propagatedInputs;
+
+          env = {
+            inherit (pkg) outputs;
+            # Map old frameworks to new ones and the package’s outputs to their original outPaths.
+            # Also map any packages that have propagated frameworks to their proxy packages using
+            # the requested SDK version. These mappings are rendered into tab-separated files to be
+            # parsed and read back with `read`.
+            dependencies = lib.concatMapStrings (pair: "${pair.fst}\t${pair.snd}\n") (lib.zipLists propagatedInputs mappedInputs);
+            pkgOutputs = lib.concatMapStrings (output: "${output}\t${(lib.getOutput output pkg).outPath}\n") pkg.outputs;
+            passAsFile = [ "dependencies" "pkgOutputs" ];
+          };
+        in
+        # Only remap the package’s propagated inputs if there are any and if any of them were themselves remapped.
+        if lib.length propagatedInputs > 0 && propagatedInputs != mappedInputs
+          then pkgs.runCommand pkg.name env ''
+            # Iterate over the outputs in the package being replaced to make sure the proxy is
+            # a fully functional replacement. This is like `symlinkJoin` except for outputs and
+            # the contents of `nix-support`, which will be customized for the requested SDK.
+            while IFS=$'\t\n' read -r outputName pkgOutputPath; do
+              mkdir -p "''${!outputName}"
+
+              for targetPath in "$pkgOutputPath"/*; do
+                targetName=$(basename "$targetPath")
+
+                # `nix-support` is special-cased because any propagated inputs need their SDK
+                # frameworks replaced with those from the requested SDK.
+                if [ "$targetName" == "nix-support" ]; then
+                  mkdir "''${!outputName}/nix-support"
+
+                  for file in "$targetPath"/*; do
+                    fileName=$(basename "$file")
+
+                    if [ "$fileName" == "propagated-build-inputs" ]; then
+                      cp "$file" "''${!outputName}/nix-support/$fileName"
+
+                      while IFS=$'\t\n' read -r oldFramework newFramework; do
+                        substituteInPlace "''${!outputName}/nix-support/$fileName" \
+                          --replace "$oldFramework" "$newFramework"
+                      done < "$dependenciesPath"
+                    fi
+                  done
+                else
+                  ln -s "$targetPath" "''${!outputName}/$targetName"
+                fi
+              done
+            done < "$pkgOutputsPath"
+          ''
+        else pkg;
+
+      # Remap a framework from one SDK version to another.
+      mapPackageToSDK = pkg:
+        let
+          name = lib.getName pkg;
+          framework = lib.removePrefix "apple-framework-" name;
+        in
+        /**/ if pkg == null then pkg
+        else if name != framework then sdk.frameworks."${framework}"
+        else replacePropagatedFrameworks pkg;
+
+      mapRuntimeToSDK = pkg:
+        # Only remap xcbuild for now, which exports the SDK used to build it.
+        if pkg != null && lib.isAttrs pkg && lib.getName pkg == "xcodebuild"
+          then pkg.override { stdenv = overrideSDK stdenv { inherit darwinMinVersion darwinSdkVersion; }; }
+          else pkg;
+
+      mapInputsToSDK = inputs: args:
+        let
+          runsAtBuild = lib.flip lib.elem [
+            "depsBuildBuild"
+            "depsBuildBuildPropagated"
+            "nativeBuildInputs"
+            "propagatedNativeBuildInputs"
+            "depsBuildTarget"
+            "depsBuildTargetPropagated"
+          ];
+          atBuildInputs = lib.filter runsAtBuild inputs;
+          atRuntimeInputs = lib.subtractLists atBuildInputs inputs;
+        in
+        lib.genAttrs atRuntimeInputs (input: map mapPackageToSDK (args."${input}" or [ ]))
+        // lib.genAttrs atBuildInputs (input: map mapRuntimeToSDK (args."${input}" or [ ]));
+
+      mkCC = cc: cc.override {
+        bintools = cc.bintools.override { libc = Libsystem; };
+        libc = Libsystem;
+      };
+    in
+    # TODO: make this work across all input types and not just propagatedBuildInputs
+    stdenv.override (old: {
+      buildPlatform = old.buildPlatform // { inherit darwinMinVersion darwinSdkVersion; };
+      hostPlatform = old.hostPlatform // { inherit darwinMinVersion darwinSdkVersion; };
+      targetPlatform = old.targetPlatform // { inherit darwinMinVersion darwinSdkVersion; };
+
+      allowedRequisites = null;
+      cc = mkCC old.cc;
+
+      extraBuildInputs = [sdk.frameworks.CoreFoundation ];
+      mkDerivationFromStdenv = extendMkDerivationArgs old (mapInputsToSDK [
+        "buildInputs"
+        "nativeBuildInputs"
+        "propagatedNativeBuildInputs"
+        "propagatedBuildInputs"
+      ]);
+    });
 }
diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix
index 25a80fd11aa..9ee6dfb1080 100644
--- a/pkgs/stdenv/darwin/default.nix
+++ b/pkgs/stdenv/darwin/default.nix
@@ -1047,9 +1047,9 @@ in
 
     overrides = self: super: {
       inherit (prevStage) ccWrapperStdenv
-        autoconf automake bash bison cmake cmakeMinimal cpio cyrus_sasl db expat flex groff
-        libedit libtool m4 ninja openldap openssh patchutils pbzx perl pkg-config python3
-        python3Minimal scons serf sqlite subversion sysctl texinfo unzip which
+        autoconf automake bash bison cmake cmakeMinimal cyrus_sasl db expat flex groff
+        libedit libtool m4 ninja openldap openssh patchutils perl pkg-config python3 scons
+        serf sqlite subversion sysctl texinfo unzip which
 
         # CF dependencies - don’t rebuild them.
         icu
@@ -1057,11 +1057,40 @@ in
         # LLVM dependencies - don’t rebuild them.
         libffi libiconv libxml2 ncurses zlib;
 
+      # These overrides are required to break an infinite recursion. curl depends on Darwin
+      # frameworks, but those frameworks require these dependencies to build, which
+      # depend on curl indirectly.
+      cpio = super.cpio.override {
+        inherit (prevStage) fetchurl;
+      };
+
+      libyaml = super.libyaml.override {
+        inherit (prevStage) fetchFromGitHub;
+      };
+
+      pbzx = super.pbzx.override {
+        inherit (prevStage) fetchFromGitHub;
+      };
+
+      python3Minimal = super.python3Minimal.override {
+        inherit (prevStage) fetchurl;
+      };
+
+      xar = super.xar.override {
+        inherit (prevStage) fetchurl;
+      };
+
       darwin = super.darwin.overrideScope (selfDarwin: superDarwin: {
         inherit (prevStage.darwin) dyld CF Libsystem darwin-stubs
           # CF dependencies - don’t rebuild them.
           libobjc objc4;
 
+        # rewrite-tbd is also needed to build Darwin frameworks, so it’s built using the
+        # previous stage’s fetchFromGitHub to avoid an infinite recursion (same as above).
+        rewrite-tbd = superDarwin.rewrite-tbd.override {
+          inherit (prevStage) fetchFromGitHub;
+        };
+
         signingUtils = superDarwin.signingUtils.override {
           inherit (selfDarwin) sigtool;
         };
@@ -1158,9 +1187,10 @@ in
   (prevStage:
     # previous stage4 stdenv:
     assert lib.all isBuiltByNixpkgsCompiler (with prevStage; [
-      bash binutils-unwrapped brotli bzip2 curl diffutils ed file findutils gawk gettext gmp
-      gnugrep gnumake gnused gnutar gzip icu libffi libiconv libidn2 libkrb5 libssh2
-      libunistring libxml2 ncurses nghttp2 openbsm openpam openssl patch pcre xz zlib zstd
+      bash binutils-unwrapped brotli bzip2 cpio curl diffutils ed file findutils gawk
+      gettext gmp gnugrep gnumake gnused gnutar gzip icu libffi libiconv libidn2 libkrb5
+      libssh2 libunistring libxml2 libyaml ncurses nghttp2 openbsm openpam openssl patch
+      pbzx pcre python3Minimal xar xz zlib zstd
     ]);
 
     assert lib.all isBuiltByNixpkgsCompiler (with prevStage.darwin; [
@@ -1176,9 +1206,9 @@ in
     ]);
 
     assert lib.all isBuiltByBootstrapFilesCompiler (with prevStage; [
-      autoconf automake bison cmake cmakeMinimal cpio cyrus_sasl db expat flex groff libedit
-      libtool m4 ninja openldap openssh patchutils pbzx perl pkg-config.pkg-config python3
-      python3Minimal scons serf sqlite subversion sysctl.provider texinfo unzip which
+      autoconf automake bison cmake cmakeMinimal cyrus_sasl db expat flex groff libedit
+      libtool m4 ninja openldap openssh patchutils perl pkg-config.pkg-config python3 scons
+      serf sqlite subversion sysctl.provider texinfo unzip which
     ]);
 
     assert prevStage.darwin.cctools == prevStage.darwin.cctools-llvm;
@@ -1307,14 +1337,14 @@ in
 
       overrides = self: super: {
         inherit (prevStage)
-          bash binutils brotli bzip2 coreutils curl diffutils ed file findutils gawk gettext
-          gmp gnugrep gnumake gnused gnutar gzip icu libffi libiconv libidn2 libssh2
-          libunistring libxml2 ncurses nghttp2 openbsm openpam openssl patch pcre xz zlib
-          zstd;
+          bash binutils brotli bzip2 coreutils cpio curl diffutils ed file findutils gawk
+          gettext gmp gnugrep gnumake gnused gnutar gzip icu libffi libiconv libidn2 libssh2
+          libunistring libxml2 libyaml ncurses nghttp2 openbsm openpam openssl patch pbzx
+          pcre python3Minimal xar xz zlib zstd;
 
         darwin = super.darwin.overrideScope (_: _: {
           inherit (prevStage.darwin)
-            CF ICU Libsystem darwin-stubs dyld locale libobjc libtapi xnu;
+            CF ICU Libsystem darwin-stubs dyld locale libobjc libtapi rewrite-tbd xnu;
         } // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) {
           inherit (prevStage.darwin) binutils binutils-unwrapped cctools-llvm cctools-port;
         });
diff --git a/pkgs/stdenv/generic/default-builder.sh b/pkgs/stdenv/generic/default-builder.sh
index 8c6fec7873b..d49fb8aa57f 100644
--- a/pkgs/stdenv/generic/default-builder.sh
+++ b/pkgs/stdenv/generic/default-builder.sh
@@ -1,6 +1,4 @@
-if [ -f .attrs.sh ]; then
-    . .attrs.sh
-fi
+if [ -e "$NIX_ATTRS_SH_FILE" ]; then . "$NIX_ATTRS_SH_FILE"; elif [ -f .attrs.sh ]; then . .attrs.sh; fi
 
 source $stdenv/setup
 genericBuild
diff --git a/pkgs/stdenv/generic/setup.sh b/pkgs/stdenv/generic/setup.sh
index ad9857fc9d6..419a66261e6 100644
--- a/pkgs/stdenv/generic/setup.sh
+++ b/pkgs/stdenv/generic/setup.sh
@@ -16,29 +16,15 @@ if (( "${NIX_DEBUG:-0}" >= 6 )); then
     set -x
 fi
 
-if [ -f .attrs.sh ]; then
+if [ -f .attrs.sh ] || [[ -n "${NIX_ATTRS_JSON_FILE:-}" ]]; then
     __structuredAttrs=1
     echo "structuredAttrs is enabled"
-else
-    __structuredAttrs=
-fi
 
-if [ -n "$__structuredAttrs" ]; then
     for outputName in "${!outputs[@]}"; do
         # ex: out=/nix/store/...
         export "$outputName=${outputs[$outputName]}"
     done
 
-    # Before Nix 2.4, $NIX_ATTRS_*_FILE was named differently:
-    # https://github.com/NixOS/nix/commit/27ce722
-    if [[ -n "${ATTRS_JSON_FILE:-}" ]]; then
-        export NIX_ATTRS_JSON_FILE="$ATTRS_JSON_FILE"
-    fi
-
-    if [[ -n "${ATTRS_SH_FILE:-}" ]]; then
-        export NIX_ATTRS_SH_FILE="$ATTRS_SH_FILE"
-    fi
-
     # $NIX_ATTRS_JSON_FILE pointed to the wrong location in sandbox
     # https://github.com/NixOS/nix/issues/6736; please keep around until the
     # fix reaches *every patch version* that's >= lib/minver.nix
@@ -49,6 +35,7 @@ if [ -n "$__structuredAttrs" ]; then
         export NIX_ATTRS_SH_FILE="$NIX_BUILD_TOP/.attrs.sh"
     fi
 else
+    __structuredAttrs=
     : "${outputs:=out}"
 fi