1# This file constructs the standard build environment for the
2# Linux platform. It's completely pure; that is, it relies on no
3# external (non-Nix) tools, such as /usr/bin/gcc, and it contains a C
4# compiler and linker that do not search in default locations,
5# ensuring purity of components produced by it.
6#
7# It starts from prebuilt seed bootstrapFiles and creates a series of
8# nixpkgs instances (stages) to gradually rebuild stdenv, which
9# is used to build all other packages (including the bootstrapFiles).
10#
11# Goals of the bootstrap process:
12# 1. final stdenv must not reference any of the bootstrap files.
13# 2. final stdenv must not contain any of the bootstrap files.
14# 3. final stdenv must not contain any of the files directly
15# generated by the bootstrap code generators (assembler, linker,
16# compiler).
17#
18# These goals ensure that final packages and final stdenv are built
19# exclusively using nixpkgs package definitions and don't depend
20# on bootstrapTools (via direct references, inclusion
21# of copied code, or code compiled directly by bootstrapTools).
22#
23# Stages are described below along with their definitions.
24#
25# Debugging stdenv dependency graph:
26# An useful tool to explore dependencies across stages is to use
27# '__bootPackages' attribute of 'stdenv. Examples of last 3 stages:
28# - stdenv
29# - stdenv.__bootPackages.stdenv
30# - stdenv.__bootPackages.stdenv.__bootPackages.stdenv
31# - ... and so on.
32#
33# To explore build-time dependencies in graphical form one can use
34# the following:
35# $ nix-store --query --graph $(nix-instantiate -A stdenv) |
36# grep -P -v '[.]sh|[.]patch|bash|[.]tar' | # avoid clutter
37# dot -Tsvg > stdenv-final.svg
38#
39# To find all the packages built by a particular stdenv instance:
40# $ for stage in 0 1 2 3 4; do
41# echo "stage${stage} used in:"
42# nix-store --query --graph $(nix-instantiate -A stdenv) |
43# grep -P ".*bootstrap-stage${stage}-stdenv.*->.*" |
44# sed 's/"[0-9a-z]\{32\}-/"/g'
45# done
46#
47# To verify which stdenv was used to build a given final package:
48# $ nix-store --query --graph $(nix-instantiate -A stdenv) |
49# grep -P -v '[.]sh|[.]patch|bash|[.]tar' |
50# grep -P '.*stdenv.*->.*glibc-2'
51# "...-bootstrap-stage2-stdenv-linux.drv" -> "...-glibc-2.35-224.drv";
52#
53# For a TUI (rather than CLI) view, you can use:
54#
55# $ nix-tree --derivation $(nix-instantiate -A stdenv)
56{
57 lib,
58 localSystem,
59 crossSystem,
60 config,
61 overlays,
62 crossOverlays ? [ ],
63
64 bootstrapFiles ?
65 let
66 table = {
67 glibc = {
68 i686-linux = import ./bootstrap-files/i686-unknown-linux-gnu.nix;
69 x86_64-linux = import ./bootstrap-files/x86_64-unknown-linux-gnu.nix;
70 armv5tel-linux = import ./bootstrap-files/armv5tel-unknown-linux-gnueabi.nix;
71 armv6l-linux = import ./bootstrap-files/armv6l-unknown-linux-gnueabihf.nix;
72 armv7l-linux = import ./bootstrap-files/armv7l-unknown-linux-gnueabihf.nix;
73 aarch64-linux = import ./bootstrap-files/aarch64-unknown-linux-gnu.nix;
74 mipsel-linux = import ./bootstrap-files/mipsel-unknown-linux-gnu.nix;
75 mips64el-linux = import (
76 if localSystem.isMips64n32 then
77 ./bootstrap-files/mips64el-unknown-linux-gnuabin32.nix
78 else
79 ./bootstrap-files/mips64el-unknown-linux-gnuabi64.nix
80 );
81 powerpc64-linux = import (
82 if localSystem.isAbiElfv2 then
83 ./bootstrap-files/powerpc64-unknown-linux-gnuabielfv2.nix
84 else
85 ./bootstrap-files/powerpc64-unknown-linux-gnuabielfv1.nix
86 );
87 powerpc64le-linux = import ./bootstrap-files/powerpc64le-unknown-linux-gnu.nix;
88 riscv64-linux = import ./bootstrap-files/riscv64-unknown-linux-gnu.nix;
89 s390x-linux = import ./bootstrap-files/s390x-unknown-linux-gnu.nix;
90 loongarch64-linux = import ./bootstrap-files/loongarch64-unknown-linux-gnu.nix;
91 };
92 musl = {
93 aarch64-linux = import ./bootstrap-files/aarch64-unknown-linux-musl.nix;
94 armv6l-linux = import ./bootstrap-files/armv6l-unknown-linux-musleabihf.nix;
95 x86_64-linux = import ./bootstrap-files/x86_64-unknown-linux-musl.nix;
96 };
97 };
98
99 # Try to find an architecture compatible with our current system. We
100 # just try every bootstrap we’ve got and test to see if it is
101 # compatible with or current architecture.
102 getCompatibleTools = lib.foldl (
103 v: system:
104 if v != null then
105 v
106 else if localSystem.canExecute (lib.systems.elaborate { inherit system; }) then
107 archLookupTable.${system}
108 else
109 null
110 ) null (lib.attrNames archLookupTable);
111
112 archLookupTable = table.${localSystem.libc} or (throw "unsupported libc for the pure Linux stdenv");
113 files =
114 archLookupTable.${localSystem.system} or (
115 if getCompatibleTools != null then
116 getCompatibleTools
117 else
118 (throw "unsupported platform for the pure Linux stdenv")
119 );
120 in
121 (config.replaceBootstrapFiles or lib.id) files,
122}:
123
124assert crossSystem == localSystem;
125
126let
127 inherit (localSystem) system;
128
129 isFromNixpkgs = pkg: !(isFromBootstrapFiles pkg);
130 isFromBootstrapFiles = pkg: pkg.passthru.isFromBootstrapFiles or false;
131 isBuiltByNixpkgsCompiler = pkg: isFromNixpkgs pkg && isFromNixpkgs pkg.stdenv.cc.cc;
132 isBuiltByBootstrapFilesCompiler = pkg: isFromNixpkgs pkg && isFromBootstrapFiles pkg.stdenv.cc.cc;
133
134 commonGccOverrides = {
135 # Use a deterministically built compiler
136 # see https://github.com/NixOS/nixpkgs/issues/108475 for context
137 reproducibleBuild = true;
138 profiledCompiler = false;
139
140 # It appears that libcc1 (which is not a g++ plugin; it is a gdb plugin) gets linked against
141 # the libstdc++ from the compiler that *built* g++, not the libstdc++ which was just built.
142 # This causes a reference chain from stdenv to the bootstrapFiles:
143 #
144 # stdenv -> gcc-lib -> xgcc-lib -> bootstrapFiles
145 #
146 disableGdbPlugin = true;
147 };
148
149 commonPreHook = ''
150 export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}"
151 export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}"
152 '';
153
154 # The bootstrap process proceeds in several steps.
155
156 # Create a standard environment by downloading pre-built binaries of
157 # coreutils, GCC, etc.
158
159 # Download and unpack the bootstrap tools (coreutils, GCC, Glibc, ...).
160 bootstrapTools = import ./bootstrap-tools {
161 inherit (localSystem) libc system;
162 inherit lib bootstrapFiles config;
163 isFromBootstrapFiles = true;
164 };
165
166 # This function builds the various standard environments used during
167 # the bootstrap. In all stages, we build an stdenv and the package
168 # set that can be built with that stdenv.
169 stageFun =
170 prevStage:
171 {
172 name,
173 overrides ? (self: super: { }),
174 extraNativeBuildInputs ? [ ],
175 }:
176
177 let
178
179 thisStdenv = import ../generic {
180 name = "${name}-stdenv-linux";
181 buildPlatform = localSystem;
182 hostPlatform = localSystem;
183 targetPlatform = localSystem;
184 inherit config extraNativeBuildInputs;
185 preHook = ''
186 # Don't patch #!/interpreter because it leads to retained
187 # dependencies on the bootstrapTools in the final stdenv.
188 dontPatchShebangs=1
189 ${commonPreHook}
190 '';
191 shell = "${bootstrapTools}/bin/bash";
192 initialPath = [ bootstrapTools ];
193
194 fetchurlBoot = import ../../build-support/fetchurl/boot.nix {
195 inherit system;
196 inherit (config) rewriteURL;
197 };
198
199 cc =
200 if prevStage.gcc-unwrapped == null then
201 null
202 else
203 (lib.makeOverridable (import ../../build-support/cc-wrapper) {
204 name = "${name}-gcc-wrapper";
205 nativeTools = false;
206 nativeLibc = false;
207 expand-response-params = lib.optionalString (
208 prevStage.stdenv.hasCC or false && prevStage.stdenv.cc != "/dev/null"
209 ) prevStage.expand-response-params;
210 cc = prevStage.gcc-unwrapped;
211 bintools = prevStage.binutils;
212 isGNU = true;
213 inherit (prevStage) libc;
214 inherit lib;
215 inherit (prevStage) coreutils gnugrep;
216 stdenvNoCC = prevStage.ccWrapperStdenv;
217 fortify-headers = prevStage.fortify-headers;
218 runtimeShell = prevStage.ccWrapperStdenv.shell;
219 }).overrideAttrs
220 (
221 a:
222 lib.optionalAttrs (prevStage.gcc-unwrapped.passthru.isXgcc or false) {
223 # This affects only `xgcc` (the compiler which compiles the final compiler).
224 postFixup = (a.postFixup or "") + ''
225 echo "--sysroot=${lib.getDev prevStage.libc}" >> $out/nix-support/cc-cflags
226 '';
227 }
228 );
229
230 overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; };
231 };
232
233 in
234 {
235 inherit config overlays;
236 stdenv = thisStdenv;
237 };
238
239in
240assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
241[
242
243 (
244 { }:
245 {
246 __raw = true;
247
248 gcc-unwrapped = null;
249 binutils = null;
250 coreutils = null;
251 gnugrep = null;
252 }
253 )
254
255 # Build a dummy stdenv with no GCC or working fetchurl. This is
256 # because we need a stdenv to build the GCC wrapper and fetchurl.
257 (
258 prevStage:
259 stageFun prevStage {
260 name = "bootstrap-stage0";
261
262 overrides = self: super: {
263 # We thread stage0's stdenv through under this name so downstream stages
264 # can use it for wrapping gcc too. This way, downstream stages don't need
265 # to refer to this stage directly, which violates the principle that each
266 # stage should only access the stage that came before it.
267 ccWrapperStdenv = self.stdenv;
268 # The Glibc include directory cannot have the same prefix as the
269 # GCC include directory, since GCC gets confused otherwise (it
270 # will search the Glibc headers before the GCC headers). So
271 # create a dummy Glibc here, which will be used in the stdenv of
272 # stage1.
273 ${localSystem.libc} = self.stdenv.mkDerivation {
274 pname = "bootstrap-stage0-${localSystem.libc}";
275 strictDeps = true;
276 version = "bootstrapFiles";
277 enableParallelBuilding = true;
278 buildCommand = ''
279 mkdir -p $out
280 ln -s ${bootstrapTools}/lib $out/lib
281 ''
282 + lib.optionalString (localSystem.libc == "glibc") ''
283 ln -s ${bootstrapTools}/include-glibc $out/include
284 ''
285 + lib.optionalString (localSystem.libc == "musl") ''
286 ln -s ${bootstrapTools}/include-libc $out/include
287 '';
288 passthru.isFromBootstrapFiles = true;
289 };
290 gcc-unwrapped = bootstrapTools;
291 binutils = import ../../build-support/bintools-wrapper {
292 name = "bootstrap-stage0-binutils-wrapper";
293 nativeTools = false;
294 nativeLibc = false;
295 expand-response-params = "";
296 inherit lib;
297 inherit (self)
298 stdenvNoCC
299 coreutils
300 gnugrep
301 libc
302 ;
303 bintools = bootstrapTools;
304 runtimeShell = "${bootstrapTools}/bin/bash";
305 };
306 coreutils = bootstrapTools;
307 gnugrep = bootstrapTools;
308 };
309 }
310 )
311
312 # Create the first "real" standard environment. This one consists
313 # of bootstrap tools only, and a minimal Glibc to keep the GCC
314 # configure script happy.
315 #
316 # For clarity, we only use the previous stage when specifying these
317 # stages. So stageN should only ever have references for stage{N-1}.
318 #
319 # If we ever need to use a package from more than one stage back, we
320 # simply re-export those packages in the middle stage(s) using the
321 # overrides attribute and the inherit syntax.
322 (
323 prevStage:
324 # previous stage0 stdenv:
325 assert isFromBootstrapFiles prevStage.binutils.bintools;
326 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
327 assert isFromBootstrapFiles prevStage.libc;
328 assert isFromBootstrapFiles prevStage.gcc-unwrapped;
329 assert isFromBootstrapFiles prevStage.coreutils;
330 assert isFromBootstrapFiles prevStage.gnugrep;
331 stageFun prevStage {
332 name = "bootstrap-stage1";
333
334 # Rebuild binutils to use from stage2 onwards.
335 overrides = self: super: {
336 binutils-unwrapped = super.binutils-unwrapped.override {
337 enableGold = false;
338 };
339 inherit (prevStage)
340 ccWrapperStdenv
341 gcc-unwrapped
342 coreutils
343 gnugrep
344 binutils
345 ;
346
347 ${localSystem.libc} = prevStage.${localSystem.libc};
348
349 # A threaded perl build needs glibc/libpthread_nonshared.a,
350 # which is not included in bootstrapTools, so disable threading.
351 # This is not an issue for the final stdenv, because this perl
352 # won't be included in the final stdenv and won't be exported to
353 # top-level pkgs as an override either.
354 perl = super.perl.override {
355 enableThreading = false;
356 enableCrypt = false;
357 };
358
359 # Let gettext "checking for working iconv" success without trying
360 # to convert between UTF-8 and EUC-JP which doesn't work here
361 # because of missing locale and gconv, same for libunistring below
362 gettext = super.gettext.overrideAttrs (attrs: {
363 env = attrs.env or { } // {
364 am_cv_func_iconv_works = "yes";
365 };
366 });
367 };
368
369 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
370 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
371 }
372 )
373
374 # First rebuild of gcc; this is linked against all sorts of junk
375 # from the bootstrap-files, but we only care about the code that
376 # this compiler *emits*. The `gcc` binary produced in this stage
377 # is not part of the final stdenv.
378 (
379 prevStage:
380 assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
381 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
382 assert isFromBootstrapFiles prevStage.libc;
383 assert isFromBootstrapFiles prevStage.gcc-unwrapped;
384 assert isFromBootstrapFiles prevStage.coreutils;
385 assert isFromBootstrapFiles prevStage.gnugrep;
386 assert isBuiltByBootstrapFilesCompiler prevStage.patchelf;
387 stageFun prevStage {
388 name = "bootstrap-stage-xgcc";
389 overrides = self: super: {
390 inherit (prevStage)
391 ccWrapperStdenv
392 coreutils
393 gnugrep
394 gettext
395 bison
396 texinfo
397 zlib
398 gnum4
399 perl
400 patchelf
401 ;
402 ${localSystem.libc} = prevStage.${localSystem.libc};
403 gmp = super.gmp.override { cxx = false; };
404 # This stage also rebuilds binutils which will of course be used only in the next stage.
405 # We inherit this until stage3, in stage4 it will be rebuilt using the adjacent bash/runtimeShell pkg.
406 # TODO(@sternenseemann): Can we already build the wrapper with the actual runtimeShell here?
407 # Historically, the wrapper didn't use runtimeShell, so the used shell had to be changed explicitly
408 # (or stdenvNoCC.shell would be used) which happened in stage4.
409 binutils = super.binutils.override {
410 runtimeShell = "${bootstrapTools}/bin/bash";
411 };
412 gcc-unwrapped =
413 (super.gcc-unwrapped.override (
414 commonGccOverrides
415 // {
416 # The most logical name for this package would be something like
417 # "gcc-stage1". Unfortunately "stage" is already reserved for the
418 # layers of stdenv, so using "stage" in the name of this package
419 # would cause massive confusion.
420 #
421 # Gcc calls its "stage1" compiler `xgcc` (--disable-bootstrap results
422 # in `xgcc` being copied to $prefix/bin/gcc). So we imitate that.
423 #
424 name = "xgcc";
425
426 # xgcc uses ld linked against nixpkgs' glibc and gcc built
427 # against bootstrapTools glibc. We can't allow loading
428 # $out/libexec/gcc/x86_64-unknown-linux-gnu/13.0.1/liblto_plugin.so
429 # to mix libc.so:
430 # ...-binutils-patchelfed-ld-2.40/bin/ld: ...-xgcc-13.0.0/libexec/gcc/x86_64-unknown-linux-gnu/13.0.1/liblto_plugin.so:
431 # error loading plugin: ...-bootstrap-tools/lib/libpthread.so.0: undefined symbol: __libc_vfork, version GLIBC_PRIVATE
432 enableLTO = false;
433 }
434 )).overrideAttrs
435 (a: {
436
437 # This signals to cc-wrapper (as overridden above in this file) to add `--sysroot`
438 # to `$out/nix-support/cc-cflags`.
439 passthru = a.passthru // {
440 isXgcc = true;
441 };
442
443 # Gcc will look for the C library headers in
444 #
445 # ${with_build_sysroot}${native_system_header_dir}
446 #
447 # The ordinary gcc expression sets `--with-build-sysroot=/` and sets
448 # `native-system-header-dir` to `"${lib.getDev stdenv.cc.libc}/include`.
449 #
450 # Unfortunately the value of "--with-native-system-header-dir=" gets "burned in" to the
451 # compiler, and it is quite difficult to get the compiler to change or ignore it
452 # afterwards. On the other hand, the `sysroot` is very easy to change; you can just pass
453 # a `--sysroot` flag to `gcc`.
454 #
455 # So we override the expression to remove the default settings for these flags, and
456 # replace them such that the concatenated value will be the same as before, but we split
457 # the value between the two variables differently: `--native-system-header-dir=/include`,
458 # and `--with-build-sysroot=${lib.getDev stdenv.cc.libc}`.
459 #
460 configureFlags = (a.configureFlags or [ ]) ++ [
461 "--with-native-system-header-dir=/include"
462 "--with-build-sysroot=${lib.getDev self.stdenv.cc.libc}"
463 # Don't assume that `gettext` was built with iconv support, since we don't have
464 # our own `glibc` yet.
465 "--disable-nls"
466 ];
467
468 # This is a separate phase because gcc assembles its phase scripts
469 # in bash instead of nix (we should fix that).
470 preFixupPhases = (a.preFixupPhases or [ ]) ++ [ "preFixupXgccPhase" ];
471
472 # This is needed to prevent "error: cycle detected in build of '...-xgcc-....drv'
473 # in the references of output 'lib' from output 'out'"
474 preFixupXgccPhase = ''
475 find $lib/lib/ -name \*.so\* -exec patchelf --shrink-rpath {} \; || true
476 '';
477 });
478 };
479
480 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
481 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
482 }
483 )
484
485 # 2nd stdenv that contains our own rebuilt binutils and is used for
486 # compiling our own Glibc.
487 #
488 (
489 prevStage:
490 # previous stage1 stdenv:
491 assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
492 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
493 assert isFromBootstrapFiles prevStage.libc;
494 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
495 assert isFromBootstrapFiles prevStage.coreutils;
496 assert isFromBootstrapFiles prevStage.gnugrep;
497 assert isBuiltByBootstrapFilesCompiler prevStage.patchelf;
498 stageFun prevStage {
499 name = "bootstrap-stage2";
500
501 overrides = self: super: {
502 inherit (prevStage)
503 ccWrapperStdenv
504 gettext
505 gcc-unwrapped
506 coreutils
507 gnugrep
508 perl
509 gnum4
510 bison
511 texinfo
512 which
513 ;
514 dejagnu = super.dejagnu.overrideAttrs (a: {
515 doCheck = false;
516 });
517
518 # Avoids infinite recursion, as this is in the build-time dependencies of libc.
519 libiconv = self.libcIconv prevStage.libc;
520
521 # We need libidn2 and its dependency libunistring as glibc dependency.
522 # To avoid the cycle, we build against bootstrap libc, nuke references,
523 # and use the result as input for our final glibc. We also pass this pair
524 # through, so the final package-set uses exactly the same builds.
525 libunistring = super.libunistring.overrideAttrs (attrs: {
526 postFixup = attrs.postFixup or "" + ''
527 ${self.nukeReferences}/bin/nuke-refs "$out"/lib/lib*.so.*.*
528 '';
529 # Apparently iconv won't work with bootstrap glibc, but it will be used
530 # with glibc built later where we keep *this* build of libunistring,
531 # so we need to trick it into supporting libiconv.
532 env = attrs.env or { } // {
533 am_cv_func_iconv_works = "yes";
534 };
535 });
536 libidn2 = super.libidn2.overrideAttrs (attrs: {
537 postFixup = attrs.postFixup or "" + ''
538 ${self.nukeReferences}/bin/nuke-refs -e '${lib.getLib self.libunistring}' \
539 "$out"/lib/lib*.so.*.*
540 '';
541 });
542
543 # This also contains the full, dynamically linked, final Glibc.
544 binutils = prevStage.binutils.override {
545 # Rewrap the binutils with the new glibc, so both the next
546 # stage's wrappers use it.
547 inherit (self) libc;
548
549 # Unfortunately, when building gcc in the next stage, its LTO plugin
550 # would use the final libc but `ld` would use the bootstrap one,
551 # and that can fail to load. Therefore we upgrade `ld` to use newer libc;
552 # apparently the interpreter needs to match libc, too.
553 bintools = self.stdenvNoCC.mkDerivation {
554 pname = prevStage.bintools.bintools.pname + "-patchelfed-ld";
555 inherit (prevStage.bintools.bintools) version;
556 passthru = { inherit (prevStage.bintools.passthru) isFromBootstrapFiles; };
557 enableParallelBuilding = true;
558 dontUnpack = true;
559 dontBuild = true;
560 strictDeps = true;
561 # We wouldn't need to *copy* all, but it's easier and the result is temporary anyway.
562 installPhase = ''
563 mkdir -p "$out"/bin
564 cp -a '${prevStage.bintools.bintools}'/bin/* "$out"/bin/
565 chmod +w "$out"/bin/ld.bfd
566 patchelf --set-interpreter '${self.libc}'/lib/ld*.so.? \
567 --set-rpath "${self.libc}/lib:$(patchelf --print-rpath "$out"/bin/ld.bfd)" \
568 "$out"/bin/ld.bfd
569 '';
570 };
571 };
572
573 # TODO(amjoseph): It is not yet entirely clear why this is necessary.
574 # Something strange is going on with xgcc and libstdc++ on pkgsMusl.
575 patchelf = super.patchelf.overrideAttrs (
576 previousAttrs:
577 lib.optionalAttrs super.stdenv.hostPlatform.isMusl {
578 NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or "") + " -static-libstdc++";
579 }
580 );
581
582 };
583
584 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
585 # `libtool` comes with obsolete config.sub/config.guess that don't recognize Risc-V.
586 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
587 }
588 )
589
590 # Construct a third stdenv identical to the 2nd, except that this
591 # one uses the rebuilt Glibc from stage2. It still uses the recent
592 # binutils and rest of the bootstrap tools, including GCC.
593 (
594 prevStage:
595 # previous stage2 stdenv:
596 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
597 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
598 assert isBuiltByNixpkgsCompiler prevStage.libc;
599 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
600 assert isFromBootstrapFiles prevStage.coreutils;
601 assert isFromBootstrapFiles prevStage.gnugrep;
602 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
603 assert lib.all isBuiltByNixpkgsCompiler [
604 prevStage.gmp
605 prevStage.isl_0_20
606 prevStage.libmpc
607 prevStage.mpfr
608 ];
609 stageFun prevStage {
610 name = "bootstrap-stage3";
611
612 overrides =
613 self: super:
614 {
615 inherit (prevStage)
616 ccWrapperStdenv
617 binutils
618 coreutils
619 gnugrep
620 perl
621 patchelf
622 linuxHeaders
623 gnum4
624 bison
625 libidn2
626 libunistring
627 libxcrypt
628 ;
629 # We build a special copy of libgmp which doesn't use libstdc++, because
630 # xgcc++'s libstdc++ references the bootstrap-files (which is what
631 # compiles xgcc++).
632 gmp = super.gmp.override { cxx = false; };
633 }
634 // {
635 ${localSystem.libc} = prevStage.${localSystem.libc};
636 gcc-unwrapped =
637 (super.gcc-unwrapped.override (
638 commonGccOverrides
639 // {
640 inherit (prevStage) which;
641 }
642 )).overrideAttrs
643 (a: {
644 # so we can add them to allowedRequisites below
645 passthru = a.passthru // {
646 inherit (self)
647 gmp
648 mpfr
649 libmpc
650 isl
651 ;
652 };
653 });
654 };
655 extraNativeBuildInputs = [
656 prevStage.patchelf
657 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
658 prevStage.updateAutotoolsGnuConfigScriptsHook
659 ];
660 }
661 )
662
663 # Construct a fourth stdenv that uses the new GCC. But coreutils is
664 # still from the bootstrap tools.
665 #
666 (
667 prevStage:
668 # previous stage3 stdenv:
669 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
670 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
671 assert isBuiltByNixpkgsCompiler prevStage.libc;
672 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
673 assert isFromBootstrapFiles prevStage.coreutils;
674 assert isFromBootstrapFiles prevStage.gnugrep;
675 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
676 stageFun prevStage {
677 name = "bootstrap-stage4";
678
679 overrides = self: super: {
680 # Zlib has to be inherited and not rebuilt in this stage,
681 # because gcc (since JAR support) already depends on zlib, and
682 # then if we already have a zlib we want to use that for the
683 # other purposes (binutils and top-level pkgs) too.
684 inherit (prevStage)
685 gettext
686 gnum4
687 bison
688 perl
689 texinfo
690 zlib
691 linuxHeaders
692 libidn2
693 libunistring
694 ;
695 ${localSystem.libc} = prevStage.${localSystem.libc};
696 # Since this is the first fresh build of binutils since stage2, our own runtimeShell will be used.
697 binutils = super.binutils.override {
698 # Build expand-response-params with last stage like below
699 inherit (prevStage) expand-response-params;
700 };
701
702 # To allow users' overrides inhibit dependencies too heavy for
703 # bootstrap, like guile: https://github.com/NixOS/nixpkgs/issues/181188
704 gnumake = super.gnumake.override { inBootstrap = true; };
705
706 gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
707 nativeTools = false;
708 nativeLibc = false;
709 isGNU = true;
710 inherit (prevStage) expand-response-params;
711 cc = prevStage.gcc-unwrapped;
712 bintools = self.binutils;
713 inherit lib;
714 inherit (self)
715 stdenvNoCC
716 coreutils
717 gnugrep
718 runtimeShell
719 libc
720 ;
721 fortify-headers = self.fortify-headers;
722 };
723 };
724 extraNativeBuildInputs = [
725 prevStage.patchelf
726 prevStage.xz
727 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
728 prevStage.updateAutotoolsGnuConfigScriptsHook
729 ];
730 }
731 )
732
733 # Construct the final stdenv. It uses the Glibc and GCC, and adds
734 # in a new binutils that doesn't depend on bootstrap-tools, as well
735 # as dynamically linked versions of all other tools.
736 #
737 # When updating stdenvLinux, make sure that the result has no
738 # dependency (`nix-store -qR') on bootstrapTools or the first
739 # binutils built.
740 #
741 (
742 prevStage:
743 # previous stage4 stdenv; see stage3 comment regarding gcc,
744 # which applies here as well.
745 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
746 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
747 assert isBuiltByNixpkgsCompiler prevStage.libc;
748 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
749 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
750 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
751 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
752 {
753 inherit config overlays;
754 stdenv = import ../generic rec {
755 name = "stdenv-linux";
756
757 buildPlatform = localSystem;
758 hostPlatform = localSystem;
759 targetPlatform = localSystem;
760 inherit config;
761
762 preHook = commonPreHook;
763
764 initialPath = ((import ../generic/common-path.nix) { pkgs = prevStage; });
765
766 extraNativeBuildInputs = [
767 prevStage.patchelf
768 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
769 prevStage.updateAutotoolsGnuConfigScriptsHook
770 ];
771
772 cc = prevStage.gcc;
773
774 shell = cc.shell;
775
776 inherit (prevStage.stdenv) fetchurlBoot;
777
778 extraAttrs = {
779 inherit bootstrapTools;
780 shellPackage = prevStage.bash;
781 };
782
783 disallowedRequisites = [ bootstrapTools.out ];
784
785 # Mainly avoid reference to bootstrap tools
786 allowedRequisites =
787 let
788 inherit (prevStage)
789 gzip
790 bzip2
791 xz
792 zlib
793 bashNonInteractive
794 binutils
795 coreutils
796 diffutils
797 findutils
798 gawk
799 gmp
800 gnumake
801 gnused
802 gnutar
803 gnugrep
804 gnupatch
805 patchelf
806 ed
807 file
808 glibc
809 attr
810 acl
811 libidn2
812 libunistring
813 linuxHeaders
814 gcc
815 fortify-headers
816 gcc-unwrapped
817 ;
818 in
819 # Simple executable tools
820 lib.concatMap
821 (p: [
822 (lib.getBin p)
823 (lib.getLib p)
824 ])
825 [
826 gzip
827 bzip2
828 xz
829 bashNonInteractive
830 binutils.bintools
831 coreutils
832 diffutils
833 findutils
834 gawk
835 gmp
836 gnumake
837 gnused
838 gnutar
839 gnugrep
840 gnupatch
841 patchelf
842 ed
843 file
844 ]
845 # Library dependencies
846 ++ map lib.getLib [
847 attr
848 acl
849 zlib
850 gnugrep.pcre2
851 libidn2
852 libunistring
853 ]
854 # More complicated cases
855 ++ (map (x: lib.getOutput x (prevStage.libc)) [
856 "out"
857 "dev"
858 "bin"
859 ])
860 ++ [
861 linuxHeaders # propagated from .dev
862 binutils
863 gcc
864 gcc.cc
865 gcc.cc.lib
866 gcc.expand-response-params # != (prevStage.)expand-response-params
867 gcc.cc.libgcc
868 glibc.passthru.libgcc
869 ]
870 ++ lib.optionals (localSystem.libc == "musl") [ fortify-headers ]
871 ++ [
872 prevStage.updateAutotoolsGnuConfigScriptsHook
873 prevStage.gnu-config
874 ]
875 ++ [
876 gcc-unwrapped.gmp
877 gcc-unwrapped.libmpc
878 gcc-unwrapped.mpfr
879 gcc-unwrapped.isl
880 ];
881
882 overrides =
883 self: super:
884 {
885 inherit (prevStage)
886 gzip
887 bzip2
888 xz
889 bashNonInteractive
890 coreutils
891 diffutils
892 findutils
893 gawk
894 gnused
895 gnutar
896 gnugrep
897 gnupatch
898 patchelf
899 attr
900 acl
901 zlib
902 libunistring
903 ;
904 inherit (prevStage.gnugrep) pcre2;
905 ${localSystem.libc} = prevStage.${localSystem.libc};
906
907 # Hack: avoid libidn2.{bin,dev} referencing bootstrap tools. There's a logical cycle.
908 libidn2 = import ../../development/libraries/libidn2/no-bootstrap-reference.nix {
909 inherit lib;
910 inherit (prevStage) libidn2;
911 inherit (self)
912 stdenv
913 runCommandLocal
914 patchelf
915 libunistring
916 ;
917 };
918
919 gnumake = super.gnumake.override { inBootstrap = false; };
920 }
921 // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) {
922 # Need to get rid of these when cross-compiling.
923 inherit (prevStage) binutils binutils-unwrapped;
924 gcc = cc;
925 };
926 };
927 }
928 )
929
930 # This "no-op" stage is just a place to put the assertions about stage5.
931 (
932 prevStage:
933 # previous stage5 stdenv; see stage3 comment regarding gcc,
934 # which applies here as well.
935 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
936 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
937 assert isBuiltByNixpkgsCompiler prevStage.libc;
938 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
939 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
940 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
941 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
942 {
943 inherit (prevStage) config overlays stdenv;
944 }
945 )
946]