[#derivations]
= Derivations

Derivations can be created using the primitive built-in `derivation` function.
It takes the following arguments.

- `system` (e.g. `x86_64-linux`).
- `name`, the package name.
- `builder`, the executable that builds the package.
  Attributes are passed to the builder as environment variables.
- `args` (optional), command line arguments to be passed to the builder.
- `outputs` (optional, defaults to `out`), output names.
  Nix will pass them to the builder as environment variables containing
  the output paths.

    d = derivation { name = "myname"; builder = "mybuilder"; system = "mysystem"; }

[source]
.Example
....
nix-repl> d = derivation { name = "myname"; builder = "mybuilder"; system = "mysystem"; }
....

In place of using `derivation`, it is generally more convenient to use
`stdenv.mkDerivation`, which will be be introduced in
<<#mkDerivation>>

== Instantiation vs Realisation

When a derivation is _instantiated_ (_evaluated_),
the Nix expression is parsed and interpreted.
The result is a `.drv` file containing a derivation set.
The package is not built in this step.

// TODO Discuss nix-instantiate or the modern equivalent

The package itself is created when the derivation is _built_ (_realised_).
Any dependencies are also built at this time.

// TODO discuss nix-store -r  or the modern equivalent

== Instantiate (evaluate) a derivation

Using the derivation "d" created above...

[source]
.Example
....
nix-repl> d
«derivation /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv»
....

That `.drv` file is plain text; it contains the derivation in a different format.
The mysterious sequence of characters in the filename is a hash of the derivation.
The hash is unique to this derivation.
We could have multiple derivations for a package, perhaps different versions or with different options enabled,
but each one would have a unique hash.
Any changes to the derivation would result in a new hash.
Using the hash, Nix can tell the different derivations apart,
and avoid rebuilding a derivation that has already been built.

We can inspect the derivation in the Nix repl.

[source]
.Example
....
nix-repl> d.drvAttrs
{ builder = "mybuilder"; name = "myname"; system = "mysystem"; }
....

We can examine the `.drv` file.

[source]
.Example
....
$ cat /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
Derive([("out","/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname","","")],[],[],"mysystem","mybuilder",[],[("builder","mybuilder"),("name","myname"),("out","/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname"),("system","mysystem")])%
....

Or get a nicely formatted version.

[source]
.Example
....
$ nix show-derivation /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
{
  "/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv": {
    "outputs": {
      "out": {
        "path": "/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname"
      }
    },
    "inputSrcs": [],
    "inputDrvs": {},
    "system": "mysystem",
    "builder": "mybuilder",
    "args": [],
    "env": {
      "builder": "mybuilder",
      "name": "myname",
      "out": "/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname",
      "system": "mysystem"
    }
  }
}
....

== Find out where the package would be (or was) installed

Using the derivation "d" created above...

[source]
.Example
....
nix-repl> d.outPath
"/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname"

nix-repl> builtins.toString d     # also works
"/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname"
....

== Build (realise) a derivation.

In the Nix REPL, using the derivation "d" created above...

[source]
.Example
....
nix-repl> :b d
error: a 'mysystem' with features {} is required to build '/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv', but I am a 'x86_64-linux' with features {benchmark, big-parallel, kvm, nixos-test}
....

Of course, this example failed to build because the builder and system are fake.
We can achieve the same result at the command line.

[source]
.Example
....
nix-build /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
this derivation will be built:
  /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
error: a 'mysystem' with features {} is required to build '/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv', but I am a 'x86_64-linux' with features {benchmark, big-parallel, kvm, nixos-test}
....

== Remove a derivation

Delete a path from the store *if it is safe to do so* (i.e. if it is
eligible for garbage collection).

[source]
.Example
....
nix-store --delete /nix/store/rc3n0lc4aijyi9wwpmcss7hbxryz6bnh-foo
....

// TODO Contine from this point in ~/github/eolas/nix/nix.md
