2020-07-22 21:17:48 +00:00
|
|
|
|
# Derivations
|
|
|
|
|
|
|
|
|
|
The most important built-in function is `derivation`, which is used to
|
|
|
|
|
describe a single derivation (a build action). It takes as input a set,
|
|
|
|
|
the attributes of which specify the inputs of the build.
|
|
|
|
|
|
|
|
|
|
- There must be an attribute named `system` whose value must be a
|
2020-07-24 09:43:44 +00:00
|
|
|
|
string specifying a Nix system type, such as `"i686-linux"` or
|
|
|
|
|
`"x86_64-darwin"`. (To figure out your system type, run `nix -vv
|
|
|
|
|
--version`.) The build can only be performed on a machine and
|
|
|
|
|
operating system matching the system type. (Nix can automatically
|
2020-07-24 12:31:33 +00:00
|
|
|
|
[forward builds for other
|
|
|
|
|
platforms](../advanced-topics/distributed-builds.md) by forwarding
|
|
|
|
|
them to other machines.)
|
2020-07-22 21:17:48 +00:00
|
|
|
|
|
|
|
|
|
- There must be an attribute named `name` whose value must be a
|
|
|
|
|
string. This is used as a symbolic name for the package by
|
|
|
|
|
`nix-env`, and it is appended to the output paths of the derivation.
|
|
|
|
|
|
|
|
|
|
- There must be an attribute named `builder` that identifies the
|
|
|
|
|
program that is executed to perform the build. It can be either a
|
|
|
|
|
derivation or a source (a local file reference, e.g.,
|
|
|
|
|
`./builder.sh`).
|
|
|
|
|
|
|
|
|
|
- Every attribute is passed as an environment variable to the builder.
|
|
|
|
|
Attribute values are translated to environment variables as follows:
|
|
|
|
|
|
|
|
|
|
- Strings and numbers are just passed verbatim.
|
|
|
|
|
|
|
|
|
|
- A *path* (e.g., `../foo/sources.tar`) causes the referenced file
|
|
|
|
|
to be copied to the store; its location in the store is put in
|
|
|
|
|
the environment variable. The idea is that all sources should
|
|
|
|
|
reside in the Nix store, since all inputs to a derivation should
|
|
|
|
|
reside in the Nix store.
|
|
|
|
|
|
|
|
|
|
- A *derivation* causes that derivation to be built prior to the
|
|
|
|
|
present derivation; its default output path is put in the
|
|
|
|
|
environment variable.
|
|
|
|
|
|
|
|
|
|
- Lists of the previous types are also allowed. They are simply
|
|
|
|
|
concatenated, separated by spaces.
|
|
|
|
|
|
|
|
|
|
- `true` is passed as the string `1`, `false` and `null` are
|
|
|
|
|
passed as an empty string.
|
|
|
|
|
|
|
|
|
|
- The optional attribute `args` specifies command-line arguments to be
|
|
|
|
|
passed to the builder. It should be a list.
|
|
|
|
|
|
|
|
|
|
- The optional attribute `outputs` specifies a list of symbolic
|
|
|
|
|
outputs of the derivation. By default, a derivation produces a
|
|
|
|
|
single output path, denoted as `out`. However, derivations can
|
|
|
|
|
produce multiple output paths. This is useful because it allows
|
|
|
|
|
outputs to be downloaded or garbage-collected separately. For
|
|
|
|
|
instance, imagine a library package that provides a dynamic library,
|
|
|
|
|
header files, and documentation. A program that links against the
|
|
|
|
|
library doesn’t need the header files and documentation at runtime,
|
|
|
|
|
and it doesn’t need the documentation at build time. Thus, the
|
|
|
|
|
library package could specify:
|
|
|
|
|
|
2020-07-31 13:43:25 +00:00
|
|
|
|
```nix
|
|
|
|
|
outputs = [ "lib" "headers" "doc" ];
|
|
|
|
|
```
|
2020-07-22 21:17:48 +00:00
|
|
|
|
|
|
|
|
|
This will cause Nix to pass environment variables `lib`, `headers`
|
|
|
|
|
and `doc` to the builder containing the intended store paths of each
|
|
|
|
|
output. The builder would typically do something like
|
|
|
|
|
|
2020-07-31 13:43:25 +00:00
|
|
|
|
```bash
|
|
|
|
|
./configure \
|
|
|
|
|
--libdir=$lib/lib \
|
|
|
|
|
--includedir=$headers/include \
|
|
|
|
|
--docdir=$doc/share/doc
|
|
|
|
|
```
|
2020-07-22 21:17:48 +00:00
|
|
|
|
|
|
|
|
|
for an Autoconf-style package. You can refer to each output of a
|
|
|
|
|
derivation by selecting it as an attribute, e.g.
|
|
|
|
|
|
2020-07-31 13:43:25 +00:00
|
|
|
|
```nix
|
|
|
|
|
buildInputs = [ pkg.lib pkg.headers ];
|
|
|
|
|
```
|
2020-07-22 21:17:48 +00:00
|
|
|
|
|
|
|
|
|
The first element of `outputs` determines the *default output*.
|
|
|
|
|
Thus, you could also write
|
|
|
|
|
|
2020-07-31 13:43:25 +00:00
|
|
|
|
```nix
|
|
|
|
|
buildInputs = [ pkg pkg.headers ];
|
|
|
|
|
```
|
2020-07-22 21:17:48 +00:00
|
|
|
|
|
|
|
|
|
since `pkg` is equivalent to `pkg.lib`.
|
|
|
|
|
|
|
|
|
|
The function `mkDerivation` in the Nixpkgs standard environment is a
|
|
|
|
|
wrapper around `derivation` that adds a default value for `system` and
|
|
|
|
|
always uses Bash as the builder, to which the supplied builder is passed
|
|
|
|
|
as a command-line argument. See the Nixpkgs manual for details.
|
|
|
|
|
|
|
|
|
|
The builder is executed as follows:
|
|
|
|
|
|
|
|
|
|
- A temporary directory is created under the directory specified by
|
2020-07-23 08:44:54 +00:00
|
|
|
|
`TMPDIR` (default `/tmp`) where the build will take place. The
|
|
|
|
|
current directory is changed to this directory.
|
2020-07-22 21:17:48 +00:00
|
|
|
|
|
|
|
|
|
- The environment is cleared and set to the derivation attributes, as
|
|
|
|
|
specified above.
|
|
|
|
|
|
|
|
|
|
- In addition, the following variables are set:
|
|
|
|
|
|
2020-07-23 08:44:54 +00:00
|
|
|
|
- `NIX_BUILD_TOP` contains the path of the temporary directory for
|
2020-07-22 21:17:48 +00:00
|
|
|
|
this build.
|
|
|
|
|
|
2020-07-23 08:44:54 +00:00
|
|
|
|
- Also, `TMPDIR`, `TEMPDIR`, `TMP`, `TEMP` are set to point to the
|
2020-07-22 21:17:48 +00:00
|
|
|
|
temporary directory. This is to prevent the builder from
|
|
|
|
|
accidentally writing temporary files anywhere else. Doing so
|
|
|
|
|
might cause interference by other processes.
|
|
|
|
|
|
2020-07-23 08:44:54 +00:00
|
|
|
|
- `PATH` is set to `/path-not-set` to prevent shells from
|
2020-07-22 21:17:48 +00:00
|
|
|
|
initialising it to their built-in default value.
|
|
|
|
|
|
2020-07-23 08:44:54 +00:00
|
|
|
|
- `HOME` is set to `/homeless-shelter` to prevent programs from
|
2020-07-22 21:17:48 +00:00
|
|
|
|
using `/etc/passwd` or the like to find the user's home
|
2020-07-23 08:44:54 +00:00
|
|
|
|
directory, which could cause impurity. Usually, when `HOME` is
|
2020-07-22 21:17:48 +00:00
|
|
|
|
set, it is used as the location of the home directory, even if
|
|
|
|
|
it points to a non-existent path.
|
|
|
|
|
|
2020-07-23 08:44:54 +00:00
|
|
|
|
- `NIX_STORE` is set to the path of the top-level Nix store
|
2020-07-22 21:17:48 +00:00
|
|
|
|
directory (typically, `/nix/store`).
|
|
|
|
|
|
|
|
|
|
- For each output declared in `outputs`, the corresponding
|
|
|
|
|
environment variable is set to point to the intended path in the
|
|
|
|
|
Nix store for that output. Each output path is a concatenation
|
|
|
|
|
of the cryptographic hash of all build inputs, the `name`
|
|
|
|
|
attribute and the output name. (The output name is omitted if
|
|
|
|
|
it’s `out`.)
|
|
|
|
|
|
|
|
|
|
- If an output path already exists, it is removed. Also, locks are
|
|
|
|
|
acquired to prevent multiple Nix instances from performing the same
|
|
|
|
|
build at the same time.
|
|
|
|
|
|
|
|
|
|
- A log of the combined standard output and error is written to
|
|
|
|
|
`/nix/var/log/nix`.
|
|
|
|
|
|
|
|
|
|
- The builder is executed with the arguments specified by the
|
|
|
|
|
attribute `args`. If it exits with exit code 0, it is considered to
|
|
|
|
|
have succeeded.
|
|
|
|
|
|
|
|
|
|
- The temporary directory is removed (unless the `-K` option was
|
|
|
|
|
specified).
|
|
|
|
|
|
|
|
|
|
- If the build was successful, Nix scans each output path for
|
|
|
|
|
references to input paths by looking for the hash parts of the input
|
|
|
|
|
paths. Since these are potential runtime dependencies, Nix registers
|
|
|
|
|
them as dependencies of the output paths.
|
|
|
|
|
|
|
|
|
|
- After the build, Nix sets the last-modified timestamp on all files
|
|
|
|
|
in the build result to 1 (00:00:01 1/1/1970 UTC), sets the group to
|
|
|
|
|
the default group, and sets the mode of the file to 0444 or 0555
|
|
|
|
|
(i.e., read-only, with execute permission enabled if the file was
|
|
|
|
|
originally executable). Note that possible `setuid` and `setgid`
|
|
|
|
|
bits are cleared. Setuid and setgid programs are not currently
|
|
|
|
|
supported by Nix. This is because the Nix archives used in
|
|
|
|
|
deployment have no concept of ownership information, and because it
|
|
|
|
|
makes the build result dependent on the user performing the build.
|