about summary refs log tree commit diff
path: root/pkgs/stdenv
diff options
context:
space:
mode:
authorR-VdP <141248+R-VdP@users.noreply.github.com>2023-01-20 15:56:31 +0100
committerR-VdP <141248+R-VdP@users.noreply.github.com>2023-01-30 17:58:05 +0100
commit51acc6245e5995c06c1304741263a8b954192e70 (patch)
tree681cdeab46e0919a994e54ca92f42ebec8f800f2 /pkgs/stdenv
parent645af55243a863c174aa78fdf329930021aebb3d (diff)
downloadnixlib-51acc6245e5995c06c1304741263a8b954192e70.tar
nixlib-51acc6245e5995c06c1304741263a8b954192e70.tar.gz
nixlib-51acc6245e5995c06c1304741263a8b954192e70.tar.bz2
nixlib-51acc6245e5995c06c1304741263a8b954192e70.tar.lz
nixlib-51acc6245e5995c06c1304741263a8b954192e70.tar.xz
nixlib-51acc6245e5995c06c1304741263a8b954192e70.tar.zst
nixlib-51acc6245e5995c06c1304741263a8b954192e70.zip
stdenv: don't include drvs in disallowedRefs as build-time deps.
Derivations listed as disallowedReferences or disallowedRequisites,
currently end up as build-time dependencies.
This is problematic since the disallowed derivations will be built by nix as
build-time dependencies, while those derivations might take a very long time
to build, or might not even build successfully on the platform used.
However, in order to scan for disallowed references in the final output,
knowing the out path is sufficient, and the out path can be calculated from
the derivation without needing to build it, saving time and resources.

While the problem is less severe for allowedReferences and allowedRequisites,
since we want the derivation to be built eventually, we would still like to
get the error early and without having to wait while nix builds a derivation
that might not be used (e.g. if we listed the wrong one).
Diffstat (limited to 'pkgs/stdenv')
-rw-r--r--pkgs/stdenv/generic/make-derivation.nix41
1 files changed, 41 insertions, 0 deletions
diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix
index 517cfc03aea5..c53eed3dfa12 100644
--- a/pkgs/stdenv/generic/make-derivation.nix
+++ b/pkgs/stdenv/generic/make-derivation.nix
@@ -173,6 +173,13 @@ let
   separateDebugInfo' = separateDebugInfo && stdenv.hostPlatform.isLinux && !(stdenv.hostPlatform.useLLVM or false);
   outputs' = outputs ++ lib.optional separateDebugInfo' "debug";
 
+  # Turn a derivation into its outPath without a string context attached.
+  # See the comment at the usage site.
+  unsafeDerivationToUntrackedOutpath = drv:
+    if lib.isDerivation drv
+    then builtins.unsafeDiscardStringContext drv.outPath
+    else drv;
+
   noNonNativeDeps = builtins.length (depsBuildTarget ++ depsBuildTargetPropagated
                                   ++ depsHostHost ++ depsHostHostPropagated
                                   ++ buildInputs ++ propagatedBuildInputs
@@ -446,6 +453,40 @@ else let
         "/bin/sh"
       ];
       __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps;
+    } //
+    # If we use derivations directly here, they end up as build-time dependencies.
+    # This is especially problematic in the case of disallowed*, since the disallowed
+    # derivations will be built by nix as build-time dependencies, while those
+    # derivations might take a very long time to build, or might not even build
+    # successfully on the platform used.
+    # We can improve on this situation by instead passing only the outPath,
+    # without an attached string context, to nix. The out path will be a placeholder
+    # which will be replaced by the actual out path if the derivation in question
+    # is part of the final closure (and thus needs to be built). If it is not
+    # part of the final closure, then the placeholder will be passed along,
+    # but in that case we know for a fact that the derivation is not part of the closure.
+    # This means that passing the out path to nix does the right thing in either
+    # case, both for disallowed and allowed references/requisites, and we won't
+    # build the derivation if it wouldn't be part of the closure, saving time and resources.
+    # While the problem is less severe for allowed*, since we want the derivation
+    # to be built eventually, we would still like to get the error early and without
+    # having to wait while nix builds a derivation that might not be used.
+    # See also https://github.com/NixOS/nix/issues/4629
+    lib.optionalAttrs (attrs ? disallowedReferences) {
+      disallowedReferences =
+        map unsafeDerivationToUntrackedOutpath attrs.disallowedReferences;
+    } //
+    lib.optionalAttrs (attrs ? disallowedRequisites) {
+      disallowedRequisites =
+        map unsafeDerivationToUntrackedOutpath attrs.disallowedRequisites;
+    } //
+    lib.optionalAttrs (attrs ? allowedReferences) {
+      allowedReferences =
+        lib.mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedReferences;
+    } //
+    lib.optionalAttrs (attrs ? allowedRequisites) {
+      allowedRequisites =
+        lib.mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedRequisites;
     };
 
   validity = checkMeta { inherit meta attrs; };