From 21f149763ff502f9e7b24128157efdfad88524a7 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 01/12] stdenv/darwin: overlay llvmLibrariesDarwinDepsNoCC where needed --- pkgs/stdenv/darwin/default.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index a63e0c9b074b5..13b2f8e25fef8 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -657,7 +657,9 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check xar = super.xarMinimal; darwin = super.darwin.overrideScope ( - selfDarwin: superDarwin: { + selfDarwin: superDarwin: + llvmLibrariesDarwinDepsNoCC prevStage + // { signingUtils = prevStage.darwin.signingUtils.override { inherit (selfDarwin) sigtool; }; # Rewrap binutils with the real libSystem @@ -820,6 +822,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check darwin = super.darwin.overrideScope ( selfDarwin: superDarwin: darwinPackages prevStage + // llvmLibrariesDarwinDepsNoCC prevStage // { inherit (prevStage.darwin) binutils-unwrapped; # Rewrap binutils so it uses the rebuilt Libsystem. @@ -903,6 +906,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check selfDarwin: superDarwin: darwinPackages prevStage // sdkDarwinPackages prevStage + // llvmLibrariesDarwinDepsNoCC prevStage # Rebuild darwin.binutils with the new LLVM, so only inherit libSystem from the previous stage. // { inherit (prevStage.darwin) libSystem; @@ -977,6 +981,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check darwin = super.darwin.overrideScope ( _: superDarwin: sdkDarwinPackages prevStage + // llvmLibrariesDarwinDepsNoCC prevStage // { inherit (prevStage.darwin) binutils-unwrapped libSystem; binutils = superDarwin.binutils.override { @@ -1217,6 +1222,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check darwin = super.darwin.overrideScope ( _: _: sdkDarwinPackages prevStage + // llvmLibrariesDarwinDepsNoCC prevStage // { inherit (prevStage.darwin) libSystem locale sigtool; } From 8abaff604273bb899a5e1c569d3d6573b6f5f0b2 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 02/12] stdenv/darwin: use a versioned `llvmPackages` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s not ideal that the version has to be hardcoded, but right now it’s not recorded in any configuration accessible from the bootstrap outside of a package set. If that changes in the future, this should be changed to get `llvmVersion` from that source. --- pkgs/stdenv/darwin/default.nix | 65 +++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 13b2f8e25fef8..34f02a35f33ba 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -28,6 +28,7 @@ assert crossSystem == localSystem; let inherit (localSystem) system; + llvmVersion = "21"; # This needs to be updated when the default LLVM version is changed. sdkMajorVersion = lib.versions.major localSystem.darwinSdkVersion; commonImpureHostDeps = [ @@ -304,13 +305,15 @@ let disallowedPackages = prevStage: { inherit (prevStage) binutils-unwrapped curl; }; # LLVM tools packages are staged separately (xclang, stage3) from LLVM libs (xclang). - llvmLibrariesPackages = prevStage: { inherit (prevStage.llvmPackages) compiler-rt libcxx; }; + llvmLibrariesPackages = prevStage: { + inherit (prevStage."llvmPackages_${llvmVersion}") compiler-rt libcxx; + }; llvmLibrariesDarwinDepsNoCC = prevStage: { inherit (prevStage.darwin) libcxx; }; llvmLibrariesDeps = _: { }; llvmToolsPackages = prevStage: { - inherit (prevStage.llvmPackages) clang-unwrapped + inherit (prevStage."llvmPackages_${llvmVersion}") libclang libllvm lld @@ -378,8 +381,8 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check sigtool = null; }; - llvmPackages = { clang-unwrapped = null; + "llvmPackages_${llvmVersion}" = { compiler-rt = null; libcxx = null; libllvm = null; @@ -466,8 +469,8 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - llvmPackages = - (super.llvmPackages.overrideScope ( + "llvmPackages_${llvmVersion}" = + (super."llvmPackages_${llvmVersion}".overrideScope ( selfLlvmPackages: _: { libclang = self.stdenv.mkDerivation { name = "bootstrap-stage0-clang"; @@ -477,11 +480,19 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check "lib" ]; buildCommand = '' - mkdir -p $out/lib + mkdir -p $out ln -s $out $lib ln -s ${bootstrapTools}/bin $out/bin - ln -s ${bootstrapTools}/lib/clang $out/lib ln -s ${bootstrapTools}/include $out + + # The version of clang in the bootstrap tools may be different from the default, but that’s okay. + # Symlink its resource-dir to the default version just to get past the first stage. + if (( $(ls "$clangLib" | wc -l) > 1 )); then + echo "Multiple LLVM versions were found at "$clangLib", but there must only be one used when building the stdenv." >&2 + exit 1 + fi + mkdir -p $out/lib/clang + ln -s ${bootstrapTools}/lib/clang/$(ls -1 ${bootstrapTools}/lib/clang) $out/lib/clang/${llvmVersion} ''; passthru = { isFromBootstrapFiles = true; @@ -549,7 +560,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } )) // { - inherit (super.llvmPackages) override; + inherit (super."llvmPackages_${llvmVersion}") override; }; }; @@ -677,12 +688,12 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - llvmPackages = - (super.llvmPackages.overrideScope ( + "llvmPackages_${llvmVersion}" = + (super."llvmPackages_${llvmVersion}".overrideScope ( _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage )) // { - inherit (super.llvmPackages) override; + inherit (super."llvmPackages_${llvmVersion}") override; }; }; @@ -833,17 +844,17 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - llvmPackages = - (super.llvmPackages.overrideScope ( + "llvmPackages_${llvmVersion}" = + (super."llvmPackages_${llvmVersion}".overrideScope ( _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage // { - inherit (prevStage.llvmPackages) clangNoCompilerRtWithLibc; + inherit (prevStage."llvmPackages_${llvmVersion}") clangNoCompilerRtWithLibc; } )) // { - inherit (super.llvmPackages) override; + inherit (super."llvmPackages_${llvmVersion}") override; }; } ]; @@ -920,9 +931,11 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - llvmPackages = (super.llvmPackages.overrideScope (_: _: llvmLibrariesPackages prevStage)) // { - inherit (super.llvmPackages) override; - }; + "llvmPackages_${llvmVersion}" = + (super."llvmPackages_${llvmVersion}".overrideScope (_: _: llvmLibrariesPackages prevStage)) + // { + inherit (super."llvmPackages_${llvmVersion}") override; + }; } ]; @@ -993,8 +1006,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - llvmPackages = - (super.llvmPackages.overrideScope ( _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage @@ -1032,9 +1043,11 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ; }; } + "llvmPackages_${llvmVersion}" = + (super."llvmPackages_${llvmVersion}".overrideScope ( )) // { - inherit (super.llvmPackages) override; + inherit (super."llvmPackages_${llvmVersion}") override; }; } ]; @@ -1079,7 +1092,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ]; let - cc = prevStage.llvmPackages.clang; + cc = prevStage."llvmPackages_${llvmVersion}".clang; in { inherit config overlays; @@ -1181,7 +1194,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check libSystem locale ]) - ++ (with prevStage.llvmPackages; [ + ++ (with prevStage."llvmPackages_${llvmVersion}"; [ bintools-unwrapped clang-unwrapped (lib.getLib clang-unwrapped) @@ -1242,11 +1255,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check # Since LLVM should be the same regardless of target platform, overlay it to avoid an unnecessary # rebuild when cross-compiling from Darwin to another platform using clang. { - - "llvmPackages_${lib.versions.major prevStage.llvmPackages.release_version}" = - let - llvmVersion = lib.versions.major prevStage.llvmPackages.release_version; - in + "llvmPackages_${llvmVersion}" = (super."llvmPackages_${llvmVersion}".overrideScope ( _: _: llvmToolsPackages prevStage From 6e9c55e202b565a0133ff166b991f3ae487cc0a9 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 03/12] stdenv/darwin: align LLVM tool package overrides with derivation The LLVM derivation defines `llvm` as an alias for `libllvm`. The same is true for `clang-unwrapped` and `clang`. Doing the overrides this way allows overrides to work as expected (especially at the end). --- pkgs/stdenv/darwin/default.nix | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 34f02a35f33ba..a693cec5b7c2e 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -312,13 +312,10 @@ let llvmLibrariesDeps = _: { }; llvmToolsPackages = prevStage: { - clang-unwrapped inherit (prevStage."llvmPackages_${llvmVersion}") libclang libllvm lld - llvm - llvm-manpages ; }; @@ -381,9 +378,10 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check sigtool = null; }; - clang-unwrapped = null; + clang = null; "llvmPackages_${llvmVersion}" = { compiler-rt = null; + libclang = null; libcxx = null; libllvm = null; }; From ecf7a3e955e864292251f143e3a6815fdb8942a8 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 04/12] stdenv/darwin: clean up LLVM overrides at the end This change allows `overrideScope` to work correctly outside of the bootstrap. Packages have to be overriden manually with the final `libllvm` to make sure any overrides to `libllvm` are picked up. The workaround is being dropped because rebuilds are expected. Note that the top-level `clang` is being dropped because it is an alias for `llvmPackages.clang`. Not overlaying it preserves the expected behavior if someone overlays `llvmPackages.clang` in their config (which is that the top-level one will be the same derivation as the overlay). --- pkgs/stdenv/darwin/default.nix | 55 ++++++++++++++++------------------ 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index a693cec5b7c2e..ad2667247d651 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -1244,23 +1244,37 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } # These have to be dropped from the overlay when cross-compiling. Wrappers are obviously target-specific. # darwin.binutils is not yet ready to be target-independent. - ( - lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) (bintoolsPackages prevStage) - // { - inherit (prevStage.llvmPackages) clang; - } - ) - # Since LLVM should be the same regardless of target platform, overlay it to avoid an unnecessary - # rebuild when cross-compiling from Darwin to another platform using clang. + (lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) (bintoolsPackages prevStage)) { "llvmPackages_${llvmVersion}" = (super."llvmPackages_${llvmVersion}".overrideScope ( - _: _: - llvmToolsPackages prevStage - // llvmLibrariesPackages prevStage + finalLLVM: _: + # These are defined explicitly to make sure that overriding their dependencies using `overrideScope` + # still works. `llvmPackages.libcxx` is not included because it’s not part of the Darwin stdenv. + { + inherit (prevStage."llvmPackages_${llvmVersion}") libllvm; + libclang = prevStage."llvmPackages_${llvmVersion}".libclang.override { + inherit (finalLLVM) libllvm; + }; + lld = prevStage."llvmPackages_${llvmVersion}".lld.override { + inherit (finalLLVM) libllvm; + }; + } + # Avoid using the llvm-manpages package from the bootstrap, which won’t build due to needing curl. // { inherit (super."llvmPackages_${llvmVersion}") llvm-manpages; } + // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) { + # Make sure the following are all the same in the local == target case: + # - clang + # - llvmPackages.stdenv.cc + # - llvmPackages.systemLibcxxClang. + # - llvmPackages.clang + # - stdenv.cc + systemLibcxxClang = prevStage."llvmPackages_${llvmVersion}".systemLibcxxClang.override { + cc = finalLLVM.clang-unwrapped; + }; + } )) // { inherit (super."llvmPackages_${llvmVersion}") override; @@ -1297,24 +1311,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check assert prevStage.libiconv == prevStage.darwin.libiconv; { - inherit (prevStage) config overlays; - # This should be done in the `overrideScope` above, but it causes rebuilds. - # TODO: Move it there once https://github.com/NixOS/nixpkgs/pull/445668 is merged. - stdenv = prevStage.stdenv // { - overrides = - self: super: - (prevStage.stdenv.overrides self super) - // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) ( - let - llvmVersion = lib.versions.major prevStage.llvmPackages.release_version; - in - { - "llvmPackages_${llvmVersion}" = prevStage."llvmPackages_${llvmVersion}" // { - inherit (prevStage) clang; - }; - } - ); - }; + inherit (prevStage) config overlays stdenv; } ) ] From d8513416ecf6f3ffada4145865f45e38adfe4ebf Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 05/12] stdenv/darwin: clean up `allowedRequisites` The Darwin bintools were moved to have all `darwin` packages in the same place. The LLVM ones are using the original, unaliased names. --- pkgs/stdenv/darwin/default.nix | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index ad2667247d651..495fd25ebc7d7 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -1144,8 +1144,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check cctools cctools.libtool coreutils - darwin.binutils - darwin.binutils.bintools diffutils ed file @@ -1185,6 +1183,8 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ] ++ lib.optionals localSystem.isx86_64 [ prevStage.darwin.Csu ] ++ (with prevStage.darwin; [ + binutils + binutils.bintools libcxx libiconv.out libresolv.out @@ -1194,13 +1194,13 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ]) ++ (with prevStage."llvmPackages_${llvmVersion}"; [ bintools-unwrapped - clang-unwrapped - (lib.getLib clang-unwrapped) compiler-rt compiler-rt.dev + libclang + libclang.lib + libllvm + libllvm.lib lld - llvm - llvm.lib ]); __stdenvImpureHostDeps = commonImpureHostDeps; From 1d7ad2626191b8086e3f613ee08107dfbea6d624 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 06/12] stdenv/darwin: use top-level libc --- pkgs/stdenv/darwin/default.nix | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 495fd25ebc7d7..10dd30a2416fd 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -673,9 +673,8 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check # Rewrap binutils with the real libSystem binutils = superDarwin.binutils.override { - inherit (self) coreutils; + inherit (self) coreutils libc; bintools = selfDarwin.binutils-unwrapped; - libc = selfDarwin.libSystem; }; # Avoid building unnecessary Python dependencies due to building LLVM manpages. @@ -837,7 +836,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check # Rewrap binutils so it uses the rebuilt Libsystem. binutils = superDarwin.binutils.override { inherit (prevStage) expand-response-params; - libc = selfDarwin.libSystem; + inherit (self) libc; }; } ); @@ -1125,7 +1124,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check extraAttrs = { inherit bootstrapTools; - libc = prevStage.darwin.libSystem; + inherit (prevStage) libc; shellPackage = prevStage.bashNonInteractive; }; From d474ba3a83169a74f2c5435187f59b6d2a9caa72 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 07/12] stdenv/darwin: build `expand-response-params` with an unwrapped compiler Building `expand-response-params` early in the bootstrap will allow the custom wrappers (for `cc` and `bintools`) to be dropped. --- pkgs/stdenv/darwin/default.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 10dd30a2416fd..3569978fbe311 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -415,6 +415,16 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check gnugrep = bootstrapTools; pbzx = bootstrapTools; + # Build expand-response-params with an unwrapped clang. This works because the SDK has headers and stubs, + # which is all that’s needed. + expand-response-params = super.expand-response-params.overrideAttrs (old: { + buildPhase = '' + CC=${bootstrapTools}/bin/clang + export SDKROOT=${self.apple-sdk.sdkroot} + '' + + old.buildPhase; + }); + jq = bootstrapTools; cctools = bootstrapTools // { From 2869d09ae92f236c412ccd53290f5ea12461c3aa Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 08/12] stdenv/darwin: drop custom wrappers for the standard ones This removes the need to keep these in sync, which should (hopefully) simplify maintenance. --- pkgs/stdenv/darwin/default.nix | 117 +-------------------------------- 1 file changed, 3 insertions(+), 114 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 3569978fbe311..c8dfde8297e1c 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -91,64 +91,7 @@ let }: let - cc = - if prevStage.llvmPackages.clang-unwrapped == null then - null - else - prevStage.wrapCCWith { - name = "${name}-clang-wrapper"; - - nativeTools = false; - nativeLibc = false; - - expand-response-params = lib.optionalString ( - prevStage.stdenv.hasCC or false && prevStage.stdenv.cc != "/dev/null" - ) prevStage.expand-response-params; - - extraPackages = [ prevStage.llvmPackages.compiler-rt ]; - - extraBuildCommands = - let - inherit (prevStage.llvmPackages) clang-unwrapped compiler-rt; - in - '' - function clangResourceRootIncludePath() { - clangLib="$1/lib/clang" - if (( $(ls "$clangLib" | wc -l) > 1 )); then - echo "Multiple LLVM versions were found at "$clangLib", but there must only be one used when building the stdenv." >&2 - exit 1 - fi - echo "$clangLib/$(ls -1 "$clangLib")/include" - } - - rsrc="$out/resource-root" - mkdir "$rsrc" - ln -s "$(clangResourceRootIncludePath "${lib.getLib clang-unwrapped}")" "$rsrc" - ln -s "${compiler-rt.out}/lib" "$rsrc/lib" - ln -s "${compiler-rt.out}/share" "$rsrc/share" - echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags - ''; - - cc = prevStage.llvmPackages.clang-unwrapped; - bintools = prevStage.darwin.binutils; - - isClang = true; - inherit (prevStage) libc; - # TODO: replace with `darwin.libcxx` once the bootstrap tools no longer have libc++. - libcxx = - if - prevStage.darwin.libcxx == null || name == "bootstrap-stage1" || name == "bootstrap-stage-xclang" - then - prevStage.llvmPackages.libcxx - else - prevStage.darwin.libcxx; - - inherit lib; - inherit (prevStage) coreutils gnugrep; - - stdenvNoCC = prevStage.ccWrapperStdenv; - runtimeShell = prevStage.ccWrapperStdenv.shell; - }; + cc = if prevStage.clang == null then null else prevStage.clang; bashNonInteractive = prevStage.bashNonInteractive or bootstrapTools; @@ -440,21 +383,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check darwin = super.darwin.overrideScope ( selfDarwin: superDarwin: { - binutils = super.wrapBintoolsWith { - name = "bootstrap-stage0-binutils-wrapper"; - - nativeTools = false; - nativeLibc = false; - - expand-response-params = ""; - libc = selfDarwin.libSystem; - - inherit lib; - inherit (self) stdenvNoCC coreutils gnugrep; - runtimeShell = self.stdenvNoCC.shell; - - bintools = selfDarwin.binutils-unwrapped; - }; binutils-unwrapped = (superDarwin.binutils-unwrapped.override { enableManpages = false; }).overrideAttrs @@ -503,6 +431,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ln -s ${bootstrapTools}/lib/clang/$(ls -1 ${bootstrapTools}/lib/clang) $out/lib/clang/${llvmVersion} ''; passthru = { + isClang = true; isFromBootstrapFiles = true; hardeningUnsupportedFlags = [ "fortify3" @@ -1004,54 +933,14 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check // llvmLibrariesDarwinDepsNoCC prevStage // { inherit (prevStage.darwin) binutils-unwrapped libSystem; - binutils = superDarwin.binutils.override { - # Build expand-response-params with last stage like below - inherit (prevStage) expand-response-params; - }; # Avoid rebuilding bmake (and Python) just for locales locale = superDarwin.locale.override { inherit (prevStage) bmake; }; } ); - _: _: - llvmToolsPackages prevStage - // llvmLibrariesPackages prevStage - // { - systemLibcxxClang = super.wrapCCWith rec { - nativeTools = false; - nativeLibc = false; - - inherit (prevStage) expand-response-params; - - extraPackages = [ self.llvmPackages.compiler-rt ]; - - extraBuildCommands = '' - rsrc="$out/resource-root" - mkdir "$rsrc" - ln -s "${lib.getLib cc}/lib/clang/${lib.versions.major (lib.getVersion cc)}/include" "$rsrc" - echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags - ln -s "${prevStage.llvmPackages.compiler-rt.out}/lib" "$rsrc/lib" - ln -s "${prevStage.llvmPackages.compiler-rt.out}/share" "$rsrc/share" - ''; - - cc = self.llvmPackages.clang-unwrapped; - bintools = self.darwin.binutils; - - isClang = true; - libc = self.darwin.libSystem; - inherit (self.darwin) libcxx; - - inherit lib; - inherit (self) - stdenvNoCC - coreutils - gnugrep - runtimeShell - ; - }; - } "llvmPackages_${llvmVersion}" = (super."llvmPackages_${llvmVersion}".overrideScope ( + _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage )) // { inherit (super."llvmPackages_${llvmVersion}") override; From 1e15717339ba7b656c029e9e5ff7d55896decc06 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 09/12] stdenv/darwin: manually propagate libc++ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the libc++ from the bootstrap. Once the past the xclang stage, the bootstrap uses the system libc++. Unfortunately, it doesn’t seem to work with the bootstrap tools. --- pkgs/stdenv/darwin/default.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index c8dfde8297e1c..9b2076f5e0577 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -383,6 +383,9 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check darwin = super.darwin.overrideScope ( selfDarwin: superDarwin: { + # The bootstrap tools provide a libc++ that is definitely compatible with the Clang in the bootstrap tools. + # Otherwise, it is possible for the bootstrap tools Clang to be too old for the system libc++ headers. + inherit (self.llvmPackages) libcxx; binutils-unwrapped = (superDarwin.binutils-unwrapped.override { enableManpages = false; }).overrideAttrs @@ -608,6 +611,10 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check selfDarwin: superDarwin: llvmLibrariesDarwinDepsNoCC prevStage // { + # The bootstrap tools provide a libc++ that is definitely compatible with the Clang in the bootstrap tools. + # Otherwise, it is possible for the bootstrap tools Clang to be too old for the system libc++ headers. + inherit (self.llvmPackages) libcxx; + signingUtils = prevStage.darwin.signingUtils.override { inherit (selfDarwin) sigtool; }; # Rewrap binutils with the real libSystem From ff91b8ca870ae60789d0285c2a653d19d0c3dc5d Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Fri, 21 Nov 2025 20:20:38 -0500 Subject: [PATCH 10/12] stdenv/darwin: remove unnecessary override --- pkgs/stdenv/darwin/default.nix | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 9b2076f5e0577..5a8b427c35c46 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -789,12 +789,7 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check "llvmPackages_${llvmVersion}" = (super."llvmPackages_${llvmVersion}".overrideScope ( - _: _: - llvmToolsPackages prevStage - // llvmLibrariesPackages prevStage - // { - inherit (prevStage."llvmPackages_${llvmVersion}") clangNoCompilerRtWithLibc; - } + _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage )) // { inherit (super."llvmPackages_${llvmVersion}") override; From 0adefff506db1205d8fa11c247822d046d18165d Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Tue, 18 Nov 2025 19:13:45 -0500 Subject: [PATCH 11/12] stdenv/darwin: drop unnecessary llvm-manpages override --- pkgs/stdenv/darwin/default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 5a8b427c35c46..7669332bed834 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -467,7 +467,6 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check ''; passthru.isFromBootstrapFiles = true; }; - llvm-manpages = self.llvmPackages.libllvm; lld = self.stdenv.mkDerivation { name = "bootstrap-stage0-lld"; buildCommand = ""; From ad2b074402ac146733f75ccd8bc8da19e575c886 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Sat, 20 Dec 2025 20:20:20 -0500 Subject: [PATCH 12/12] stdenv/darwin: work around `override` with `overrideScope` Co-authored-by: Emily --- pkgs/stdenv/darwin/default.nix | 282 ++++++++++++++++----------------- 1 file changed, 134 insertions(+), 148 deletions(-) diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 7669332bed834..1953e582369d5 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -45,6 +45,15 @@ let # Dependencies in dependency sets should be mutually exclusive. mergeDisjointAttrs = lib.foldl' lib.attrsets.unionOfDisjoint { }; + # Workaround for losing `override` after using `overrideScope` + # https://github.com/NixOS/nixpkgs/issues/447012 + overrideLlvmPackagesScope = + llvmPackages: f: + let + override = args: (llvmPackages.override args).overrideScope f; + in + lib.makeOverridable (lib.mirrorFunctionArgs llvmPackages.override override) { }; + commonPreHook = '' export NIX_ENFORCE_NO_NATIVE=''${NIX_ENFORCE_NO_NATIVE-1} export NIX_ENFORCE_PURITY=''${NIX_ENFORCE_PURITY-1} @@ -408,99 +417,95 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - "llvmPackages_${llvmVersion}" = - (super."llvmPackages_${llvmVersion}".overrideScope ( - selfLlvmPackages: _: { - libclang = self.stdenv.mkDerivation { - name = "bootstrap-stage0-clang"; - version = "boot"; - outputs = [ - "out" - "lib" - ]; - buildCommand = '' - mkdir -p $out - ln -s $out $lib - ln -s ${bootstrapTools}/bin $out/bin - ln -s ${bootstrapTools}/include $out - - # The version of clang in the bootstrap tools may be different from the default, but that’s okay. - # Symlink its resource-dir to the default version just to get past the first stage. - if (( $(ls "$clangLib" | wc -l) > 1 )); then - echo "Multiple LLVM versions were found at "$clangLib", but there must only be one used when building the stdenv." >&2 - exit 1 - fi - mkdir -p $out/lib/clang - ln -s ${bootstrapTools}/lib/clang/$(ls -1 ${bootstrapTools}/lib/clang) $out/lib/clang/${llvmVersion} - ''; - passthru = { - isClang = true; - isFromBootstrapFiles = true; - hardeningUnsupportedFlags = [ - "fortify3" - "pacret" - "shadowstack" - "stackclashprotection" - "zerocallusedregs" - ]; - }; - }; - libllvm = self.stdenv.mkDerivation { - name = "bootstrap-stage0-llvm"; - outputs = [ - "out" - "lib" + "llvmPackages_${llvmVersion}" = overrideLlvmPackagesScope super."llvmPackages_${llvmVersion}" ( + selfLlvmPackages: _: { + libclang = self.stdenv.mkDerivation { + name = "bootstrap-stage0-clang"; + version = "boot"; + outputs = [ + "out" + "lib" + ]; + buildCommand = '' + mkdir -p $out + ln -s $out $lib + ln -s ${bootstrapTools}/bin $out/bin + ln -s ${bootstrapTools}/include $out + + # The version of clang in the bootstrap tools may be different from the default, but that’s okay. + # Symlink its resource-dir to the default version just to get past the first stage. + if (( $(ls "$clangLib" | wc -l) > 1 )); then + echo "Multiple LLVM versions were found at "$clangLib", but there must only be one used when building the stdenv." >&2 + exit 1 + fi + mkdir -p $out/lib/clang + ln -s ${bootstrapTools}/lib/clang/$(ls -1 ${bootstrapTools}/lib/clang) $out/lib/clang/${llvmVersion} + ''; + passthru = { + isClang = true; + isFromBootstrapFiles = true; + hardeningUnsupportedFlags = [ + "fortify3" + "pacret" + "shadowstack" + "stackclashprotection" + "zerocallusedregs" ]; - buildCommand = '' - mkdir -p $out/bin $out/lib - ln -s $out $lib - for tool in ${toString super.darwin.binutils-unwrapped.llvm_cmds}; do - cctoolsTool=''${tool//-/_} - toolsrc="${bootstrapTools}/bin/$cctoolsTool" - if [ -e "$toolsrc" ]; then - ln -s "$toolsrc" $out/bin/llvm-$tool - fi - done - ln -s ${bootstrapTools}/bin/dsymutil $out/bin/dsymutil - ln -s ${bootstrapTools}/bin/llvm-readtapi $out/bin/llvm-readtapi - ln -s ${bootstrapTools}/lib/libLLVM* $out/lib - ''; - passthru.isFromBootstrapFiles = true; - }; - lld = self.stdenv.mkDerivation { - name = "bootstrap-stage0-lld"; - buildCommand = ""; - passthru = { - isLLVM = true; - isFromBootstrapFiles = true; - }; }; - compiler-rt = self.stdenv.mkDerivation { - name = "bootstrap-stage0-compiler-rt"; - buildCommand = '' - mkdir -p $out/lib $out/share - ln -s ${bootstrapTools}/lib/libclang_rt* $out/lib - ln -s ${bootstrapTools}/lib/darwin $out/lib - ''; - passthru.isFromBootstrapFiles = true; + }; + libllvm = self.stdenv.mkDerivation { + name = "bootstrap-stage0-llvm"; + outputs = [ + "out" + "lib" + ]; + buildCommand = '' + mkdir -p $out/bin $out/lib + ln -s $out $lib + for tool in ${toString super.darwin.binutils-unwrapped.llvm_cmds}; do + cctoolsTool=''${tool//-/_} + toolsrc="${bootstrapTools}/bin/$cctoolsTool" + if [ -e "$toolsrc" ]; then + ln -s "$toolsrc" $out/bin/llvm-$tool + fi + done + ln -s ${bootstrapTools}/bin/dsymutil $out/bin/dsymutil + ln -s ${bootstrapTools}/bin/llvm-readtapi $out/bin/llvm-readtapi + ln -s ${bootstrapTools}/lib/libLLVM* $out/lib + ''; + passthru.isFromBootstrapFiles = true; + }; + lld = self.stdenv.mkDerivation { + name = "bootstrap-stage0-lld"; + buildCommand = ""; + passthru = { + isLLVM = true; + isFromBootstrapFiles = true; }; - libcxx = self.stdenv.mkDerivation { - name = "bootstrap-stage0-libcxx"; - buildCommand = '' - mkdir -p $out/lib $out/include - ln -s ${bootstrapTools}/lib/libc++.dylib $out/lib - ln -s ${bootstrapTools}/include/c++ $out/include - ''; - passthru = { - isLLVM = true; - isFromBootstrapFiles = true; - }; + }; + compiler-rt = self.stdenv.mkDerivation { + name = "bootstrap-stage0-compiler-rt"; + buildCommand = '' + mkdir -p $out/lib $out/share + ln -s ${bootstrapTools}/lib/libclang_rt* $out/lib + ln -s ${bootstrapTools}/lib/darwin $out/lib + ''; + passthru.isFromBootstrapFiles = true; + }; + libcxx = self.stdenv.mkDerivation { + name = "bootstrap-stage0-libcxx"; + buildCommand = '' + mkdir -p $out/lib $out/include + ln -s ${bootstrapTools}/lib/libc++.dylib $out/lib + ln -s ${bootstrapTools}/include/c++ $out/include + ''; + passthru = { + isLLVM = true; + isFromBootstrapFiles = true; }; - } - )) - // { - inherit (super."llvmPackages_${llvmVersion}") override; - }; + }; + } + ); }; extraPreHook = '' @@ -630,13 +635,9 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - "llvmPackages_${llvmVersion}" = - (super."llvmPackages_${llvmVersion}".overrideScope ( - _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage - )) - // { - inherit (super."llvmPackages_${llvmVersion}") override; - }; + "llvmPackages_${llvmVersion}" = overrideLlvmPackagesScope super."llvmPackages_${llvmVersion}" ( + _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage + ); }; extraNativeBuildInputs = lib.optionals localSystem.isAarch64 [ @@ -786,13 +787,9 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - "llvmPackages_${llvmVersion}" = - (super."llvmPackages_${llvmVersion}".overrideScope ( - _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage - )) - // { - inherit (super."llvmPackages_${llvmVersion}") override; - }; + "llvmPackages_${llvmVersion}" = overrideLlvmPackagesScope super."llvmPackages_${llvmVersion}" ( + _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage + ); } ]; @@ -868,11 +865,9 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - "llvmPackages_${llvmVersion}" = - (super."llvmPackages_${llvmVersion}".overrideScope (_: _: llvmLibrariesPackages prevStage)) - // { - inherit (super."llvmPackages_${llvmVersion}") override; - }; + "llvmPackages_${llvmVersion}" = overrideLlvmPackagesScope super."llvmPackages_${llvmVersion}" ( + _: _: llvmLibrariesPackages prevStage + ); } ]; @@ -939,13 +934,9 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check } ); - "llvmPackages_${llvmVersion}" = - (super."llvmPackages_${llvmVersion}".overrideScope ( - _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage - )) - // { - inherit (super."llvmPackages_${llvmVersion}") override; - }; + "llvmPackages_${llvmVersion}" = overrideLlvmPackagesScope super."llvmPackages_${llvmVersion}" ( + _: _: llvmToolsPackages prevStage // llvmLibrariesPackages prevStage + ); } ]; @@ -1145,40 +1136,35 @@ assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check # darwin.binutils is not yet ready to be target-independent. (lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) (bintoolsPackages prevStage)) { - "llvmPackages_${llvmVersion}" = - (super."llvmPackages_${llvmVersion}".overrideScope ( - finalLLVM: _: - # These are defined explicitly to make sure that overriding their dependencies using `overrideScope` - # still works. `llvmPackages.libcxx` is not included because it’s not part of the Darwin stdenv. - { - inherit (prevStage."llvmPackages_${llvmVersion}") libllvm; - libclang = prevStage."llvmPackages_${llvmVersion}".libclang.override { - inherit (finalLLVM) libllvm; - }; - lld = prevStage."llvmPackages_${llvmVersion}".lld.override { - inherit (finalLLVM) libllvm; - }; - } - # Avoid using the llvm-manpages package from the bootstrap, which won’t build due to needing curl. - // { - inherit (super."llvmPackages_${llvmVersion}") llvm-manpages; - } - // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) { - # Make sure the following are all the same in the local == target case: - # - clang - # - llvmPackages.stdenv.cc - # - llvmPackages.systemLibcxxClang. - # - llvmPackages.clang - # - stdenv.cc - systemLibcxxClang = prevStage."llvmPackages_${llvmVersion}".systemLibcxxClang.override { - cc = finalLLVM.clang-unwrapped; - }; - } - )) + "llvmPackages_${llvmVersion}" = overrideLlvmPackagesScope super."llvmPackages_${llvmVersion}" ( + finalLLVM: _: + # These are defined explicitly to make sure that overriding their dependencies using `overrideScope` + # still works. `llvmPackages.libcxx` is not included because it’s not part of the Darwin stdenv. + { + inherit (prevStage."llvmPackages_${llvmVersion}") libllvm; + libclang = prevStage."llvmPackages_${llvmVersion}".libclang.override { + inherit (finalLLVM) libllvm; + }; + lld = prevStage."llvmPackages_${llvmVersion}".lld.override { + inherit (finalLLVM) libllvm; + }; + } + # Avoid using the llvm-manpages package from the bootstrap, which won’t build due to needing curl. // { - inherit (super."llvmPackages_${llvmVersion}") override; - recurseForDerivations = true; - }; + inherit (super."llvmPackages_${llvmVersion}") llvm-manpages; + } + // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) { + # Make sure the following are all the same in the local == target case: + # - clang + # - llvmPackages.stdenv.cc + # - llvmPackages.systemLibcxxClang. + # - llvmPackages.clang + # - stdenv.cc + systemLibcxxClang = prevStage."llvmPackages_${llvmVersion}".systemLibcxxClang.override { + cc = finalLLVM.clang-unwrapped; + }; + } + ); } ]; };