1# This file contains the standard build environment for Darwin. It is based on LLVM and is patterned
2# after the Linux stdenv. It shares similar goals to the Linux standard environment in that the
3# resulting environment should be built purely and not contain any references to it.
4#
5# For more on the design of the stdenv and updating it, see `README.md`.
6#
7# See also the top comments of the Linux stdenv `../linux/default.nix` for a good overview of
8# the bootstrap process and working with it.
9
10{
11 lib,
12 localSystem,
13 crossSystem,
14 config,
15 overlays,
16 crossOverlays ? [ ],
17 # Allow passing in bootstrap files directly so we can test the stdenv bootstrap process when changing the bootstrap tools
18 bootstrapFiles ? (config.replaceBootstrapFiles or lib.id) (
19 if localSystem.isAarch64 then
20 import ./bootstrap-files/aarch64-apple-darwin.nix
21 else
22 import ./bootstrap-files/x86_64-apple-darwin.nix
23 ),
24}:
25
26assert crossSystem == localSystem;
27
28let
29 inherit (localSystem) system;
30
31 sdkMajorVersion = lib.versions.major localSystem.darwinSdkVersion;
32
33 commonImpureHostDeps = [
34 "/bin/sh"
35 "/usr/lib/libSystem.B.dylib"
36 "/usr/lib/system/libunc.dylib" # This dependency is "hidden", so our scanning code doesn't pick it up
37 ];
38
39 isFromNixpkgs = pkg: !(isFromBootstrapFiles pkg);
40 isFromBootstrapFiles = pkg: pkg.passthru.isFromBootstrapFiles or false;
41 isBuiltByNixpkgsCompiler = pkg: isFromNixpkgs pkg && isFromNixpkgs pkg.stdenv.cc.cc;
42 isBuiltByBootstrapFilesCompiler = pkg: isFromNixpkgs pkg && isFromBootstrapFiles pkg.stdenv.cc.cc;
43
44 # Dependencies in dependency sets should be mutually exclusive.
45 mergeDisjointAttrs = lib.foldl' lib.attrsets.unionOfDisjoint { };
46
47 commonPreHook = ''
48 export NIX_ENFORCE_NO_NATIVE=''${NIX_ENFORCE_NO_NATIVE-1}
49 export NIX_ENFORCE_PURITY=''${NIX_ENFORCE_PURITY-1}
50 export NIX_IGNORE_LD_THROUGH_GCC=1
51 '';
52
53 bootstrapTools =
54 derivation (
55 {
56 inherit system;
57
58 name = "bootstrap-tools";
59 builder = "${bootstrapFiles.unpack}/bin/bash";
60
61 args = [
62 "${bootstrapFiles.unpack}/bootstrap-tools-unpack.sh"
63 bootstrapFiles.bootstrapTools
64 ];
65
66 PATH = lib.makeBinPath [
67 (placeholder "out")
68 bootstrapFiles.unpack
69 ];
70
71 __impureHostDeps = commonImpureHostDeps;
72 }
73 // lib.optionalAttrs config.contentAddressedByDefault {
74 __contentAddressed = true;
75 outputHashAlgo = "sha256";
76 outputHashMode = "recursive";
77 }
78 )
79 // {
80 passthru.isFromBootstrapFiles = true;
81 };
82
83 stageFun =
84 prevStage:
85 {
86 name,
87 overrides ? (self: super: { }),
88 extraNativeBuildInputs ? [ ],
89 extraPreHook ? "",
90 }:
91
92 let
93 cc =
94 if prevStage.llvmPackages.clang-unwrapped == null then
95 null
96 else
97 prevStage.wrapCCWith {
98 name = "${name}-clang-wrapper";
99
100 nativeTools = false;
101 nativeLibc = false;
102
103 expand-response-params = lib.optionalString (
104 prevStage.stdenv.hasCC or false && prevStage.stdenv.cc != "/dev/null"
105 ) prevStage.expand-response-params;
106
107 extraPackages = [ prevStage.llvmPackages.compiler-rt ];
108
109 extraBuildCommands =
110 let
111 inherit (prevStage.llvmPackages) clang-unwrapped compiler-rt;
112 in
113 ''
114 function clangResourceRootIncludePath() {
115 clangLib="$1/lib/clang"
116 if (( $(ls "$clangLib" | wc -l) > 1 )); then
117 echo "Multiple LLVM versions were found at "$clangLib", but there must only be one used when building the stdenv." >&2
118 exit 1
119 fi
120 echo "$clangLib/$(ls -1 "$clangLib")/include"
121 }
122
123 rsrc="$out/resource-root"
124 mkdir "$rsrc"
125 ln -s "$(clangResourceRootIncludePath "${lib.getLib clang-unwrapped}")" "$rsrc"
126 ln -s "${compiler-rt.out}/lib" "$rsrc/lib"
127 ln -s "${compiler-rt.out}/share" "$rsrc/share"
128 echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
129 '';
130
131 cc = prevStage.llvmPackages.clang-unwrapped;
132 bintools = prevStage.darwin.binutils;
133
134 isClang = true;
135 inherit (prevStage) libc;
136 inherit (prevStage.llvmPackages) libcxx;
137
138 inherit lib;
139 inherit (prevStage) coreutils gnugrep;
140
141 stdenvNoCC = prevStage.ccWrapperStdenv;
142 runtimeShell = prevStage.ccWrapperStdenv.shell;
143 };
144
145 bashNonInteractive = prevStage.bashNonInteractive or bootstrapTools;
146
147 thisStdenv = import ../generic {
148 name = "${name}-stdenv-darwin";
149
150 buildPlatform = localSystem;
151 hostPlatform = localSystem;
152 targetPlatform = localSystem;
153
154 inherit config;
155
156 extraBuildInputs = [ prevStage.apple-sdk ];
157 inherit extraNativeBuildInputs;
158
159 preHook =
160 lib.optionalString (!isBuiltByNixpkgsCompiler bashNonInteractive) ''
161 # Don't patch #!/interpreter because it leads to retained
162 # dependencies on the bootstrapTools in the final stdenv.
163 dontPatchShebangs=1
164 ''
165 + ''
166 ${commonPreHook}
167 ${extraPreHook}
168 ''
169 + lib.optionalString (prevStage.darwin ? locale) ''
170 export PATH_LOCALE=${prevStage.darwin.locale}/share/locale
171 '';
172
173 shell = bashNonInteractive + "/bin/bash";
174 initialPath = [
175 bashNonInteractive
176 prevStage.file
177 bootstrapTools
178 ];
179
180 fetchurlBoot = import ../../build-support/fetchurl {
181 inherit lib;
182 stdenvNoCC = prevStage.ccWrapperStdenv or thisStdenv;
183 curl = bootstrapTools;
184 inherit (config) rewriteURL;
185 };
186
187 inherit cc;
188
189 # The stdenvs themselves don't use mkDerivation, so I need to specify this here
190 __stdenvImpureHostDeps = commonImpureHostDeps;
191 __extraImpureHostDeps = commonImpureHostDeps;
192
193 # Using the bootstrap tools curl for fetchers allows the stdenv bootstrap to avoid
194 # having a dependency on curl, allowing curl to be updated without triggering a
195 # new stdenv bootstrap on Darwin.
196 overrides =
197 self: super:
198 (overrides self super)
199 // {
200 fetchurl = thisStdenv.fetchurlBoot;
201 fetchpatch = super.fetchpatch.override { inherit (self) fetchurl; };
202 fetchzip = super.fetchzip.override { inherit (self) fetchurl; };
203 };
204 };
205
206 in
207 {
208 inherit config overlays;
209 stdenv = thisStdenv;
210 };
211
212 # Dependencies - these are packages that are rebuilt together in groups. Defining them here ensures they are
213 # asserted and overlaid together. It also removes a lot of clutter from the stage definitions.
214 #
215 # When multiple dependency sets share a dependency, it should be put in the one that will be (re)built first.
216 # That makes sure everything else will share the same dependency in the final stdenv.
217
218 allDeps =
219 checkFn: sets:
220 let
221 sets' = mergeDisjointAttrs sets;
222 result = lib.all checkFn (lib.attrValues sets');
223 resultDetails = lib.mapAttrs (_: checkFn) sets';
224 in
225 lib.traceIf (!result) (lib.deepSeq resultDetails resultDetails) result;
226
227 # These packages are built in stage 1 then never built again. They must not be included in the final overlay
228 # or as dependencies to packages that are in the final overlay. They are mostly tools used as native build inputs.
229 # Any libraries in the list must only be used as dependencies of packages in this list.
230 stage1Packages = prevStage: {
231 inherit (prevStage)
232 atf
233 autoconf
234 automake
235 bison
236 bmake
237 brotli
238 cmake
239 cpio
240 cyrus_sasl
241 ed
242 expat
243 flex
244 gettext
245 groff
246 jq
247 kyua
248 libedit
249 libtool
250 m4
251 meson
252 ninja
253 openssh
254 patchutils
255 pbzx
256 perl
257 pkg-config
258 python3
259 python3Minimal
260 scons
261 serf
262 sqlite
263 subversion
264 texinfo
265 unzip
266 which
267 ;
268 };
269
270 # These packages include both the core bintools (other than LLVM) packages as well as their dependencies.
271 bintoolsPackages = prevStage: {
272 inherit (prevStage)
273 cctools
274 ld64
275 bzip2
276 coreutils
277 gmp
278 gnugrep
279 openssl
280 pcre2
281 xar
282 xz
283 ;
284 };
285
286 darwinPackages = prevStage: { inherit (prevStage.darwin) sigtool; };
287 darwinPackagesNoCC = prevStage: {
288 inherit (prevStage.darwin)
289 binutils
290 binutils-unwrapped
291 libSystem
292 locale
293 ;
294 };
295
296 # These packages are not allowed to be used in the Darwin bootstrap
297 disallowedPackages = prevStage: { inherit (prevStage) binutils-unwrapped curl; };
298
299 # LLVM tools packages are staged separately (xclang, stage3) from LLVM libs (xclang).
300 llvmLibrariesPackages = prevStage: { inherit (prevStage.llvmPackages) compiler-rt libcxx; };
301 llvmLibrariesDeps = _: { };
302
303 llvmToolsPackages = prevStage: {
304 inherit (prevStage.llvmPackages)
305 clang-unwrapped
306 libclang
307 libllvm
308 lld
309 llvm
310 llvm-manpages
311 ;
312 };
313
314 llvmToolsDeps = prevStage: { inherit (prevStage) libffi; };
315
316 # SDK packages include propagated packages and source release packages built during the bootstrap.
317 sdkPackages = prevStage: {
318 inherit (prevStage)
319 bashNonInteractive
320 libpng
321 libxml2
322 libxo
323 ncurses
324 openpam
325 xcbuild
326 zlib
327 ;
328 };
329 sdkDarwinPackages = prevStage: {
330 inherit (prevStage.darwin)
331 Csu
332 adv_cmds
333 copyfile
334 libiconv
335 libresolv
336 libsbuf
337 libutil
338 system_cmds
339 ;
340 };
341 sdkPackagesNoCC = prevStage: { inherit (prevStage) apple-sdk; };
342
343in
344assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
345[
346 (
347 { }:
348 {
349 __raw = true;
350
351 apple-sdk = null;
352
353 cctools = null;
354 ld64 = null;
355
356 coreutils = null;
357 file = null;
358 gnugrep = null;
359
360 pbzx = null;
361 cpio = null;
362
363 jq = null;
364
365 darwin = {
366 binutils = null;
367 binutils-unwrapped = null;
368 libSystem = null;
369 sigtool = null;
370 };
371
372 llvmPackages = {
373 clang-unwrapped = null;
374 compiler-rt = null;
375 libcxx = null;
376 libllvm = null;
377 };
378 }
379 )
380
381 # Create a stage with the bootstrap tools. This will be used to build the subsequent stages and
382 # build up the standard environment.
383 #
384 # Note: Each stage depends only on the the packages in `prevStage`. If a package is not to be
385 # rebuilt, it should be passed through by inheriting it.
386 (
387 prevStage:
388 stageFun prevStage {
389 name = "bootstrap-stage0";
390
391 overrides = self: super: {
392 # We thread stage0's stdenv through under this name so downstream stages
393 # can use it for wrapping gcc too. This way, downstream stages don't need
394 # to refer to this stage directly, which violates the principle that each
395 # stage should only access the stage that came before it.
396 ccWrapperStdenv = self.stdenv;
397
398 bashNonInteractive = bootstrapTools // {
399 shellPath = "/bin/bash";
400 };
401
402 coreutils = bootstrapTools;
403 cpio = bootstrapTools;
404 file = null;
405 gnugrep = bootstrapTools;
406 pbzx = bootstrapTools;
407
408 jq = bootstrapTools;
409
410 cctools = bootstrapTools // {
411 libtool = bootstrapTools;
412 targetPrefix = "";
413 version = "boot";
414 };
415
416 ld64 = bootstrapTools // {
417 targetPrefix = "";
418 version = "boot";
419 };
420
421 darwin = super.darwin.overrideScope (
422 selfDarwin: superDarwin: {
423 binutils = super.wrapBintoolsWith {
424 name = "bootstrap-stage0-binutils-wrapper";
425
426 nativeTools = false;
427 nativeLibc = false;
428
429 expand-response-params = "";
430 libc = selfDarwin.libSystem;
431
432 inherit lib;
433 inherit (self) stdenvNoCC coreutils gnugrep;
434 runtimeShell = self.stdenvNoCC.shell;
435
436 bintools = selfDarwin.binutils-unwrapped;
437 };
438
439 binutils-unwrapped =
440 (superDarwin.binutils-unwrapped.override { enableManpages = false; }).overrideAttrs
441 (old: {
442 version = "boot";
443 __intentionallyOverridingVersion = true; # to avoid a warning suggesting to provide src
444 passthru = (old.passthru or { }) // {
445 isFromBootstrapFiles = true;
446 };
447 });
448
449 locale = self.stdenv.mkDerivation {
450 name = "bootstrap-stage0-locale";
451 buildCommand = ''
452 mkdir -p $out/share/locale
453 '';
454 };
455
456 sigtool = bootstrapTools;
457 }
458 );
459
460 llvmPackages =
461 super.llvmPackages
462 // (
463 let
464 tools = super.llvmPackages.tools.extend (
465 selfTools: _: {
466 libclang = self.stdenv.mkDerivation {
467 name = "bootstrap-stage0-clang";
468 version = "boot";
469 outputs = [
470 "out"
471 "lib"
472 ];
473 buildCommand = ''
474 mkdir -p $out/lib
475 ln -s $out $lib
476 ln -s ${bootstrapTools}/bin $out/bin
477 ln -s ${bootstrapTools}/lib/clang $out/lib
478 ln -s ${bootstrapTools}/include $out
479 '';
480 passthru = {
481 isFromBootstrapFiles = true;
482 hardeningUnsupportedFlags = [
483 "fortify3"
484 "pacret"
485 "shadowstack"
486 "stackclashprotection"
487 "zerocallusedregs"
488 ];
489 };
490 };
491 libllvm = self.stdenv.mkDerivation {
492 name = "bootstrap-stage0-llvm";
493 outputs = [
494 "out"
495 "lib"
496 ];
497 buildCommand = ''
498 mkdir -p $out/bin $out/lib
499 ln -s $out $lib
500 for tool in ${toString super.darwin.binutils-unwrapped.llvm_cmds}; do
501 cctoolsTool=''${tool//-/_}
502 toolsrc="${bootstrapTools}/bin/$cctoolsTool"
503 if [ -e "$toolsrc" ]; then
504 ln -s "$toolsrc" $out/bin/llvm-$tool
505 fi
506 done
507 ln -s ${bootstrapTools}/bin/dsymutil $out/bin/dsymutil
508 ln -s ${bootstrapTools}/bin/llvm-readtapi $out/bin/llvm-readtapi
509 ln -s ${bootstrapTools}/lib/libLLVM* $out/lib
510 '';
511 passthru.isFromBootstrapFiles = true;
512 };
513 llvm-manpages = self.llvmPackages.libllvm;
514 lld = self.stdenv.mkDerivation {
515 name = "bootstrap-stage0-lld";
516 buildCommand = "";
517 passthru = {
518 isLLVM = true;
519 isFromBootstrapFiles = true;
520 };
521 };
522 }
523 );
524 libraries = super.llvmPackages.libraries.extend (
525 _: _: {
526 compiler-rt = self.stdenv.mkDerivation {
527 name = "bootstrap-stage0-compiler-rt";
528 buildCommand = ''
529 mkdir -p $out/lib $out/share
530 ln -s ${bootstrapTools}/lib/libclang_rt* $out/lib
531 ln -s ${bootstrapTools}/lib/darwin $out/lib
532 '';
533 passthru.isFromBootstrapFiles = true;
534 };
535 libcxx = self.stdenv.mkDerivation {
536 name = "bootstrap-stage0-libcxx";
537 buildCommand = ''
538 mkdir -p $out/lib $out/include
539 ln -s ${bootstrapTools}/lib/libc++.dylib $out/lib
540 ln -s ${bootstrapTools}/include/c++ $out/include
541 '';
542 passthru = {
543 isLLVM = true;
544 isFromBootstrapFiles = true;
545 };
546 };
547 }
548 );
549 in
550 { inherit tools libraries; } // tools // libraries
551 );
552 };
553
554 extraPreHook = ''
555 stripDebugFlags="-S" # llvm-strip does not support "-p" for Mach-O
556 '';
557 }
558 )
559
560 # This stage is primarily responsible for setting up versions of certain dependencies needed
561 # by the rest of the build process. This stage also builds CF and Libsystem to simplify assertions
562 # and assumptions for later by making sure both packages are present on x86_64-darwin and aarch64-darwin.
563 (
564 prevStage:
565 # previous stage0 stdenv:
566 assert allDeps isFromBootstrapFiles [
567 (llvmToolsPackages prevStage)
568 (llvmLibrariesPackages prevStage)
569 {
570 inherit (prevStage)
571 bashNonInteractive
572 cctools
573 coreutils
574 cpio
575 gnugrep
576 ld64
577 pbzx
578 ;
579 inherit (prevStage.darwin) binutils-unwrapped sigtool;
580 }
581 ];
582
583 assert allDeps isFromNixpkgs [
584 (sdkPackagesNoCC prevStage)
585 {
586 inherit (prevStage.darwin) binutils libSystem;
587 inherit (prevStage) libc;
588 }
589 ];
590
591 stageFun prevStage {
592 name = "bootstrap-stage1";
593
594 overrides = self: super: {
595 inherit (prevStage) ccWrapperStdenv cctools ld64;
596
597 binutils-unwrapped = builtins.throw "nothing in the Darwin bootstrap should depend on GNU binutils";
598 curl = builtins.throw "nothing in the Darwin bootstrap can depend on curl";
599
600 # Use this stage’s CF to build CMake. It’s required but can’t be included in the stdenv.
601 cmake = self.cmakeMinimal;
602
603 # Use libiconvReal with gettext to break an infinite recursion.
604 gettext = super.gettext.override { libiconv = super.libiconvReal; };
605
606 # Disable grep’s tests for now due to impure locale updates in
607 # macOS 15.4 breaking them in the bootstrap.
608 gnugrep = super.gnugrep.overrideAttrs { doCheck = false; };
609
610 # Disable tests because they use dejagnu, which fails to run.
611 libffi = super.libffi.override { doCheck = false; };
612
613 # Avoid pulling in a full python and its extra dependencies for the llvm/clang builds.
614 libxml2 = super.libxml2.override { pythonSupport = false; };
615
616 # TODO: The Meson tests fail when using pkgconf, as we do in
617 # the bootstrap. Remove this once that’s fixed.
618 meson = super.meson.overrideAttrs { doInstallCheck = false; };
619
620 ninja = super.ninja.override { buildDocs = false; };
621
622 # pkg-config builds glib, which checks for `arpa/nameser.h` and fails to build if it can’t find it.
623 # libresolv is normally propagated by the SDK, but propagation is disabled early in the bootstrap.
624 # Trying to add libresolv as a dependency causes an infinite recursion. Use pkgconf instead.
625 pkg-config =
626 (super.pkg-config.override {
627 pkg-config = self.libpkgconf.override {
628 removeReferencesTo = self.removeReferencesTo.override {
629 # Avoid an infinite recursion by using the previous stage‘s sigtool.
630 signingUtils = prevStage.darwin.signingUtils.override { inherit (prevStage.darwin) sigtool; };
631 };
632 };
633 baseBinName = "pkgconf";
634 }).overrideAttrs
635 # Passthru the wrapped pkgconf’s stdenv to make the bootstrap assertions happy.
636 (
637 old: {
638 passthru = old.passthru or { } // {
639 inherit (self) stdenv;
640 };
641 }
642 );
643
644 # Use a full Python for the bootstrap. This allows Meson to be built in stage 1 and makes it easier to build
645 # packages that have Python dependencies.
646 python3 = self.python3-bootstrap;
647 python3-bootstrap = super.python3.override {
648 self = self.python3-bootstrap;
649 pythonAttr = "python3-bootstrap";
650 enableLTO = false;
651 };
652
653 scons = super.scons.override { python3Packages = self.python3.pkgs; };
654
655 xar = super.xarMinimal;
656
657 darwin = super.darwin.overrideScope (
658 selfDarwin: superDarwin: {
659 signingUtils = prevStage.darwin.signingUtils.override { inherit (selfDarwin) sigtool; };
660
661 # Rewrap binutils with the real libSystem
662 binutils = superDarwin.binutils.override {
663 inherit (self) coreutils;
664 bintools = selfDarwin.binutils-unwrapped;
665 libc = selfDarwin.libSystem;
666 };
667
668 # Avoid building unnecessary Python dependencies due to building LLVM manpages.
669 binutils-unwrapped = superDarwin.binutils-unwrapped.override {
670 inherit (self) cctools ld64;
671 enableManpages = false;
672 };
673 }
674 );
675
676 llvmPackages =
677 let
678 tools = super.llvmPackages.tools.extend (_: _: llvmToolsPackages prevStage);
679 libraries = super.llvmPackages.libraries.extend (_: _: llvmLibrariesPackages prevStage);
680 in
681 super.llvmPackages // { inherit tools libraries; } // tools // libraries;
682 };
683
684 extraNativeBuildInputs = lib.optionals localSystem.isAarch64 [
685 prevStage.updateAutotoolsGnuConfigScriptsHook
686 prevStage.gnu-config
687 ];
688
689 extraPreHook = ''
690 stripDebugFlags="-S" # llvm-strip does not support "-p" for Mach-O
691 '';
692 }
693 )
694
695 # First rebuild of LLVM. While this LLVM is linked to a bunch of junk from the bootstrap tools,
696 # the compiler-rt, libc++, and libc++abi it produces are not. The compiler will be
697 # rebuilt in a later stage, but those libraries will be used in the final stdenv.
698 (
699 prevStage:
700 # previous stage1 stdenv:
701 assert allDeps isFromBootstrapFiles [
702 (llvmLibrariesPackages prevStage)
703 (llvmToolsPackages prevStage)
704 { inherit (prevStage) ld64; }
705 ];
706
707 assert allDeps isBuiltByBootstrapFilesCompiler [
708 (stage1Packages prevStage)
709 (darwinPackages prevStage)
710 (llvmLibrariesDeps prevStage)
711 (llvmToolsDeps prevStage)
712 (sdkPackages prevStage)
713 (sdkDarwinPackages prevStage)
714 ];
715
716 assert allDeps isFromNixpkgs [
717 (darwinPackagesNoCC prevStage)
718 (sdkPackagesNoCC prevStage)
719 ];
720
721 stageFun prevStage {
722 name = "bootstrap-stage-xclang";
723
724 overrides =
725 self: super:
726 mergeDisjointAttrs [
727 (stage1Packages prevStage)
728 (disallowedPackages prevStage)
729 # Only cctools and ld64 are rebuilt from `bintoolsPackages` to avoid rebuilding their dependencies
730 # again in this stage after building them in stage 1.
731 (lib.filterAttrs (name: _: name != "ld64" && name != "cctools") (bintoolsPackages prevStage))
732 (llvmToolsDeps prevStage)
733 (sdkPackages prevStage)
734 (sdkPackagesNoCC prevStage)
735 {
736 inherit (prevStage) ccWrapperStdenv;
737
738 # Disable ld64’s install check phase because the required LTO libraries are not built yet.
739 ld64 = super.ld64.overrideAttrs { doInstallCheck = false; };
740
741 darwin = super.darwin.overrideScope (
742 selfDarwin: superDarwin:
743 darwinPackages prevStage
744 // sdkDarwinPackages prevStage
745 // {
746 inherit (prevStage.darwin) libSystem;
747 binutils-unwrapped = superDarwin.binutils-unwrapped.override { enableManpages = false; };
748 }
749 );
750 }
751 ];
752
753 extraNativeBuildInputs = lib.optionals localSystem.isAarch64 [
754 prevStage.updateAutotoolsGnuConfigScriptsHook
755 prevStage.gnu-config
756 ];
757
758 extraPreHook = ''
759 stripDebugFlags="-S" # llvm-strip does not support "-p" for Mach-O
760 '';
761 }
762 )
763
764 # This stage rebuilds the SDK. It also rebuilds bash, which will be needed in later stages
765 # to use in patched shebangs (e.g., to make sure `icu-config` uses bash from nixpkgs).
766 (
767 prevStage:
768 # previous stage-xclang stdenv:
769 assert allDeps isBuiltByBootstrapFilesCompiler [
770 (stage1Packages prevStage)
771 (bintoolsPackages prevStage)
772 (darwinPackages prevStage)
773 (llvmToolsDeps prevStage)
774 (llvmToolsPackages prevStage)
775 (sdkPackages prevStage)
776 (sdkDarwinPackages prevStage)
777 ];
778
779 assert allDeps isBuiltByNixpkgsCompiler [
780 (llvmLibrariesDeps prevStage)
781 (llvmLibrariesPackages prevStage)
782 ];
783
784 assert allDeps isFromNixpkgs [
785 (darwinPackagesNoCC prevStage)
786 (sdkPackagesNoCC prevStage)
787 ];
788
789 stageFun prevStage {
790 name = "bootstrap-stage2";
791
792 overrides =
793 self: super:
794 mergeDisjointAttrs [
795 (stage1Packages prevStage)
796 (disallowedPackages prevStage)
797 (bintoolsPackages prevStage)
798 (llvmLibrariesDeps prevStage)
799 (llvmToolsDeps prevStage)
800 {
801 inherit (prevStage) ccWrapperStdenv;
802
803 # Avoid an infinite recursion due to the SDK’s including ncurses, which depends on bash in its `dev` output.
804 bashNonInteractive = super.bashNonInteractive.override { stdenv = self.darwin.bootstrapStdenv; };
805
806 # Avoid pulling in a full python and its extra dependencies for the llvm/clang builds.
807 libxml2 = super.libxml2.override { pythonSupport = false; };
808
809 # Use Bash from this stage to avoid propagating Bash from a previous stage to the final stdenv.
810 ncurses = super.ncurses.override {
811 stdenv = self.darwin.bootstrapStdenv.override { shell = lib.getExe self.bashNonInteractive; };
812 };
813
814 darwin = super.darwin.overrideScope (
815 selfDarwin: superDarwin:
816 darwinPackages prevStage
817 // {
818 inherit (prevStage.darwin) binutils-unwrapped;
819 # Rewrap binutils so it uses the rebuilt Libsystem.
820 binutils = superDarwin.binutils.override {
821 inherit (prevStage) expand-response-params;
822 libc = selfDarwin.libSystem;
823 };
824 }
825 );
826
827 llvmPackages =
828 let
829 tools = super.llvmPackages.tools.extend (
830 _: _: llvmToolsPackages prevStage // { inherit (prevStage.llvmPackages) clangNoCompilerRtWithLibc; }
831 );
832 libraries = super.llvmPackages.libraries.extend (_: _: llvmLibrariesPackages prevStage);
833 in
834 super.llvmPackages // { inherit tools libraries; } // tools // libraries;
835 }
836 ];
837
838 extraNativeBuildInputs = lib.optionals localSystem.isAarch64 [
839 prevStage.updateAutotoolsGnuConfigScriptsHook
840 prevStage.gnu-config
841 ];
842
843 extraPreHook = ''
844 stripDebugFlags="-S" # llvm-strip does not support "-p" for Mach-O
845 '';
846 }
847 )
848
849 # Rebuild LLVM with LLVM. This stage also rebuilds certain dependencies needed by LLVM.
850 # The SDK (but not its other inputs) is also rebuilt this stage to pick up the rebuilt cctools for `libtool`.
851 (
852 prevStage:
853 # previous stage2 stdenv:
854 assert allDeps isBuiltByBootstrapFilesCompiler [
855 (stage1Packages prevStage)
856 (bintoolsPackages prevStage)
857 (darwinPackages prevStage)
858 (llvmToolsPackages prevStage)
859 (llvmToolsDeps prevStage)
860 ];
861
862 assert allDeps isBuiltByNixpkgsCompiler [
863 (llvmLibrariesDeps prevStage)
864 (llvmLibrariesPackages prevStage)
865 (sdkPackages prevStage)
866 (sdkDarwinPackages prevStage)
867 ];
868
869 assert allDeps isFromNixpkgs [
870 (darwinPackagesNoCC prevStage)
871 (sdkPackagesNoCC prevStage)
872 ];
873
874 stageFun prevStage {
875 name = "bootstrap-stage3";
876
877 overrides =
878 self: super:
879 mergeDisjointAttrs [
880 (stage1Packages prevStage)
881 (disallowedPackages prevStage)
882 (llvmLibrariesDeps prevStage)
883 (sdkPackages prevStage)
884 {
885 inherit (prevStage) ccWrapperStdenv;
886
887 # Disable tests because they use dejagnu, which fails to run.
888 libffi = super.libffi.override { doCheck = false; };
889
890 xar = super.xarMinimal;
891
892 darwin = super.darwin.overrideScope (
893 selfDarwin: superDarwin:
894 darwinPackages prevStage
895 // sdkDarwinPackages prevStage
896 # Rebuild darwin.binutils with the new LLVM, so only inherit libSystem from the previous stage.
897 // {
898 inherit (prevStage.darwin) libSystem;
899
900 # Disable building the documentation due to the dependency on llvm-manpages,
901 # which brings in a bunch of Python dependencies.
902 binutils-unwrapped = superDarwin.binutils-unwrapped.override {
903 inherit (self) cctools ld64;
904 enableManpages = false;
905 };
906 }
907 );
908
909 llvmPackages =
910 let
911 libraries = super.llvmPackages.libraries.extend (_: _: llvmLibrariesPackages prevStage);
912 in
913 super.llvmPackages // { inherit libraries; } // libraries;
914 }
915 ];
916
917 extraNativeBuildInputs = lib.optionals localSystem.isAarch64 [
918 prevStage.updateAutotoolsGnuConfigScriptsHook
919 prevStage.gnu-config
920 ];
921
922 extraPreHook = ''
923 stripDebugFlags="-S" # llvm-strip does not support "-p" for Mach-O
924 '';
925 }
926 )
927
928 # Construct a standard environment with the new clang. Also use the new compiler to rebuild
929 # everything that will be part of the final stdenv and isn’t required by it, CF, or Libsystem.
930 (
931 prevStage:
932 # previous stage3 stdenv:
933 assert allDeps isBuiltByBootstrapFilesCompiler [
934 (stage1Packages prevStage)
935 (darwinPackages prevStage)
936 ];
937
938 assert allDeps isBuiltByNixpkgsCompiler [
939 (bintoolsPackages prevStage)
940 (llvmLibrariesDeps prevStage)
941 (llvmLibrariesPackages prevStage)
942 (llvmToolsDeps prevStage)
943 (llvmToolsPackages prevStage)
944 (sdkPackages prevStage)
945 (sdkDarwinPackages prevStage)
946 ];
947
948 assert allDeps isFromNixpkgs [
949 (darwinPackagesNoCC prevStage)
950 (sdkPackagesNoCC prevStage)
951 ];
952
953 stageFun prevStage {
954 name = "bootstrap-stage4";
955
956 overrides =
957 self: super:
958 mergeDisjointAttrs [
959 (bintoolsPackages prevStage)
960 (disallowedPackages prevStage)
961 (llvmLibrariesDeps prevStage)
962 (llvmToolsDeps prevStage)
963 (sdkPackages prevStage)
964 (sdkPackagesNoCC prevStage)
965 {
966 inherit (prevStage) ccWrapperStdenv;
967
968 # Rebuild locales and sigtool with the new clang.
969 darwin = super.darwin.overrideScope (
970 _: superDarwin:
971 sdkDarwinPackages prevStage
972 // {
973 inherit (prevStage.darwin) binutils-unwrapped libSystem;
974 binutils = superDarwin.binutils.override {
975 # Build expand-response-params with last stage like below
976 inherit (prevStage) expand-response-params;
977 };
978 # Avoid rebuilding bmake (and Python) just for locales
979 locale = superDarwin.locale.override { inherit (prevStage) bmake; };
980 }
981 );
982
983 llvmPackages =
984 let
985 tools = super.llvmPackages.tools.extend (
986 _: _:
987 llvmToolsPackages prevStage
988 // {
989 libcxxClang = super.wrapCCWith rec {
990 nativeTools = false;
991 nativeLibc = false;
992
993 inherit (prevStage) expand-response-params;
994
995 extraPackages = [ self.llvmPackages.compiler-rt ];
996
997 extraBuildCommands = ''
998 rsrc="$out/resource-root"
999 mkdir "$rsrc"
1000 ln -s "${lib.getLib cc}/lib/clang/${lib.versions.major (lib.getVersion cc)}/include" "$rsrc"
1001 echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
1002 ln -s "${prevStage.llvmPackages.compiler-rt.out}/lib" "$rsrc/lib"
1003 ln -s "${prevStage.llvmPackages.compiler-rt.out}/share" "$rsrc/share"
1004 '';
1005
1006 cc = self.llvmPackages.clang-unwrapped;
1007 bintools = self.darwin.binutils;
1008
1009 isClang = true;
1010 libc = self.darwin.libSystem;
1011 inherit (self.llvmPackages) libcxx;
1012
1013 inherit lib;
1014 inherit (self)
1015 stdenvNoCC
1016 coreutils
1017 gnugrep
1018 runtimeShell
1019 ;
1020 };
1021 }
1022 );
1023 libraries = super.llvmPackages.libraries.extend (_: _: llvmLibrariesPackages prevStage);
1024 in
1025 super.llvmPackages // { inherit tools libraries; } // tools // libraries;
1026 }
1027 ];
1028
1029 extraNativeBuildInputs = lib.optionals localSystem.isAarch64 [
1030 prevStage.updateAutotoolsGnuConfigScriptsHook
1031 prevStage.gnu-config
1032 ];
1033
1034 extraPreHook = ''
1035 stripDebugFlags="-S" # llvm-strip does not support "-p" for Mach-O
1036 '';
1037 }
1038 )
1039
1040 # Construct the final stdenv. The version of LLVM provided should match the one defined in
1041 # `all-packages.nix` for Darwin. Nothing should depend on the bootstrap tools or originate from
1042 # the bootstrap tools.
1043 #
1044 # When updating the Darwin stdenv, make sure that the result has no dependency (`nix-store -qR`)
1045 # on `bootstrapTools` or the binutils built in stage 1.
1046 (
1047 prevStage:
1048 # previous stage4 stdenv:
1049
1050 assert allDeps isBuiltByNixpkgsCompiler [
1051 (lib.filterAttrs (_: pkg: lib.getName pkg != "pkg-config-wrapper") (stage1Packages prevStage)) # pkg-config is a wrapper
1052 (bintoolsPackages prevStage)
1053 (darwinPackages prevStage)
1054 (llvmLibrariesDeps prevStage)
1055 (llvmLibrariesPackages prevStage)
1056 (llvmToolsDeps prevStage)
1057 (llvmToolsPackages prevStage)
1058 (sdkPackages prevStage)
1059 (sdkDarwinPackages prevStage)
1060 { inherit (prevStage.pkg-config) pkg-config; }
1061 ];
1062
1063 assert allDeps isFromNixpkgs [
1064 (darwinPackagesNoCC prevStage)
1065 (sdkPackagesNoCC prevStage)
1066 ];
1067
1068 let
1069 cc = prevStage.llvmPackages.clang;
1070 in
1071 {
1072 inherit config overlays;
1073 stdenv = import ../generic {
1074 name = "stdenv-darwin";
1075
1076 buildPlatform = localSystem;
1077 hostPlatform = localSystem;
1078 targetPlatform = localSystem;
1079
1080 inherit config;
1081
1082 preHook = ''
1083 ${commonPreHook}
1084 stripDebugFlags="-S" # llvm-strip does not support "-p" for Mach-O
1085 export PATH_LOCALE=${prevStage.darwin.locale}/share/locale
1086 '';
1087
1088 initialPath = ((import ../generic/common-path.nix) { pkgs = prevStage; });
1089
1090 extraNativeBuildInputs = lib.optionals localSystem.isAarch64 [
1091 prevStage.updateAutotoolsGnuConfigScriptsHook
1092 ];
1093
1094 extraBuildInputs = [ prevStage.apple-sdk ];
1095
1096 inherit cc;
1097
1098 shell = cc.shell;
1099
1100 inherit (prevStage.stdenv) fetchurlBoot;
1101
1102 extraAttrs = {
1103 inherit bootstrapTools;
1104 libc = prevStage.darwin.libSystem;
1105 shellPackage = prevStage.bashNonInteractive;
1106 };
1107
1108 disallowedRequisites = [ bootstrapTools.out ];
1109
1110 allowedRequisites =
1111 (
1112 with prevStage;
1113 [
1114 apple-sdk
1115 bashNonInteractive
1116 bzip2.bin
1117 bzip2.out
1118 cc.expand-response-params
1119 cctools
1120 cctools.libtool
1121 coreutils
1122 darwin.binutils
1123 darwin.binutils.bintools
1124 diffutils
1125 ed
1126 file
1127 findutils
1128 gawk
1129 gettext
1130 gmp.out
1131 gnugrep
1132 gnugrep.pcre2.out
1133 gnumake
1134 gnused
1135 gnutar
1136 gzip
1137 ld64.lib
1138 ld64.out
1139 libffi.out
1140 libxml2.out
1141 ncurses.dev
1142 ncurses.man
1143 ncurses.out
1144 openpam
1145 openssl.out
1146 patch
1147 xar.lib
1148 xcbuild
1149 xcbuild.xcrun
1150 xz.bin
1151 xz.out
1152 zlib.dev
1153 zlib.out
1154 ]
1155 ++ apple-sdk.propagatedBuildInputs
1156 )
1157 ++ lib.optionals localSystem.isAarch64 [
1158 prevStage.updateAutotoolsGnuConfigScriptsHook
1159 prevStage.gnu-config
1160 ]
1161 ++ lib.optionals localSystem.isx86_64 [ prevStage.darwin.Csu ]
1162 ++ (with prevStage.darwin; [
1163 libiconv.out
1164 libresolv.out
1165 libsbuf.out
1166 libSystem
1167 locale
1168 ])
1169 ++ (with prevStage.llvmPackages; [
1170 bintools-unwrapped
1171 clang-unwrapped
1172 (lib.getLib clang-unwrapped)
1173 compiler-rt
1174 compiler-rt.dev
1175 libcxx
1176 libcxx.dev
1177 lld
1178 llvm
1179 llvm.lib
1180 ]);
1181
1182 __stdenvImpureHostDeps = commonImpureHostDeps;
1183 __extraImpureHostDeps = commonImpureHostDeps;
1184
1185 overrides =
1186 self: super:
1187 mergeDisjointAttrs [
1188 (llvmLibrariesDeps prevStage)
1189 (llvmToolsDeps prevStage)
1190 (sdkPackages prevStage)
1191 (sdkPackagesNoCC prevStage)
1192 {
1193 inherit (prevStage)
1194 diffutils
1195 ed
1196 file
1197 findutils
1198 gawk
1199 gettext
1200 gnumake
1201 gnused
1202 gnutar
1203 gzip
1204 patch
1205 ;
1206
1207 "apple-sdk_${sdkMajorVersion}" = self.apple-sdk;
1208
1209 darwin = super.darwin.overrideScope (
1210 _: _:
1211 sdkDarwinPackages prevStage
1212 // {
1213 inherit (prevStage.darwin) libSystem locale sigtool;
1214 }
1215 // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) {
1216 inherit (prevStage.darwin) binutils binutils-unwrapped;
1217 }
1218 );
1219 }
1220 # These have to be dropped from the overlay when cross-compiling. Wrappers are obviously target-specific.
1221 # darwin.binutils is not yet ready to be target-independent.
1222 (
1223 lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) (bintoolsPackages prevStage)
1224 // {
1225 inherit (prevStage.llvmPackages) clang;
1226 }
1227 )
1228 # Since LLVM should be the same regardless of target platform, overlay it to avoid an unnecessary
1229 # rebuild when cross-compiling from Darwin to another platform using clang.
1230 {
1231
1232 "llvmPackages_${lib.versions.major prevStage.llvmPackages.release_version}" =
1233 let
1234 llvmVersion = lib.versions.major prevStage.llvmPackages.release_version;
1235 tools = super."llvmPackages_${llvmVersion}".tools.extend (_: _: llvmToolsPackages prevStage);
1236 libraries = super."llvmPackages_${llvmVersion}".libraries.extend (
1237 _: _:
1238 llvmLibrariesPackages prevStage
1239 # Avoid depending on llvm-manpages from the bootstrap, which brings a bunch of Python dependencies
1240 # into the bootstrap. This means that there are no man pages in darwin.binutils, but they are still
1241 # available from llvm-manpages, ld64, and cctools.
1242 // {
1243 inherit (super."llvmPackages_${llvmVersion}") llvm-manpages;
1244 }
1245 // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) {
1246 inherit (prevStage.llvmPackages) clang;
1247 }
1248 );
1249 in
1250 super."llvmPackages_${llvmVersion}" // { inherit tools libraries; } // tools // libraries;
1251 }
1252 ];
1253 };
1254 }
1255 )
1256
1257 # This "no-op" stage is just a place to put the assertions about the final stage.
1258 (
1259 prevStage:
1260 # previous final stage stdenv:
1261 assert isBuiltByNixpkgsCompiler prevStage.cctools;
1262 assert isBuiltByNixpkgsCompiler prevStage.ld64;
1263 assert isBuiltByNixpkgsCompiler prevStage.darwin.sigtool;
1264
1265 assert isFromNixpkgs prevStage.darwin.libSystem;
1266 assert isFromNixpkgs prevStage.libc;
1267 assert isFromNixpkgs prevStage.darwin.binutils-unwrapped;
1268
1269 assert isBuiltByNixpkgsCompiler prevStage.llvmPackages.clang-unwrapped;
1270 assert isBuiltByNixpkgsCompiler prevStage.llvmPackages.libllvm;
1271 assert isBuiltByNixpkgsCompiler prevStage.llvmPackages.libcxx;
1272 assert isBuiltByNixpkgsCompiler prevStage.llvmPackages.compiler-rt;
1273
1274 # Make sure these evaluate since they were disabled explicitly in the bootstrap.
1275 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
1276 assert isFromNixpkgs prevStage.binutils-unwrapped.src;
1277 assert isBuiltByNixpkgsCompiler prevStage.curl;
1278
1279 # libiconv should be an alias for darwin.libiconv
1280 assert prevStage.libiconv == prevStage.darwin.libiconv;
1281
1282 {
1283 inherit (prevStage) config overlays stdenv;
1284 }
1285 )
1286]