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, callPackage }:
|
||||||
stdenv.mkDerivation (self: {
|
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`
|
### 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
|
```nix
|
||||||
mkDerivation (self: {
|
mkDerivation (self: {
|
||||||
|
@ -331,9 +331,14 @@ mkDerivation (self: {
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that this does not use the `rec` keyword to reuse `withFeature` in `configureFlags`.
|
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`
|
Instead, the definition references `self`, allowing users to change `withFeature`
|
||||||
consistently with `overrideAttrs`.
|
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
|
Let's look at a more elaborate example to understand the differences between
|
||||||
various bindings:
|
various bindings:
|
||||||
|
|
||||||
|
@ -347,11 +352,11 @@ let pkg =
|
||||||
packages = [];
|
packages = [];
|
||||||
|
|
||||||
# `passthru.tests` is a commonly defined attribute.
|
# `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
|
# An example of an attribute containing a function
|
||||||
passthru.appendPackages = packages':
|
passthru.appendPackages = packages':
|
||||||
self.overrideAttrs (newSelf: super: {
|
self.public.overrideAttrs (newSelf: super: {
|
||||||
packages = super.packages ++ packages';
|
packages = super.packages ++ packages';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -363,9 +368,7 @@ let pkg =
|
||||||
in 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`.
|
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`.
|
||||||
|
|
||||||
This is also different from `mkDerivation rec { ..... }`, which binds the recursive references immediately, so it allows you to reference original _inputs_ only.
|
|
||||||
|
|
||||||
See also the section about [`passthru.tests`](#var-meta-tests).
|
See also the section about [`passthru.tests`](#var-meta-tests).
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ stdenv.mkDerivation (self: {
|
||||||
(nixos { environment.noXlibs = true; }).pkgs.hello;
|
(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; {
|
meta = with lib; {
|
||||||
description = "A program that produces a familiar, friendly greeting";
|
description = "A program that produces a familiar, friendly greeting";
|
||||||
|
|
|
@ -17,52 +17,50 @@ let
|
||||||
else makeDerivationExtensibleConst mkDerivationSimple fnOrAttrs;
|
else makeDerivationExtensibleConst mkDerivationSimple fnOrAttrs;
|
||||||
|
|
||||||
# Based off lib.makeExtensible, with modifications:
|
# 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:
|
makeDerivationExtensible = mkDerivationSimple: rattrs:
|
||||||
let
|
let
|
||||||
r = mkDerivationSimple
|
args = rattrs (args // { inherit public; });
|
||||||
(f0:
|
public =
|
||||||
let
|
mkDerivationSimple
|
||||||
f = self: super:
|
(f0:
|
||||||
# Convert f0 to an overlay. Legacy is:
|
let
|
||||||
# overrideAttrs (super: {})
|
f = self: super:
|
||||||
# We want to introduce self. We follow the convention of overlays:
|
# Convert f0 to an overlay. Legacy is:
|
||||||
# overrideAttrs (self: super: {})
|
# overrideAttrs (super: {})
|
||||||
# Which means the first parameter can be either self or super.
|
# We want to introduce self. We follow the convention of overlays:
|
||||||
# This is surprising, but far better than the confusion that would
|
# overrideAttrs (self: super: {})
|
||||||
# arise from flipping an overlay's parameters in some cases.
|
# Which means the first parameter can be either self or super.
|
||||||
let x = f0 super;
|
# This is surprising, but far better than the confusion that would
|
||||||
in
|
# arise from flipping an overlay's parameters in some cases.
|
||||||
if builtins.isFunction x
|
let x = f0 super;
|
||||||
then
|
in
|
||||||
# Can't reuse `x`, because `self` comes first.
|
if builtins.isFunction x
|
||||||
# Looks inefficient, but `f0 super` was a cheap thunk.
|
then
|
||||||
f0 self super
|
# Can't reuse `x`, because `self` comes first.
|
||||||
else x;
|
# Looks inefficient, but `f0 super` was a cheap thunk.
|
||||||
in
|
f0 self super
|
||||||
makeDerivationExtensible mkDerivationSimple
|
else x;
|
||||||
(self: let super = rattrs self; in super // f self super))
|
in
|
||||||
(rattrs r);
|
makeDerivationExtensible mkDerivationSimple
|
||||||
in r;
|
(self: let super = rattrs self; in super // f self super))
|
||||||
|
args;
|
||||||
|
in public;
|
||||||
|
|
||||||
# makeDerivationExtensibleConst == makeDerivationExtensible (_: attrs),
|
# makeDerivationExtensibleConst == makeDerivationExtensible (_: attrs),
|
||||||
# but pre-evaluated for a slight improvement in performance.
|
# but pre-evaluated for a slight improvement in performance.
|
||||||
makeDerivationExtensibleConst = mkDerivationSimple: attrs:
|
makeDerivationExtensibleConst = mkDerivationSimple: attrs:
|
||||||
mkDerivationSimple (f0:
|
mkDerivationSimple
|
||||||
let
|
(f0:
|
||||||
f = self: super:
|
let
|
||||||
let x = f0 super;
|
f = self: super:
|
||||||
in
|
let x = f0 super;
|
||||||
if builtins.isFunction x
|
in
|
||||||
then
|
if builtins.isFunction x
|
||||||
# Can't reuse `x`, because `self` comes first.
|
then
|
||||||
# Looks inefficient, but `f0 super` was a cheap thunk.
|
f0 self super
|
||||||
f0 self super
|
else x;
|
||||||
else x;
|
in
|
||||||
in
|
makeDerivationExtensible mkDerivationSimple (self: attrs // f self attrs))
|
||||||
makeDerivationExtensible mkDerivationSimple (self: attrs // f self attrs))
|
|
||||||
attrs;
|
attrs;
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
Loading…
Reference in a new issue