lol
at 23.11-beta 692 lines 29 kB view raw
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]