Skip to content

Build Independently confirmed2 publishers 3 min read Published

Zig 0.17 evaluates build.zig in a separate process from the one that runs the build

Zig 0.17.0 splits zig build into two executables, a configurer that evaluates build.zig and a maker that runs the build graph, according to a dev.to post. Script edits no longer rebuild the maker, while skipping the configure step as well requires build scripts that declare their host dependencies.

The Engineer · Build desk

Send a correction

Illustration accompanying Zig 0.17 evaluates build.zig in a separate process from the one that runs the build
Generated illustration

What happened

  • Probing the host at configure time, such as checking whether scdoc is installed, now has a name: configure cache poisoning.
  • Four new declaration functions and a lazy findProgramLazy lookup let scripts declare file inputs or push tool searches to make time.
  • Passing --listen=- starts a Build Server Protocol on stdin/stdout that lets IDEs inspect the graph and request specific steps.

Why it matters

  • What it limits constraint A build.zig that probes the host at configure time keeps the configurer running on every invocation, so only scripts written to be pure get the skip.
  • Who has to decide decision Maintainers porting large build scripts have to choose, probe by probe, between configure-time findProgram and findProgramLazy or a declared dependency.
  • What's now possible capability Editors and other tools can read a project's build graph statically from the serialized configuration, without parsing or running build.zig themselves.

Before 0.17, build.zig ran inside the build system's own process, so editing the script meant rebuilding the build system [6]. Every invocation after an edit started from scratch: recompile the build runner, re-evaluate the script, then execute the graph [7]. According to the dev.to post that walks through the release, that cost is a rounding error for small projects and compounds for large projects with complex build scripts [8]. The post does not include timings.

An edit in 0.17 still costs something. build.zig is Zig source that runs at configure time [9]. The configurer is the process that evaluates it [1], so a changed script still goes through the configurer [18]. What an edit no longer touches is the maker, which is built once and left unmodified when build.zig changes [10]. The maker is also built with optimizations enabled. The post says that matters more now that --watch and --fuzz modes exist [11].

For the large-project claim to transfer to a given tree, two things have to be true. The maker rebuild has to have been a real share of what an edit cost before. And the script has to keep the configure cache clean between runs.

The second condition is the harder one. The configurer can be skipped on identical inputs, but only while the cache stays pure [13]. Some CLI flags bypass configuration entirely [12]. A poisoned cache means the configure logic had side effects or did something the cache could not track [14]. The post's example is a build.zig that checks whether scdoc is installed to decide whether to build man pages. The result depends on host state the cache cannot see, so the cache is poisoned [14]. That is a lot of cache to lose over a man page. Side effects at make time are expected: a Run step that prints output does not poison anything [15].

Porting a large script means finding each configure-time probe and moving it to one of two forms. Four declaration functions cover file contents, file metadata (size, inode, mtime), directory contents and directory metadata, through calls such as std.Build.dependOnFileContents and std.Build.dependOnDirectoryContents [16]. For tool lookups, findProgram still exists for cases that need the answer at configure time. The new findProgramLazy returns a LazyPath that defers the search to make time [17].

I think the serialization boundary is the best engineering in the release. The configurer writes a compact binary serialization of the build graph, and the maker reads it [2]. Third-party tools can consume the same format, and it is the foundation of the new Build Server Protocol [5]. One artifact gives the cache something to key on and gives tools something to read. Passing --listen=- starts the server on stdin/stdout. IDEs can then inspect the graph statically, get notified when steps start and complete, and request specific steps [3]. The post calls the protocol early. Today it exposes available steps, options and dependencies, and module names plus a multiplexed compiler server protocol for type information and refactoring are planned [4].

What to watch

  • Post-edit build timings from a large Zig codebase on the previous release and 0.17 would show whether the maker rebuild was a large share of the old cost.
  • Whether the Build Server Protocol ships the module names and multiplexed compiler server protocol the post lists as planned.
  • How many widely used build.zig files still call findProgram at configure time after porting, keeping the configurer on every run.

Clarity's read

What the record supports and how the coverage leans. The claims behind it follow.

Reality

Evidence55
Adoption30
Hype gap+15
Incentives
Not scored
Confidence55
Why these scores

Claim ledger

Ranked by verification strength, evidence, and original report placement.

  1. [1]

    Zig 0.17.0 splits the build system into two separate executables: a configurer that evaluates build.zig and a maker that executes the build graph.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  2. [2]

    The configurer process evaluates build.zig and produces a compact binary serialization of the build graph; the maker process consumes that serialization and executes the steps.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  3. [3]

    Passing --listen=- starts the Build Server Protocol on stdin/stdout, letting IDEs and other tools inspect the build graph statically, receive notifications when steps start and complete, and request specific steps to build.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  4. [4]

    The Build Server Protocol is still early; it exposes available steps, options and dependencies, and planned additions include module names and a multiplexed compiler server protocol for type information and refactoring.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  5. [5]

    The serialized configuration is in a format third-party tooling can consume, and that format is the foundation of the new Build Server Protocol.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  6. [6]

    Under the previous design, build.zig ran inside the build system's own process, so changing build.zig meant the build system itself had to be rebuilt.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  7. [7]

    Before 0.17, every invocation after a build.zig edit started from scratch: recompile the build runner, re-evaluate the script, then execute the graph.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  8. [8]

    The post says the rebuild cost is a rounding error for small projects and compounds for large projects with complex build scripts.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  9. [9]

    build.zig is Zig source code that runs at configure time to declare what steps exist, what dependencies connect them, and what options are available.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  10. [10]

    The maker executable is built once and remains unmodified when build.zig changes.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  11. [11]

    The maker is built with optimizations enabled, which the post says matters more now that --watch and --fuzz modes exist.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  12. [12]

    The configurer can be skipped entirely for certain CLI flags, so some zig build invocations go straight to the maker.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  13. [13]

    When dependencies are declared instead of probed, the cache stays pure and the configurer can be skipped on identical inputs.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  14. [14]

    A poisoned configure cache means the configure logic had side effects or did something the cache could not track; checking at configure time whether scdoc is installed to choose whether to build man pages poisons the cache because the result depends on host state the cache cannot see.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  15. [15]

    A Run step that prints output has side effects at make time, which is expected and does not poison the cache.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  16. [16]

    Four declaration functions cover file contents, file metadata (size, inode, mtime), directory contents and directory metadata, with examples std.Build.dependOnFileContents and std.Build.dependOnDirectoryContents.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  17. [17]

    findProgram still exists for cases that need the result at configure time; a new findProgramLazy function returns a LazyPath that defers the search to make time.

    Reported Supported Source: dev.to post on Zig 0.17View cited source
  18. [18]

    After a build.zig edit in 0.17, the configurer still has to evaluate the changed script; the maker is the part spared from rebuilding.

    Derived Supported

Sources

2 independent publishers whose own reporting we read for this story.

  1. dev.to

    1 article · October 3, 2026

    Zig 0.17 Split Its Build Into Two Processes: Why That Matters
  2. lwn.net

    1 article · October 3, 2026

    Zig 0.17 released

Topics and entities

Topics

  • Language Servers
  • Build Systems and Cross-Compilation
  • Incremental compilation

Entities

  • Zig Build Server Protocol
  • Zig