What is a derivation?

Hey folks - so I am a big confused as to what a derivation is. I am looking at the nix reference manual entry for derivation. The best I can do given that is that a derivation is an attribute set. There are some required attributes - system, name and builder. Any extra attributes are forwarded to the builder script as environmental variables.

This attribute set it can then be used by some nix command to realize the derivation and create the output (in the nix store) that the derivation describes.

Is this correct so far?

1 Like

That sounds about right to me.

1 Like

The only correction I’d make is that the attribute set you’re describing is passed to the builtins.derivation function, which returns a derivation, which coincidentally contains the same attributes for convenience’s sake. Yes, this builtins.derivation function is a primop, so it is magical, and you cannot create derivations without it.

1 Like

Got it. The attribute set itself is not a derivation. A derivation is the output of calling builtins.derviation with the attribute set that I described.

1 Like

In general the derivation is a data format with three required attributes: name, builder, and system. The format itself is similar to json, and can be serialized to it with nix show-derivation.

The derivation itself is just a recipe for how to build a package. When you actually reify or “realize” this derivation, then Nix essentially calls the builder attribute, with any potential args, and creates the specified store paths for the given system.

If the derivation does not output anything to the Nix store during build time, Nix considers this an error.

So a Nix build essentially has 2 parts, Nix code evaluation to produce the derivation(s), then realization of these derivations to outputs. It is possible to short circuit repeated evaluations by producing a derivation beforehand and simply calling nix-build on the derivation file directly.

1 Like

If you wanted to build a house, then it would be a blueprint. If you wanted to cook a dish, it would be a recipe. A derivation tells a builder, how to construct the packaged.

Technically a “derivation” is just an attrset with type = "derivation".

This:

nix-build -E '{
  type = "derivation";
  outputName = "out";
  name = "foo";
  system = builtins.currentSystem;
  builder = "foo";
  drvPath = "/nix/store/3vbky1rhgrzfl8cbn4d2dv9g2myn2r7f-foo.drv";
}'

will start to realise (and obviously fail) but, as you can see, derivation was never invoked.

2 Likes

Repeating this experiment with Nix 2.15.0. No instantiation actually happens (i.e. the store derivation, the file /nix/store/3vbky1rhgrzfl8cbn4d2dv9g2myn2r7f-foo.drv, will not be created) no matter if you invoke nix-instantiate or nix-build. The instantiation seems to be triggered (magically) by the builtins.derivation function.

It’s nix derivation show since Nix 2.15 to complement the new nix derivation add.

This is been kept saying, though the fact, that calling builtins.derivation args is different from just evaluating or trying to “realize” an equivalent attribute set makes clear that it is not just an attribute set.

There has to be something special about it.

I tried to find the implementation of builtins.derivation but was unable to.

It’s here: https://github.com/NixOS/nix/blob/cafb5e8a1751b2c951347d5d9188b2e0bee357be/src/libexpr/primops/derivation.nix

And the implementation of derivationStrict is here: https://github.com/NixOS/nix/blob/cafb5e8a1751b2c951347d5d9188b2e0bee357be/src/libexpr/primops.cc#L1020