296 lines
10 KiB
Nix
296 lines
10 KiB
Nix
# This file constructs the standard build environment for the
|
|
# Linux/i686 platform. It's completely pure; that is, it relies on no
|
|
# external (non-Nix) tools, such as /usr/bin/gcc, and it contains a C
|
|
# compiler and linker that do not search in default locations,
|
|
# ensuring purity of components produced by it.
|
|
{ lib
|
|
, system, platform, crossSystem, config, overlays
|
|
|
|
, bootstrapFiles ?
|
|
if system == "i686-linux" then import ./bootstrap-files/i686.nix
|
|
else if system == "x86_64-linux" then import ./bootstrap-files/x86_64.nix
|
|
else if system == "armv5tel-linux" then import ./bootstrap-files/armv5tel.nix
|
|
else if system == "armv6l-linux" then import ./bootstrap-files/armv6l.nix
|
|
else if system == "armv7l-linux" then import ./bootstrap-files/armv7l.nix
|
|
else if system == "mips64el-linux" then import ./bootstrap-files/loongson2f.nix
|
|
else abort "unsupported platform for the pure Linux stdenv"
|
|
}:
|
|
|
|
assert crossSystem == null;
|
|
|
|
let
|
|
|
|
commonPreHook =
|
|
''
|
|
export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}"
|
|
export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}"
|
|
${if system == "x86_64-linux" then "NIX_LIB64_IN_SELF_RPATH=1" else ""}
|
|
${if system == "mips64el-linux" then "NIX_LIB32_IN_SELF_RPATH=1" else ""}
|
|
'';
|
|
|
|
|
|
# The bootstrap process proceeds in several steps.
|
|
|
|
|
|
# Create a standard environment by downloading pre-built binaries of
|
|
# coreutils, GCC, etc.
|
|
|
|
|
|
# Download and unpack the bootstrap tools (coreutils, GCC, Glibc, ...).
|
|
bootstrapTools = import ./bootstrap-tools { inherit system bootstrapFiles; };
|
|
|
|
|
|
# This function builds the various standard environments used during
|
|
# the bootstrap. In all stages, we build an stdenv and the package
|
|
# set that can be built with that stdenv.
|
|
stageFun = prevStage:
|
|
{ name, overrides ? (self: super: {}), extraBuildInputs ? [] }:
|
|
|
|
let
|
|
|
|
thisStdenv = import ../generic {
|
|
inherit system config extraBuildInputs;
|
|
name = "stdenv-linux-boot";
|
|
preHook =
|
|
''
|
|
# Don't patch #!/interpreter because it leads to retained
|
|
# dependencies on the bootstrapTools in the final stdenv.
|
|
dontPatchShebangs=1
|
|
${commonPreHook}
|
|
'';
|
|
shell = "${bootstrapTools}/bin/bash";
|
|
initialPath = [bootstrapTools];
|
|
|
|
fetchurlBoot = import ../../build-support/fetchurl/boot.nix {
|
|
inherit system;
|
|
};
|
|
|
|
cc = if isNull prevStage.gcc-unwrapped
|
|
then null
|
|
else lib.makeOverridable (import ../../build-support/cc-wrapper) {
|
|
nativeTools = false;
|
|
nativeLibc = false;
|
|
cc = prevStage.gcc-unwrapped;
|
|
isGNU = true;
|
|
libc = prevStage.glibc;
|
|
inherit (prevStage) binutils coreutils gnugrep;
|
|
name = name;
|
|
stdenv = prevStage.ccWrapperStdenv;
|
|
};
|
|
|
|
extraAttrs = {
|
|
# Having the proper 'platform' in all the stdenvs allows getting proper
|
|
# linuxHeaders for example.
|
|
inherit platform;
|
|
|
|
# stdenv.glibc is used by GCC build to figure out the system-level
|
|
# /usr/include directory.
|
|
inherit (prevStage) glibc;
|
|
};
|
|
overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; };
|
|
};
|
|
|
|
in {
|
|
inherit system platform crossSystem config overlays;
|
|
stdenv = thisStdenv;
|
|
};
|
|
|
|
in
|
|
|
|
[
|
|
|
|
({}: {
|
|
__raw = true;
|
|
|
|
gcc-unwrapped = null;
|
|
glibc = null;
|
|
binutils = null;
|
|
coreutils = null;
|
|
gnugrep = null;
|
|
})
|
|
|
|
# Build a dummy stdenv with no GCC or working fetchurl. This is
|
|
# because we need a stdenv to build the GCC wrapper and fetchurl.
|
|
(prevStage: stageFun prevStage {
|
|
name = null;
|
|
|
|
overrides = self: super: {
|
|
# We thread stage0's stdenv through under this name so downstream stages
|
|
# can use it for wrapping gcc too. This way, downstream stages don't need
|
|
# to refer to this stage directly, which violates the principle that each
|
|
# stage should only access the stage that came before it.
|
|
ccWrapperStdenv = self.stdenv;
|
|
# The Glibc include directory cannot have the same prefix as the
|
|
# GCC include directory, since GCC gets confused otherwise (it
|
|
# will search the Glibc headers before the GCC headers). So
|
|
# create a dummy Glibc here, which will be used in the stdenv of
|
|
# stage1.
|
|
glibc = self.stdenv.mkDerivation {
|
|
name = "bootstrap-glibc";
|
|
buildCommand = ''
|
|
mkdir -p $out
|
|
ln -s ${bootstrapTools}/lib $out/lib
|
|
ln -s ${bootstrapTools}/include-glibc $out/include
|
|
'';
|
|
};
|
|
gcc-unwrapped = bootstrapTools;
|
|
binutils = bootstrapTools;
|
|
coreutils = bootstrapTools;
|
|
gnugrep = bootstrapTools;
|
|
};
|
|
})
|
|
|
|
|
|
# Create the first "real" standard environment. This one consists
|
|
# of bootstrap tools only, and a minimal Glibc to keep the GCC
|
|
# configure script happy.
|
|
#
|
|
# For clarity, we only use the previous stage when specifying these
|
|
# stages. So stageN should only ever have references for stage{N-1}.
|
|
#
|
|
# 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.
|
|
(prevStage: stageFun prevStage {
|
|
name = "bootstrap-gcc-wrapper";
|
|
|
|
# Rebuild binutils to use from stage2 onwards.
|
|
overrides = self: super: {
|
|
binutils = super.binutils.override { gold = false; };
|
|
inherit (prevStage)
|
|
ccWrapperStdenv
|
|
glibc gcc-unwrapped coreutils gnugrep;
|
|
|
|
# A threaded perl build needs glibc/libpthread_nonshared.a,
|
|
# which is not included in bootstrapTools, so disable threading.
|
|
# This is not an issue for the final stdenv, because this perl
|
|
# won't be included in the final stdenv and won't be exported to
|
|
# top-level pkgs as an override either.
|
|
perl = super.perl.override { enableThreading = false; };
|
|
};
|
|
})
|
|
|
|
|
|
# 2nd stdenv that contains our own rebuilt binutils and is used for
|
|
# compiling our own Glibc.
|
|
(prevStage: stageFun prevStage {
|
|
name = "bootstrap-gcc-wrapper";
|
|
|
|
overrides = self: super: {
|
|
inherit (prevStage)
|
|
ccWrapperStdenv
|
|
binutils gcc-unwrapped coreutils gnugrep
|
|
perl paxctl gnum4 bison;
|
|
# This also contains the full, dynamically linked, final Glibc.
|
|
};
|
|
})
|
|
|
|
|
|
# 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.
|
|
(prevStage: stageFun prevStage {
|
|
name = "bootstrap-gcc-wrapper";
|
|
|
|
overrides = self: super: rec {
|
|
inherit (prevStage)
|
|
ccWrapperStdenv
|
|
binutils glibc coreutils gnugrep
|
|
perl patchelf linuxHeaders gnum4 bison;
|
|
# Link GCC statically against GMP etc. This makes sense because
|
|
# these builds of the libraries are only used by GCC, so it
|
|
# reduces the size of the stdenv closure.
|
|
gmp = super.gmp.override { stdenv = self.makeStaticLibraries self.stdenv; };
|
|
mpfr = super.mpfr.override { stdenv = self.makeStaticLibraries self.stdenv; };
|
|
libmpc = super.libmpc.override { stdenv = self.makeStaticLibraries self.stdenv; };
|
|
isl_0_14 = super.isl_0_14.override { stdenv = self.makeStaticLibraries self.stdenv; };
|
|
gcc-unwrapped = super.gcc-unwrapped.override {
|
|
isl = isl_0_14;
|
|
};
|
|
};
|
|
extraBuildInputs = [ prevStage.patchelf prevStage.paxctl ];
|
|
})
|
|
|
|
|
|
# Construct a fourth stdenv that uses the new GCC. But coreutils is
|
|
# still from the bootstrap tools.
|
|
(prevStage: stageFun prevStage {
|
|
name = "";
|
|
|
|
overrides = self: super: {
|
|
# Zlib has to be inherited and not rebuilt in this stage,
|
|
# because gcc (since JAR support) already depends on zlib, and
|
|
# then if we already have a zlib we want to use that for the
|
|
# other purposes (binutils and top-level pkgs) too.
|
|
inherit (prevStage) gettext gnum4 bison gmp perl glibc zlib linuxHeaders;
|
|
|
|
gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
|
|
nativeTools = false;
|
|
nativeLibc = false;
|
|
isGNU = true;
|
|
cc = prevStage.gcc-unwrapped;
|
|
libc = self.glibc;
|
|
inherit (self) stdenv binutils coreutils gnugrep;
|
|
name = "";
|
|
shell = self.bash + "/bin/bash";
|
|
};
|
|
};
|
|
extraBuildInputs = [ prevStage.patchelf prevStage.xz ];
|
|
})
|
|
|
|
# Construct the final stdenv. It uses the Glibc and GCC, and adds
|
|
# in a new binutils that doesn't depend on bootstrap-tools, as well
|
|
# as dynamically linked versions of all other tools.
|
|
#
|
|
# When updating stdenvLinux, make sure that the result has no
|
|
# dependency (`nix-store -qR') on bootstrapTools or the first
|
|
# binutils built.
|
|
(prevStage: {
|
|
inherit system crossSystem platform config overlays;
|
|
stdenv = import ../generic rec {
|
|
inherit system config;
|
|
|
|
preHook = ''
|
|
# Make "strip" produce deterministic output, by setting
|
|
# timestamps etc. to a fixed value.
|
|
commonStripFlags="--enable-deterministic-archives"
|
|
${commonPreHook}
|
|
'';
|
|
|
|
initialPath =
|
|
((import ../common-path.nix) {pkgs = prevStage;});
|
|
|
|
extraBuildInputs = [ prevStage.patchelf prevStage.paxctl ];
|
|
|
|
cc = prevStage.gcc;
|
|
|
|
shell = cc.shell;
|
|
|
|
inherit (prevStage.stdenv) fetchurlBoot;
|
|
|
|
extraAttrs = {
|
|
inherit (prevStage) glibc;
|
|
inherit platform bootstrapTools;
|
|
shellPackage = prevStage.bash;
|
|
};
|
|
|
|
/* outputs TODO
|
|
allowedRequisites = with prevStage;
|
|
[ gzip bzip2 xz bash binutils coreutils diffutils findutils gawk
|
|
glibc gnumake gnused gnutar gnugrep gnupatch patchelf attr acl
|
|
paxctl zlib pcre linuxHeaders ed gcc gcc.cc libsigsegv
|
|
];
|
|
*/
|
|
|
|
overrides = self: super: {
|
|
gcc = cc;
|
|
|
|
inherit (prevStage)
|
|
gzip bzip2 xz bash binutils coreutils diffutils findutils gawk
|
|
glibc gnumake gnused gnutar gnugrep gnupatch patchelf
|
|
attr acl paxctl zlib pcre;
|
|
};
|
|
};
|
|
})
|
|
|
|
]
|