derivations
the build instruction at the heart of nix.
“every build is won before it begins”
a derivation is the value that nix knows how to build. it is an attribute set with a specific shape, and when nix encounters one, it writes a .drv file into the store, computes its hash, and knows exactly what to do with it.
every package in nixpkgs is a derivation. every nix build resolves to one. store paths, references, the language. this is where they meet.
the primitive
builtins.derivation {
name = "hello";
system = "x86_64-linux";
builder = "/bin/sh";
args = [ "-c" "echo hello > $out" ];
}
builtins.derivation is the bottom of the stack. give it a name, a system, a builder, and nix will write a .drv file and build it. the output lands in /nix/store/{hash}-hello.
nobody uses builtins.derivation directly. it is too raw. you have to set up PATH, provide a compiler, handle source unpacking, configure flags, install into $out. all manually.
what everyone uses
stdenv.mkDerivation {
pname = "hello";
version = "1.0";
src = ./src;
buildInputs = [ openssl ];
}
stdenv.mkDerivation wraps the primitive with a standard build environment: a shell, coreutils, a compiler, and a phased build script that handles unpacking, configuring, building, and installing. nearly every package in nixpkgs uses it.
the attribute set you pass to mkDerivation is not the derivation itself. mkDerivation transforms it: it merges your attributes with stdenv's defaults, constructs the builder arguments, resolves dependencies, and calls builtins.derivation underneath.