about summary refs log tree commit diff
path: root/pkgs/stdenv
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2017-07-09 18:07:00 +0200
committerVladimír Čunát <vcunat@gmail.com>2017-07-09 18:07:52 +0200
commitbfb7ef86f3f2417b6866c704b7423c33bc33286c (patch)
treec466dc1a8c5e41bc2be1b349ac93ed4fd5a5a0d2 /pkgs/stdenv
parentd10c3cc5eedf58e80e270d7c912cf68ea1a822e4 (diff)
parent466e7e23c6f71ebed7050802d377102002fc2a0d (diff)
downloadnixlib-bfb7ef86f3f2417b6866c704b7423c33bc33286c.tar
nixlib-bfb7ef86f3f2417b6866c704b7423c33bc33286c.tar.gz
nixlib-bfb7ef86f3f2417b6866c704b7423c33bc33286c.tar.bz2
nixlib-bfb7ef86f3f2417b6866c704b7423c33bc33286c.tar.lz
nixlib-bfb7ef86f3f2417b6866c704b7423c33bc33286c.tar.xz
nixlib-bfb7ef86f3f2417b6866c704b7423c33bc33286c.tar.zst
nixlib-bfb7ef86f3f2417b6866c704b7423c33bc33286c.zip
Merge branch 'master' into staging
Mass rebuilds incoming.  The mass-rebuild situation got really messy
this weekend.
Diffstat (limited to 'pkgs/stdenv')
-rw-r--r--pkgs/stdenv/adapters.nix8
-rw-r--r--pkgs/stdenv/cross/default.nix11
-rw-r--r--pkgs/stdenv/custom/default.nix8
-rw-r--r--pkgs/stdenv/darwin/default.nix20
-rw-r--r--pkgs/stdenv/freebsd/default.nix14
-rw-r--r--pkgs/stdenv/generic/check-meta.nix197
-rw-r--r--pkgs/stdenv/generic/default.nix385
-rw-r--r--pkgs/stdenv/generic/make-derivation.nix150
-rw-r--r--pkgs/stdenv/linux/default.nix20
-rw-r--r--pkgs/stdenv/native/default.nix9
-rw-r--r--pkgs/stdenv/nix/default.nix7
11 files changed, 426 insertions, 403 deletions
diff --git a/pkgs/stdenv/adapters.nix b/pkgs/stdenv/adapters.nix
index 7515a72fcfdf..5848ee87b1b0 100644
--- a/pkgs/stdenv/adapters.nix
+++ b/pkgs/stdenv/adapters.nix
@@ -61,11 +61,9 @@ rec {
                     , buildPlatform, hostPlatform, targetPlatform
                     } @ overrideArgs: let
     stdenv = overrideArgs.stdenv.override {
-      # TODO(@Ericson2314): Cannot do this for now because then Nix thinks the
-      # resulting derivation should be built on the host platform.
-      #hostPlatform = buildPlatform;
-      #targetPlatform = hostPlatform;
-      inherit cc;
+      inherit
+        buildPlatform hostPlatform targetPlatform
+        cc;
 
       allowedRequisites = null;
 
diff --git a/pkgs/stdenv/cross/default.nix b/pkgs/stdenv/cross/default.nix
index 125c4300975a..c83714d01f2c 100644
--- a/pkgs/stdenv/cross/default.nix
+++ b/pkgs/stdenv/cross/default.nix
@@ -14,21 +14,18 @@ in bootStages ++ [
 
   # Build Packages
   (vanillaPackages: {
-    buildPlatform = localSystem;
-    hostPlatform = localSystem;
-    targetPlatform = crossSystem;
     inherit config overlays;
     selfBuild = false;
+    stdenv =
+      assert vanillaPackages.hostPlatform == localSystem;
+      assert vanillaPackages.targetPlatform == localSystem;
+      vanillaPackages.stdenv.override { targetPlatform = crossSystem; };
     # It's OK to change the built-time dependencies
     allowCustomOverrides = true;
-    inherit (vanillaPackages) stdenv;
   })
 
   # Run Packages
   (buildPackages: {
-    buildPlatform = localSystem;
-    hostPlatform = crossSystem;
-    targetPlatform = crossSystem;
     inherit config overlays;
     selfBuild = false;
     stdenv = buildPackages.makeStdenvCross {
diff --git a/pkgs/stdenv/custom/default.nix b/pkgs/stdenv/custom/default.nix
index d5dc977b37a7..b6ea8685f8e6 100644
--- a/pkgs/stdenv/custom/default.nix
+++ b/pkgs/stdenv/custom/default.nix
@@ -15,11 +15,11 @@ in bootStages ++ [
 
   # Additional stage, built using custom stdenv
   (vanillaPackages: {
-    buildPlatform = localSystem;
-    hostPlatform = localSystem;
-    targetPlatform = localSystem;
     inherit config overlays;
-    stdenv = config.replaceStdenv { pkgs = vanillaPackages; };
+    stdenv =
+      assert vanillaPackages.hostPlatform == localSystem;
+      assert vanillaPackages.targetPlatform == localSystem;
+      config.replaceStdenv { pkgs = vanillaPackages; };
   })
 
 ]
diff --git a/pkgs/stdenv/darwin/default.nix b/pkgs/stdenv/darwin/default.nix
index 1c0b42886ca3..f6d9bcac5104 100644
--- a/pkgs/stdenv/darwin/default.nix
+++ b/pkgs/stdenv/darwin/default.nix
@@ -68,6 +68,10 @@ in rec {
 
         name = "stdenv-darwin-boot-${toString step}";
 
+        buildPlatform = localSystem;
+        hostPlatform = localSystem;
+        targetPlatform = localSystem;
+
         cc = if isNull last then "/dev/null" else import ../../build-support/cc-wrapper {
           inherit shell;
           inherit (last) stdenv;
@@ -96,9 +100,6 @@ in rec {
         '';
         initialPath  = [ bootstrapTools ];
 
-        hostPlatform = localSystem;
-        targetPlatform = localSystem;
-
         fetchurlBoot = import ../../build-support/fetchurl {
           stdenv = stage0.stdenv;
           curl   = bootstrapTools;
@@ -113,9 +114,6 @@ in rec {
       };
 
     in {
-      buildPlatform = localSystem;
-      hostPlatform = localSystem;
-      targetPlatform = localSystem;
       inherit config overlays;
       stdenv = thisStdenv;
     };
@@ -285,6 +283,10 @@ in rec {
 
     name = "stdenv-darwin";
 
+    buildPlatform = localSystem;
+    hostPlatform = localSystem;
+    targetPlatform = localSystem;
+
     preHook = commonPreHook + ''
       export PATH_LOCALE=${pkgs.darwin.locale}/share/locale
     '';
@@ -292,9 +294,6 @@ in rec {
     stdenvSandboxProfile = binShClosure + libSystemProfile;
     extraSandboxProfile  = binShClosure + libSystemProfile;
 
-    hostPlatform = localSystem;
-    targetPlatform = localSystem;
-
     initialPath = import ../common-path.nix { inherit pkgs; };
     shell       = "${pkgs.bash}/bin/bash";
 
@@ -348,9 +347,6 @@ in rec {
     stage3
     stage4
     (prevStage: {
-      buildPlatform = localSystem;
-      hostPlatform = localSystem;
-      targetPlatform = localSystem;
       inherit config overlays;
       stdenv = stdenvDarwin prevStage;
     })
diff --git a/pkgs/stdenv/freebsd/default.nix b/pkgs/stdenv/freebsd/default.nix
index 389a5b9985fe..d15afe761894 100644
--- a/pkgs/stdenv/freebsd/default.nix
+++ b/pkgs/stdenv/freebsd/default.nix
@@ -35,6 +35,9 @@ let inherit (localSystem) system; in
 
     stdenv = import ../generic {
       name = "stdenv-freebsd-boot-1";
+      buildPlatform = localSystem;
+      hostPlatform = localSystem;
+      targetPlatform = localSystem;
       inherit config;
       initialPath = [ "/" "/usr" ];
       hostPlatform = localSystem;
@@ -52,6 +55,9 @@ let inherit (localSystem) system; in
 
     stdenv = import ../generic {
       name = "stdenv-freebsd-boot-0";
+      buildPlatform = localSystem;
+      hostPlatform = localSystem;
+      targetPlatform = localSystem;
       inherit config;
       initialPath = [ prevStage.bootstrapTools ];
       inherit (prevStage.stdenv)
@@ -62,12 +68,12 @@ let inherit (localSystem) system; in
   })
 
   (prevStage: {
-    buildPlatform = localSystem;
-    hostPlatform = localSystem;
-    targetPlatform = localSystem;
     inherit config overlays;
     stdenv = import ../generic {
       name = "stdenv-freebsd-boot-3";
+      buildPlatform = localSystem;
+      hostPlatform = localSystem;
+      targetPlatform = localSystem;
       inherit config;
 
       inherit (prevStage.stdenv)
@@ -77,8 +83,6 @@ let inherit (localSystem) system; in
         nativeTools  = true;
         nativePrefix = "/usr";
         nativeLibc   = true;
-        hostPlatform = localSystem;
-        targetPlatform = localSystem;
         inherit (prevStage) stdenv;
         cc           = {
           name    = "clang-9.9.9";
diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix
new file mode 100644
index 000000000000..8b2cf01f169b
--- /dev/null
+++ b/pkgs/stdenv/generic/check-meta.nix
@@ -0,0 +1,197 @@
+# Extend a derivation with checks for brokenness, license, etc.  Throw a
+# descriptive error when the check fails; return `derivationArg` otherwise.
+# Note: no dependencies are checked in this step.
+
+{ lib, config, system, meta, derivationArg, mkDerivationArg }:
+
+let
+  attrs = mkDerivationArg; # TODO: probably get rid of passing this one
+
+  # See discussion at https://github.com/NixOS/nixpkgs/pull/25304#issuecomment-298385426
+  # for why this defaults to false, but I (@copumpkin) want to default it to true soon.
+  shouldCheckMeta = config.checkMeta or false;
+
+  allowUnfree = config.allowUnfree or false || builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1";
+
+  whitelist = config.whitelistedLicenses or [];
+  blacklist = config.blacklistedLicenses or [];
+
+  onlyLicenses = list:
+    lib.lists.all (license:
+      let l = lib.licenses.${license.shortName or "BROKEN"} or false; in
+      if license == l then true else
+        throw ''‘${showLicense license}’ is not an attribute of lib.licenses''
+    ) list;
+
+  areLicenseListsValid =
+    if lib.mutuallyExclusive whitelist blacklist then
+      assert onlyLicenses whitelist; assert onlyLicenses blacklist; true
+    else
+      throw "whitelistedLicenses and blacklistedLicenses are not mutually exclusive.";
+
+  hasLicense = attrs:
+    attrs ? meta.license;
+
+  hasWhitelistedLicense = assert areLicenseListsValid; attrs:
+    hasLicense attrs && builtins.elem attrs.meta.license whitelist;
+
+  hasBlacklistedLicense = assert areLicenseListsValid; attrs:
+    hasLicense attrs && builtins.elem attrs.meta.license blacklist;
+
+  allowBroken = config.allowBroken or false || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1";
+
+  isUnfree = licenses: lib.lists.any (l:
+    !l.free or true || l == "unfree" || l == "unfree-redistributable") licenses;
+
+  # Alow granular checks to allow only some unfree packages
+  # Example:
+  # {pkgs, ...}:
+  # {
+  #   allowUnfree = false;
+  #   allowUnfreePredicate = (x: pkgs.lib.hasPrefix "flashplayer-" x.name);
+  # }
+  allowUnfreePredicate = config.allowUnfreePredicate or (x: false);
+
+  # Check whether unfree packages are allowed and if not, whether the
+  # package has an unfree license and is not explicitely allowed by the
+  # `allowUNfreePredicate` function.
+  hasDeniedUnfreeLicense = attrs:
+    !allowUnfree &&
+    hasLicense attrs &&
+    isUnfree (lib.lists.toList attrs.meta.license) &&
+    !allowUnfreePredicate attrs;
+
+  allowInsecureDefaultPredicate = x: builtins.elem x.name (config.permittedInsecurePackages or []);
+  allowInsecurePredicate = x: (config.allowUnfreePredicate or allowInsecureDefaultPredicate) x;
+
+  hasAllowedInsecure = attrs:
+    (attrs.meta.knownVulnerabilities or []) == [] ||
+    allowInsecurePredicate attrs ||
+    builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
+
+  showLicense = license: license.shortName or "unknown";
+
+  pos_str = meta.position or "«unknown-file»";
+
+  remediation = {
+    unfree = remediate_whitelist "Unfree";
+    broken = remediate_whitelist "Broken";
+    blacklisted = x: "";
+    insecure = remediate_insecure;
+    unknown-meta = x: "";
+  };
+  remediate_whitelist = allow_attr: attrs:
+    ''
+      a) For `nixos-rebuild` you can set
+        { nixpkgs.config.allow${allow_attr} = true; }
+      in configuration.nix to override this.
+
+      b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
+        { allow${allow_attr} = true; }
+      to ~/.config/nixpkgs/config.nix.
+    '';
+
+  remediate_insecure = attrs:
+    ''
+
+      Known issues:
+
+    '' + (lib.fold (issue: default: "${default} - ${issue}\n") "" attrs.meta.knownVulnerabilities) + ''
+
+        You can install it anyway by whitelisting this package, using the
+        following methods:
+
+        a) for `nixos-rebuild` you can add ‘${attrs.name or "«name-missing»"}’ to
+           `nixpkgs.config.permittedInsecurePackages` in the configuration.nix,
+           like so:
+
+             {
+               nixpkgs.config.permittedInsecurePackages = [
+                 "${attrs.name or "«name-missing»"}"
+               ];
+             }
+
+        b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
+        ‘${attrs.name or "«name-missing»"}’ to `permittedInsecurePackages` in
+        ~/.config/nixpkgs/config.nix, like so:
+
+             {
+               permittedInsecurePackages = [
+                 "${attrs.name or "«name-missing»"}"
+               ];
+             }
+
+      '';
+
+  throwEvalHelp = { reason , errormsg ? "" }:
+    throw (''
+      Package ‘${attrs.name or "«name-missing»"}’ in ${pos_str} ${errormsg}, refusing to evaluate.
+
+      '' + ((builtins.getAttr reason remediation) attrs));
+
+  metaTypes = with lib.types; rec {
+    # These keys are documented
+    description = str;
+    longDescription = str;
+    branch = str;
+    homepage = str;
+    downloadPage = str;
+    license = either (listOf lib.types.attrs) (either lib.types.attrs str);
+    maintainers = listOf str;
+    priority = int;
+    platforms = listOf str;
+    hydraPlatforms = listOf str;
+    broken = bool;
+
+    # Weirder stuff that doesn't appear in the documentation?
+    version = str;
+    tag = str;
+    updateWalker = bool;
+    executables = listOf str;
+    outputsToInstall = listOf str;
+    position = str;
+    repositories = attrsOf str;
+    isBuildPythonPackage = platforms;
+    schedulingPriority = str;
+    downloadURLRegexp = str;
+    isFcitxEngine = bool;
+    isIbusEngine = bool;
+  };
+
+  checkMetaAttr = k: v:
+    if metaTypes?${k} then
+      if metaTypes.${k}.check v then null else "key '${k}' has a value ${v} of an invalid type ${builtins.typeOf v}; expected ${metaTypes.${k}.description}"
+    else "key '${k}' is unrecognized; expected one of: \n\t      [${lib.concatMapStringsSep ", " (x: "'${x}'") (lib.attrNames metaTypes)}]";
+  checkMeta = meta: if shouldCheckMeta then lib.remove null (lib.mapAttrsToList checkMetaAttr meta) else [];
+
+  # Check if a derivation is valid, that is whether it passes checks for
+  # e.g brokenness or license.
+  #
+  # Return { valid: Bool } and additionally
+  # { reason: String; errormsg: String } if it is not valid, where
+  # reason is one of "unfree", "blacklisted" or "broken".
+  checkValidity = attrs:
+    if hasDeniedUnfreeLicense attrs && !(hasWhitelistedLicense attrs) then
+      { valid = false; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
+    else if hasBlacklistedLicense attrs then
+      { valid = false; reason = "blacklisted"; errormsg = "has a blacklisted license (‘${showLicense attrs.meta.license}’)"; }
+    else if !allowBroken && attrs.meta.broken or false then
+      { valid = false; reason = "broken"; errormsg = "is marked as broken"; }
+    else if !allowBroken && attrs.meta.platforms or null != null && !lib.lists.elem system attrs.meta.platforms then
+      { valid = false; reason = "broken"; errormsg = "is not supported on ‘${system}’"; }
+    else if !(hasAllowedInsecure attrs) then
+      { valid = false; reason = "insecure"; errormsg = "is marked as insecure"; }
+    else let res = checkMeta (attrs.meta or {}); in if res != [] then
+      { valid = false; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
+    else { valid = true; };
+
+  # Throw an error if trying to evaluate an non-valid derivation
+  validityCondition =
+         let v = checkValidity attrs;
+         in if !v.valid
+           then throwEvalHelp (removeAttrs v ["valid"])
+           else true;
+
+in
+  assert validityCondition;
+  derivationArg
diff --git a/pkgs/stdenv/generic/default.nix b/pkgs/stdenv/generic/default.nix
index ce9beb2bbc62..a5d3c5a8ff5c 100644
--- a/pkgs/stdenv/generic/default.nix
+++ b/pkgs/stdenv/generic/default.nix
@@ -15,89 +15,32 @@ let lib = import ../../../lib; in lib.makeOverridable (
 , stdenvSandboxProfile ? ""
 , extraSandboxProfile ? ""
 
-, # The platforms here do *not* correspond to the stage the stdenv is
-  # used in, but rather the previous one, in which it was built. We
-  # use the latter two platforms, like a cross compiler, because the
-  # stand environment is a build tool if you squint at it, and because
-  # neither of these are used when building stdenv so we know the
-  # build platform is irrelevant.
-  hostPlatform, targetPlatform
+  ## Platform parameters
+  ##
+  ## The "build" "host" "target" terminology below comes from GNU Autotools. See
+  ## its documentation for more information on what those words mean. Note that
+  ## each should always be defined, even when not cross compiling.
+  ##
+  ## For purposes of bootstrapping, think of each stage as a "sliding window"
+  ## over a list of platforms. Specifically, the host platform of the previous
+  ## stage becomes the build platform of the current one, and likewise the
+  ## target platform of the previous stage becomes the host platform of the
+  ## current one.
+  ##
+
+, # The platform on which packages are built. Consists of `system`, a
+  # string (e.g.,`i686-linux') identifying the most import attributes of the
+  # build platform, and `platform` a set of other details.
+  buildPlatform
+
+, # The platform on which packages run.
+  hostPlatform
+
+, # The platform which build tools (especially compilers) build for in this stage,
+  targetPlatform
 }:
 
 let
-  inherit (targetPlatform) system;
-
-  # See discussion at https://github.com/NixOS/nixpkgs/pull/25304#issuecomment-298385426
-  # for why this defaults to false, but I (@copumpkin) want to default it to true soon.
-  shouldCheckMeta = config.checkMeta or false;
-
-  allowUnfree = config.allowUnfree or false || builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1";
-
-  whitelist = config.whitelistedLicenses or [];
-  blacklist = config.blacklistedLicenses or [];
-
-  ifDarwin = attrs: if system == "x86_64-darwin" then attrs else {};
-
-  onlyLicenses = list:
-    lib.lists.all (license:
-      let l = lib.licenses.${license.shortName or "BROKEN"} or false; in
-      if license == l then true else
-        throw ''‘${showLicense license}’ is not an attribute of lib.licenses''
-    ) list;
-
-  mutuallyExclusive = a: b:
-    (builtins.length a) == 0 ||
-    (!(builtins.elem (builtins.head a) b) &&
-     mutuallyExclusive (builtins.tail a) b);
-
-  areLicenseListsValid =
-    if mutuallyExclusive whitelist blacklist then
-      assert onlyLicenses whitelist; assert onlyLicenses blacklist; true
-    else
-      throw "whitelistedLicenses and blacklistedLicenses are not mutually exclusive.";
-
-  hasLicense = attrs:
-    attrs ? meta.license;
-
-  hasWhitelistedLicense = assert areLicenseListsValid; attrs:
-    hasLicense attrs && builtins.elem attrs.meta.license whitelist;
-
-  hasBlacklistedLicense = assert areLicenseListsValid; attrs:
-    hasLicense attrs && builtins.elem attrs.meta.license blacklist;
-
-  allowBroken = config.allowBroken or false || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1";
-
-  isUnfree = licenses: lib.lists.any (l:
-    !l.free or true || l == "unfree" || l == "unfree-redistributable") licenses;
-
-  # Alow granular checks to allow only some unfree packages
-  # Example:
-  # {pkgs, ...}:
-  # {
-  #   allowUnfree = false;
-  #   allowUnfreePredicate = (x: pkgs.lib.hasPrefix "flashplayer-" x.name);
-  # }
-  allowUnfreePredicate = config.allowUnfreePredicate or (x: false);
-
-  # Check whether unfree packages are allowed and if not, whether the
-  # package has an unfree license and is not explicitely allowed by the
-  # `allowUNfreePredicate` function.
-  hasDeniedUnfreeLicense = attrs:
-    !allowUnfree &&
-    hasLicense attrs &&
-    isUnfree (lib.lists.toList attrs.meta.license) &&
-    !allowUnfreePredicate attrs;
-
-  allowInsecureDefaultPredicate = x: builtins.elem x.name (config.permittedInsecurePackages or []);
-  allowInsecurePredicate = x: (config.allowUnfreePredicate or allowInsecureDefaultPredicate) x;
-
-  hasAllowedInsecure = attrs:
-    (attrs.meta.knownVulnerabilities or []) == [] ||
-    allowInsecurePredicate attrs ||
-    builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
-
-  showLicense = license: license.shortName or "unknown";
-
   defaultNativeBuildInputs = extraBuildInputs ++
     [ ../../build-support/setup-hooks/move-docs.sh
       ../../build-support/setup-hooks/compress-man-pages.sh
@@ -106,7 +49,7 @@ let
     ]
       # FIXME this on Darwin; see
       # https://github.com/NixOS/nixpkgs/commit/94d164dd7#commitcomment-22030369
-    ++ lib.optional result.isLinux ../../build-support/setup-hooks/audit-tmpdir.sh
+    ++ lib.optional hostPlatform.isLinux ../../build-support/setup-hooks/audit-tmpdir.sh
     ++ [
       ../../build-support/setup-hooks/multiple-outputs.sh
       ../../build-support/setup-hooks/move-sbin.sh
@@ -115,272 +58,16 @@ let
       cc
     ];
 
-  # `mkDerivation` wraps the builtin `derivation` function to
-  # produce derivations that use this stdenv and its shell.
-  #
-  # See also:
-  #
-  # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
-  #   Details on how to use this mkDerivation function
-  #
-  # * https://nixos.org/nix/manual/#ssec-derivation
-  #   Explanation about derivations in general
-  mkDerivation =
-    { nativeBuildInputs ? []
-    , buildInputs ? []
-
-    , propagatedNativeBuildInputs ? []
-    , propagatedBuildInputs ? []
-
-    , crossConfig ? null
-    , meta ? {}
-    , passthru ? {}
-    , pos ? null # position used in error messages and for meta.position
-    , separateDebugInfo ? false
-    , outputs ? [ "out" ]
-    , __impureHostDeps ? []
-    , __propagatedImpureHostDeps ? []
-    , sandboxProfile ? ""
-    , propagatedSandboxProfile ? ""
-    , ... } @ attrs:
-    let
-      dependencies = [
-        (map (drv: drv.nativeDrv or drv) nativeBuildInputs)
-        (map (drv: drv.crossDrv or drv) buildInputs)
-      ];
-      propagatedDependencies = [
-        (map (drv: drv.nativeDrv or drv) propagatedNativeBuildInputs)
-        (map (drv: drv.crossDrv or drv) propagatedBuildInputs)
-      ];
-    in let
-      pos' =
-        if pos != null then
-          pos
-        else if attrs.meta.description or null != null then
-          builtins.unsafeGetAttrPos "description" attrs.meta
-        else
-          builtins.unsafeGetAttrPos "name" attrs;
-      pos'' = if pos' != null then "‘" + pos'.file + ":" + toString pos'.line + "’" else "«unknown-file»";
-
-
-      remediation = {
-        unfree = remediate_whitelist "Unfree";
-        broken = remediate_whitelist "Broken";
-        blacklisted = x: "";
-        insecure = remediate_insecure;
-        unknown-meta = x: "";
-      };
-      remediate_whitelist = allow_attr: attrs:
-        ''
-          a) For `nixos-rebuild` you can set
-            { nixpkgs.config.allow${allow_attr} = true; }
-          in configuration.nix to override this.
-
-          b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
-            { allow${allow_attr} = true; }
-          to ~/.config/nixpkgs/config.nix.
-        '';
-
-      remediate_insecure = attrs:
-        ''
-
-          Known issues:
-
-        '' + (lib.fold (issue: default: "${default} - ${issue}\n") "" attrs.meta.knownVulnerabilities) + ''
-
-          You can install it anyway by whitelisting this package, using the
-          following methods:
-
-          a) for `nixos-rebuild` you can add ‘${attrs.name or "«name-missing»"}’ to
-             `nixpkgs.config.permittedInsecurePackages` in the configuration.nix,
-             like so:
-
-               {
-                 nixpkgs.config.permittedInsecurePackages = [
-                   "${attrs.name or "«name-missing»"}"
-                 ];
-               }
-
-          b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
-          ‘${attrs.name or "«name-missing»"}’ to `permittedInsecurePackages` in
-          ~/.config/nixpkgs/config.nix, like so:
-
-               {
-                 permittedInsecurePackages = [
-                   "${attrs.name or "«name-missing»"}"
-                 ];
-               }
-
-        '';
-
-
-      throwEvalHelp = { reason , errormsg ? "" }:
-        throw (''
-          Package ‘${attrs.name or "«name-missing»"}’ in ${pos''} ${errormsg}, refusing to evaluate.
-
-          '' + ((builtins.getAttr reason remediation) attrs));
-
-      metaTypes = with lib.types; rec {
-        # These keys are documented
-        description = str;
-        longDescription = str;
-        branch = str;
-        homepage = str;
-        downloadPage = str;
-        license = either (listOf lib.types.attrs) (either lib.types.attrs str);
-        maintainers = listOf str;
-        priority = int;
-        platforms = listOf str;
-        hydraPlatforms = listOf str;
-        broken = bool;
-
-        # Weirder stuff that doesn't appear in the documentation?
-        version = str;
-        tag = str;
-        updateWalker = bool;
-        executables = listOf str;
-        outputsToInstall = listOf str;
-        position = str;
-        repositories = attrsOf str;
-        isBuildPythonPackage = platforms;
-        schedulingPriority = str;
-        downloadURLRegexp = str;
-        isFcitxEngine = bool;
-        isIbusEngine = bool;
-      };
-
-      checkMetaAttr = k: v:
-        if metaTypes?${k} then
-          if metaTypes.${k}.check v then null else "key '${k}' has a value ${v} of an invalid type ${builtins.typeOf v}; expected ${metaTypes.${k}.description}"
-        else "key '${k}' is unrecognized; expected one of: \n\t      [${lib.concatMapStringsSep ", " (x: "'${x}'") (lib.attrNames metaTypes)}]";
-      checkMeta = meta: if shouldCheckMeta then lib.remove null (lib.mapAttrsToList checkMetaAttr meta) else [];
-
-      # Check if a derivation is valid, that is whether it passes checks for
-      # e.g brokenness or license.
-      #
-      # Return { valid: Bool } and additionally
-      # { reason: String; errormsg: String } if it is not valid, where
-      # reason is one of "unfree", "blacklisted" or "broken".
-      checkValidity = attrs:
-        if hasDeniedUnfreeLicense attrs && !(hasWhitelistedLicense attrs) then
-          { valid = false; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
-        else if hasBlacklistedLicense attrs then
-          { valid = false; reason = "blacklisted"; errormsg = "has a blacklisted license (‘${showLicense attrs.meta.license}’)"; }
-        else if !allowBroken && attrs.meta.broken or false then
-          { valid = false; reason = "broken"; errormsg = "is marked as broken"; }
-        else if !allowBroken && attrs.meta.platforms or null != null && !lib.lists.elem result.system attrs.meta.platforms then
-          { valid = false; reason = "broken"; errormsg = "is not supported on ‘${result.system}’"; }
-        else if !(hasAllowedInsecure attrs) then
-          { valid = false; reason = "insecure"; errormsg = "is marked as insecure"; }
-        else let res = checkMeta (attrs.meta or {}); in if res != [] then
-          { valid = false; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
-        else { valid = true; };
-
-      outputs' =
-        outputs ++
-        (if separateDebugInfo then assert targetPlatform.isLinux; [ "debug" ] else []);
-
-      dependencies' = let
-          justMap = map lib.chooseDevOutputs dependencies;
-          nativeBuildInputs = lib.elemAt justMap 0
-            ++ lib.optional targetPlatform.isWindows ../../build-support/setup-hooks/win-dll-link.sh;
-          buildInputs = lib.elemAt justMap 1
-               # TODO(@Ericson2314): Should instead also be appended to `nativeBuildInputs`.
-            ++ lib.optional separateDebugInfo ../../build-support/setup-hooks/separate-debug-info.sh;
-        in [ nativeBuildInputs buildInputs ];
-
-      propagatedDependencies' = map lib.chooseDevOutputs propagatedDependencies;
-    in
-
-      # Throw an error if trying to evaluate an non-valid derivation
-      assert let v = checkValidity attrs;
-             in if !v.valid
-               then throwEvalHelp (removeAttrs v ["valid"])
-               else true;
-
-      lib.addPassthru (derivation (
-        (removeAttrs attrs
-          ["meta" "passthru" "crossAttrs" "pos"
-           "__impureHostDeps" "__propagatedImpureHostDeps"
-           "sandboxProfile" "propagatedSandboxProfile"])
-        // (let
-          # TODO(@Ericson2314): Reversing of dep lists is just temporary to avoid Darwin mass rebuild.
-          computedSandboxProfile =
-            lib.concatMap (input: input.__propagatedSandboxProfile or []) (extraBuildInputs ++ lib.concatLists (lib.reverseList dependencies'));
-          computedPropagatedSandboxProfile =
-            lib.concatMap (input: input.__propagatedSandboxProfile or []) (lib.concatLists (lib.reverseList propagatedDependencies'));
-          computedImpureHostDeps =
-            lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (extraBuildInputs ++ lib.concatLists (lib.reverseList dependencies')));
-          computedPropagatedImpureHostDeps =
-            lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (lib.concatLists (lib.reverseList propagatedDependencies')));
-        in
-        {
-          builder = attrs.realBuilder or shell;
-          args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)];
-          stdenv = result;
-          system = result.system;
-          userHook = config.stdenv.userHook or null;
-          __ignoreNulls = true;
-
-          nativeBuildInputs = lib.elemAt dependencies' 0;
-          buildInputs = lib.elemAt dependencies' 1;
-
-          propagatedNativeBuildInputs = lib.elemAt propagatedDependencies' 0;
-          propagatedBuildInputs = lib.elemAt propagatedDependencies' 1;
-        } // ifDarwin {
-          # TODO: remove lib.unique once nix has a list canonicalization primitive
-          __sandboxProfile =
-          let profiles = [ extraSandboxProfile ] ++ computedSandboxProfile ++ computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile sandboxProfile ];
-              final = lib.concatStringsSep "\n" (lib.filter (x: x != "") (lib.unique profiles));
-          in final;
-          __propagatedSandboxProfile = lib.unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]);
-          __impureHostDeps = computedImpureHostDeps ++ computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps ++ __impureHostDeps ++ __extraImpureHostDeps ++ [
-            "/dev/zero"
-            "/dev/random"
-            "/dev/urandom"
-            "/bin/sh"
-          ];
-          __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps;
-        } // (if outputs' != [ "out" ] then {
-          outputs = outputs';
-        } else { })))) (
-      {
-        overrideAttrs = f: mkDerivation (attrs // (f attrs));
-        # The meta attribute is passed in the resulting attribute set,
-        # but it's not part of the actual derivation, i.e., it's not
-        # passed to the builder and is not a dependency.  But since we
-        # include it in the result, it *is* available to nix-env for queries.
-        meta = { }
-            # If the packager hasn't specified `outputsToInstall`, choose a default,
-            # which is the name of `p.bin or p.out or p`;
-            # if he has specified it, it will be overridden below in `// meta`.
-            #   Note: This default probably shouldn't be globally configurable.
-            #   Services and users should specify outputs explicitly,
-            #   unless they are comfortable with this default.
-          // { outputsToInstall =
-            let
-              outs = outputs'; # the value passed to derivation primitive
-              hasOutput = out: builtins.elem out outs;
-            in [( lib.findFirst hasOutput null (["bin" "out"] ++ outs) )];
-          }
-          // meta
-            # Fill `meta.position` to identify the source location of the package.
-          // lib.optionalAttrs (pos' != null)
-            { position = pos'.file + ":" + toString pos'.line; }
-          ;
-        inherit passthru;
-      } //
-      # Pass through extra attributes that are not inputs, but
-      # should be made available to Nix expressions using the
-      # derivation (e.g., in assertions).
-      passthru);
-
   # The stdenv that we are producing.
-  result =
+  stdenv =
     derivation (
     (if isNull allowedRequisites then {} else { allowedRequisites = allowedRequisites ++ defaultNativeBuildInputs; }) //
     {
-      inherit system name;
+      inherit name;
+
+      # Nix itself uses the `system` field of a derivation to decide where to
+      # build it. This is a bit confusing for cross compilation.
+      inherit (buildPlatform) system;
 
       builder = shell;
 
@@ -390,7 +77,7 @@ let
 
       inherit preHook initialPath shell defaultNativeBuildInputs;
     }
-    // ifDarwin {
+    // lib.optionalAttrs buildPlatform.isDarwin {
       __sandboxProfile = stdenvSandboxProfile;
       __impureHostDeps = __stdenvImpureHostDeps;
     })
@@ -402,6 +89,10 @@ let
         platforms = lib.platforms.all;
       };
 
+      inherit buildPlatform hostPlatform targetPlatform;
+
+      inherit extraBuildInputs __extraImpureHostDeps extraSandboxProfile;
+
       # Utility flags to test the type of platform.
       inherit (hostPlatform)
         isDarwin isLinux isSunOS isHurd isCygwin isFreeBSD isOpenBSD
@@ -412,7 +103,9 @@ let
       # Whether we should run paxctl to pax-mark binaries.
       needsPax = isLinux;
 
-      inherit mkDerivation;
+      inherit (import ./make-derivation.nix {
+        inherit lib config stdenv;
+      }) mkDerivation;
 
       # For convenience, bring in the library functions in lib/ so
       # packages don't have to do that themselves.
@@ -431,4 +124,4 @@ let
     # like curl = if stdenv ? curl then stdenv.curl else ...).
     // extraAttrs;
 
-in result)
+in stdenv)
diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix
new file mode 100644
index 000000000000..31b0428eeb2b
--- /dev/null
+++ b/pkgs/stdenv/generic/make-derivation.nix
@@ -0,0 +1,150 @@
+{ lib, config, stdenv }:
+
+rec {
+  # `mkDerivation` wraps the builtin `derivation` function to
+  # produce derivations that use this stdenv and its shell.
+  #
+  # See also:
+  #
+  # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
+  #   Details on how to use this mkDerivation function
+  #
+  # * https://nixos.org/nix/manual/#ssec-derivation
+  #   Explanation about derivations in general
+  mkDerivation =
+    { nativeBuildInputs ? []
+    , buildInputs ? []
+
+    , propagatedNativeBuildInputs ? []
+    , propagatedBuildInputs ? []
+
+    , crossConfig ? null
+    , meta ? {}
+    , passthru ? {}
+    , pos ? # position used in error messages and for meta.position
+        (if attrs.meta.description or null != null
+          then builtins.unsafeGetAttrPos "description" attrs.meta
+          else builtins.unsafeGetAttrPos "name" attrs)
+    , separateDebugInfo ? false
+    , outputs ? [ "out" ]
+    , __impureHostDeps ? []
+    , __propagatedImpureHostDeps ? []
+    , sandboxProfile ? ""
+    , propagatedSandboxProfile ? ""
+    , ... } @ attrs:
+    let
+      dependencies = [
+        (map (drv: drv.nativeDrv or drv) nativeBuildInputs)
+        (map (drv: drv.crossDrv or drv) buildInputs)
+      ];
+      propagatedDependencies = [
+        (map (drv: drv.nativeDrv or drv) propagatedNativeBuildInputs)
+        (map (drv: drv.crossDrv or drv) propagatedBuildInputs)
+      ];
+    in let
+
+      outputs' =
+        outputs ++
+        (if separateDebugInfo then assert stdenv.hostPlatform.isLinux; [ "debug" ] else []);
+
+      dependencies' = let
+          justMap = map lib.chooseDevOutputs dependencies;
+          nativeBuildInputs = lib.elemAt justMap 0
+            ++ lib.optional stdenv.hostPlatform.isWindows ../../build-support/setup-hooks/win-dll-link.sh;
+          buildInputs = lib.elemAt justMap 1
+               # TODO(@Ericson2314): Should instead also be appended to `nativeBuildInputs`.
+            ++ lib.optional separateDebugInfo ../../build-support/setup-hooks/separate-debug-info.sh;
+        in [ nativeBuildInputs buildInputs ];
+
+      propagatedDependencies' = map lib.chooseDevOutputs propagatedDependencies;
+
+      derivationArg =
+        (removeAttrs attrs
+          ["meta" "passthru" "crossAttrs" "pos"
+           "__impureHostDeps" "__propagatedImpureHostDeps"
+           "sandboxProfile" "propagatedSandboxProfile"])
+        // (let
+          # TODO(@Ericson2314): Reversing of dep lists is just temporary to avoid Darwin mass rebuild.
+          computedSandboxProfile =
+            lib.concatMap (input: input.__propagatedSandboxProfile or []) (stdenv.extraBuildInputs ++ lib.concatLists (lib.reverseList dependencies'));
+          computedPropagatedSandboxProfile =
+            lib.concatMap (input: input.__propagatedSandboxProfile or []) (lib.concatLists (lib.reverseList propagatedDependencies'));
+          computedImpureHostDeps =
+            lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (stdenv.extraBuildInputs ++ lib.concatLists (lib.reverseList dependencies')));
+          computedPropagatedImpureHostDeps =
+            lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (lib.concatLists (lib.reverseList propagatedDependencies')));
+        in
+        {
+          builder = attrs.realBuilder or stdenv.shell;
+          args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)];
+          inherit stdenv;
+          inherit (stdenv) system;
+          userHook = config.stdenv.userHook or null;
+          __ignoreNulls = true;
+
+          nativeBuildInputs = lib.elemAt dependencies' 0;
+          buildInputs = lib.elemAt dependencies' 1;
+
+          propagatedNativeBuildInputs = lib.elemAt propagatedDependencies' 0;
+          propagatedBuildInputs = lib.elemAt propagatedDependencies' 1;
+        } // lib.optionalAttrs (stdenv.buildPlatform.isDarwin) {
+          # TODO: remove lib.unique once nix has a list canonicalization primitive
+          __sandboxProfile =
+          let profiles = [ stdenv.extraSandboxProfile ] ++ computedSandboxProfile ++ computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile sandboxProfile ];
+              final = lib.concatStringsSep "\n" (lib.filter (x: x != "") (lib.unique profiles));
+          in final;
+          __propagatedSandboxProfile = lib.unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]);
+          __impureHostDeps = computedImpureHostDeps ++ computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps ++ __impureHostDeps ++ stdenv.__extraImpureHostDeps ++ [
+            "/dev/zero"
+            "/dev/random"
+            "/dev/urandom"
+            "/bin/sh"
+          ];
+          __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps;
+        } // (if outputs' != [ "out" ] then {
+          outputs = outputs';
+        } else { }));
+
+      # The meta attribute is passed in the resulting attribute set,
+      # but it's not part of the actual derivation, i.e., it's not
+      # passed to the builder and is not a dependency.  But since we
+      # include it in the result, it *is* available to nix-env for queries.
+      meta = { }
+          # If the packager hasn't specified `outputsToInstall`, choose a default,
+          # which is the name of `p.bin or p.out or p`;
+          # if he has specified it, it will be overridden below in `// meta`.
+          #   Note: This default probably shouldn't be globally configurable.
+          #   Services and users should specify outputs explicitly,
+          #   unless they are comfortable with this default.
+        // { outputsToInstall =
+          let
+            outs = outputs'; # the value passed to derivation primitive
+            hasOutput = out: builtins.elem out outs;
+          in [( lib.findFirst hasOutput null (["bin" "out"] ++ outs) )];
+        }
+        // attrs.meta or {}
+          # Fill `meta.position` to identify the source location of the package.
+        // lib.optionalAttrs (pos != null)
+          { position = pos.file + ":" + toString pos.line; }
+        ;
+
+    in
+
+      lib.addPassthru
+        (derivation (import ./check-meta.nix
+          {
+            inherit lib config meta derivationArg;
+            mkDerivationArg = attrs;
+            # Nix itself uses the `system` field of a derivation to decide where
+            # to build it. This is a bit confusing for cross compilation.
+            inherit (stdenv) system;
+          }))
+        ( {
+            overrideAttrs = f: mkDerivation (attrs // (f attrs));
+            inherit meta passthru;
+          } //
+          # Pass through extra attributes that are not inputs, but
+          # should be made available to Nix expressions using the
+          # derivation (e.g., in assertions).
+          passthru);
+}
diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix
index c2879d93e17c..c475d2d1e927 100644
--- a/pkgs/stdenv/linux/default.nix
+++ b/pkgs/stdenv/linux/default.nix
@@ -52,8 +52,11 @@ let
     let
 
       thisStdenv = import ../generic {
-        inherit config extraBuildInputs;
         name = "stdenv-linux-boot";
+        buildPlatform = localSystem;
+        hostPlatform = localSystem;
+        targetPlatform = localSystem;
+        inherit config extraBuildInputs;
         preHook =
           ''
             # Don't patch #!/interpreter because it leads to retained
@@ -64,9 +67,6 @@ let
         shell = "${bootstrapTools}/bin/bash";
         initialPath = [bootstrapTools];
 
-        hostPlatform = localSystem;
-        targetPlatform = localSystem;
-
         fetchurlBoot = import ../../build-support/fetchurl/boot.nix {
           inherit system;
         };
@@ -102,9 +102,6 @@ let
       };
 
     in {
-      buildPlatform = localSystem;
-      hostPlatform = localSystem;
-      targetPlatform = localSystem;
       inherit config overlays;
       stdenv = thisStdenv;
     };
@@ -269,11 +266,11 @@ in
   # dependency (`nix-store -qR') on bootstrapTools or the first
   # binutils built.
   (prevStage: {
-    buildPlatform = localSystem;
-    hostPlatform = localSystem;
-    targetPlatform = localSystem;
     inherit config overlays;
     stdenv = import ../generic rec {
+      buildPlatform = localSystem;
+      hostPlatform = localSystem;
+      targetPlatform = localSystem;
       inherit config;
 
       preHook = ''
@@ -286,9 +283,6 @@ in
       initialPath =
         ((import ../common-path.nix) {pkgs = prevStage;});
 
-      hostPlatform = localSystem;
-      targetPlatform = localSystem;
-
       extraBuildInputs = [ prevStage.patchelf prevStage.paxctl ] ++
         # Many tarballs come with obsolete config.sub/config.guess that don't recognize aarch64.
         lib.optional (system == "aarch64-linux") prevStage.updateAutotoolsGnuConfigScriptsHook;
diff --git a/pkgs/stdenv/native/default.nix b/pkgs/stdenv/native/default.nix
index 31973c2cdc50..02734f2f3e59 100644
--- a/pkgs/stdenv/native/default.nix
+++ b/pkgs/stdenv/native/default.nix
@@ -81,6 +81,7 @@ let
     { cc, fetchurl, extraPath ? [], overrides ? (self: super: { }) }:
 
     import ../generic {
+      buildPlatform = localSystem;
       hostPlatform = localSystem;
       targetPlatform = localSystem;
 
@@ -125,8 +126,6 @@ in
         "i686-solaris" = "/usr/gnu";
         "x86_64-solaris" = "/opt/local/gcc47";
       }.${system} or "/usr";
-      hostPlatform = localSystem;
-      targetPlatform = localSystem;
       inherit stdenv;
     };
 
@@ -140,9 +139,6 @@ in
 
   # First build a stdenv based only on tools outside the store.
   (prevStage: {
-    buildPlatform = localSystem;
-    hostPlatform = localSystem;
-    targetPlatform = localSystem;
     inherit config overlays;
     stdenv = makeStdenv {
       inherit (prevStage) cc fetchurl;
@@ -152,9 +148,6 @@ in
   # 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: {
-    buildPlatform = localSystem;
-    hostPlatform = localSystem;
-    targetPlatform = localSystem;
     inherit config overlays;
     stdenv = makeStdenv {
       inherit (prevStage.stdenv) cc fetchurl;
diff --git a/pkgs/stdenv/nix/default.nix b/pkgs/stdenv/nix/default.nix
index 7ab797ce91ba..aaf6c523ea4a 100644
--- a/pkgs/stdenv/nix/default.nix
+++ b/pkgs/stdenv/nix/default.nix
@@ -10,10 +10,13 @@ bootStages ++ [
   (prevStage: let
     inherit (prevStage) stdenv;
   in {
-    inherit (prevStage) buildPlatform hostPlatform targetPlatform;
     inherit config overlays;
 
     stdenv = import ../generic rec {
+      buildPlatform = localSystem;
+      hostPlatform = localSystem;
+      targetPlatform = localSystem;
+
       inherit config;
 
       preHook = ''
@@ -30,8 +33,6 @@ bootStages ++ [
         nativeTools = false;
         nativePrefix = stdenv.lib.optionalString hostPlatform.isSunOS "/usr";
         nativeLibc = true;
-        hostPlatform = localSystem;
-        targetPlatform = localSystem;
         inherit stdenv;
         inherit (prevStage) binutils coreutils gnugrep;
         cc = prevStage.gcc.cc;