diff --git a/pkgs/stdenv/cross/default.nix b/pkgs/stdenv/cross/default.nix index 0cde6a05943e..10e2a7663563 100644 --- a/pkgs/stdenv/cross/default.nix +++ b/pkgs/stdenv/cross/default.nix @@ -1,14 +1,14 @@ -{ system, allPackages, platform, crossSystem, config, ... } @ args: +{ lib, allPackages +, system, platform, crossSystem, config +}: rec { - argClobber = { + vanillaStdenv = (import ../. { + inherit lib allPackages system platform; crossSystem = null; # Ignore custom stdenvs when cross compiling for compatability config = builtins.removeAttrs config [ "replaceStdenv" ]; - }; - vanillaStdenv = (import ../. (args // argClobber // { - allPackages = args: allPackages (argClobber // args); - })).stdenv // { + }) // { # Needed elsewhere as a hacky way to pass the target cross = crossSystem; }; @@ -17,10 +17,10 @@ rec { # be used to build compilers and other such tools targeting the cross # platform. Then, `forceNativeDrv` can be removed. buildPackages = allPackages { + inherit system platform crossSystem config; # It's OK to change the built-time dependencies allowCustomOverrides = true; - bootStdenv = vanillaStdenv; - inherit system platform crossSystem config; + stdenv = vanillaStdenv; }; stdenvCross = buildPackages.makeStdenvCross diff --git a/pkgs/stdenv/custom/default.nix b/pkgs/stdenv/custom/default.nix index 2f2f495b388b..188d00277731 100644 --- a/pkgs/stdenv/custom/default.nix +++ b/pkgs/stdenv/custom/default.nix @@ -1,16 +1,21 @@ -{ system, allPackages, platform, crossSystem, config, ... } @ args: +{ lib, allPackages +, system, platform, crossSystem, config +}: + +assert crossSystem == null; rec { - vanillaStdenv = (import ../. (args // { + vanillaStdenv = import ../. { + inherit lib allPackages system platform crossSystem; # Remove config.replaceStdenv to ensure termination. config = builtins.removeAttrs config [ "replaceStdenv" ]; - })).stdenv; + }; buildPackages = allPackages { + inherit system platform crossSystem config; # It's OK to change the built-time dependencies allowCustomOverrides = true; - bootStdenv = vanillaStdenv; - inherit system platform crossSystem config; + stdenv = vanillaStdenv; }; stdenvCustom = config.replaceStdenv { pkgs = buildPackages; }; diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix index 1bc983d63129..b9044f25cd7a 100644 --- a/pkgs/stdenv/darwin/default.nix +++ b/pkgs/stdenv/darwin/default.nix @@ -1,7 +1,5 @@ -{ system ? builtins.currentSystem -, allPackages ? import ../../.. -, platform ? null -, config ? {} +{ lib, allPackages +, system, platform, crossSystem, config # Allow passing in bootstrap files directly so we can test the stdenv bootstrap process when changing the bootstrap tools , bootstrapFiles ? let @@ -17,12 +15,14 @@ } }: +assert crossSystem == null; + let libSystemProfile = '' (import "${./standard-sandbox.sb}") ''; in rec { - allPackages = import ../../..; + inherit allPackages; commonPreHook = '' export NIX_ENFORCE_PURITY="''${NIX_ENFORCE_PURITY-1}" @@ -100,8 +100,9 @@ in rec { }; thisPkgs = allPackages { - inherit system platform; - bootStdenv = thisStdenv; + inherit system platform crossSystem config; + allowCustomOverrides = false; + stdenv = thisStdenv; }; in { stdenv = thisStdenv; pkgs = thisPkgs; }; diff --git a/pkgs/stdenv/darwin/make-bootstrap-tools.nix b/pkgs/stdenv/darwin/make-bootstrap-tools.nix index 10d2b4decddd..bd581f71a436 100644 --- a/pkgs/stdenv/darwin/make-bootstrap-tools.nix +++ b/pkgs/stdenv/darwin/make-bootstrap-tools.nix @@ -332,10 +332,10 @@ in rec { }; # The ultimate test: bootstrap a whole stdenv from the tools specified above and get a package set out of it - test-pkgs = let - stdenv = import (test-pkgspath + "/pkgs/stdenv/darwin") { inherit system bootstrapFiles; }; - in import test-pkgspath { + test-pkgs = import test-pkgspath { inherit system; - bootStdenv = stdenv.stdenvDarwin; + stdenv = args: let + args' = args // { inherit bootstrapFiles; }; + in (import (test-pkgspath + "/pkgs/stdenv/darwin") args').stdenvDarwin; }; } diff --git a/pkgs/stdenv/default.nix b/pkgs/stdenv/default.nix index 4be34a35acb3..3b49d0de8306 100644 --- a/pkgs/stdenv/default.nix +++ b/pkgs/stdenv/default.nix @@ -5,45 +5,48 @@ # Posix utilities, the GNU C compiler, and so on. On other systems, # we use the native C library. -{ system, allPackages ? import ../.., platform, config, crossSystem, lib }: - - -rec { - +{ # Args just for stdenvs' usage + lib, allPackages + # Args to pass on to `allPacakges` too +, system, platform, crossSystem, config +} @ args: +let # The native (i.e., impure) build environment. This one uses the # tools installed on the system outside of the Nix environment, # 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 { inherit system allPackages config; }) stdenvNative; + inherit (import ./native args) stdenvNative; stdenvNativePkgs = allPackages { - bootStdenv = stdenvNative; + inherit system platform crossSystem config; + allowCustomOverrides = false; + stdenv = stdenvNative; noSysDirs = false; }; # The Nix build environment. - stdenvNix = import ./nix { + stdenvNix = assert crossSystem == null; import ./nix { inherit config lib; stdenv = stdenvNative; pkgs = stdenvNativePkgs; }; - inherit (import ./freebsd { inherit system allPackages platform config; }) stdenvFreeBSD; + inherit (import ./freebsd args) stdenvFreeBSD; # Linux standard environment. - inherit (import ./linux { inherit system allPackages platform config lib; }) stdenvLinux; + inherit (import ./linux args) stdenvLinux; - inherit (import ./darwin { inherit system allPackages platform config; }) stdenvDarwin; + inherit (import ./darwin args) stdenvDarwin; - inherit (import ./cross { inherit system allPackages platform crossSystem config lib; }) stdenvCross stdenvCrossiOS; + inherit (import ./cross args) stdenvCross stdenvCrossiOS; - inherit (import ./custom { inherit system allPackages platform crossSystem config lib; }) stdenvCustom; + inherit (import ./custom args) stdenvCustom; # Select the appropriate stdenv for the platform `system'. - stdenv = +in if crossSystem != null then if crossSystem.useiOSCross or false then stdenvCrossiOS else stdenvCross else @@ -60,5 +63,4 @@ rec { if system == "i686-cygwin" then stdenvNative else if system == "x86_64-cygwin" then stdenvNative else if system == "x86_64-freebsd" then stdenvFreeBSD else - stdenvNative; -} + stdenvNative diff --git a/pkgs/stdenv/freebsd/default.nix b/pkgs/stdenv/freebsd/default.nix index 4c7ebc16239b..ea2ebcc7917a 100644 --- a/pkgs/stdenv/freebsd/default.nix +++ b/pkgs/stdenv/freebsd/default.nix @@ -1,11 +1,11 @@ -{ system ? builtins.currentSystem -, allPackages ? import ../../.. -, platform ? null -, config ? {} +{ lib, allPackages +, system, platform, crossSystem, config }: +assert crossSystem == null; + rec { - allPackages = import ../../..; + inherit allPackages; bootstrapTools = derivation { inherit system; diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index e3aeafe178d3..34196359f525 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -3,11 +3,9 @@ # 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 +, system, platform, crossSystem, config -# The function defaults are for easy testing. -{ system ? builtins.currentSystem -, allPackages ? import ../../.. -, platform ? null, config ? {}, lib ? (import ../../../lib) , bootstrapFiles ? if system == "i686-linux" then import ./bootstrap/i686.nix else if system == "x86_64-linux" then import ./bootstrap/x86_64.nix @@ -18,6 +16,8 @@ else abort "unsupported platform for the pure Linux stdenv" }: +assert crossSystem == null; + rec { commonPreHook = @@ -106,8 +106,9 @@ rec { }; thisPkgs = allPackages { - inherit system platform; - bootStdenv = thisStdenv; + inherit system platform crossSystem config; + allowCustomOverrides = false; + stdenv = thisStdenv; }; in { stdenv = thisStdenv; pkgs = thisPkgs; }; diff --git a/pkgs/stdenv/linux/make-bootstrap-tools.nix b/pkgs/stdenv/linux/make-bootstrap-tools.nix index 1ecb222af3ec..7063d7bfcb6a 100644 --- a/pkgs/stdenv/linux/make-bootstrap-tools.nix +++ b/pkgs/stdenv/linux/make-bootstrap-tools.nix @@ -175,6 +175,13 @@ rec { bootstrapTools = (import ./default.nix { inherit system bootstrapFiles; + + lib = assert false; null; + allPackages = assert false; null; + + platform = assert false; null; + crossSystem = assert false; null; + config = assert false; null; }).bootstrapTools; test = derivation { diff --git a/pkgs/stdenv/native/default.nix b/pkgs/stdenv/native/default.nix index fcd0805275be..8396bd0cb017 100644 --- a/pkgs/stdenv/native/default.nix +++ b/pkgs/stdenv/native/default.nix @@ -1,4 +1,8 @@ -{ system, allPackages ? import ../../.., config }: +{ lib, allPackages +, system, platform, crossSystem, config +}: + +assert crossSystem == null; rec { @@ -126,8 +130,9 @@ rec { } // {inherit fetchurl;}; stdenvBoot1Pkgs = allPackages { - inherit system; - bootStdenv = stdenvBoot1; + inherit system platform crossSystem config; + allowCustomOverrides = false; + stdenv = stdenvBoot1; }; diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix index 831b1db0cea3..31c51215676b 100644 --- a/pkgs/top-level/default.nix +++ b/pkgs/top-level/default.nix @@ -1,40 +1,40 @@ -/* This file composes the Nix Packages collection. That is, it - imports the functions that build the various packages, and calls - them with appropriate arguments. The result is a set of all the - packages in the Nix Packages collection for some particular - platform. */ +/* This function composes the Nix Packages collection. It: + 1. Applies the final stage to the given `config` if it is a function + + 2. Infers an appropriate `platform` based on the `system` if none is + provided + + 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 + + 5. Builds the final stage --- a fully booted package set with 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 + or dot-files. */ { # The system (e.g., `i686-linux') for which to build the packages. system -, # The standard environment to use. Only used for bootstrapping. If - # null, the default standard environment is used. - bootStdenv ? null - -, # 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 ? (bootStdenv == null) - -, # Non-GNU/Linux OSes are currently "impure" platforms, with their libc - # outside of the store. Thus, GCC, GFortran, & co. must always look for - # files in standard system directories (/usr/include, etc.) - noSysDirs ? (system != "x86_64-freebsd" && system != "i686-freebsd" - && system != "x86_64-solaris" - && system != "x86_64-kfreebsd-gnu") - , # 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. + stdenv ? assert false; null + , crossSystem ? null -, platform ? null +, platform ? assert false; null } @ args: +let # Rename the function arguments + configExpr = config; -let configExpr = config; platform_ = platform; in # rename the function arguments - -let +in let lib = import ../../lib; # Allow both: @@ -45,21 +45,12 @@ let then configExpr { inherit pkgs; } else configExpr; - # Allow setting the platform in the config file. Otherwise, let's use a reasonable default (pc) - - platformAuto = let - platforms = (import ./platforms.nix); - in - if system == "armv6l-linux" then platforms.raspberrypi - else if system == "armv7l-linux" then platforms.armv7l-hf-multiplatform - else if system == "armv5tel-linux" then platforms.sheevaplug - else if system == "mips64el-linux" then platforms.fuloong2f_n32 - else if system == "x86_64-linux" then platforms.pc64 - else if system == "i686-linux" then platforms.pc32 - else platforms.pcBase; - - platform = if platform_ != null then platform_ - else config.platform or platformAuto; + # Allow setting the platform in the config file. Otherwise, let's use a + # reasonable default. + platform = + args.platform + or (config.platform + or (import ./platforms.nix).selectPlatformBySystem system); # A few packages make a new package set to draw their dependencies from. # (Currently to get a cross tool chain, or forced-i686 package.) Rather than @@ -68,79 +59,27 @@ let # whatever arguments it doesn't explicitly provide. This way, # `all-packages.nix` doesn't know more than it needs too. # - # It's OK that `args` doesn't include the defaults: they'll be - # deterministically inferred the same way. + # It's OK that `args` doesn't include default arguemtns from this file: + # they'll be deterministically inferred. In fact we must *not* include them, + # because it's important that if some parameter which affects the default is + # substituted with a different argument, the default is re-inferred. + # + # To put this in concrete terms, this function is basically just used today to + # use package for a different platform for the current platform (namely cross + # compiling toolchains and 32-bit packages on x86_64). In both those cases we + # want the provided non-native `system` argument to affect the stdenv chosen. nixpkgsFun = newArgs: import ./. (args // newArgs); - stdenvAdapters = self: super: - let res = import ../stdenv/adapters.nix self; in res // { - stdenvAdapters = res; - }; + # Partially apply some arguments for building bootstraping stage pkgs + # sets. Only apply arguments which no stdenv would want to override. + allPackages = newArgs: import ./stage.nix ({ + inherit lib nixpkgsFun; + } // newArgs); - trivialBuilders = self: super: - import ../build-support/trivial-builders.nix { - inherit lib; inherit (self) stdenv stdenvNoCC; inherit (self.xorg) lndir; - }; + stdenv = (args.stdenv or (import ../stdenv)) { + inherit lib allPackages system platform crossSystem config; + }; - stdenvDefault = self: super: - import ./stdenv.nix { - inherit system bootStdenv crossSystem config platform lib nixpkgsFun; - }; + pkgs = allPackages { inherit system stdenv config crossSystem platform; }; - allPackages = self: super: - let res = import ./all-packages.nix - { inherit system noSysDirs config crossSystem platform lib nixpkgsFun; } - res self; - in res; - - aliases = self: super: import ./aliases.nix super; - - # stdenvOverrides is used to avoid circular dependencies for building - # the standard build environment. This mechanism uses the override - # mechanism to implement some staged compilation of the stdenv. - # - # We don't want stdenv overrides in the case of cross-building, or - # otherwise the basic overridden packages will not be built with the - # crossStdenv adapter. - stdenvOverrides = self: super: - lib.optionalAttrs (crossSystem == null && super.stdenv ? overrides) - (super.stdenv.overrides super); - - # Allow packages to be overridden globally via the `packageOverrides' - # configuration option, which must be a function that takes `pkgs' - # as an argument and returns a set of new or overridden packages. - # The `packageOverrides' function is called with the *original* - # (un-overridden) set of packages, allowing packageOverrides - # attributes to refer to the original attributes (e.g. "foo = - # ... pkgs.foo ..."). - configOverrides = self: super: - lib.optionalAttrs allowCustomOverrides - ((config.packageOverrides or (super: {})) super); - - # The complete chain of package set builders, applied from top to bottom - toFix = lib.foldl' (lib.flip lib.extends) (self: {}) [ - stdenvAdapters - trivialBuilders - stdenvDefault - allPackages - aliases - stdenvOverrides - configOverrides - ]; - - # Use `overridePackages` to easily override this package set. - # Warning: this function is very expensive and must not be used - # from within the nixpkgs repository. - # - # Example: - # pkgs.overridePackages (self: super: { - # foo = super.foo.override { ... }; - # } - # - # The result is `pkgs' where all the derivations depending on `foo' - # will use the new version. - - # Return the complete set of packages. Warning: this function is very - # expensive! - pkgs = lib.makeExtensibleWithCustomName "overridePackages" toFix; in pkgs diff --git a/pkgs/top-level/platforms.nix b/pkgs/top-level/platforms.nix index efeae9a9d202..671aaea4491a 100644 --- a/pkgs/top-level/platforms.nix +++ b/pkgs/top-level/platforms.nix @@ -443,4 +443,12 @@ rec { }; }; + selectPlatformBySystem = system: + if system == "armv6l-linux" then raspberrypi + else if system == "armv7l-linux" then armv7l-hf-multiplatform + else if system == "armv5tel-linux" then sheevaplug + else if system == "mips64el-linux" then fuloong2f_n32 + else if system == "x86_64-linux" then pc64 + else if system == "i686-linux" then pc32 + else pcBase; } diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix new file mode 100644 index 000000000000..1d6305151ca6 --- /dev/null +++ b/pkgs/top-level/stage.nix @@ -0,0 +1,108 @@ +/* This file composes a single bootstrapping stage of the Nix Packages + collection. That is, it imports the functions that build the various + packages, and calls them with appropriate arguments. The result is a set of + all the packages in the Nix Packages collection for some particular platform + for some particular stage. + + Default arguments are only provided for bootstrapping + arguments. Normal users should not import this directly but instead + import `pkgs/default.nix` or `default.nix`. */ + + +{ # The system (e.g., `i686-linux') for which to build the packages. + system + +, # The standard environment to use for building packages. + stdenv + +, # 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 + +, # Non-GNU/Linux OSes are currently "impure" platforms, with their libc + # outside of the store. Thus, GCC, GFortran, & co. must always look for + # files in standard system directories (/usr/include, etc.) + noSysDirs ? (system != "x86_64-freebsd" && system != "i686-freebsd" + && system != "x86_64-solaris" + && system != "x86_64-kfreebsd-gnu") + +, # The configuration attribute set + config + +, crossSystem +, platform +, lib +, nixpkgsFun +}: + +let + stdenvAdapters = self: super: + let res = import ../stdenv/adapters.nix self; in res // { + stdenvAdapters = res; + }; + + trivialBuilders = self: super: + import ../build-support/trivial-builders.nix { + inherit lib; inherit (self) stdenv stdenvNoCC; inherit (self.xorg) lndir; + }; + + stdenvDefault = self: super: + { stdenv = stdenv // { inherit platform; }; }; + + allPackages = self: super: + let res = import ./all-packages.nix + { inherit system noSysDirs config crossSystem platform lib nixpkgsFun; } + res self; + in res; + + aliases = self: super: import ./aliases.nix super; + + # stdenvOverrides is used to avoid circular dependencies for building + # the standard build environment. This mechanism uses the override + # mechanism to implement some staged compilation of the stdenv. + # + # We don't want stdenv overrides in the case of cross-building, or + # otherwise the basic overridden packages will not be built with the + # crossStdenv adapter. + stdenvOverrides = self: super: + lib.optionalAttrs (crossSystem == null && super.stdenv ? overrides) + (super.stdenv.overrides super); + + # Allow packages to be overridden globally via the `packageOverrides' + # configuration option, which must be a function that takes `pkgs' + # as an argument and returns a set of new or overridden packages. + # The `packageOverrides' function is called with the *original* + # (un-overridden) set of packages, allowing packageOverrides + # attributes to refer to the original attributes (e.g. "foo = + # ... pkgs.foo ..."). + configOverrides = self: super: + lib.optionalAttrs allowCustomOverrides + ((config.packageOverrides or (super: {})) super); + + # The complete chain of package set builders, applied from top to bottom + toFix = lib.foldl' (lib.flip lib.extends) (self: {}) [ + stdenvDefault + stdenvAdapters + trivialBuilders + allPackages + aliases + stdenvOverrides + configOverrides + ]; + + # Use `overridePackages` to easily override this package set. + # Warning: this function is very expensive and must not be used + # from within the nixpkgs repository. + # + # Example: + # pkgs.overridePackages (self: super: { + # foo = super.foo.override { ... }; + # } + # + # The result is `pkgs' where all the derivations depending on `foo' + # will use the new version. + + # Return the complete set of packages. Warning: this function is very + # expensive! +in lib.makeExtensibleWithCustomName "overridePackages" toFix diff --git a/pkgs/top-level/stdenv.nix b/pkgs/top-level/stdenv.nix deleted file mode 100644 index 9f485b8c90ef..000000000000 --- a/pkgs/top-level/stdenv.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ system, bootStdenv, crossSystem, config, platform, lib, nixpkgsFun }: - -rec { - allStdenvs = import ../stdenv { - inherit system platform config crossSystem lib; - allPackages = nixpkgsFun; - }; - - defaultStdenv = allStdenvs.stdenv // { inherit platform; }; - - stdenv = - if bootStdenv != null - then (bootStdenv // { inherit platform; }) - else defaultStdenv; -}