Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
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# A 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 # relocatable libs may not be available in the bootstrap
435 # which will cause compilation to fail with
436 # configure: error: C compiler cannot create executables
437 enableDefaultPie = false;
438 }
439 )).overrideAttrs
440 (a: {
441
442 # This signals to cc-wrapper (as overridden above in this file) to add `--sysroot`
443 # to `$out/nix-support/cc-cflags`.
444 passthru = a.passthru // {
445 isXgcc = true;
446 };
447
448 # Gcc will look for the C library headers in
449 #
450 # ${with_build_sysroot}${native_system_header_dir}
451 #
452 # The ordinary gcc expression sets `--with-build-sysroot=/` and sets
453 # `native-system-header-dir` to `"${lib.getDev stdenv.cc.libc}/include`.
454 #
455 # Unfortunately the value of "--with-native-system-header-dir=" gets "burned in" to the
456 # compiler, and it is quite difficult to get the compiler to change or ignore it
457 # afterwards. On the other hand, the `sysroot` is very easy to change; you can just pass
458 # a `--sysroot` flag to `gcc`.
459 #
460 # So we override the expression to remove the default settings for these flags, and
461 # replace them such that the concatenated value will be the same as before, but we split
462 # the value between the two variables differently: `--native-system-header-dir=/include`,
463 # and `--with-build-sysroot=${lib.getDev stdenv.cc.libc}`.
464 #
465 configureFlags = (a.configureFlags or [ ]) ++ [
466 "--with-native-system-header-dir=/include"
467 "--with-build-sysroot=${lib.getDev self.stdenv.cc.libc}"
468 # Don't assume that `gettext` was built with iconv support, since we don't have
469 # our own `glibc` yet.
470 "--disable-nls"
471 ];
472
473 # This is a separate phase because gcc assembles its phase scripts
474 # in bash instead of nix (we should fix that).
475 preFixupPhases = (a.preFixupPhases or [ ]) ++ [ "preFixupXgccPhase" ];
476
477 # This is needed to prevent "error: cycle detected in build of '...-xgcc-....drv'
478 # in the references of output 'lib' from output 'out'"
479 preFixupXgccPhase = ''
480 find $lib/lib/ -name \*.so\* -exec patchelf --shrink-rpath {} \; || true
481 '';
482 });
483 };
484
485 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
486 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
487 }
488 )
489
490 # 2nd stdenv that contains our own rebuilt binutils and is used for
491 # compiling our own Glibc.
492 #
493 (
494 prevStage:
495 # previous stage1 stdenv:
496 assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
497 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
498 assert isFromBootstrapFiles prevStage.libc;
499 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
500 assert isFromBootstrapFiles prevStage.coreutils;
501 assert isFromBootstrapFiles prevStage.gnugrep;
502 assert isBuiltByBootstrapFilesCompiler prevStage.patchelf;
503 stageFun prevStage {
504 name = "bootstrap-stage2";
505
506 overrides = self: super: {
507 inherit (prevStage)
508 ccWrapperStdenv
509 gettext
510 gcc-unwrapped
511 coreutils
512 gnugrep
513 perl
514 gnum4
515 bison
516 texinfo
517 which
518 ;
519 dejagnu = super.dejagnu.overrideAttrs (a: {
520 doCheck = false;
521 });
522
523 # Avoids infinite recursion, as this is in the build-time dependencies of libc.
524 libiconv = self.libcIconv prevStage.libc;
525
526 # We need libidn2 and its dependency libunistring as glibc dependency.
527 # To avoid the cycle, we build against bootstrap libc, nuke references,
528 # and use the result as input for our final glibc. We also pass this pair
529 # through, so the final package-set uses exactly the same builds.
530 libunistring = super.libunistring.overrideAttrs (attrs: {
531 postFixup = attrs.postFixup or "" + ''
532 ${self.nukeReferences}/bin/nuke-refs "$out"/lib/lib*.so.*.*
533 '';
534 # Apparently iconv won't work with bootstrap glibc, but it will be used
535 # with glibc built later where we keep *this* build of libunistring,
536 # so we need to trick it into supporting libiconv.
537 env = attrs.env or { } // {
538 am_cv_func_iconv_works = "yes";
539 };
540 });
541 libidn2 = super.libidn2.overrideAttrs (attrs: {
542 postFixup = attrs.postFixup or "" + ''
543 ${self.nukeReferences}/bin/nuke-refs -e '${lib.getLib self.libunistring}' \
544 "$out"/lib/lib*.so.*.*
545 '';
546 });
547
548 # This also contains the full, dynamically linked, final Glibc.
549 binutils = prevStage.binutils.override {
550 # Rewrap the binutils with the new glibc, so both the next
551 # stage's wrappers use it.
552 inherit (self) libc;
553
554 # Unfortunately, when building gcc in the next stage, its LTO plugin
555 # would use the final libc but `ld` would use the bootstrap one,
556 # and that can fail to load. Therefore we upgrade `ld` to use newer libc;
557 # apparently the interpreter needs to match libc, too.
558 bintools = self.stdenvNoCC.mkDerivation {
559 pname = prevStage.bintools.bintools.pname + "-patchelfed-ld";
560 inherit (prevStage.bintools.bintools) version;
561 passthru = { inherit (prevStage.bintools.passthru) isFromBootstrapFiles; };
562 enableParallelBuilding = true;
563 dontUnpack = true;
564 dontBuild = true;
565 strictDeps = true;
566 # We wouldn't need to *copy* all, but it's easier and the result is temporary anyway.
567 installPhase = ''
568 mkdir -p "$out"/bin
569 cp -a '${prevStage.bintools.bintools}'/bin/* "$out"/bin/
570 chmod +w "$out"/bin/ld.bfd
571 patchelf --set-interpreter '${self.libc}'/lib/ld*.so.? \
572 --set-rpath "${self.libc}/lib:$(patchelf --print-rpath "$out"/bin/ld.bfd)" \
573 "$out"/bin/ld.bfd
574 '';
575 };
576 };
577
578 # TODO(amjoseph): It is not yet entirely clear why this is necessary.
579 # Something strange is going on with xgcc and libstdc++ on pkgsMusl.
580 patchelf = super.patchelf.overrideAttrs (
581 previousAttrs:
582 lib.optionalAttrs super.stdenv.hostPlatform.isMusl {
583 NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or "") + " -static-libstdc++";
584 }
585 );
586
587 };
588
589 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
590 # `libtool` comes with obsolete config.sub/config.guess that don't recognize Risc-V.
591 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
592 }
593 )
594
595 # Construct a third stdenv identical to the 2nd, except that this
596 # one uses the rebuilt Glibc from stage2. It still uses the recent
597 # binutils and rest of the bootstrap tools, including GCC.
598 (
599 prevStage:
600 # previous stage2 stdenv:
601 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
602 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
603 assert isBuiltByNixpkgsCompiler prevStage.libc;
604 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
605 assert isFromBootstrapFiles prevStage.coreutils;
606 assert isFromBootstrapFiles prevStage.gnugrep;
607 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
608 assert lib.all isBuiltByNixpkgsCompiler [
609 prevStage.gmp
610 prevStage.isl_0_20
611 prevStage.libmpc
612 prevStage.mpfr
613 ];
614 stageFun prevStage {
615 name = "bootstrap-stage3";
616
617 overrides =
618 self: super:
619 {
620 inherit (prevStage)
621 ccWrapperStdenv
622 binutils
623 coreutils
624 gnugrep
625 perl
626 patchelf
627 linuxHeaders
628 gnum4
629 bison
630 libidn2
631 libunistring
632 libxcrypt
633 ;
634 # We build a special copy of libgmp which doesn't use libstdc++, because
635 # xgcc++'s libstdc++ references the bootstrap-files (which is what
636 # compiles xgcc++).
637 gmp = super.gmp.override { cxx = false; };
638 }
639 // {
640 ${localSystem.libc} = prevStage.${localSystem.libc};
641 gcc-unwrapped =
642 (super.gcc-unwrapped.override (
643 commonGccOverrides
644 // {
645 inherit (prevStage) which;
646 }
647 )).overrideAttrs
648 (a: {
649 # so we can add them to allowedRequisites below
650 passthru = a.passthru // {
651 inherit (self)
652 gmp
653 mpfr
654 libmpc
655 isl
656 ;
657 };
658 });
659 };
660 extraNativeBuildInputs = [
661 prevStage.patchelf
662 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
663 prevStage.updateAutotoolsGnuConfigScriptsHook
664 ];
665 }
666 )
667
668 # Construct a fourth stdenv that uses the new GCC. But coreutils is
669 # still from the bootstrap tools.
670 #
671 (
672 prevStage:
673 # previous stage3 stdenv:
674 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
675 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
676 assert isBuiltByNixpkgsCompiler prevStage.libc;
677 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
678 assert isFromBootstrapFiles prevStage.coreutils;
679 assert isFromBootstrapFiles prevStage.gnugrep;
680 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
681 stageFun prevStage {
682 name = "bootstrap-stage4";
683
684 overrides = self: super: {
685 # Zlib has to be inherited and not rebuilt in this stage,
686 # because gcc (since JAR support) already depends on zlib, and
687 # then if we already have a zlib we want to use that for the
688 # other purposes (binutils and top-level pkgs) too.
689 inherit (prevStage)
690 gettext
691 gnum4
692 bison
693 perl
694 texinfo
695 zlib
696 linuxHeaders
697 libidn2
698 libunistring
699 ;
700 ${localSystem.libc} = prevStage.${localSystem.libc};
701 # Since this is the first fresh build of binutils since stage2, our own runtimeShell will be used.
702 binutils = super.binutils.override {
703 # Build expand-response-params with last stage like below
704 inherit (prevStage) expand-response-params;
705 };
706
707 # To allow users' overrides inhibit dependencies too heavy for
708 # bootstrap, like guile: https://github.com/NixOS/nixpkgs/issues/181188
709 gnumake = super.gnumake.override { inBootstrap = true; };
710
711 gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
712 nativeTools = false;
713 nativeLibc = false;
714 isGNU = true;
715 inherit (prevStage) expand-response-params;
716 cc = prevStage.gcc-unwrapped;
717 bintools = self.binutils;
718 inherit lib;
719 inherit (self)
720 stdenvNoCC
721 coreutils
722 gnugrep
723 runtimeShell
724 libc
725 ;
726 fortify-headers = self.fortify-headers;
727 };
728 };
729 extraNativeBuildInputs = [
730 prevStage.patchelf
731 prevStage.xz
732 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
733 prevStage.updateAutotoolsGnuConfigScriptsHook
734 ];
735 }
736 )
737
738 # Construct the final stdenv. It uses the Glibc and GCC, and adds
739 # in a new binutils that doesn't depend on bootstrap-tools, as well
740 # as dynamically linked versions of all other tools.
741 #
742 # When updating stdenvLinux, make sure that the result has no
743 # dependency (`nix-store -qR') on bootstrapTools or the first
744 # binutils built.
745 #
746 (
747 prevStage:
748 # previous stage4 stdenv; see stage3 comment regarding gcc,
749 # which applies here as well.
750 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
751 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
752 assert isBuiltByNixpkgsCompiler prevStage.libc;
753 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
754 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
755 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
756 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
757 {
758 inherit config overlays;
759 stdenv = import ../generic rec {
760 name = "stdenv-linux";
761
762 buildPlatform = localSystem;
763 hostPlatform = localSystem;
764 targetPlatform = localSystem;
765 inherit config;
766
767 preHook = commonPreHook;
768
769 initialPath = ((import ../generic/common-path.nix) { pkgs = prevStage; });
770
771 extraNativeBuildInputs = [
772 prevStage.patchelf
773 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
774 prevStage.updateAutotoolsGnuConfigScriptsHook
775 ];
776
777 cc = prevStage.gcc;
778
779 shell = cc.shell;
780
781 inherit (prevStage.stdenv) fetchurlBoot;
782
783 extraAttrs = {
784 inherit bootstrapTools;
785 shellPackage = prevStage.bash;
786 };
787
788 disallowedRequisites = [ bootstrapTools.out ];
789
790 # Mainly avoid reference to bootstrap tools
791 allowedRequisites =
792 let
793 inherit (prevStage)
794 gzip
795 bzip2
796 xz
797 zlib
798 bashNonInteractive
799 binutils
800 coreutils
801 diffutils
802 findutils
803 gawk
804 gmp
805 gnumake
806 gnused
807 gnutar
808 gnugrep
809 gnupatch
810 patchelf
811 ed
812 file
813 glibc
814 attr
815 acl
816 libidn2
817 libunistring
818 linuxHeaders
819 gcc
820 fortify-headers
821 gcc-unwrapped
822 ;
823 in
824 # Simple executable tools
825 lib.concatMap
826 (p: [
827 (lib.getBin p)
828 (lib.getLib p)
829 ])
830 [
831 gzip
832 bzip2
833 xz
834 bashNonInteractive
835 binutils.bintools
836 coreutils
837 diffutils
838 findutils
839 gawk
840 gmp
841 gnumake
842 gnused
843 gnutar
844 gnugrep
845 gnupatch
846 patchelf
847 ed
848 file
849 ]
850 # Library dependencies
851 ++ map lib.getLib [
852 attr
853 acl
854 zlib
855 gnugrep.pcre2
856 libidn2
857 libunistring
858 ]
859 # More complicated cases
860 ++ (map (x: lib.getOutput x (prevStage.libc)) [
861 "out"
862 "dev"
863 "bin"
864 ])
865 ++ [
866 linuxHeaders # propagated from .dev
867 binutils
868 gcc
869 gcc.cc
870 gcc.cc.lib
871 gcc.expand-response-params # != (prevStage.)expand-response-params
872 gcc.cc.libgcc
873 glibc.passthru.libgcc
874 ]
875 ++ lib.optionals (localSystem.libc == "musl") [ fortify-headers ]
876 ++ [
877 prevStage.updateAutotoolsGnuConfigScriptsHook
878 prevStage.gnu-config
879 ]
880 ++ [
881 gcc-unwrapped.gmp
882 gcc-unwrapped.libmpc
883 gcc-unwrapped.mpfr
884 gcc-unwrapped.isl
885 ];
886
887 overrides =
888 self: super:
889 {
890 inherit (prevStage)
891 gzip
892 bzip2
893 xz
894 bashNonInteractive
895 coreutils
896 diffutils
897 findutils
898 gawk
899 gnused
900 gnutar
901 gnugrep
902 gnupatch
903 patchelf
904 attr
905 acl
906 zlib
907 libunistring
908 ;
909 inherit (prevStage.gnugrep) pcre2;
910 ${localSystem.libc} = prevStage.${localSystem.libc};
911
912 # Hack: avoid libidn2.{bin,dev} referencing bootstrap tools. There's a logical cycle.
913 libidn2 = import ../../development/libraries/libidn2/no-bootstrap-reference.nix {
914 inherit lib;
915 inherit (prevStage) libidn2;
916 inherit (self)
917 stdenv
918 runCommandLocal
919 patchelf
920 libunistring
921 ;
922 };
923
924 gnumake = super.gnumake.override { inBootstrap = false; };
925 }
926 // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) {
927 # Need to get rid of these when cross-compiling.
928 inherit (prevStage) binutils binutils-unwrapped;
929 gcc = cc;
930 };
931 };
932 }
933 )
934
935 # This "no-op" stage is just a place to put the assertions about stage5.
936 (
937 prevStage:
938 # previous stage5 stdenv; see stage3 comment regarding gcc,
939 # which applies here as well.
940 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
941 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
942 assert isBuiltByNixpkgsCompiler prevStage.libc;
943 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
944 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
945 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
946 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
947 {
948 inherit (prevStage) config overlays stdenv;
949 }
950 )
951]