Troubleshooting

The build panics about the Zig cache

Zig cache is not writable. Set ZIG_GLOBAL_CACHE_DIR and ZIG_LOCAL_CACHE_DIR,
or enable direnv (see .envrc) for a portable setup.

The build checks for a writable cache directory before doing anything else. Set both variables explicitly, or use the committed .envrc:

export ZIG_GLOBAL_CACHE_DIR="$PWD/.zig-cache-global"
export ZIG_LOCAL_CACHE_DIR="$PWD/.zig-cache"

The ./zig wrapper sets both for you.

A nested build fails with exit code 127

error: the following command exited with error code 127:
env ZAZA_EXAMPLES=package-producer ./zig build install

./zig is missing. It is gitignored, so a fresh clone does not have one. Run ./setup.sh, which creates it.

Affected targets: package-consumer, cross-compile-cli, rust-interop, and example-matrix.

CMake complains that the cache directory does not match

CMake Error: The current CMakeCache.txt directory .../deps/json/build/Debug/CMakeCache.txt
is different than the directory .../deps/json/build/Debug where CMakeCache.txt was created.

CMake caches absolute paths. If the checkout moved, or the build tree was copied from another machine, every cached path is wrong. Delete the build tree for the dependency and rebuild:

rm -rf deps/<name>/build

The JUCE examples keep their build tree inside the example directory:

rm -rf examples/juce/build
rm -rf examples/zaza-juce/build

Source checkouts under deps/ are unaffected, so this does not force a re-clone.

A build seems to hang while configuring

It is probably resolving dependencies. Zig resolves everything declared in the graph before running any step, so enabling all examples means fetching JUCE, curl, mbedtls, zlib, spdlog, and fmt. Scope the build:

ZAZA_EXAMPLES=<name> zig build <target>

run-cpp fails on a file that compiles fine elsewhere

run-cpp invokes zig c++ by name, so Zig must be on PATH, and it passes no include directories of its own. A file that includes a project header will fail:

examples/hello_zaza/src/main.cpp:2:10: fatal error: 'hello_zaza.h' file not found

Pass the flags yourself, after the source path:

zig build run-cpp -- src/simple_example.cpp -O2

Both are toolchain-dependent rather than broken. asan needs the AddressSanitizer runtime to be available to the linker. lto needs the toolchain to be using LLD. Neither is guaranteed on a given machine.

The C++20 modules example cannot find a compiler

The example does not use zig c++, because zig c++ rejects -x c++-module and ignores -fmodule-output. It uses /opt/homebrew/opt/llvm/bin/clang++ by default. Point it elsewhere:

ZAZA_MODULES_CXX=/path/to/clang++ zig build cxx20-modules-run

Benchmarks

benchmarks/ holds one benchmark. It generates a synthetic C++ project, builds it with zig build and with CMake plus Ninja, and times the real processes:

zig build --build-file benchmarks/build.zig bench

It runs on 0.14.1 and 0.15.2. On 0.16.0 the step fails with a message, because the harness uses std.process.Child.run, which 0.16 removed. Nothing in zig build test or zig build example-matrix reaches this build file.

Four earlier files here (performance_benchmark.zig, memory_benchmark.zig, scalability_benchmark.zig, cmake_comparison.zig) computed their results from hardcoded constants instead of measuring anything, and did not compile. They were deleted. See benchmarks/README.md for the details, and do not restore them from history.

A tracked file changed after a build

Two files at the repo root are generated output and gitignored: CMakeLists.txt and build/CMakeLists.txt. They are rewritten by whichever CMake-exporting example built last. Leave them out of commits.

Note that the top-level build/ directory itself holds real tracked Zig sources that build.zig imports. Only the generated CMake output inside it is ignored.

Which Zig versions actually work

0.14.1, 0.15.2 and 0.16.0. All three are verified against the full test suite:

Build Summary: 43/43 steps succeeded; 87/87 tests passed

The sources use spellings valid in all three. Where no shared spelling exists, a if (comptime @hasDecl(...)) picks one: the std.Io filesystem move, ArrayList.writer, Compile's add*/link* forwarders, and std.json's unmanaged ObjectMap. Other versions may work and are not tested. setup.sh warns when it sees one.