nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at fix-function-merge 699 lines 30 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 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]