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