express #208478 as assertions

PR #208478 added a lot of documentation about which packages were
rebuilt in each stage of the stdenv bootstrap.  However nothing
checks that these comments agree with reality; they can bitrot over
time.  This PR rewrites those comments as assertions, so they cannot
bitrot.

This conversion did expose some ambiguity in our scheme for naming
the stages.   Suppose that `pkgs.stdenv.name=="stdenv-stage4", then
which of these is "the stage4 coreutils"?

```
pkgs.coreutils
pkgs.stdenv.__bootPackages.coreutils
```

The choice is arbitrary, and both choices have confusing corner
cases.  We should revisit this at some point.
This commit is contained in:
Adam Joseph 2023-01-10 02:19:17 -08:00
parent fa169bb239
commit d7aad24531

View file

@ -100,6 +100,14 @@ assert crossSystem == localSystem;
let
inherit (localSystem) system;
isFromNixpkgs = pkg: !(isFromBootstrapFiles pkg);
isFromBootstrapFiles =
pkg: pkg.passthru.isFromBootstrapFiles or false;
isBuiltByNixpkgsCompiler =
pkg: isFromNixpkgs pkg && isFromNixpkgs pkg.stdenv.cc.cc;
isBuiltByBootstrapFilesCompiler =
pkg: isFromNixpkgs pkg && isFromBootstrapFiles pkg.stdenv.cc.cc;
commonPreHook =
''
export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}"
@ -117,16 +125,14 @@ let
# Download and unpack the bootstrap tools (coreutils, GCC, Glibc, ...).
bootstrapTools = import (if localSystem.libc == "musl" then ./bootstrap-tools-musl else ./bootstrap-tools) {
bootstrapTools = (import (if localSystem.libc == "musl" then ./bootstrap-tools-musl else ./bootstrap-tools) {
inherit system bootstrapFiles;
extraAttrs = lib.optionalAttrs
config.contentAddressedByDefault
{
__contentAddressed = true;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
};
};
extraAttrs = lib.optionalAttrs config.contentAddressedByDefault {
__contentAddressed = true;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
};
}) // { passthru.isFromBootstrapFiles = true; };
getLibc = stage: stage.${localSystem.libc};
@ -186,7 +192,7 @@ let
};
in
assert bootstrapTools.passthru.isFromBootstrapFiles or false; # sanity check
[
({}: {
@ -200,9 +206,6 @@ in
# Build a dummy stdenv with no GCC or working fetchurl. This is
# because we need a stdenv to build the GCC wrapper and fetchurl.
#
# resulting stage0 stdenv:
# - coreutils, binutils, glibc, gcc: from bootstrapFiles
(prevStage: stageFun prevStage {
name = "bootstrap-stage0";
@ -230,6 +233,7 @@ in
'' + lib.optionalString (localSystem.libc == "musl") ''
ln -s ${bootstrapTools}/include-libc $out/include
'';
passthru.isFromBootstrapFiles = true;
};
gcc-unwrapped = bootstrapTools;
binutils = import ../../build-support/bintools-wrapper {
@ -258,10 +262,14 @@ in
# If we ever need to use a package from more than one stage back, we
# simply re-export those packages in the middle stage(s) using the
# overrides attribute and the inherit syntax.
#
# resulting stage1 stdenv:
# - coreutils, binutils, glibc, gcc: from bootstrapFiles
(prevStage: stageFun prevStage {
(prevStage:
# previous stage0 stdenv:
assert isFromBootstrapFiles prevStage.binutils.bintools;
assert isFromBootstrapFiles prevStage."${localSystem.libc}";
assert isFromBootstrapFiles prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep;
stageFun prevStage {
name = "bootstrap-stage1";
# Rebuild binutils to use from stage2 onwards.
@ -288,10 +296,14 @@ in
# 2nd stdenv that contains our own rebuilt binutils and is used for
# compiling our own Glibc.
#
# resulting stage2 stdenv:
# - coreutils, glibc, gcc: from bootstrapFiles
# - binutils: from nixpkgs, built by bootstrapFiles toolchain
(prevStage: stageFun prevStage {
(prevStage:
# previous stage1 stdenv:
assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
assert isFromBootstrapFiles prevStage."${localSystem.libc}";
assert isFromBootstrapFiles prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep;
stageFun prevStage {
name = "bootstrap-stage2";
overrides = self: super: {
@ -334,6 +346,7 @@ in
bintools = self.stdenvNoCC.mkDerivation {
pname = prevStage.bintools.bintools.pname + "-patchelfed-ld";
inherit (prevStage.bintools.bintools) version;
passthru = { inherit (prevStage.bintools.passthru) isFromBootstrapFiles; };
enableParallelBuilding = true;
dontUnpack = true;
dontBuild = true;
@ -360,11 +373,14 @@ in
# Construct a third stdenv identical to the 2nd, except that this
# one uses the rebuilt Glibc from stage2. It still uses the recent
# binutils and rest of the bootstrap tools, including GCC.
#
# resulting stage3 stdenv:
# - coreutils, gcc: from bootstrapFiles
# - glibc, binutils: from nixpkgs, built by bootstrapFiles toolchain
(prevStage: stageFun prevStage {
(prevStage:
# previous stage2 stdenv:
assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc};
assert isFromBootstrapFiles prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep;
stageFun prevStage {
name = "bootstrap-stage3";
overrides = self: super: rec {
@ -401,17 +417,21 @@ in
# Construct a fourth stdenv that uses the new GCC. But coreutils is
# still from the bootstrap tools.
#
# resulting stage4 stdenv:
# - coreutils: from bootstrapFiles
# - glibc, binutils: from nixpkgs, built by bootstrapFiles toolchain
# - gcc: from nixpkgs, built by bootstrapFiles toolchain. Can assume
# it has almost no code from bootstrapTools as gcc bootstraps
# internally. The only exceptions are crt files from glibc
# built by bootstrapTools used to link executables and libraries,
# and the bootstrapTools-built, statically-linked
# lib{mpfr,mpc,gmp,isl}.a which are linked into the final gcc
# (see commit cfde88976ba4cddd01b1bb28b40afd12ea93a11d).
(prevStage: stageFun prevStage {
(prevStage:
# previous stage3 stdenv:
assert isBuiltByBootstrapFilesCompiler prevStage.binutils-unwrapped;
assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc};
assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
assert isFromBootstrapFiles prevStage.coreutils;
assert isFromBootstrapFiles prevStage.gnugrep;
# Can assume prevStage.gcc-unwrapped has almost no code from
# bootstrapTools as gcc bootstraps internally. The only
# exceptions are crt files from glibc built bybootstrapTools
# used to link executables and libraries, and the
# bootstrapTools-built, statically-linked
# lib{mpfr,mpc,gmp,isl}.a which are linked into the final gcc
# (see commit cfde88976ba4cddd01b1bb28b40afd12ea93a11d).
stageFun prevStage {
name = "bootstrap-stage4";
overrides = self: super: {
@ -468,17 +488,15 @@ in
# dependency (`nix-store -qR') on bootstrapTools or the first
# binutils built.
#
# resulting stage5 (final) stdenv:
# - coreutils, binutils: from nixpkgs, built by nixpkgs toolchain
# - glibc: from nixpkgs, built by bootstrapFiles toolchain
# - gcc: from nixpkgs, built by bootstrapFiles toolchain. Can assume
# it has almost no code from bootstrapTools as gcc bootstraps
# internally. The only exceptions are crt files from glibc
# built by bootstrapTools used to link executables and libraries,
# and the bootstrapTools-built, statically-linked
# lib{mpfr,mpc,gmp,isl}.a which are linked into the final gcc
# (see commit cfde88976ba4cddd01b1bb28b40afd12ea93a11d).
(prevStage: {
(prevStage:
# previous stage4 stdenv; see stage3 comment regarding gcc,
# which applies here as well.
assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc};
assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.coreutils;
assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
{
inherit config overlays;
stdenv = import ../generic rec {
name = "stdenv-linux";
@ -554,4 +572,14 @@ in
};
})
# This "no-op" stage is just a place to put the assertions about stage5.
(prevStage:
# previous stage5 stdenv; see stage3 comment regarding gcc,
# which applies here as well.
assert isBuiltByNixpkgsCompiler prevStage.binutils-unwrapped;
assert isBuiltByBootstrapFilesCompiler prevStage.${localSystem.libc};
assert isBuiltByBootstrapFilesCompiler prevStage.gcc-unwrapped;
assert isBuiltByNixpkgsCompiler prevStage.coreutils;
assert isBuiltByNixpkgsCompiler prevStage.gnugrep;
{ inherit (prevStage) config overlays stdenv; })
]