lol
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{ lib
57, localSystem, crossSystem, config, overlays, crossOverlays ? []
58
59, bootstrapFiles ?
60 let table = {
61 glibc = {
62 i686-linux = import ./bootstrap-files/i686-unknown-linux-gnu.nix;
63 x86_64-linux = import ./bootstrap-files/x86_64-unknown-linux-gnu.nix;
64 armv5tel-linux = import ./bootstrap-files/armv5tel-unknown-linux-gnueabi.nix;
65 armv6l-linux = import ./bootstrap-files/armv6l-unknown-linux-gnueabihf.nix;
66 armv7l-linux = import ./bootstrap-files/armv7l-unknown-linux-gnueabihf.nix;
67 aarch64-linux = import ./bootstrap-files/aarch64-unknown-linux-gnu.nix;
68 mipsel-linux = import ./bootstrap-files/mipsel-unknown-linux-gnu.nix;
69 mips64el-linux = import
70 (if localSystem.isMips64n32
71 then ./bootstrap-files/mips64el-unknown-linux-gnuabin32.nix
72 else ./bootstrap-files/mips64el-unknown-linux-gnuabi64.nix);
73 powerpc64le-linux = import ./bootstrap-files/powerpc64le-unknown-linux-gnu.nix;
74 riscv64-linux = import ./bootstrap-files/riscv64-unknown-linux-gnu.nix;
75 };
76 musl = {
77 aarch64-linux = import ./bootstrap-files/aarch64-unknown-linux-musl.nix;
78 armv6l-linux = import ./bootstrap-files/armv6l-unknown-linux-musleabihf.nix;
79 x86_64-linux = import ./bootstrap-files/x86_64-unknown-linux-musl.nix;
80 };
81 };
82
83 # Try to find an architecture compatible with our current system. We
84 # just try every bootstrap we’ve got and test to see if it is
85 # compatible with or current architecture.
86 getCompatibleTools = lib.foldl (v: system:
87 if v != null then v
88 else if localSystem.canExecute (lib.systems.elaborate { inherit system; }) then archLookupTable.${system}
89 else null) null (lib.attrNames archLookupTable);
90
91 archLookupTable = table.${localSystem.libc}
92 or (abort "unsupported libc for the pure Linux stdenv");
93 files = archLookupTable.${localSystem.system} or (if getCompatibleTools != null then getCompatibleTools
94 else (abort "unsupported platform for the pure Linux stdenv"));
95 in files
96}:
97
98assert crossSystem == localSystem;
99
100let
101 inherit (localSystem) system;
102
103 isFromNixpkgs = pkg: !(isFromBootstrapFiles pkg);
104 isFromBootstrapFiles =
105 pkg: pkg.passthru.isFromBootstrapFiles or false;
106 isBuiltByNixpkgsCompiler =
107 pkg: isFromNixpkgs pkg && isFromNixpkgs pkg.stdenv.cc.cc;
108 isBuiltByBootstrapFilesCompiler =
109 pkg: isFromNixpkgs pkg && isFromBootstrapFiles pkg.stdenv.cc.cc;
110
111 commonGccOverrides = {
112 # Use a deterministically built compiler
113 # see https://github.com/NixOS/nixpkgs/issues/108475 for context
114 reproducibleBuild = true;
115 profiledCompiler = false;
116
117 # It appears that libcc1 (which is not a g++ plugin; it is a gdb plugin) gets linked against
118 # the libstdc++ from the compiler that *built* g++, not the libstdc++ which was just built.
119 # This causes a reference chain from stdenv to the bootstrapFiles:
120 #
121 # stdenv -> gcc-lib -> xgcc-lib -> bootstrapFiles
122 #
123 disableGdbPlugin = true;
124 };
125
126 commonPreHook =
127 ''
128 export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}"
129 export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}"
130 '';
131
132
133 # The bootstrap process proceeds in several steps.
134
135
136 # Create a standard environment by downloading pre-built binaries of
137 # coreutils, GCC, etc.
138
139
140 # Download and unpack the bootstrap tools (coreutils, GCC, Glibc, ...).
141 bootstrapTools = (import (if localSystem.libc == "musl" then ./bootstrap-tools-musl else ./bootstrap-tools) {
142 inherit system bootstrapFiles;
143 extraAttrs = lib.optionalAttrs config.contentAddressedByDefault {
144 __contentAddressed = true;
145 outputHashAlgo = "sha256";
146 outputHashMode = "recursive";
147 };
148 }) // { passthru.isFromBootstrapFiles = true; };
149
150 getLibc = stage: stage.${localSystem.libc};
151
152
153 # This function builds the various standard environments used during
154 # the bootstrap. In all stages, we build an stdenv and the package
155 # set that can be built with that stdenv.
156 stageFun = prevStage:
157 { name, overrides ? (self: super: {}), extraNativeBuildInputs ? [] }:
158
159 let
160
161 thisStdenv = import ../generic {
162 name = "${name}-stdenv-linux";
163 buildPlatform = localSystem;
164 hostPlatform = localSystem;
165 targetPlatform = localSystem;
166 inherit config extraNativeBuildInputs;
167 preHook =
168 ''
169 # Don't patch #!/interpreter because it leads to retained
170 # dependencies on the bootstrapTools in the final stdenv.
171 dontPatchShebangs=1
172 ${commonPreHook}
173 '';
174 shell = "${bootstrapTools}/bin/bash";
175 initialPath = [bootstrapTools];
176
177 fetchurlBoot = import ../../build-support/fetchurl/boot.nix {
178 inherit system;
179 };
180
181 cc = if prevStage.gcc-unwrapped == null
182 then null
183 else (lib.makeOverridable (import ../../build-support/cc-wrapper) {
184 name = "${name}-gcc-wrapper";
185 nativeTools = false;
186 nativeLibc = false;
187 buildPackages = lib.optionalAttrs (prevStage ? stdenv) {
188 inherit (prevStage) stdenv;
189 };
190 cc = prevStage.gcc-unwrapped;
191 bintools = prevStage.binutils;
192 isGNU = true;
193 libc = getLibc prevStage;
194 inherit lib;
195 inherit (prevStage) coreutils gnugrep;
196 stdenvNoCC = prevStage.ccWrapperStdenv;
197 fortify-headers = prevStage.fortify-headers;
198 }).overrideAttrs(a: lib.optionalAttrs (prevStage.gcc-unwrapped.passthru.isXgcc or false) {
199 # This affects only `xgcc` (the compiler which compiles the final compiler).
200 postFixup = (a.postFixup or "") + ''
201 echo "--sysroot=${lib.getDev (getLibc prevStage)}" >> $out/nix-support/cc-cflags
202 '';
203 });
204
205 overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; };
206 };
207
208 in {
209 inherit config overlays;
210 stdenv = thisStdenv;
211 };
212
213in
214 assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
215[
216
217 ({}: {
218 __raw = true;
219
220 gcc-unwrapped = null;
221 binutils = null;
222 coreutils = null;
223 gnugrep = null;
224 })
225
226 # Build a dummy stdenv with no GCC or working fetchurl. This is
227 # because we need a stdenv to build the GCC wrapper and fetchurl.
228 (prevStage: stageFun prevStage {
229 name = "bootstrap-stage0";
230
231 overrides = self: super: {
232 # We thread stage0's stdenv through under this name so downstream stages
233 # can use it for wrapping gcc too. This way, downstream stages don't need
234 # to refer to this stage directly, which violates the principle that each
235 # stage should only access the stage that came before it.
236 ccWrapperStdenv = self.stdenv;
237 # The Glibc include directory cannot have the same prefix as the
238 # GCC include directory, since GCC gets confused otherwise (it
239 # will search the Glibc headers before the GCC headers). So
240 # create a dummy Glibc here, which will be used in the stdenv of
241 # stage1.
242 ${localSystem.libc} = self.stdenv.mkDerivation {
243 pname = "bootstrap-stage0-${localSystem.libc}";
244 strictDeps = true;
245 version = "bootstrapFiles";
246 enableParallelBuilding = true;
247 buildCommand = ''
248 mkdir -p $out
249 ln -s ${bootstrapTools}/lib $out/lib
250 '' + lib.optionalString (localSystem.libc == "glibc") ''
251 ln -s ${bootstrapTools}/include-glibc $out/include
252 '' + lib.optionalString (localSystem.libc == "musl") ''
253 ln -s ${bootstrapTools}/include-libc $out/include
254 '';
255 passthru.isFromBootstrapFiles = true;
256 };
257 gcc-unwrapped = bootstrapTools;
258 binutils = import ../../build-support/bintools-wrapper {
259 name = "bootstrap-stage0-binutils-wrapper";
260 nativeTools = false;
261 nativeLibc = false;
262 buildPackages = { };
263 libc = getLibc self;
264 inherit lib;
265 inherit (self) stdenvNoCC coreutils gnugrep;
266 bintools = bootstrapTools;
267 };
268 coreutils = bootstrapTools;
269 gnugrep = bootstrapTools;
270 };
271 })
272
273
274 # Create the first "real" standard environment. This one consists
275 # of bootstrap tools only, and a minimal Glibc to keep the GCC
276 # configure script happy.
277 #
278 # For clarity, we only use the previous stage when specifying these
279 # stages. So stageN should only ever have references for stage{N-1}.
280 #
281 # If we ever need to use a package from more than one stage back, we
282 # simply re-export those packages in the middle stage(s) using the
283 # overrides attribute and the inherit syntax.
284 (prevStage:
285 # previous stage0 stdenv:
286 assert isFromBootstrapFiles prevStage.binutils.bintools;
287 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
288 assert isFromBootstrapFiles prevStage.gcc-unwrapped;
289 assert isFromBootstrapFiles prevStage.coreutils;
290 assert isFromBootstrapFiles prevStage.gnugrep;
291 stageFun prevStage {
292 name = "bootstrap-stage1";
293
294 # Rebuild binutils to use from stage2 onwards.
295 overrides = self: super: {
296 binutils-unwrapped = super.binutils-unwrapped.override {
297 enableGold = false;
298 };
299 inherit (prevStage)
300 ccWrapperStdenv
301 gcc-unwrapped coreutils gnugrep binutils;
302
303 ${localSystem.libc} = getLibc prevStage;
304
305 # A threaded perl build needs glibc/libpthread_nonshared.a,
306 # which is not included in bootstrapTools, so disable threading.
307 # This is not an issue for the final stdenv, because this perl
308 # won't be included in the final stdenv and won't be exported to
309 # top-level pkgs as an override either.
310 perl = super.perl.override { enableThreading = false; enableCrypt = false; };
311 };
312
313 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
314 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
315 })
316
317 # First rebuild of gcc; this is linked against all sorts of junk
318 # from the bootstrap-files, but we only care about the code that
319 # this compiler *emits*. The `gcc` binary produced in this stage
320 # is not part of the final stdenv.
321 (prevStage:
322 assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
323 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
324 assert isFromBootstrapFiles prevStage.gcc-unwrapped;
325 assert isFromBootstrapFiles prevStage.coreutils;
326 assert isFromBootstrapFiles prevStage.gnugrep;
327 assert isBuiltByBootstrapFilesCompiler prevStage.patchelf;
328 stageFun prevStage {
329 name = "bootstrap-stage-xgcc";
330 overrides = final: prev: {
331 inherit (prevStage) ccWrapperStdenv coreutils gnugrep gettext bison texinfo zlib gnum4 perl patchelf;
332 ${localSystem.libc} = getLibc prevStage;
333 gmp = prev.gmp.override { cxx = false; };
334 gcc-unwrapped =
335 (prev.gcc-unwrapped.override (commonGccOverrides // {
336 # The most logical name for this package would be something like
337 # "gcc-stage1". Unfortunately "stage" is already reserved for the
338 # layers of stdenv, so using "stage" in the name of this package
339 # would cause massive confusion.
340 #
341 # Gcc calls its "stage1" compiler `xgcc` (--disable-bootstrap results
342 # in `xgcc` being copied to $prefix/bin/gcc). So we imitate that.
343 #
344 name = "xgcc";
345
346 # xgcc uses ld linked against nixpkgs' glibc and gcc built
347 # against bootstrapTools glibc. We can't allow loading
348 # $out/libexec/gcc/x86_64-unknown-linux-gnu/13.0.1/liblto_plugin.so
349 # to mix libc.so:
350 # ...-binutils-patchelfed-ld-2.40/bin/ld: ...-xgcc-13.0.0/libexec/gcc/x86_64-unknown-linux-gnu/13.0.1/liblto_plugin.so:
351 # error loading plugin: ...-bootstrap-tools/lib/libpthread.so.0: undefined symbol: __libc_vfork, version GLIBC_PRIVATE
352 enableLTO = false;
353 })).overrideAttrs (a: {
354
355 # This signals to cc-wrapper (as overridden above in this file) to add `--sysroot`
356 # to `$out/nix-support/cc-cflags`.
357 passthru = a.passthru // { isXgcc = true; };
358
359 # Gcc will look for the C library headers in
360 #
361 # ${with_build_sysroot}${native_system_header_dir}
362 #
363 # The ordinary gcc expression sets `--with-build-sysroot=/` and sets
364 # `native-system-header-dir` to `"${lib.getDev stdenv.cc.libc}/include`.
365 #
366 # Unfortunately the value of "--with-native-system-header-dir=" gets "burned in" to the
367 # compiler, and it is quite difficult to get the compiler to change or ignore it
368 # afterwards. On the other hand, the `sysroot` is very easy to change; you can just pass
369 # a `--sysroot` flag to `gcc`.
370 #
371 # So we override the expression to remove the default settings for these flags, and
372 # replace them such that the concatenated value will be the same as before, but we split
373 # the value between the two variables differently: `--native-system-header-dir=/include`,
374 # and `--with-build-sysroot=${lib.getDev stdenv.cc.libc}`.
375 #
376 configureFlags = (a.configureFlags or []) ++ [
377 "--with-native-system-header-dir=/include"
378 "--with-build-sysroot=${lib.getDev final.stdenv.cc.libc}"
379 ];
380
381 # This is a separate phase because gcc assembles its phase scripts
382 # in bash instead of nix (we should fix that).
383 preFixupPhases = (a.preFixupPhases or []) ++ [ "preFixupXgccPhase" ];
384
385 # This is needed to prevent "error: cycle detected in build of '...-xgcc-....drv'
386 # in the references of output 'lib' from output 'out'"
387 preFixupXgccPhase = ''
388 find $lib/lib/ -name \*.so\* -exec patchelf --shrink-rpath {} \; || true
389 '';
390 });
391 };
392
393 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
394 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
395 })
396
397 # 2nd stdenv that contains our own rebuilt binutils and is used for
398 # compiling our own Glibc.
399 #
400 (prevStage:
401 # previous stage1 stdenv:
402 assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
403 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
404 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
405 assert isFromBootstrapFiles prevStage.coreutils;
406 assert isFromBootstrapFiles prevStage.gnugrep;
407 assert isBuiltByBootstrapFilesCompiler prevStage.patchelf;
408 stageFun prevStage {
409 name = "bootstrap-stage2";
410
411 overrides = self: super: {
412 inherit (prevStage)
413 ccWrapperStdenv gettext
414 gcc-unwrapped coreutils gnugrep
415 perl gnum4 bison texinfo which;
416 dejagnu = super.dejagnu.overrideAttrs (a: { doCheck = false; } );
417
418 # We need libidn2 and its dependency libunistring as glibc dependency.
419 # To avoid the cycle, we build against bootstrap libc, nuke references,
420 # and use the result as input for our final glibc. We also pass this pair
421 # through, so the final package-set uses exactly the same builds.
422 libunistring = super.libunistring.overrideAttrs (attrs: {
423 postFixup = attrs.postFixup or "" + ''
424 ${self.nukeReferences}/bin/nuke-refs "$out"/lib/lib*.so.*.*
425 '';
426 # Apparently iconv won't work with bootstrap glibc, but it will be used
427 # with glibc built later where we keep *this* build of libunistring,
428 # so we need to trick it into supporting libiconv.
429 env = attrs.env or {} // { am_cv_func_iconv_works = "yes"; };
430 });
431 libidn2 = super.libidn2.overrideAttrs (attrs: {
432 postFixup = attrs.postFixup or "" + ''
433 ${self.nukeReferences}/bin/nuke-refs -e '${lib.getLib self.libunistring}' \
434 "$out"/lib/lib*.so.*.*
435 '';
436 });
437
438 # This also contains the full, dynamically linked, final Glibc.
439 binutils = prevStage.binutils.override {
440 # Rewrap the binutils with the new glibc, so both the next
441 # stage's wrappers use it.
442 libc = getLibc self;
443
444 # Unfortunately, when building gcc in the next stage, its LTO plugin
445 # would use the final libc but `ld` would use the bootstrap one,
446 # and that can fail to load. Therefore we upgrade `ld` to use newer libc;
447 # apparently the interpreter needs to match libc, too.
448 bintools = self.stdenvNoCC.mkDerivation {
449 pname = prevStage.bintools.bintools.pname + "-patchelfed-ld";
450 inherit (prevStage.bintools.bintools) version;
451 passthru = { inherit (prevStage.bintools.passthru) isFromBootstrapFiles; };
452 enableParallelBuilding = true;
453 dontUnpack = true;
454 dontBuild = true;
455 strictDeps = true;
456 # We wouldn't need to *copy* all, but it's easier and the result is temporary anyway.
457 installPhase = ''
458 mkdir -p "$out"/bin
459 cp -a '${prevStage.bintools.bintools}'/bin/* "$out"/bin/
460 chmod +w "$out"/bin/ld.bfd
461 patchelf --set-interpreter '${getLibc self}'/lib/ld*.so.? \
462 --set-rpath "${getLibc self}/lib:$(patchelf --print-rpath "$out"/bin/ld.bfd)" \
463 "$out"/bin/ld.bfd
464 '';
465 };
466 };
467
468 # TODO(amjoseph): It is not yet entirely clear why this is necessary.
469 # Something strange is going on with xgcc and libstdc++ on pkgsMusl.
470 patchelf = super.patchelf.overrideAttrs(previousAttrs:
471 lib.optionalAttrs super.stdenv.hostPlatform.isMusl {
472 NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or "") + " -static-libstdc++";
473 });
474
475 };
476
477 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
478 # `libtool` comes with obsolete config.sub/config.guess that don't recognize Risc-V.
479 extraNativeBuildInputs = [ prevStage.updateAutotoolsGnuConfigScriptsHook ];
480 })
481
482
483 # Construct a third stdenv identical to the 2nd, except that this
484 # one uses the rebuilt Glibc from stage2. It still uses the recent
485 # binutils and rest of the bootstrap tools, including GCC.
486 (prevStage:
487 # previous stage2 stdenv:
488 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
489 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
490 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
491 assert isFromBootstrapFiles prevStage.coreutils;
492 assert isFromBootstrapFiles prevStage.gnugrep;
493 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
494 assert lib.all isBuiltByNixpkgsCompiler (with prevStage; [ gmp isl_0_20 libmpc mpfr ]);
495 stageFun prevStage {
496 name = "bootstrap-stage3";
497
498 overrides = self: super: rec {
499 inherit (prevStage)
500 ccWrapperStdenv
501 binutils coreutils gnugrep gettext
502 perl patchelf linuxHeaders gnum4 bison libidn2 libunistring libxcrypt;
503 # We build a special copy of libgmp which doesn't use libstdc++, because
504 # xgcc++'s libstdc++ references the bootstrap-files (which is what
505 # compiles xgcc++).
506 gmp = super.gmp.override { cxx = false; };
507 } // {
508 ${localSystem.libc} = getLibc prevStage;
509 gcc-unwrapped = (super.gcc-unwrapped.override (commonGccOverrides // {
510 inherit (prevStage) which;
511 }
512 )).overrideAttrs (a: {
513 # so we can add them to allowedRequisites below
514 passthru = a.passthru // { inherit (self) gmp mpfr libmpc isl; };
515 });
516 };
517 extraNativeBuildInputs = [
518 prevStage.patchelf
519 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
520 prevStage.updateAutotoolsGnuConfigScriptsHook
521 ];
522 })
523
524
525 # Construct a fourth stdenv that uses the new GCC. But coreutils is
526 # still from the bootstrap tools.
527 #
528 (prevStage:
529 # previous stage3 stdenv:
530 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
531 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
532 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
533 assert isFromBootstrapFiles prevStage.coreutils;
534 assert isFromBootstrapFiles prevStage.gnugrep;
535 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
536 stageFun prevStage {
537 name = "bootstrap-stage4";
538
539 overrides = self: super: {
540 # Zlib has to be inherited and not rebuilt in this stage,
541 # because gcc (since JAR support) already depends on zlib, and
542 # then if we already have a zlib we want to use that for the
543 # other purposes (binutils and top-level pkgs) too.
544 inherit (prevStage) gettext gnum4 bison perl texinfo zlib linuxHeaders libidn2 libunistring;
545 ${localSystem.libc} = getLibc prevStage;
546 binutils = super.binutils.override {
547 # Don't use stdenv's shell but our own
548 shell = self.bash + "/bin/bash";
549 # Build expand-response-params with last stage like below
550 buildPackages = {
551 inherit (prevStage) stdenv;
552 };
553 };
554
555 # To allow users' overrides inhibit dependencies too heavy for
556 # bootstrap, like guile: https://github.com/NixOS/nixpkgs/issues/181188
557 gnumake = super.gnumake.override { inBootstrap = true; };
558
559 gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
560 nativeTools = false;
561 nativeLibc = false;
562 isGNU = true;
563 buildPackages = {
564 inherit (prevStage) stdenv;
565 };
566 cc = prevStage.gcc-unwrapped;
567 bintools = self.binutils;
568 libc = getLibc self;
569 inherit lib;
570 inherit (self) stdenvNoCC coreutils gnugrep;
571 shell = self.bash + "/bin/bash";
572 fortify-headers = self.fortify-headers;
573 };
574 };
575 extraNativeBuildInputs = [
576 prevStage.patchelf prevStage.xz
577 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
578 prevStage.updateAutotoolsGnuConfigScriptsHook
579 ];
580 })
581
582 # Construct the final stdenv. It uses the Glibc and GCC, and adds
583 # in a new binutils that doesn't depend on bootstrap-tools, as well
584 # as dynamically linked versions of all other tools.
585 #
586 # When updating stdenvLinux, make sure that the result has no
587 # dependency (`nix-store -qR') on bootstrapTools or the first
588 # binutils built.
589 #
590 (prevStage:
591 # previous stage4 stdenv; see stage3 comment regarding gcc,
592 # which applies here as well.
593 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
594 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
595 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
596 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
597 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
598 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
599 {
600 inherit config overlays;
601 stdenv = import ../generic rec {
602 name = "stdenv-linux";
603
604 buildPlatform = localSystem;
605 hostPlatform = localSystem;
606 targetPlatform = localSystem;
607 inherit config;
608
609 preHook = commonPreHook;
610
611 initialPath =
612 ((import ../generic/common-path.nix) {pkgs = prevStage;});
613
614 extraNativeBuildInputs = [
615 prevStage.patchelf
616 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
617 prevStage.updateAutotoolsGnuConfigScriptsHook
618 ];
619
620 cc = prevStage.gcc;
621
622 shell = cc.shell;
623
624 inherit (prevStage.stdenv) fetchurlBoot;
625
626 extraAttrs = {
627 inherit bootstrapTools;
628 shellPackage = prevStage.bash;
629 };
630
631 disallowedRequisites = [ bootstrapTools.out ];
632
633 # Mainly avoid reference to bootstrap tools
634 allowedRequisites = with prevStage; with lib;
635 # Simple executable tools
636 concatMap (p: [ (getBin p) (getLib p) ]) [
637 gzip bzip2 xz bash binutils.bintools coreutils diffutils findutils
638 gawk gmp gnumake gnused gnutar gnugrep gnupatch patchelf ed file
639 ]
640 # Library dependencies
641 ++ map getLib (
642 [ attr acl zlib gnugrep.pcre2 libidn2 libunistring ]
643 ++ lib.optional (gawk.libsigsegv != null) gawk.libsigsegv
644 )
645 # More complicated cases
646 ++ (map (x: getOutput x (getLibc prevStage)) [ "out" "dev" "bin" ] )
647 ++ [ linuxHeaders # propagated from .dev
648 binutils gcc gcc.cc gcc.cc.lib gcc.expand-response-params gcc.cc.libgcc glibc.passthru.libgcc
649 ]
650 ++ lib.optionals (localSystem.libc == "musl") [ fortify-headers ]
651 ++ [ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ]
652 ++ (with gcc-unwrapped.passthru; [
653 gmp libmpc mpfr isl
654 ])
655 ;
656
657 overrides = self: super: {
658 inherit (prevStage)
659 gzip bzip2 xz bash coreutils diffutils findutils gawk
660 gnused gnutar gnugrep gnupatch patchelf
661 attr acl zlib libunistring;
662 inherit (prevStage.gnugrep) pcre2;
663 ${localSystem.libc} = getLibc prevStage;
664
665 # Hack: avoid libidn2.{bin,dev} referencing bootstrap tools. There's a logical cycle.
666 libidn2 = import ../../development/libraries/libidn2/no-bootstrap-reference.nix {
667 inherit lib;
668 inherit (prevStage) libidn2;
669 inherit (self) stdenv runCommandLocal patchelf libunistring;
670 };
671
672 gnumake = super.gnumake.override { inBootstrap = false; };
673 } // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) {
674 # Need to get rid of these when cross-compiling.
675 inherit (prevStage) binutils binutils-unwrapped;
676 gcc = cc;
677 };
678 };
679 })
680
681 # This "no-op" stage is just a place to put the assertions about stage5.
682 (prevStage:
683 # previous stage5 stdenv; see stage3 comment regarding gcc,
684 # which applies here as well.
685 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
686 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
687 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
688 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
689 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
690 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
691 { inherit (prevStage) config overlays stdenv; })
692]