diff --git a/pkgs/stdenv/booter.nix b/pkgs/stdenv/booter.nix new file mode 100644 index 00000000000..b1e1e898aa3 --- /dev/null +++ b/pkgs/stdenv/booter.nix @@ -0,0 +1,65 @@ +# This file defines a single function for booting a package set from a list of +# stages. The exact mechanics of that function are defined below; here I +# (@Ericson2314) wish to describe the purpose of the abstraction. +# +# The first goal is consistency across stdenvs. Regardless of what this function +# does, by making every stdenv use it for bootstrapping we ensure that they all +# work in a similar way. [Before this abstraction, each stdenv was its own +# special snowflake due to different authors writing in different times.] +# +# The second goal is consistency across each stdenv's stage functions. By +# writing each stage it terms of the previous stage, commonalities between them +# are more easily observable. [Before, there usually was a big attribute set +# with each stage, and stages would access the previous stage by name.] +# +# The third goal is composition. Because each stage is written in terms of the +# previous, the list can be reordered or, more practically, extended with new +# stages. The latter is used for cross compiling and custom +# stdenvs. Additionally, certain options should by default apply only to the +# last stage, whatever it may be. By delaying the creation of stage package sets +# until the final fold, we prevent these options from inhibiting composition. +# +# The fourth and final goal is debugging. Normal packages should only source +# their dependencies from the current stage. But for the sake of debugging, it +# is nice that all packages still remain accessible. We make sure previous +# stages are kept around with a `stdenv.__bootPackges` attribute referring the +# previous stage. It is idiomatic that attributes prefixed with `__` come with +# special restrictions and should not be used under normal circumstances. +{ lib, allPackages }: + +# Type: +# [ pkgset -> (args to stage/default.nix) or ({ __raw = true; } // pkgs) ] +# -> pkgset +# +# In english: This takes a list of function from the previous stage pkgset and +# returns the final pkgset. Each of those functions returns, if `__raw` is +# undefined or false, args for this stage's pkgset (the most complex and +# important arg is the stdenv), or, if `__raw = true`, simply this stage's +# pkgset itself. +# +# The list takes stages in order, so the final stage is last in the list. In +# other words, this does a foldr not foldl. +stageFuns: let + + # Take the list and disallow custom overrides in all but the final stage, + # and allow it in the final flag. Only defaults this boolean field if it + # isn't already set. + withAllowCustomOverrides = lib.lists.imap + (index: stageFun: prevStage: + { allowCustomOverrides = index == 1; } # first element, 1-indexed + // (stageFun prevStage)) + (lib.lists.reverseList stageFuns); + + # Adds the stdenv to the arguments, and sticks in it the previous stage for + # debugging purposes. + folder = stageFun: finalSoFar: let + args = stageFun finalSoFar; + stdenv = args.stdenv // { + # For debugging + __bootPackages = finalSoFar; + }; + args' = args // { inherit stdenv; }; + in + (if args.__raw or false then lib.id else allPackages) args'; + +in lib.lists.fold folder {} withAllowCustomOverrides diff --git a/pkgs/stdenv/cross/default.nix b/pkgs/stdenv/cross/default.nix index 10e2a766356..728424c0a7a 100644 --- a/pkgs/stdenv/cross/default.nix +++ b/pkgs/stdenv/cross/default.nix @@ -1,35 +1,48 @@ -{ lib, allPackages +{ lib , system, platform, crossSystem, config }: -rec { - vanillaStdenv = (import ../. { - inherit lib allPackages system platform; +let + bootStages = import ../. { + inherit lib system platform; crossSystem = null; # Ignore custom stdenvs when cross compiling for compatability config = builtins.removeAttrs config [ "replaceStdenv" ]; - }) // { - # Needed elsewhere as a hacky way to pass the target - cross = crossSystem; }; - # For now, this is just used to build the native stdenv. Eventually, it should - # be used to build compilers and other such tools targeting the cross +in bootStages ++ [ + + # Build Packages. + # + # For now, this is just used to build the native stdenv. Eventually, it + # should be used to build compilers and other such tools targeting the cross # platform. Then, `forceNativeDrv` can be removed. - buildPackages = allPackages { + (vanillaPackages: { inherit system platform crossSystem config; # It's OK to change the built-time dependencies allowCustomOverrides = true; - stdenv = vanillaStdenv; - }; + stdenv = vanillaPackages.stdenv // { + # Needed elsewhere as a hacky way to pass the target + cross = crossSystem; + }; + }) - stdenvCross = buildPackages.makeStdenvCross - buildPackages.stdenv crossSystem - buildPackages.binutilsCross buildPackages.gccCrossStageFinal; + # Run packages + (buildPackages: { + inherit system platform crossSystem config; + stdenv = if crossSystem.useiOSCross or false + then let + inherit (buildPackages.darwin.ios-cross { + prefix = crossSystem.config; + inherit (crossSystem) arch; + simulator = crossSystem.isiPhoneSimulator or false; }) + cc binutils; + in buildPackages.makeStdenvCross + buildPackages.stdenv crossSystem + binutils cc + else buildPackages.makeStdenvCross + buildPackages.stdenv crossSystem + buildPackages.binutilsCross buildPackages.gccCrossStageFinal; + }) - stdenvCrossiOS = let - inherit (buildPackages.darwin.ios-cross { prefix = crossSystem.config; inherit (crossSystem) arch; simulator = crossSystem.isiPhoneSimulator or false; }) cc binutils; - in buildPackages.makeStdenvCross - buildPackages.stdenv crossSystem - binutils cc; -} +] diff --git a/pkgs/stdenv/custom/default.nix b/pkgs/stdenv/custom/default.nix index 188d0027773..59a6e871cfd 100644 --- a/pkgs/stdenv/custom/default.nix +++ b/pkgs/stdenv/custom/default.nix @@ -1,22 +1,22 @@ -{ lib, allPackages +{ lib , system, platform, crossSystem, config }: assert crossSystem == null; -rec { - vanillaStdenv = import ../. { - inherit lib allPackages system platform crossSystem; +let + bootStages = import ../. { + inherit lib system platform crossSystem; # Remove config.replaceStdenv to ensure termination. config = builtins.removeAttrs config [ "replaceStdenv" ]; }; - buildPackages = allPackages { - inherit system platform crossSystem config; - # It's OK to change the built-time dependencies - allowCustomOverrides = true; - stdenv = vanillaStdenv; - }; +in bootStages ++ [ - stdenvCustom = config.replaceStdenv { pkgs = buildPackages; }; -} + # Additional stage, built using custom stdenv + (vanillaPackages: { + inherit system platform crossSystem config; + stdenv = config.replaceStdenv { pkgs = vanillaPackages; }; + }) + +] diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 0ff583e6ebb..9c860bfb0f9 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -1,4 +1,4 @@ -{ lib, allPackages +{ lib , system, platform, crossSystem, config # Allow passing in bootstrap files directly so we can test the stdenv bootstrap process when changing the bootstrap tools @@ -22,8 +22,6 @@ let (import "${./standard-sandbox.sb}") ''; in rec { - inherit allPackages; - commonPreHook = '' export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}" @@ -99,12 +97,10 @@ in rec { overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; }; }; - thisPkgs = allPackages { - inherit system platform crossSystem config; - allowCustomOverrides = false; - stdenv = thisStdenv; - }; - in { stdenv = thisStdenv; pkgs = thisPkgs; }; + in { + inherit system platform crossSystem config; + stdenv = thisStdenv; + }; stage0 = stageFun 0 null { overrides = self: super: with stage0; rec { @@ -145,19 +141,19 @@ in rec { extraBuildInputs = []; }; - persistent0 = _: _: {}; + persistent0 = _: _: _: {}; - stage1 = with stage0; stageFun 1 stage0 { + stage1 = prevStage: with prevStage; stageFun 1 prevStage { extraPreHook = "export NIX_CFLAGS_COMPILE+=\" -F${bootstrapTools}/Library/Frameworks\""; extraBuildInputs = [ pkgs.libcxx ]; allowedRequisites = [ bootstrapTools ] ++ (with pkgs; [ libcxx libcxxabi ]) ++ [ pkgs.darwin.Libsystem ]; - overrides = persistent0; + overrides = persistent0 prevStage; }; - persistent1 = self: super: with stage1.pkgs; { + persistent1 = prevStage: self: super: with prevStage; { inherit zlib patchutils m4 scons flex perl bison unifdef unzip openssl icu python libxml2 gettext sharutils gmp libarchive ncurses pkg-config libedit groff @@ -170,7 +166,7 @@ in rec { }; }; - stage2 = with stage1; stageFun 2 stage1 { + stage2 = prevStage: with prevStage; stageFun 2 prevStage { extraPreHook = '' export PATH_LOCALE=${pkgs.darwin.locale}/share/locale ''; @@ -182,10 +178,10 @@ in rec { (with pkgs; [ xz.bin xz.out libcxx libcxxabi icu.out ]) ++ (with pkgs.darwin; [ dyld Libsystem CF locale ]); - overrides = persistent1; + overrides = persistent1 prevStage; }; - persistent2 = self: super: with stage2.pkgs; { + persistent2 = prevStage: self: super: with prevStage; { inherit patchutils m4 scons flex perl bison unifdef unzip openssl python gettext sharutils libarchive pkg-config groff bash subversion @@ -199,7 +195,7 @@ in rec { }; }; - stage3 = with stage2; stageFun 3 stage2 { + stage3 = prevStage: with prevStage; stageFun 3 prevStage { shell = "${pkgs.bash}/bin/bash"; # We have a valid shell here (this one has no bootstrap-tools runtime deps) so stageFun @@ -218,10 +214,10 @@ in rec { (with pkgs; [ xz.bin xz.out icu.out bash libcxx libcxxabi ]) ++ (with pkgs.darwin; [ dyld Libsystem locale ]); - overrides = persistent2; + overrides = persistent2 prevStage; }; - persistent3 = self: super: with stage3.pkgs; { + persistent3 = prevStage: self: super: with prevStage; { inherit gnumake gzip gnused bzip2 gawk ed xz patch bash libcxxabi libcxx ncurses libffi zlib gmp pcre gnugrep @@ -238,16 +234,16 @@ in rec { }; }; - stage4 = with stage3; stageFun 4 stage3 { + stage4 = prevStage: with prevStage; stageFun 4 prevStage { shell = "${pkgs.bash}/bin/bash"; extraBuildInputs = with pkgs; [ xz darwin.CF libcxx pkgs.bash ]; extraPreHook = '' export PATH_LOCALE=${pkgs.darwin.locale}/share/locale ''; - overrides = persistent3; + overrides = persistent3 prevStage; }; - persistent4 = self: super: with stage4.pkgs; { + persistent4 = prevStage: self: super: with prevStage; { inherit gnumake gzip gnused bzip2 gawk ed xz patch bash libcxxabi libcxx ncurses libffi zlib icu llvm gmp pcre gnugrep @@ -262,9 +258,9 @@ in rec { }; }; - stage5 = with stage4; import ../generic rec { + stdenvDarwin = prevStage: let pkgs = prevStage; in import ../generic rec { inherit system config; - inherit (stdenv) fetchurlBoot; + inherit (pkgs.stdenv) fetchurlBoot; name = "stdenv-darwin"; @@ -279,7 +275,8 @@ in rec { shell = "${pkgs.bash}/bin/bash"; cc = import ../../build-support/cc-wrapper { - inherit stdenv shell; + inherit (pkgs) stdenv; + inherit shell; nativeTools = false; nativeLibc = false; inherit (pkgs) coreutils binutils gnugrep; @@ -294,7 +291,6 @@ in rec { inherit platform bootstrapTools; libc = pkgs.darwin.Libsystem; shellPackage = pkgs.bash; - parent = stage4; }; allowedRequisites = (with pkgs; [ @@ -307,11 +303,21 @@ in rec { dyld Libsystem CF cctools libiconv locale ]); - overrides = self: super: persistent4 self super // { + overrides = self: super: persistent4 prevStage self super // { clang = cc; inherit cc; }; }; - stdenvDarwin = stage5; + stagesDarwin = [ + ({}: stage0) + stage1 + stage2 + stage3 + stage4 + (prevStage: { + inherit system crossSystem platform config; + stdenv = stdenvDarwin prevStage; + }) + ]; } diff --git a/pkgs/stdenv/darwin/make-bootstrap-tools.nix b/pkgs/stdenv/darwin/make-bootstrap-tools.nix index c862eb141a8..85e4dabbbde 100644 --- a/pkgs/stdenv/darwin/make-bootstrap-tools.nix +++ b/pkgs/stdenv/darwin/make-bootstrap-tools.nix @@ -334,8 +334,8 @@ in rec { # The ultimate test: bootstrap a whole stdenv from the tools specified above and get a package set out of it test-pkgs = import test-pkgspath { inherit system; - stdenvFunc = args: let + stdenvStages = args: let args' = args // { inherit bootstrapFiles; }; - in (import (test-pkgspath + "/pkgs/stdenv/darwin") args').stdenvDarwin; + in (import (test-pkgspath + "/pkgs/stdenv/darwin") args').stagesDarwin; }; } diff --git a/pkgs/stdenv/default.nix b/pkgs/stdenv/default.nix index 3b49d0de830..e8e609c7220 100644 --- a/pkgs/stdenv/default.nix +++ b/pkgs/stdenv/default.nix @@ -1,13 +1,12 @@ -# This file defines the various standard build environments. +# This file chooses a sane default stdenv given the system, platform, etc. # -# On Linux systems, the standard build environment consists of -# Nix-built instances glibc and the `standard' Unix tools, i.e., the -# Posix utilities, the GNU C compiler, and so on. On other systems, -# we use the native C library. +# Rather than returning a stdenv, this returns a list of functions---one per +# each bootstrapping stage. See `./booter.nix` for exactly what this list should +# contain. { # Args just for stdenvs' usage - lib, allPackages - # Args to pass on to `allPacakges` too + lib + # Args to pass on to the pkgset builder, too , system, platform, crossSystem, config } @ args: @@ -17,50 +16,39 @@ let # i.e., the stuff in /bin, /usr/bin, etc. This environment should # be used with care, since many Nix packages will not build properly # with it (e.g., because they require GNU Make). - inherit (import ./native args) stdenvNative; - - stdenvNativePkgs = allPackages { - inherit system platform crossSystem config; - allowCustomOverrides = false; - stdenv = stdenvNative; - noSysDirs = false; - }; - + stagesNative = import ./native args; # The Nix build environment. - stdenvNix = assert crossSystem == null; import ./nix { - inherit config lib; - stdenv = stdenvNative; - pkgs = stdenvNativePkgs; - }; + stagesNix = import ./nix (args // { bootStages = stagesNative; }); - inherit (import ./freebsd args) stdenvFreeBSD; + stagesFreeBSD = import ./freebsd args; - # Linux standard environment. - inherit (import ./linux args) stdenvLinux; + # On Linux systems, the standard build environment consists of Nix-built + # instances glibc and the `standard' Unix tools, i.e., the Posix utilities, + # the GNU C compiler, and so on. + inherit (import ./linux args) stagesLinux; - inherit (import ./darwin args) stdenvDarwin; + inherit (import ./darwin args) stagesDarwin; - inherit (import ./cross args) stdenvCross stdenvCrossiOS; + stagesCross = import ./cross args; - inherit (import ./custom args) stdenvCustom; + stagesCustom = import ./custom args; - # Select the appropriate stdenv for the platform `system'. + # Select the appropriate stages for the platform `system'. in - if crossSystem != null then - if crossSystem.useiOSCross or false then stdenvCrossiOS - else stdenvCross else - if config ? replaceStdenv then stdenvCustom else - if system == "i686-linux" then stdenvLinux else - if system == "x86_64-linux" then stdenvLinux else - if system == "armv5tel-linux" then stdenvLinux else - if system == "armv6l-linux" then stdenvLinux else - if system == "armv7l-linux" then stdenvLinux else - if system == "mips64el-linux" then stdenvLinux else - if system == "powerpc-linux" then /* stdenvLinux */ stdenvNative else - if system == "x86_64-darwin" then stdenvDarwin else - if system == "x86_64-solaris" then stdenvNix else - if system == "i686-cygwin" then stdenvNative else - if system == "x86_64-cygwin" then stdenvNative else - if system == "x86_64-freebsd" then stdenvFreeBSD else - stdenvNative + if crossSystem != null then stagesCross + else if config ? replaceStdenv then stagesCustom + else { # switch + "i686-linux" = stagesLinux; + "x86_64-linux" = stagesLinux; + "armv5tel-linux" = stagesLinux; + "armv6l-linux" = stagesLinux; + "armv7l-linux" = stagesLinux; + "mips64el-linux" = stagesLinux; + "powerpc-linux" = /* stagesLinux */ stagesNative; + "x86_64-darwin" = stagesDarwin; + "x86_64-solaris" = stagesNix; + "i686-cygwin" = stagesNative; + "x86_64-cygwin" = stagesNative; + "x86_64-freebsd" = stagesFreeBSD; + }.${system} or stagesNative diff --git a/pkgs/stdenv/freebsd/default.nix b/pkgs/stdenv/freebsd/default.nix index ea2ebcc7917..e0256e26f5f 100644 --- a/pkgs/stdenv/freebsd/default.nix +++ b/pkgs/stdenv/freebsd/default.nix @@ -1,65 +1,86 @@ -{ lib, allPackages +{ lib , system, platform, crossSystem, config }: assert crossSystem == null; -rec { - inherit allPackages; - bootstrapTools = derivation { - inherit system; +[ - name = "trivial-bootstrap-tools"; - builder = "/usr/local/bin/bash"; - args = [ ./trivial-bootstrap.sh ]; + ({}: { + __raw = true; - mkdir = "/bin/mkdir"; - ln = "/bin/ln"; - }; + bootstrapTools = derivation { + inherit system; + + name = "trivial-bootstrap-tools"; + builder = "/usr/local/bin/bash"; + args = [ ./trivial-bootstrap.sh ]; + + mkdir = "/bin/mkdir"; + ln = "/bin/ln"; + }; + }) + + ({ bootstrapTools, ... }: rec { + __raw = true; + + inherit bootstrapTools; + + fetchurl = import ../../build-support/fetchurl { + inherit stdenv; + curl = bootstrapTools; + }; - fetchurl = import ../../build-support/fetchurl { stdenv = import ../generic { name = "stdenv-freebsd-boot-1"; inherit system config; - - initialPath = [ "/" "/usr" ]; - shell = "${bootstrapTools}/bin/bash"; + initialPath = [ "/" "/usr" ]; + shell = "${bootstrapTools}/bin/bash"; fetchurlBoot = null; cc = null; - }; - curl = bootstrapTools; - }; - - stdenvFreeBSD = import ../generic { - name = "stdenv-freebsd-boot-3"; - - inherit system config; - - initialPath = [ bootstrapTools ]; - shell = "${bootstrapTools}/bin/bash"; - fetchurlBoot = fetchurl; - - cc = import ../../build-support/cc-wrapper { - nativeTools = true; - nativePrefix = "/usr"; - nativeLibc = true; - stdenv = import ../generic { - inherit system config; - name = "stdenv-freebsd-boot-0"; - initialPath = [ bootstrapTools ]; - shell = stdenvFreeBSD.shell; - fetchurlBoot = fetchurl; - cc = null; + overrides = self: super: { }; - cc = { - name = "clang-9.9.9"; - cc = "/usr"; - outPath = "/usr"; - }; - isClang = true; }; + }) - preHook = ''export NIX_NO_SELF_RPATH=1''; - }; -} + (prevStage: { + __raw = true; + + stdenv = import ../generic { + name = "stdenv-freebsd-boot-0"; + inherit system config; + initialPath = [ prevStage.bootstrapTools ]; + inherit (prevStage.stdenv) shell; + fetchurlBoot = prevStage.fetchurl; + cc = null; + }; + }) + + (prevStage: { + inherit system crossSystem platform config; + stdenv = import ../generic { + name = "stdenv-freebsd-boot-3"; + inherit system config; + + inherit (prevStage.stdenv) + initialPath shell fetchurlBoot; + + cc = import ../../build-support/cc-wrapper { + nativeTools = true; + nativePrefix = "/usr"; + nativeLibc = true; + inherit (prevStage) stdenv; + cc = { + name = "clang-9.9.9"; + cc = "/usr"; + outPath = "/usr"; + }; + isClang = true; + }; + + preHook = ''export NIX_NO_SELF_RPATH=1''; + }; + }) + +] diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index 708f0ec3b6d..71642332079 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -3,7 +3,7 @@ # 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, allPackages +{ lib , system, platform, crossSystem, config , bootstrapFiles ? @@ -90,14 +90,10 @@ rec { overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; }; }; - thisPkgs = allPackages { - inherit system platform crossSystem config; - allowCustomOverrides = false; - stdenv = thisStdenv; - }; - - in { stdenv = thisStdenv; pkgs = thisPkgs; }; - + in { + inherit system platform crossSystem config; + stdenv = thisStdenv; + }; # Build a dummy stdenv with no GCC or working fetchurl. This is # because we need a stdenv to build the GCC wrapper and fetchurl. @@ -137,9 +133,9 @@ rec { # 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. - stage1 = stageFun { + stage1 = prevStage: stageFun { gccPlain = bootstrapTools; - inherit (stage0.pkgs) glibc; + inherit (prevStage) glibc; binutils = bootstrapTools; coreutils = bootstrapTools; gnugrep = bootstrapTools; @@ -148,7 +144,7 @@ rec { # Rebuild binutils to use from stage2 onwards. overrides = self: super: { binutils = super.binutils.override { gold = false; }; - inherit (stage0.pkgs) glibc; + inherit (prevStage) glibc; # A threaded perl build needs glibc/libpthread_nonshared.a, # which is not included in bootstrapTools, so disable threading. @@ -162,16 +158,16 @@ rec { # 2nd stdenv that contains our own rebuilt binutils and is used for # compiling our own Glibc. - stage2 = stageFun { + stage2 = prevStage: stageFun { gccPlain = bootstrapTools; - inherit (stage1.pkgs) glibc; - binutils = stage1.pkgs.binutils; + inherit (prevStage) glibc; + binutils = prevStage.binutils; coreutils = bootstrapTools; gnugrep = bootstrapTools; name = "bootstrap-gcc-wrapper"; overrides = self: super: { - inherit (stage1.pkgs) perl binutils paxctl gnum4 bison; + inherit (prevStage) perl binutils paxctl gnum4 bison; # This also contains the full, dynamically linked, final Glibc. }; }; @@ -180,15 +176,15 @@ rec { # 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. - stage3 = stageFun { + stage3 = prevStage: stageFun { gccPlain = bootstrapTools; - inherit (stage2.pkgs) glibc binutils; + inherit (prevStage) glibc binutils; coreutils = bootstrapTools; gnugrep = bootstrapTools; name = "bootstrap-gcc-wrapper"; overrides = self: super: rec { - inherit (stage2.pkgs) binutils glibc perl patchelf linuxHeaders gnum4 bison; + inherit (prevStage) binutils glibc 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. @@ -200,14 +196,14 @@ rec { isl = isl_0_14; }; }; - extraBuildInputs = [ stage2.pkgs.patchelf stage2.pkgs.paxctl ]; + extraBuildInputs = [ prevStage.patchelf prevStage.paxctl ]; }; # Construct a fourth stdenv that uses the new GCC. But coreutils is # still from the bootstrap tools. - stage4 = stageFun { - inherit (stage3.pkgs) gccPlain glibc binutils; + stage4 = prevStage: stageFun { + inherit (prevStage) gccPlain glibc binutils; gnugrep = bootstrapTools; coreutils = bootstrapTools; name = ""; @@ -217,7 +213,7 @@ rec { # 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 (stage3.pkgs) gettext gnum4 bison gmp perl glibc zlib linuxHeaders; + inherit (prevStage) gettext gnum4 bison gmp perl glibc zlib linuxHeaders; gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) { nativeTools = false; @@ -230,7 +226,7 @@ rec { shell = self.bash + "/bin/bash"; }; }; - extraBuildInputs = [ stage3.pkgs.patchelf stage3.pkgs.xz ]; + extraBuildInputs = [ prevStage.patchelf prevStage.xz ]; }; @@ -241,7 +237,7 @@ rec { # When updating stdenvLinux, make sure that the result has no # dependency (`nix-store -qR') on bootstrapTools or the first # binutils built. - stdenvLinux = import ../generic rec { + stdenvLinux = prevStage: import ../generic rec { inherit system config; preHook = @@ -253,24 +249,24 @@ rec { ''; initialPath = - ((import ../common-path.nix) {pkgs = stage4.pkgs;}); + ((import ../common-path.nix) {pkgs = prevStage;}); - extraBuildInputs = [ stage4.pkgs.patchelf stage4.pkgs.paxctl ]; + extraBuildInputs = [ prevStage.patchelf prevStage.paxctl ]; - cc = stage4.pkgs.gcc; + cc = prevStage.gcc; shell = cc.shell; - inherit (stage4.stdenv) fetchurlBoot; + inherit (prevStage.stdenv) fetchurlBoot; extraAttrs = { - inherit (stage4.pkgs) glibc; + inherit (prevStage) glibc; inherit platform bootstrapTools; - shellPackage = stage4.pkgs.bash; + shellPackage = prevStage.bash; }; /* outputs TODO - allowedRequisites = with stage4.pkgs; + 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 @@ -280,11 +276,22 @@ rec { overrides = self: super: { gcc = cc; - inherit (stage4.pkgs) + inherit (prevStage) gzip bzip2 xz bash binutils coreutils diffutils findutils gawk glibc gnumake gnused gnutar gnugrep gnupatch patchelf attr acl paxctl zlib pcre; }; }; + stagesLinux = [ + ({}: stage0) + stage1 + stage2 + stage3 + stage4 + (prevStage: { + inherit system crossSystem platform config; + stdenv = stdenvLinux prevStage; + }) + ]; } diff --git a/pkgs/stdenv/native/default.nix b/pkgs/stdenv/native/default.nix index 5a2d2c96559..57182fae523 100644 --- a/pkgs/stdenv/native/default.nix +++ b/pkgs/stdenv/native/default.nix @@ -1,10 +1,10 @@ -{ lib, allPackages +{ lib , system, platform, crossSystem, config }: assert crossSystem == null; -rec { +let shell = if system == "i686-freebsd" || system == "x86_64-freebsd" then "/usr/local/bin/bash" @@ -101,50 +101,54 @@ rec { inherit system shell cc overrides config; }; +in - stdenvBoot0 = makeStdenv { - cc = null; - fetchurl = null; - }; +[ + ({}: rec { + __raw = true; - cc = import ../../build-support/cc-wrapper { - name = "cc-native"; - nativeTools = true; - nativeLibc = true; - nativePrefix = if system == "i686-solaris" then "/usr/gnu" else if system == "x86_64-solaris" then "/opt/local/gcc47" else "/usr"; - stdenv = stdenvBoot0; - }; + stdenv = makeStdenv { + cc = null; + fetchurl = null; + }; + cc = import ../../build-support/cc-wrapper { + name = "cc-native"; + nativeTools = true; + nativeLibc = true; + nativePrefix = { # switch + "i686-solaris" = "/usr/gnu"; + "x86_64-solaris" = "/opt/local/gcc47"; + }.${system} or "/usr"; + inherit stdenv; + }; - fetchurl = import ../../build-support/fetchurl { - stdenv = stdenvBoot0; - # Curl should be in /usr/bin or so. - curl = null; - }; + fetchurl = import ../../build-support/fetchurl { + inherit stdenv; + # Curl should be in /usr/bin or so. + curl = null; + }; + }) # First build a stdenv based only on tools outside the store. - stdenvBoot1 = makeStdenv { - inherit cc fetchurl; - } // {inherit fetchurl;}; + (prevStage: { + inherit system crossSystem platform config; + stdenv = makeStdenv { + inherit (prevStage) cc fetchurl; + } // { inherit (prevStage) fetchurl; }; + }) - stdenvBoot1Pkgs = allPackages { - inherit system platform crossSystem config; - allowCustomOverrides = false; - stdenv = stdenvBoot1; - }; + # Using that, build a stdenv that adds the ‘xz’ command (which most systems + # don't have, so we mustn't rely on the native environment providing it). + (prevStage: { + inherit system crossSystem platform config; + stdenv = makeStdenv { + inherit (prevStage.stdenv) cc fetchurl; + extraPath = [ prevStage.xz ]; + overrides = self: super: { inherit (prevStage) xz; }; + }; + }) - - # Using that, build a stdenv that adds the ‘xz’ command (which most - # systems don't have, so we mustn't rely on the native environment - # providing it). - stdenvBoot2 = makeStdenv { - inherit cc fetchurl; - extraPath = [ stdenvBoot1Pkgs.xz ]; - overrides = self: super: { inherit (stdenvBoot1Pkgs) xz; }; - }; - - - stdenvNative = stdenvBoot2; -} +] diff --git a/pkgs/stdenv/nix/default.nix b/pkgs/stdenv/nix/default.nix index 21ee29ad5af..a5f0a18464c 100644 --- a/pkgs/stdenv/nix/default.nix +++ b/pkgs/stdenv/nix/default.nix @@ -1,39 +1,53 @@ -{ stdenv, pkgs, config, lib }: +{ lib +, crossSystem, config +, bootStages +, ... +}: -import ../generic rec { - inherit config; +assert crossSystem == null; - preHook = - '' - export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" - export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}" - export NIX_IGNORE_LD_THROUGH_GCC=1 - ''; +bootStages ++ [ + (prevStage: let + inherit (prevStage) stdenv; + inherit (stdenv) system platform; + in { + inherit system platform crossSystem config; - initialPath = (import ../common-path.nix) {pkgs = pkgs;}; + stdenv = import ../generic rec { + inherit config; - system = stdenv.system; + preHook = '' + export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" + export NIX_ENFORCE_NO_NATIVE="''${NIX_ENFORCE_NO_NATIVE-1}" + export NIX_IGNORE_LD_THROUGH_GCC=1 + ''; - cc = import ../../build-support/cc-wrapper { - nativeTools = false; - nativePrefix = stdenv.lib.optionalString stdenv.isSunOS "/usr"; - nativeLibc = true; - inherit stdenv; - inherit (pkgs) binutils coreutils gnugrep; - cc = pkgs.gcc.cc; - isGNU = true; - shell = pkgs.bash + "/bin/sh"; - }; + initialPath = (import ../common-path.nix) { pkgs = prevStage; }; - shell = pkgs.bash + "/bin/sh"; + system = stdenv.system; - fetchurlBoot = stdenv.fetchurlBoot; + cc = import ../../build-support/cc-wrapper { + nativeTools = false; + nativePrefix = stdenv.lib.optionalString stdenv.isSunOS "/usr"; + nativeLibc = true; + inherit stdenv; + inherit (prevStage) binutils coreutils gnugrep; + cc = prevStage.gcc.cc; + isGNU = true; + shell = prevStage.bash + "/bin/sh"; + }; - overrides = self: super: { - inherit cc; - inherit (cc) binutils; - inherit (pkgs) - gzip bzip2 xz bash coreutils diffutils findutils gawk - gnumake gnused gnutar gnugrep gnupatch perl; - }; -} + shell = prevStage.bash + "/bin/sh"; + + fetchurlBoot = stdenv.fetchurlBoot; + + overrides = self: super: { + inherit cc; + inherit (cc) binutils; + inherit (prevStage) + gzip bzip2 xz bash coreutils diffutils findutils gawk + gnumake gnused gnutar gnugrep gnupatch perl; + }; + }; + }) +] diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix index db3abb531f1..04daf9778ff 100644 --- a/pkgs/top-level/default.nix +++ b/pkgs/top-level/default.nix @@ -7,11 +7,11 @@ 3. Defaults to no non-standard config and no cross-compilation target - 4. Uses the above to infer the default standard environment (stdenv) if - none is provided + 4. Uses the above to infer the default standard environment's (stdenv's) + stages if no stdenv's are provided - 5. Builds the final stage --- a fully booted package set with the chosen - stdenv + 5. Folds the stages to yield the final fully booted package set for the + chosen stdenv Use `impure.nix` to also infer the `system` based on the one on which evaluation is taking place, and the configuration from environment variables @@ -23,9 +23,10 @@ , # Allow a configuration attribute set to be passed in as an argument. config ? {} -, # The standard environment for building packages, or rather a function - # providing it. See below for the arguments given to that function. - stdenvFunc ? import ../stdenv +, # A function booting the final package set for a specific standard + # environment. See below for the arguments given to that function, + # the type of list it returns. + stdenvStages ? import ../stdenv , crossSystem ? null , platform ? assert false; null @@ -76,10 +77,12 @@ in let inherit lib nixpkgsFun; } // newArgs); - stdenv = stdenvFunc { - inherit lib allPackages system platform crossSystem config; + boot = import ../stdenv/booter.nix { inherit lib allPackages; }; + + stages = stdenvStages { + inherit lib system platform crossSystem config; }; - pkgs = allPackages { inherit system stdenv config crossSystem platform; }; + pkgs = boot stages; in pkgs diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 7c8860bf4e9..0b1326414b6 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -18,7 +18,7 @@ , # This is used because stdenv replacement and the stdenvCross do benefit from # the overridden configuration provided by the user, as opposed to the normal # bootstrapping stdenvs. - allowCustomOverrides ? true + allowCustomOverrides , # Non-GNU/Linux OSes are currently "impure" platforms, with their libc # outside of the store. Thus, GCC, GFortran, & co. must always look for