Hedronite Lesson · Polyglot-Dev / Nix · Thu 2026-09-24

Fundamentals of Stdenv — Pill 19

Walk stdenv.mkDerivation → default-builder.sh → $stdenv/setup → genericBuild.

Lesson Class: Asr (Nix language track)
Focus: stdenv · mkDerivation · default-builder.sh · setup · genericBuild · phases
Done-criteria: walk stdenv.mkDerivation → default-builder.sh → $stdenv/setup → genericBuild
Grounding: on-disk nix-pills.epub Pill 19 · live nixos.org canonical
Note: Not Pill 15 · not flakes · not install · not Python wrap · not Pill 20 hooks · next session 15 Pills 20
Setup Source
Source $stdenv/setup to fill PATH and helpers; host PATH is not required.
Phase Walk
genericBuild runs unpack/configure/build/check/install/fixup as bash functions.
MkDeriv Wrap
stdenv.mkDerivation wires bash + default-builder.sh + $stdenv env.
stdenv is a store path with a /setup script, not a Nix language keyword.

<!-- hal:authoritative:yaml -->

*Walk four steps aloud: stdenv.mkDerivation, default-builder.sh, $stdenv/setup, genericBuild. Say what each one hands to the next.*

§I — Frame

Asr session 14. Fourteenth live fire of the Nix language track. Week 5 fire 1. The page is Nix Pills Fundamentals of Stdenv, Pill 19. Luca Bruno wrote the series. License CC BY-SA 4.0. Ground from the on-disk EPUB at . Live URL is canonical if the EPUB drifts: https://nixos.org/guides/nix-pills/19-fundamentals-of-stdenv.html.

Session 13 named store paths (Source Seal, Output Predict, Fixed Bind). This session asks how nixpkgs packages actually build: an ordinary derivation called stdenv plus a thin wrapper that sources its /setup and runs genericBuild. Dualfire seat for this lane: Nix paves Rust roads; stdenv is the pave layer under nearly every nixpkgs package you will lean on for Rust toolchains and dep graphs later.

Done-criteria from the syllabus: you can walk stdenv.mkDerivation → default-builder.sh → $stdenv/setup → genericBuild.

Not Pill 15 (NIX_PATH; dropped). Not flakes. Not install. Not Python wrapping. Not Pill 20 hooks depth (tomorrow’s unmarked). Launch a terminal when you have Nix. If Nix is absent today, read the Pill’s nix-shell drill and the .drv paste from this lesson.

§II — stdenv is an ordinary derivation

Musashi declarative: stdenv is a store path with a /setup script, not a Nix language keyword.

$ nix-build '<nixpkgs>' -A stdenv
/nix/store/…-stdenv
$ ls -R result/
result/:
nix-support/  setup

Two files matter for today: /setup and an empty propagated-user-env-packages. Runtime references (nix-store -q --references) still list bash, coreutils, gcc-wrapper, bzip2, and friends. Those paths are hardcoded inside /setup (SHELL=…, initialPath=…, defaultNativeBuildInputs=…). Referring to the stdenv out path therefore pulls the toolchain graph without magic builtins.

§III — Setup Source (named technique)

Yagyu names the cut once. Setup Source: treat $stdenv/setup as the single entry that fills PATH and helper functions so a build can proceed without a host PATH.

Pill drill (fake empty derivation, then strip PATH):

$ nix-shell -E 'derivation { name = "fake"; builder = "fake"; system = "x86_64-linux"; }'
nix-shell$ unset PATH
nix-shell$ source /nix/store/…-stdenv/setup
nix-shell$ tar -xf hello-2.10.tar.gz && cd hello-2.10
nix-shell$ configurePhase
…
nix-shell$ buildPhase
…

After Setup Source, configurePhase and buildPhase are ordinary bash functions from the setup file. The unset PATH proves the environment is self-contained for a plain autotools tree with no extra deps.

If-then-thus: if PATH is empty and $stdenv/setup has been sourced, then initialPath and the helper functions supply the toolchain, thus a host PATH is not required for the default phases to run.

§IV — Phase Walk (named technique)

Phase Walk: name the default phase list that genericBuild runs, and treat each phase as a bash function with before/after hooks.

Default phases from the Pill / setup: unpack, configure, build, check, install, fixup (and related helpers). genericBuild walks that list. You may overwrite a phase, reorder the list, or inject hooks; it stays bash.

unpackPhase is the piece that expands src and enters the source directory, the same job your older hand-written builders did. Read the functions in the setup file once with the Pill open; do not memorize line numbers.

§V — MkDeriv Wrap (named technique)

MkDeriv Wrap: call stdenv.mkDerivation instead of raw derivation. The wrapper selects bash as builder, passes default-builder.sh as args, and injects the stdenv env var that points at the stdenv out path.

hello.nix shape from the Pill:

with import <nixpkgs> { };
stdenv.mkDerivation {
  name = "hello";
  src = ./hello-2.10.tar.gz;
}

stdenv is both a derivation and an attrset that carries mkDerivation. Convenience, not a second language.

default-builder.sh is two lines:

source $stdenv/setup
genericBuild

That is the whole bridge from Nix expression to Phase Walk. On nix-shell entry, setup prepares the environment without building; on nix-build, genericBuild runs the phases.

Inspect the .drv after nix-instantiate hello.nix. Builder is bash with -e and the store path of default-builder.sh. Env shows src, stdenv, empty buildInputs for this minimal case, and the predicted out. Input drvs include bash and stdenv. That table is today’s done-criteria diagram in machine form.

§VI — Four-step walk (done-criteria)

Say this chain once without looking:

  1. **stdenv.mkDerivation { … }**: MkDeriv Wrap. Attrs become a derivation that forces bash + default-builder.sh + $stdenv.
  2. **bash -e default-builder.sh**: builder entry from the .drv args.
  3. **source $stdenv/setup**: Setup Source. PATH, helpers, phase functions.
  4. **genericBuild**: Phase Walk. unpack → configure → build → check → install → fixup (defaults).

If-then-thus: if you can name those four arrows in order, then you can locate any failure (missing src, broken phase, empty PATH before source) on the correct step, thus Pill 20’s buildInputs and hooks land on a known spine instead of a mystery builder.

§VII — Common mistakes

  1. Treating stdenv as a Nix builtin instead of an ordinary derivation with a /setup file.
  2. Expecting mkDerivation to invent phases outside what genericBuild and the setup file define.
  3. Skipping Setup Source and blaming the host PATH when phases fail inside a clean shell.
  4. Re-opening Pill 15 search paths as if they explained stdenv (Pill 15 stays dropped).
  5. Jumping to flakes schemas before you can walk the four steps in Pill language.
  6. Pulling Pill 20 hook depth into today’s drill (hooks named only as “exist”; depth is next session).

§VIII — Boundaries

§IX — Close

Session 13 named what lands under /nix/store. Session 14 walks how nixpkgs builds get there: Setup Source fills the environment, Phase Walk runs the defaults, MkDeriv Wrap wires bash → default-builder.sh → setup → genericBuild. Next unmarked: session 15, Pills 20, buildInputs and hooks.

Related:

Write the four-step chain on one line. Source $stdenv/setup once in a throwaway nix-shell if Nix is present, then leave the keyboard.