stdenv.mkDerivation: Make self more overlay-like; use self.public
`self` is now arguments, like `super`. The final package is in `self.public`.
This commit is contained in:
parent
2f21bc2fdb
commit
6d7efb3a16
4 changed files with 49 additions and 48 deletions
|
@ -187,7 +187,7 @@ all places.
|
|||
{ stdenv, callPackage }:
|
||||
stdenv.mkDerivation (self: {
|
||||
# ...
|
||||
passthru.tests.example = callPackage ./example.nix { my-package = self; };
|
||||
passthru.tests.example = callPackage ./example.nix { my-package = self.public; }
|
||||
})
|
||||
```
|
||||
|
||||
|
|
|
@ -319,7 +319,7 @@ For information about how to run the updates, execute `nix-shell maintainers/scr
|
|||
|
||||
### Recursive attributes in `mkDerivation`
|
||||
|
||||
If you pass a function to `mkDerivation`, it will receive as its argument the final output of the same `mkDerivation` call. For example:
|
||||
If you pass a function to `mkDerivation`, it will receive as its argument the final arguments, considering use of `overrideAttrs`. For example:
|
||||
|
||||
```nix
|
||||
mkDerivation (self: {
|
||||
|
@ -331,9 +331,14 @@ mkDerivation (self: {
|
|||
```
|
||||
|
||||
Note that this does not use the `rec` keyword to reuse `withFeature` in `configureFlags`.
|
||||
The `rec` keyword works at the syntax level and is unaware of overriding.
|
||||
|
||||
Instead, the definition references `self`, allowing users to change `withFeature`
|
||||
consistently with `overrideAttrs`.
|
||||
|
||||
`self` also contains the attribute `public`, which represents the final package,
|
||||
including the output paths, etc.
|
||||
|
||||
Let's look at a more elaborate example to understand the differences between
|
||||
various bindings:
|
||||
|
||||
|
@ -347,11 +352,11 @@ let pkg =
|
|||
packages = [];
|
||||
|
||||
# `passthru.tests` is a commonly defined attribute.
|
||||
passthru.tests.simple = f self;
|
||||
passthru.tests.simple = f self.public;
|
||||
|
||||
# An example of an attribute containing a function
|
||||
passthru.appendPackages = packages':
|
||||
self.overrideAttrs (newSelf: super: {
|
||||
self.public.overrideAttrs (newSelf: super: {
|
||||
packages = super.packages ++ packages';
|
||||
});
|
||||
|
||||
|
@ -363,9 +368,7 @@ let pkg =
|
|||
in pkg
|
||||
```
|
||||
|
||||
Unlike the `pkg` binding in the above example, the `self` parameter always references the final package. For instance `(pkg.overrideAttrs(x)).self` is identical to `pkg.overrideAttrs(x)`, whereas `(pkg.overrideAttrs(x)).original` is the same as `pkg`.
|
||||
|
||||
This is also different from `mkDerivation rec { ..... }`, which binds the recursive references immediately, so it allows you to reference original _inputs_ only.
|
||||
Unlike the `pkg` binding in the above example, the `self` parameter always references the final attributes. For instance `(pkg.overrideAttrs(x)).self.public` is identical to `pkg.overrideAttrs(x)`, whereas `(pkg.overrideAttrs(x)).original` is the same as `pkg`.
|
||||
|
||||
See also the section about [`passthru.tests`](#var-meta-tests).
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ stdenv.mkDerivation (self: {
|
|||
(nixos { environment.noXlibs = true; }).pkgs.hello;
|
||||
};
|
||||
|
||||
passthru.tests.run = callPackage ./test.nix { hello = self; };
|
||||
passthru.tests.run = callPackage ./test.nix { hello = self.public; };
|
||||
|
||||
meta = with lib; {
|
||||
description = "A program that produces a familiar, friendly greeting";
|
||||
|
|
|
@ -17,52 +17,50 @@ let
|
|||
else makeDerivationExtensibleConst mkDerivationSimple fnOrAttrs;
|
||||
|
||||
# Based off lib.makeExtensible, with modifications:
|
||||
# - lib.fix' -> lib.fix ∘ mkDerivationSimple; then inline fix
|
||||
# - convert `f` to an overlay
|
||||
# - inline overrideAttrs and make it positional instead of // to reduce allocs
|
||||
makeDerivationExtensible = mkDerivationSimple: rattrs:
|
||||
let
|
||||
r = 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))
|
||||
(rattrs r);
|
||||
in r;
|
||||
args = rattrs (args // { inherit public; });
|
||||
public =
|
||||
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 public;
|
||||
|
||||
# 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
|
||||
# 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: attrs // f self 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
|
||||
|
|
Loading…
Reference in a new issue