Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Any Zig Version

A project can pin the exact compiler it is built with, in its build.zig.zon:

.minimum_zig_version = "0.15.1",

When it does, every zig command run in that project, or in any directory below it, runs that version instead of the zig that was invoked: zig build, zig test, zig env, and zig cc alike. The first time a version is needed, Zig++ downloads it into the global cache and verifies it; after that, it only reads the project’s build.zig.zon and starts the installed compiler.

zig init writes the version of the compiler that ran it, so a new project keeps building with the compiler that made it.

The version names the exact compiler, the way anyzig reads it, not a lower bound. It can be:

VersionWhere it comes fromVerified with
a Zig++ release, 0.17.0-dev.2361+zigpp.5b96e6d21the GitHub release zigpp-0.17.0-dev.2361the SHA-256 in the release’s index.json
an upstream Zig release, 0.15.1ziglang.org/downloadthe SHA-256 in upstream’s download index, and the minisign signature
an upstream dev build, 0.16.0-dev.1234+abcdef012ziglang.org/buildsthe minisign signature

Every upstream archive is checked against the minisign signature that ziglang.org publishes next to it, made with the Zig Software Foundation’s key, and the signature has to name that archive. ziglang.org keeps only its recent dev builds, so an archive it no longer has comes from one of the community mirrors, tried in a random order, whose copy has to pass the same check. An archive that fails its check is never installed.

Running a version by hand

zig any 0.15.1 version   # run that exact version, installing it if needed
zig any list             # the installed versions, one per line
ZIG_ANY=off zig version  # the zig that was invoked, whatever the project pins

zig any <version> takes any command after the version, the same way zig does.

Where versions go

Each version lives in <global cache>/any/<version>/, next to the packages that zig fetch downloads; zig env prints the global cache directory. An install downloads and unpacks in a temporary directory and moves the result into place in one step, so a version is either complete or absent, even if the download is interrupted. Two zig commands that need the same new version at the same time end up with one install of it.

Deleting a version’s directory uninstalls it.

What the other version sees

The other version runs with the same arguments and the same environment, except that ZIG_LIB_DIR is removed: it points at the standard library of the zig that was invoked.

A compiler that runs from <global cache>/any/<version>/ never dispatches to that version again, so an installed Zig++ does not restart itself. Every other zig still dispatches: a build step that runs zig from PATH gets the pinned version too, and a project nested inside another one, pinning a different version, gets its own. zig any <version> starts its compiler with ZIG_ANY=off, so the version asked for runs even inside a project that pins another one.

If no source has the version, zig says what it tried, and that ZIG_ANY=off runs the compiler that was invoked instead.

A project created by a Zig++ that was never released, such as one you built from source, pins a version that has nothing to download. Build it with ZIG_ANY=off, or change minimum_zig_version to a released version.