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