doc/fixed-point-arguments: restructure chapter to make it more approachable (#537509)

This commit is contained in:
Johannes Kirschbauer 2026-07-02 12:32:32 +00:00 committed by GitHub
commit fdefb4bb67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,46 +1,39 @@
# Fixed-point arguments of build helpers {#chap-build-helpers-finalAttrs}
As mentioned in the beginning of this part, `stdenv.mkDerivation` could alternatively accept a fixed-point function. The input of this function, typically named `finalAttrs`, is expected to be the final state of the attribute set. A build helper like this is said to accept **fixed-point arguments**.
`stdenv.mkDerivation` also accepts a [fixed-point function](#function-library-lib.fixedPoints.fix) instead of a plain attribute set:
Build helpers don't always support fixed-point arguments yet, as support in [`stdenv.mkDerivation`](#mkderivation-recursive-attributes) was first included in Nixpkgs 22.05.
```nix
stdenv.mkDerivation (finalAttrs: {
pname = "hello";
version = "2.12";
## Defining a build helper with `lib.extendMkDerivation` {#sec-build-helper-extendMkDerivation}
src = fetchurl {
url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz";
hash = "sha256-...";
};
})
```
Developers can use the Nixpkgs library function [`lib.customisation.extendMkDerivation`](#function-library-lib.customisation.extendMkDerivation) to define a build helper supporting fixed-point arguments from an existing one with such support, with an attribute overlay similar to the one taken by [`<pkg>.overrideAttrs`](#sec-pkg-overrideAttrs).
The function's input, conventionally named `finalAttrs`, is the final state of the attribute set. Here `src` reads `finalAttrs.version` instead of repeating the version string. A build helper like this is said to accept **fixed-point arguments**.
Attributes that reference each other through `finalAttrs` stay correct when changing any of them with [`overrideAttrs`](#sec-pkg-overrideAttrs), because they all access the final values of the fixed-point computation.
`rec` cannot do this: its self-references are fixed when the set is defined and ignore later overrides.
See [recursive-sets](https://nix.dev/manual/nix/stable/language/syntax#recursive-sets) for the underlying mechanism.
## Define a build helper with `lib.extendMkDerivation` {#sec-build-helper-extendMkDerivation}
Use [`lib.customisation.extendMkDerivation`](#function-library-lib.customisation.extendMkDerivation) to define a build helper with fixed-point support from an existing one. It takes an attribute overlay similar to [`<pkg>.overrideAttrs`](#sec-pkg-overrideAttrs).
Besides overriding, `lib.extendMkDerivation` also supports `excludeDrvArgNames` to optionally exclude some arguments in the input fixed-point arguments from passing down to the base build helper (specified as `constructDrv`).
:::{.example #ex-build-helpers-extendMkDerivation}
# Example definition of `mkLocalDerivation` extended from `stdenv.mkDerivation` with `lib.extendMkDerivation`
# Example `mkLocalDerivation` - a build helper over `mkDerivation`
We want to define a build helper named `mkLocalDerivation` that builds locally without using substitutes by default.
Define a build helper named `mkLocalDerivation` that builds locally without using substitutes by default.
Instead of taking a plain attribute set,
```nix
{
preferLocalBuild ? true,
allowSubstitute ? false,
specialArg ? (_: false),
...
}@args:
stdenv.mkDerivation (
removeAttrs [
# Don't pass specialArg into mkDerivation.
"specialArg"
] args
// {
# Arguments to pass
inherit preferLocalBuild allowSubstitute;
# Some expressions involving specialArg
greeting = if specialArg "hi" then "hi" else "hello";
}
)
```
we could define with `lib.extendMkDerivation` an attribute overlay to make the result build helper also accept the attribute set's fixed point passing to the underlying `stdenv.mkDerivation`, named `finalAttrs` here:
Use `lib.extendMkDerivation`:
```nix
lib.extendMkDerivation {
@ -67,4 +60,8 @@ lib.extendMkDerivation {
```
:::
If one needs to apply extra changes to the result derivation, pass the derivation transformation function to `lib.extendMkDerivation` as `lib.customisation.extendMkDerivation { transformDrv = drv: ...; }`.
To apply extra changes to the result derivation, pass `transformDrv` to `lib.extendMkDerivation`:
```nix
lib.customisation.extendMkDerivation { transformDrv = drv: /...; }
```