Skip to content

nixpkgs

Fixed-point arguments of build helpers {#chap-build-helpers-finalAttrs}

Nixpkgs

Fixed-point arguments of build helpers {#chap-build-helpers-finalAttrs}

Fixed-point arguments of build helpers {#chap-build-helpers-finalAttrs}

stdenv.mkDerivation also accepts a fixed-point function instead of a plain attribute set:

stdenv.mkDerivation (finalAttrs: {
  pname = "hello";
  version = "2.12";

  src = fetchurl {
    url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz";
    hash = "sha256-...";
  };
})

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, 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 for the underlying mechanism.

Define a build helper with lib.extendMkDerivation {#sec-build-helper-extendMkDerivation}

Use 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.

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 mkLocalDerivation - a build helper over mkDerivation

Define a build helper named mkLocalDerivation that builds locally without using substitutes by default.

Use lib.extendMkDerivation:

lib.extendMkDerivation {
  constructDrv = stdenv.mkDerivation;
  excludeDrvArgNames = [
    # Don't pass specialArg into mkDerivation.
    "specialArg"
  ];
  extendDrvArgs =
    finalAttrs:
    {
      preferLocalBuild ? true,
      allowSubstitute ? false,
      specialArg ? (_: false),
      ...
    }@args:
    {
      # Arguments to pass
      inherit preferLocalBuild allowSubstitute;
      # Some expressions involving specialArg
      greeting = if specialArg "hi" then "hi" else "hello";
    };
}

:::

To apply extra changes to the result derivation, pass transformDrv to lib.extendMkDerivation:

lib.customisation.extendMkDerivation { transformDrv = drv: /...; }