OFFSET偏移
← All articlesOFFSET / FIELD NOTESNO. 024

Derivations: from expressions to build outputs

Trace the relationship between evaluation, building or downloading substitutes, and store outputs.

English translation · Code and commands follow the Chinese original.

IN THESE READING PATHSThe Nix language and build model ↗
About 2 min readStart reading

Nix expressions can return values of any type. The build workflow discussed here begins only when evaluation produces a derivation and the build descriptions for its dependencies.


What is a derivation?#

A derivation is a core Nix primitive. It is a text file with a .drv suffix that describes how to build a package:

  1. Inputs: source code, dependency packages, and build scripts.
  2. Build environment: the build platform, builder, and environment parameters. Sandbox isolation depends on the platform and Nix settings; not every build is guaranteed to be fully isolated.
  3. Outputs: the binaries, libraries, and documentation produced by the build.

Breaking down the build process#

  1. Evaluation: The Nix interpreter runs your .nix code and generates .drv files.
  2. Realisation: Nix checks for existing outputs, preferring to download substitutes from trusted caches; otherwise, it builds according to the .drv file. The traditional nix-instantiate command evaluates expressions to produce build descriptions; it does not run the builds.
  3. Storage: Build results are stored in /nix/store.

Immutability, input addressing, and content addressing#

  • Where the hash prefix comes from: Common derivation outputs are input-addressed: their paths are determined by the build description, dependencies, and related inputs. The prefix should not simply be described as a hash of the output contents. Fixed-output and content-addressed derivations use different path rules and need to be distinguished.
  • The magic of caching: If the hash of what you are building already exists in a binary cache such as cache.nixos.org, Nix can download the corresponding outputs from a trusted substituter and avoid building locally.

Why does your configuration go into /nix/store too?#

When you run nixos-rebuild switch, module evaluation generates build descriptions for the system closure. The outputs include activation scripts, service definitions, generated configuration, and their dependencies. Activation then connects the generated files to locations such as /etc. Your source configuration may enter the store as part of the Flake source, but rolling back does not restore the source files in your working directory.

  • This is why you can roll back the system: the old configuration files are also in /nix/store, and switching back just changes the targets of the symbolic links again.

A developer's view: nix-shell#

nix-shell provides a derivation's build dependencies and corresponding environment. It normally does not run the target package's final builder, though it may still build or download dependencies. nix develop is intended for Flake development environments, while nix shell primarily adds programs provided by packages to PATH. The three are not fully equivalent.


Summary: the three stages of Nix#

  1. Describe: Write attribute sets in .nix files.
  2. Derive: Generate a .drv build plan.
  3. Produce: Create read-only directories in /nix/store.

References & further reading

  1. NixOS manual ↗
  2. Nix language manual ↗
  3. Nix: Derivations ↗
  4. Nix: Store Path ↗

Adapted from technical notes. Examples use generic names.

Continue along a reading path

The Nix language and build model

  1. 01Nix and NixOS: storage, rollback, and declarative thinking
  2. 02Nix syntax: attribute sets, lists, and built-in functions
  3. 03Nix functions and scope
  4. 04Nix attribute sets: recursion and merging
  5. 05Derivations: from expressions to build outputs
CONTINUE READING / NEXT ARTICLEFlake structure: inputs and outputs

Understand Flake inputs, outputs, self, and the levels involved in capturing function arguments.