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.nix;
63 x86_64-linux = import ./bootstrap-files/x86_64.nix;
64 armv5tel-linux = import ./bootstrap-files/armv5tel.nix;
65 armv6l-linux = import ./bootstrap-files/armv6l.nix;
66 armv7l-linux = import ./bootstrap-files/armv7l.nix;
67 aarch64-linux = import ./bootstrap-files/aarch64.nix;
68 mipsel-linux = import ./bootstrap-files/mipsel.nix;
69 mips64el-linux = import
70 (if localSystem.isMips64n32
71 then ./bootstrap-files/mips64el-n32.nix
72 else ./bootstrap-files/mips64el.nix);
73 powerpc64le-linux = import ./bootstrap-files/powerpc64le.nix;
74 riscv64-linux = import ./bootstrap-files/riscv64.nix;
75 };
76 musl = {
77 aarch64-linux = import ./bootstrap-files/aarch64-musl.nix;
78 armv6l-linux = import ./bootstrap-files/armv6l-musl.nix;
79 x86_64-linux = import ./bootstrap-files/x86_64-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 }).overrideAttrs(a: lib.optionalAttrs (prevStage.gcc-unwrapped.passthru.isXgcc or false) {
198 # This affects only `xgcc` (the compiler which compiles the final compiler).
199 postFixup = (a.postFixup or "") + ''
200 echo "--sysroot=${lib.getDev (getLibc prevStage)}" >> $out/nix-support/cc-cflags
201 '';
202 });
203
204 overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; };
205 };
206
207 in {
208 inherit config overlays;
209 stdenv = thisStdenv;
210 };
211
212in
213 assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
214[
215
216 ({}: {
217 __raw = true;
218
219 gcc-unwrapped = null;
220 binutils = null;
221 coreutils = null;
222 gnugrep = null;
223 })
224
225 # Build a dummy stdenv with no GCC or working fetchurl. This is
226 # because we need a stdenv to build the GCC wrapper and fetchurl.
227 (prevStage: stageFun prevStage {
228 name = "bootstrap-stage0";
229
230 overrides = self: super: {
231 # We thread stage0's stdenv through under this name so downstream stages
232 # can use it for wrapping gcc too. This way, downstream stages don't need
233 # to refer to this stage directly, which violates the principle that each
234 # stage should only access the stage that came before it.
235 ccWrapperStdenv = self.stdenv;
236 # The Glibc include directory cannot have the same prefix as the
237 # GCC include directory, since GCC gets confused otherwise (it
238 # will search the Glibc headers before the GCC headers). So
239 # create a dummy Glibc here, which will be used in the stdenv of
240 # stage1.
241 ${localSystem.libc} = self.stdenv.mkDerivation {
242 pname = "bootstrap-stage0-${localSystem.libc}";
243 strictDeps = true;
244 version = "bootstrapFiles";
245 enableParallelBuilding = true;
246 buildCommand = ''
247 mkdir -p $out
248 ln -s ${bootstrapTools}/lib $out/lib
249 '' + lib.optionalString (localSystem.libc == "glibc") ''
250 ln -s ${bootstrapTools}/include-glibc $out/include
251 '' + lib.optionalString (localSystem.libc == "musl") ''
252 ln -s ${bootstrapTools}/include-libc $out/include
253 '';
254 passthru.isFromBootstrapFiles = true;
255 };
256 gcc-unwrapped = bootstrapTools;
257 binutils = import ../../build-support/bintools-wrapper {
258 name = "bootstrap-stage0-binutils-wrapper";
259 nativeTools = false;
260 nativeLibc = false;
261 buildPackages = { };
262 libc = getLibc self;
263 inherit lib;
264 inherit (self) stdenvNoCC coreutils gnugrep;
265 bintools = bootstrapTools;
266 };
267 coreutils = bootstrapTools;
268 gnugrep = bootstrapTools;
269 };
270 })
271
272
273 # Create the first "real" standard environment. This one consists
274 # of bootstrap tools only, and a minimal Glibc to keep the GCC
275 # configure script happy.
276 #
277 # For clarity, we only use the previous stage when specifying these
278 # stages. So stageN should only ever have references for stage{N-1}.
279 #
280 # If we ever need to use a package from more than one stage back, we
281 # simply re-export those packages in the middle stage(s) using the
282 # overrides attribute and the inherit syntax.
283 (prevStage:
284 # previous stage0 stdenv:
285 assert isFromBootstrapFiles prevStage.binutils.bintools;
286 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
287 assert isFromBootstrapFiles prevStage.gcc-unwrapped;
288 assert isFromBootstrapFiles prevStage.coreutils;
289 assert isFromBootstrapFiles prevStage.gnugrep;
290 stageFun prevStage {
291 name = "bootstrap-stage1";
292
293 # Rebuild binutils to use from stage2 onwards.
294 overrides = self: super: {
295 binutils-unwrapped = super.binutils-unwrapped.override {
296 enableGold = false;
297 };
298 inherit (prevStage)
299 ccWrapperStdenv
300 gcc-unwrapped coreutils gnugrep binutils;
301
302 ${localSystem.libc} = getLibc prevStage;
303
304 # A threaded perl build needs glibc/libpthread_nonshared.a,
305 # which is not included in bootstrapTools, so disable threading.
306 # This is not an issue for the final stdenv, because this perl
307 # won't be included in the final stdenv and won't be exported to
308 # top-level pkgs as an override either.
309 perl = super.perl.override { enableThreading = false; enableCrypt = false; };
310 };
311
312 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
313 extraNativeBuildInputs =
314 lib.optional (localSystem.isLoongArch64) 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 =
395 lib.optional (localSystem.isLoongArch64) prevStage.updateAutotoolsGnuConfigScriptsHook;
396 })
397
398 # 2nd stdenv that contains our own rebuilt binutils and is used for
399 # compiling our own Glibc.
400 #
401 (prevStage:
402 # previous stage1 stdenv:
403 assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
404 assert isFromBootstrapFiles prevStage."${localSystem.libc}";
405 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
406 assert isFromBootstrapFiles prevStage.coreutils;
407 assert isFromBootstrapFiles prevStage.gnugrep;
408 assert isBuiltByBootstrapFilesCompiler prevStage.patchelf;
409 stageFun prevStage {
410 name = "bootstrap-stage2";
411
412 overrides = self: super: {
413 inherit (prevStage)
414 ccWrapperStdenv gettext
415 gcc-unwrapped coreutils gnugrep
416 perl gnum4 bison texinfo which;
417 dejagnu = super.dejagnu.overrideAttrs (a: { doCheck = false; } );
418
419 # We need libidn2 and its dependency libunistring as glibc dependency.
420 # To avoid the cycle, we build against bootstrap libc, nuke references,
421 # and use the result as input for our final glibc. We also pass this pair
422 # through, so the final package-set uses exactly the same builds.
423 libunistring = super.libunistring.overrideAttrs (attrs: {
424 postFixup = attrs.postFixup or "" + ''
425 ${self.nukeReferences}/bin/nuke-refs "$out"/lib/lib*.so.*.*
426 '';
427 # Apparently iconv won't work with bootstrap glibc, but it will be used
428 # with glibc built later where we keep *this* build of libunistring,
429 # so we need to trick it into supporting libiconv.
430 env = attrs.env or {} // { am_cv_func_iconv_works = "yes"; };
431 });
432 libidn2 = super.libidn2.overrideAttrs (attrs: {
433 postFixup = attrs.postFixup or "" + ''
434 ${self.nukeReferences}/bin/nuke-refs -e '${lib.getLib self.libunistring}' \
435 "$out"/lib/lib*.so.*.*
436 '';
437 });
438
439 # This also contains the full, dynamically linked, final Glibc.
440 binutils = prevStage.binutils.override {
441 # Rewrap the binutils with the new glibc, so both the next
442 # stage's wrappers use it.
443 libc = getLibc self;
444
445 # Unfortunately, when building gcc in the next stage, its LTO plugin
446 # would use the final libc but `ld` would use the bootstrap one,
447 # and that can fail to load. Therefore we upgrade `ld` to use newer libc;
448 # apparently the interpreter needs to match libc, too.
449 bintools = self.stdenvNoCC.mkDerivation {
450 pname = prevStage.bintools.bintools.pname + "-patchelfed-ld";
451 inherit (prevStage.bintools.bintools) version;
452 passthru = { inherit (prevStage.bintools.passthru) isFromBootstrapFiles; };
453 enableParallelBuilding = true;
454 dontUnpack = true;
455 dontBuild = true;
456 strictDeps = true;
457 # We wouldn't need to *copy* all, but it's easier and the result is temporary anyway.
458 installPhase = ''
459 mkdir -p "$out"/bin
460 cp -a '${prevStage.bintools.bintools}'/bin/* "$out"/bin/
461 chmod +w "$out"/bin/ld.bfd
462 patchelf --set-interpreter '${getLibc self}'/lib/ld*.so.? \
463 --set-rpath "${getLibc self}/lib:$(patchelf --print-rpath "$out"/bin/ld.bfd)" \
464 "$out"/bin/ld.bfd
465 '';
466 };
467 };
468
469 # TODO(amjoseph): It is not yet entirely clear why this is necessary.
470 # Something strange is going on with xgcc and libstdc++ on pkgsMusl.
471 patchelf = super.patchelf.overrideAttrs(previousAttrs:
472 lib.optionalAttrs super.stdenv.hostPlatform.isMusl {
473 NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or "") + " -static-libstdc++";
474 });
475
476 };
477
478 # `gettext` comes with obsolete config.sub/config.guess that don't recognize LoongArch64.
479 # `libtool` comes with obsolete config.sub/config.guess that don't recognize Risc-V.
480 extraNativeBuildInputs =
481 lib.optional (localSystem.isLoongArch64 || localSystem.isRiscV) prevStage.updateAutotoolsGnuConfigScriptsHook;
482 })
483
484
485 # Construct a third stdenv identical to the 2nd, except that this
486 # one uses the rebuilt Glibc from stage2. It still uses the recent
487 # binutils and rest of the bootstrap tools, including GCC.
488 (prevStage:
489 # previous stage2 stdenv:
490 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
491 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
492 assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
493 assert isFromBootstrapFiles prevStage.coreutils;
494 assert isFromBootstrapFiles prevStage.gnugrep;
495 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
496 assert lib.all isBuiltByNixpkgsCompiler (with prevStage; [ gmp isl_0_20 libmpc mpfr ]);
497 stageFun prevStage {
498 name = "bootstrap-stage3";
499
500 overrides = self: super: rec {
501 inherit (prevStage)
502 ccWrapperStdenv
503 binutils coreutils gnugrep gettext
504 perl patchelf linuxHeaders gnum4 bison libidn2 libunistring libxcrypt;
505 # We build a special copy of libgmp which doesn't use libstdc++, because
506 # xgcc++'s libstdc++ references the bootstrap-files (which is what
507 # compiles xgcc++).
508 gmp = super.gmp.override { cxx = false; };
509 } // {
510 ${localSystem.libc} = getLibc prevStage;
511 gcc-unwrapped = (super.gcc-unwrapped.override (commonGccOverrides // {
512 inherit (prevStage) which;
513 }
514 )).overrideAttrs (a: {
515 # so we can add them to allowedRequisites below
516 passthru = a.passthru // { inherit (self) gmp mpfr libmpc isl; };
517 });
518 };
519 extraNativeBuildInputs = [ prevStage.patchelf ] ++
520 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
521 lib.optional (!localSystem.isx86 || localSystem.libc == "musl")
522 prevStage.updateAutotoolsGnuConfigScriptsHook;
523 })
524
525
526 # Construct a fourth stdenv that uses the new GCC. But coreutils is
527 # still from the bootstrap tools.
528 #
529 (prevStage:
530 # previous stage3 stdenv:
531 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
532 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
533 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
534 assert isFromBootstrapFiles prevStage.coreutils;
535 assert isFromBootstrapFiles prevStage.gnugrep;
536 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
537 stageFun prevStage {
538 name = "bootstrap-stage4";
539
540 overrides = self: super: {
541 # Zlib has to be inherited and not rebuilt in this stage,
542 # because gcc (since JAR support) already depends on zlib, and
543 # then if we already have a zlib we want to use that for the
544 # other purposes (binutils and top-level pkgs) too.
545 inherit (prevStage) gettext gnum4 bison perl texinfo zlib linuxHeaders libidn2 libunistring;
546 ${localSystem.libc} = getLibc prevStage;
547 binutils = super.binutils.override {
548 # Don't use stdenv's shell but our own
549 shell = self.bash + "/bin/bash";
550 # Build expand-response-params with last stage like below
551 buildPackages = {
552 inherit (prevStage) stdenv;
553 };
554 };
555
556 # To allow users' overrides inhibit dependencies too heavy for
557 # bootstrap, like guile: https://github.com/NixOS/nixpkgs/issues/181188
558 gnumake = super.gnumake.override { inBootstrap = true; };
559
560 gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
561 nativeTools = false;
562 nativeLibc = false;
563 isGNU = true;
564 buildPackages = {
565 inherit (prevStage) stdenv;
566 };
567 cc = prevStage.gcc-unwrapped;
568 bintools = self.binutils;
569 libc = getLibc self;
570 inherit lib;
571 inherit (self) stdenvNoCC coreutils gnugrep;
572 shell = self.bash + "/bin/bash";
573 };
574 };
575 extraNativeBuildInputs = [ prevStage.patchelf prevStage.xz ] ++
576 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
577 lib.optional (!localSystem.isx86 || localSystem.libc == "musl")
578 prevStage.updateAutotoolsGnuConfigScriptsHook;
579 })
580
581 # Construct the final stdenv. It uses the Glibc and GCC, and adds
582 # in a new binutils that doesn't depend on bootstrap-tools, as well
583 # as dynamically linked versions of all other tools.
584 #
585 # When updating stdenvLinux, make sure that the result has no
586 # dependency (`nix-store -qR') on bootstrapTools or the first
587 # binutils built.
588 #
589 (prevStage:
590 # previous stage4 stdenv; see stage3 comment regarding gcc,
591 # which applies here as well.
592 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
593 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
594 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
595 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
596 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
597 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
598 {
599 inherit config overlays;
600 stdenv = import ../generic rec {
601 name = "stdenv-linux";
602
603 buildPlatform = localSystem;
604 hostPlatform = localSystem;
605 targetPlatform = localSystem;
606 inherit config;
607
608 preHook = commonPreHook;
609
610 initialPath =
611 ((import ../generic/common-path.nix) {pkgs = prevStage;});
612
613 extraNativeBuildInputs = [ prevStage.patchelf ] ++
614 # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
615 lib.optional (!localSystem.isx86 || localSystem.libc == "musl")
616 prevStage.updateAutotoolsGnuConfigScriptsHook;
617
618 cc = prevStage.gcc;
619
620 shell = cc.shell;
621
622 inherit (prevStage.stdenv) fetchurlBoot;
623
624 extraAttrs = {
625 inherit bootstrapTools;
626 shellPackage = prevStage.bash;
627 };
628
629 disallowedRequisites = [ bootstrapTools.out ];
630
631 # Mainly avoid reference to bootstrap tools
632 allowedRequisites = with prevStage; with lib;
633 # Simple executable tools
634 concatMap (p: [ (getBin p) (getLib p) ]) [
635 gzip bzip2 xz bash binutils.bintools coreutils diffutils findutils
636 gawk gmp gnumake gnused gnutar gnugrep gnupatch patchelf ed file
637 ]
638 # Library dependencies
639 ++ map getLib (
640 [ attr acl zlib gnugrep.pcre2 libidn2 libunistring ]
641 ++ lib.optional (gawk.libsigsegv != null) gawk.libsigsegv
642 )
643 # More complicated cases
644 ++ (map (x: getOutput x (getLibc prevStage)) [ "out" "dev" "bin" ] )
645 ++ [ linuxHeaders # propagated from .dev
646 binutils gcc gcc.cc gcc.cc.lib gcc.expand-response-params gcc.cc.libgcc glibc.passthru.libgcc
647 ]
648 ++ lib.optionals (!localSystem.isx86 || localSystem.libc == "musl")
649 [ prevStage.updateAutotoolsGnuConfigScriptsHook prevStage.gnu-config ]
650 ++ (with gcc-unwrapped.passthru; [
651 gmp libmpc mpfr isl
652 ])
653 ;
654
655 overrides = self: super: {
656 inherit (prevStage)
657 gzip bzip2 xz bash coreutils diffutils findutils gawk
658 gnused gnutar gnugrep gnupatch patchelf
659 attr acl zlib libunistring;
660 inherit (prevStage.gnugrep) pcre2;
661 ${localSystem.libc} = getLibc prevStage;
662
663 # Hack: avoid libidn2.{bin,dev} referencing bootstrap tools. There's a logical cycle.
664 libidn2 = import ../../development/libraries/libidn2/no-bootstrap-reference.nix {
665 inherit lib;
666 inherit (prevStage) libidn2;
667 inherit (self) stdenv runCommandLocal patchelf libunistring;
668 };
669
670 gnumake = super.gnumake.override { inBootstrap = false; };
671 } // lib.optionalAttrs (super.stdenv.targetPlatform == localSystem) {
672 # Need to get rid of these when cross-compiling.
673 inherit (prevStage) binutils binutils-unwrapped;
674 gcc = cc;
675 };
676 };
677 })
678
679 # This "no-op" stage is just a place to put the assertions about stage5.
680 (prevStage:
681 # previous stage5 stdenv; see stage3 comment regarding gcc,
682 # which applies here as well.
683 assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
684 assert isBuiltByNixpkgsCompiler prevStage.${localSystem.libc};
685 assert isBuiltByNixpkgsCompiler prevStage.gcc-unwrapped;
686 assert isBuiltByNixpkgsCompiler prevStage.coreutils;
687 assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
688 assert isBuiltByNixpkgsCompiler prevStage.patchelf;
689 { inherit (prevStage) config overlays stdenv; })
690]