aboutsummaryrefslogtreecommitdiff
path: root/doc/manual/src/language/derivations.md
blob: c10e8149d6389e21034e399ea9360764a2f4e4b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Derivations

The most important built-in function is `derivation`, which is used to
describe a single derivation (a build task). It takes as input a set,
the attributes of which specify the inputs of the build.

  - There must be an attribute named [`system`]{#attr-system} whose value must be a
    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
    [forward builds for other
    platforms](../advanced-topics/distributed-builds.md) by forwarding
    them to other machines.)

  - 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`]{#attr-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:

    ```nix
    outputs = [ "lib" "headers" "doc" ];
    ```

    This will cause Lix 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

    ```bash
    ./configure \
      --libdir=$lib/lib \
      --includedir=$headers/include \
      --docdir=$doc/share/doc
    ```

    for an Autoconf-style package. You can refer to each output of a
    derivation by selecting it as an attribute, e.g.

    ```nix
    buildInputs = [ pkg.lib pkg.headers ];
    ```

    The first element of `outputs` determines the *default output*.
    Thus, you could also write

    ```nix
    buildInputs = [ pkg pkg.headers ];
    ```

    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
    `TMPDIR` (default `/tmp`) where the build will take place. The
    current directory is changed to this directory.

  - The environment is cleared and set to the derivation attributes, as
    specified above.

  - In addition, the following variables are set:

      - `NIX_BUILD_TOP` contains the path of the temporary directory for
        this build.

      - Also, `TMPDIR`, `TEMPDIR`, `TMP`, `TEMP` are set to point to the
        temporary directory. This is to prevent the builder from
        accidentally writing temporary files anywhere else. Doing so
        might cause interference by other processes.

      - `PATH` is set to `/path-not-set` to prevent shells from
        initialising it to their built-in default value.

      - `HOME` is set to `/homeless-shelter` to prevent programs from
        using `/etc/passwd` or the like to find the user's home
        directory, which could cause impurity. Usually, when `HOME` is
        set, it is used as the location of the home directory, even if
        it points to a non-existent path.

      - `NIX_STORE` is set to the path of the top-level Nix store
        directory (typically, `/nix/store`).

      - `NIX_ATTRS_JSON_FILE` & `NIX_ATTRS_SH_FILE` if `__structuredAttrs`
        is set to `true` for the dervation. A detailed explanation of this
        behavior can be found in the
        [section about structured attrs](./advanced-attributes.md#adv-attr-structuredAttrs).

      - 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 Lix 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, Lix 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, Lix registers
    them as dependencies of the output paths.

  - After the build, Lix 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 Lix. This is because the Lix archives used in
    deployment have no concept of ownership information, and because it
    makes the build result dependent on the user performing the build.