about summary refs log tree commit diff
path: root/pkgs/stdenv/generic/make-derivation.nix
diff options
context:
space:
mode:
authorArtturi <Artturin@artturin.com>2022-05-04 14:31:50 +0300
committerGitHub <noreply@github.com>2022-05-04 14:31:50 +0300
commitf0e48dd98b4bc831c4bf5dde4579a85b0175b0f9 (patch)
tree280c5313622da0228abc1541fd8917d3b75159fe /pkgs/stdenv/generic/make-derivation.nix
parent538bcfe88034019ab8b60c87624bda13e3bdf598 (diff)
parent0e00acafe9dc8bbd9e6b49d4341b6bf49b6defb8 (diff)
Merge pull request #119942 from hercules-ci/mkDerivation-overridable-recursive-attributes
Diffstat (limited to 'pkgs/stdenv/generic/make-derivation.nix')
-rw-r--r--pkgs/stdenv/generic/make-derivation.nix71
1 files changed, 68 insertions, 3 deletions
diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix
index 53e391ab63f8e..11c0a29ce4f98 100644
--- a/pkgs/stdenv/generic/make-derivation.nix
+++ b/pkgs/stdenv/generic/make-derivation.nix
@@ -9,8 +9,72 @@ let
     # to build it. This is a bit confusing for cross compilation.
     inherit (stdenv) hostPlatform;
   };
+
+  makeOverlayable = mkDerivationSimple:
+    fnOrAttrs:
+      if builtins.isFunction fnOrAttrs
+      then makeDerivationExtensible mkDerivationSimple fnOrAttrs
+      else makeDerivationExtensibleConst mkDerivationSimple fnOrAttrs;
+
+  # Based off lib.makeExtensible, with modifications:
+  makeDerivationExtensible = mkDerivationSimple: rattrs:
+    let
+      # NOTE: The following is a hint that will be printed by the Nix cli when
+      # encountering an infinite recursion. It must not be formatted into
+      # separate lines, because Nix would only show the last line of the comment.
+
+      # An infinite recursion here can be caused by having the attribute names of expression `e` in `.overrideAttrs(finalAttrs: previousAttrs: e)` depend on `finalAttrs`. Only the attribute values of `e` can depend on `finalAttrs`.
+      args = rattrs (args // { inherit finalPackage; });
+      #              ^^^^
+
+      finalPackage =
+        mkDerivationSimple
+          (f0:
+            let
+              f = self: super:
+                # Convert f0 to an overlay. Legacy is:
+                #   overrideAttrs (super: {})
+                # We want to introduce self. We follow the convention of overlays:
+                #   overrideAttrs (self: super: {})
+                # Which means the first parameter can be either self or super.
+                # This is surprising, but far better than the confusion that would
+                # arise from flipping an overlay's parameters in some cases.
+                let x = f0 super;
+                in
+                  if builtins.isFunction x
+                  then
+                    # Can't reuse `x`, because `self` comes first.
+                    # Looks inefficient, but `f0 super` was a cheap thunk.
+                    f0 self super
+                  else x;
+            in
+              makeDerivationExtensible mkDerivationSimple
+                (self: let super = rattrs self; in super // f self super))
+          args;
+    in finalPackage;
+
+  # makeDerivationExtensibleConst == makeDerivationExtensible (_: attrs),
+  # but pre-evaluated for a slight improvement in performance.
+  makeDerivationExtensibleConst = mkDerivationSimple: attrs:
+    mkDerivationSimple
+      (f0:
+        let
+          f = self: super:
+            let x = f0 super;
+            in
+              if builtins.isFunction x
+              then
+                f0 self super
+              else x;
+        in
+          makeDerivationExtensible mkDerivationSimple (self: attrs // f self attrs))
+      attrs;
+
 in
 
+makeOverlayable (overrideAttrs:
+
+
 # `mkDerivation` wraps the builtin `derivation` function to
 # produce derivations that use this stdenv and its shell.
 #
@@ -70,6 +134,7 @@ in
 
 , # TODO(@Ericson2314): Make always true and remove
   strictDeps ? if config.strictDepsByDefault then true else stdenv.hostPlatform != stdenv.buildPlatform
+
 , meta ? {}
 , passthru ? {}
 , pos ? # position used in error messages and for meta.position
@@ -381,8 +446,6 @@ in
 lib.extendDerivation
   validity.handled
   ({
-     overrideAttrs = f: stdenv.mkDerivation (attrs // (f attrs));
-
      # A derivation that always builds successfully and whose runtime
      # dependencies are the original derivations build time dependencies
      # This allows easy building and distributing of all derivations
@@ -408,10 +471,12 @@ lib.extendDerivation
        args = [ "-c" "export > $out" ];
      });
 
-     inherit meta passthru;
+     inherit meta passthru overrideAttrs;
    } //
    # Pass through extra attributes that are not inputs, but
    # should be made available to Nix expressions using the
    # derivation (e.g., in assertions).
    passthru)
   (derivation derivationArg)
+
+)