Open-Source Wikis

/

Zig

/

Features

/

Incremental compilation

ziglang/zig

Incremental compilation

Purpose

Zig's compilation pipeline is incremental by design: ZIR is cached per file, Sema results are cached per declaration with explicit dependency sets, and codegen / link only re-run on invalidated decls. The user-visible feature is zig build --watch — file edits cause only the affected work to be redone.

Components

Piece File Role
ZIR cache lib/std/zig/Zir.zig, lib/std/Build/Cache.zig ZIR is content-addressed and stored on disk.
Decl dependency graph src/Zcu.zig Each analyzed decl records what it depends on (types, values, other decls).
Sema src/Sema.zig Re-runs only invalidated decls, reusing the InternPool.
InternPool src/InternPool.zig Stable identity for types and values across runs (within a process).
Codegen src/codegen/* Re-emits per-decl artifacts; the linker stitches them in.
Linker src/link/* Supports per-decl Atom updates so the binary doesn't need to be re-linked from scratch.
Watch lib/std/Build/Watch.zig OS-level file watcher (kqueue/inotify/Windows).
Debug server src/IncrementalDebugServer.zig Long-lived compiler process that serves rebuild requests.
Harness tools/incr-check.zig Test fixture driver (~38 KB).

Flow

sequenceDiagram
    participant User
    participant Watch as std.Build.Watch
    participant Build as build_runner
    participant Zig as zig (Compilation)
    participant Pool as InternPool
    User->>Watch: edit foo.zig
    Watch->>Build: notify (file changed)
    Build->>Zig: recompile request
    Zig->>Zig: re-run AstGen on foo.zig
    Zig->>Pool: invalidate decls dependent on foo.zig
    Zig->>Zig: re-run Sema on invalidated decls only
    Zig->>Zig: codegen for changed Sema results
    Zig->>Zig: linker patches affected Atoms
    Zig-->>User: updated binary

What gets invalidated

Zcu tracks for each decl:

  • Source dependencies — which files the decl reads from (header includes, @embedFile, @cImport).
  • Decl dependencies — which other decls it references (callees, types it uses, fields it reads).
  • Comptime dependencies — comptime values it captured.

When a file changes, AstGen regenerates ZIR; Sema walks the dependency graph and marks every transitive dependent dirty; only those are re-analyzed.

Per-decl atoms in the linker

Each in-tree linker (src/link/Elf.zig, src/link/MachO.zig, etc.) operates on Atoms — a single decl's emitted code/data. When codegen produces a new Atom for an existing decl, the linker patches it in place rather than rewriting the whole binary. src/link/Elf/Atom.zig and src/link/MachO/Atom.zig are the canonical examples.

Debug server

src/IncrementalDebugServer.zig (~17 KB) is a long-lived zig process that accepts recompile requests over a socket. Editor tooling and the build runner can keep one alive across many rebuilds, sidestepping process startup cost. Together with watch mode this is the foundation of the "edit-and-continue"-style workflow.

Test harness

tools/incr-check.zig runs a fixture: an initial source plus a sequence of edits and expected results. After each edit the harness asks the compiler to incrementally rebuild and asserts that the result matches a clean build. Used by zig build test-incremental and by test/incremental/.

Entry points for modification

  • New thing to depend on: add it to the Zcu dependency tracking in src/Zcu.zig.
  • New invalidation source: wire it through lib/std/Build/Watch.zig.
  • New per-decl linker support: the Atom API in the relevant src/link/<format>/Atom.zig.

See Compiler for the broader pipeline and Build system for the watch-mode entry points.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Incremental compilation – Zig wiki | Factory