Nix Tutorial 4 : Nix Derivations: The Core of Building in Nix - wimsio/universities GitHub Wiki
A derivation in Nix is a recipe for building a package or store object. It describes what to build, how to build it, and with which dependencies. The derivation
function is how you define these recipes.
- A derivation is a build recipe for the Nix store.
- It is defined as an attribute set passed to the
derivation
built-in. - Evaluating it creates a
.drv
file in/nix/store
and, once built, the outputs (binaries, libraries, docs, etc).
See the Nix manual: derivations for in-depth theory.
derivation {
name = "hello";
system = "x86_64-linux";
builder = "/bin/sh";
args = [ "-c" "echo Hello, world! > $out" ];
}
-
The result is an attribute set describing outputs, e.g.:
/nix/store/<hash>-hello.drv
/nix/store/<hash>-hello
Attribute | Type | Description | Example |
---|---|---|---|
name |
String | Name for the derivation | "hello" |
system |
String | System type (target platform) |
"x86_64-linux" or builtins.currentSystem
|
builder |
Path/String | Executable to run for building |
"/bin/bash" or ./builder.sh
|
derivation {
name = "demo";
system = builtins.currentSystem;
builder = "/bin/sh";
args = [ "-c" "echo Hi > $out" ];
}
-
args
(List of Strings): Arguments passed to the builder. -
outputs
(List of Strings): Which outputs to generate (default:[ "out" ]
). - Any other attribute: Passed to the builder as an environment variable.
Example:
derivation {
name = "libexample";
builder = "/bin/sh";
args = [ "-c" "touch $lib; touch $dev; touch $doc" ];
outputs = [ "lib" "dev" "doc" ];
system = "x86_64-linux";
}
See Advanced Attributes below for power-user settings like allowedReferences
, outputHashAlgo
, preferLocalBuild
, etc.
-
Default: a single output named
"out"
. -
Multiple outputs: e.g.,
[ "lib" "dev" "doc" ]
- Each output is available as an attribute:
myDrv.lib
,myDrv.dev
, etc. - The first output is the "default" and can be accessed via the top-level variable.
- Each output is available as an attribute:
Example:
let
myDrv = derivation {
name = "foo";
outputs = [ "bin" "doc" "out" ];
...
};
in myDrv.doc
- Outputs become store paths like
/nix/store/<hash>-foo-bin
,/nix/store/<hash>-foo-doc
, etc.
- Strings: Passed unchanged as env vars.
- Numbers: Converted to strings.
- Paths: Copied into the store, the env var gets the store path.
- Lists: Flattened to space-separated strings.
- true: "1", false/null: empty string.
Big Data: Use passAsFile = [ "myBigString" ];
to pass long data via file path env var (myBigStringPath
).
Some optional/advanced attributes for special needs:
Attribute | Description |
---|---|
exportReferencesGraph |
Pass closure graphs of dependencies to the builder. |
passAsFile |
Pass env vars via temp files, not the environment (for very long values). |
__structuredAttrs |
Serialize all attributes as JSON file (env: $NIX_ATTRS_JSON_FILE ). |
allowedReferences |
List of store paths allowed as runtime refs. |
disallowedReferences |
Store paths not allowed as runtime refs. |
preferLocalBuild |
Prefer local build over remote. |
allowSubstitutes |
If false , disables use of prebuilt binary substitutes. |
requiredSystemFeatures |
Only build on systems with listed features (e.g., [ "kvm" ] ). |
impureEnvVars |
Pass selected host env vars to the builder (for fixed-output only). |
outputHash* , __contentAddressed
|
Configure advanced content-addressed builds. |
See the Nix manual on advanced derivation attributes for the full list.
- For fixed-output or content-addressed derivations, use
outputHash
,outputHashAlgo
, andoutputHashMode
. - Supported hash algos:
"sha256"
,"sha512"
,"blake3"
, etc. - Hash mode:
"flat"
,"nar"
,"text"
,"git"
.
Example:
derivation {
...
outputHash = "abcdef123...";
outputHashAlgo = "sha256";
outputHashMode = "flat";
}
- Needed for reproducibility and trusted builds.
- You can use the output of a derivation as an input to functions like
import
,readFile
, etc. - This pauses evaluation until the dependency is built (can be slow or problematic in large builds).
- Control with
allow-import-from-derivation
setting.
Example:
let
drv = derivation {
name = "hello";
builder = "/bin/sh";
args = [ "-c" "echo -n hello > $out" ];
system = builtins.currentSystem;
};
in "${builtins.readFile drv} world" # → "hello world"
Illustration:
The Nix evaluator will build the drv
, then use its output in your expression.
derivation {
name = "myfile";
builder = "/bin/sh";
args = [ "-c" "echo hi > $out" ];
system = "x86_64-linux";
}
derivation {
name = "multifile";
outputs = [ "bin" "doc" ];
builder = "/bin/sh";
args = [ "-c" "touch $bin; echo docs > $doc" ];
system = "x86_64-linux";
}
derivation {
name = "big";
builder = "/bin/sh";
args = [ "-c" "cat $bigPath > $out" ];
system = "x86_64-linux";
passAsFile = [ "big" ];
big = "Very long content...";
}
Tip:
Try inspecting and building derivations with nix repl
or nix-instantiate
!