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