Troubleshooting

unable to load 'build_spec.zig': FileNotFound

$ zig build
build_spec.zig:1:1: error: unable to load 'build_spec.zig': FileNotFound
build.zig:2:22: note: file imported here
const spec = @import("build_spec.zig");
                     ^~~~~~~~~~~~~~~~

The spec has not been generated. It is gitignored, so a fresh clone never has one.

./gen_build_spec.sh

cue: command not found

$ ./gen_build_spec.sh
./gen_build_spec.sh: line 8: cue: command not found
$ echo $?
127

Install CUE, or run ./setup.sh --check-only to see what is missing. gen_build_spec.sh calls cue by name and does not honour a CUE environment variable; setup.sh does, and puts it on PATH for the generator.

A module I added does not get built

Check export.cue. A module in project.cue that is absent from _modules is dropped silently. cue vet returns 0 and gen_build_spec.sh prints its usual success line.

thread N panic: attempt to use null value in build.zig

$ zig build
thread 868007 panic: attempt to use null value
/path/to/azazel/build.zig:43:44: 0x1002a0033 in build (build)
            step.linkLibrary(built.get(dep).?);
                                           ^

A name in some module's deps is not a module. Compare the deps lists in project.cue against the keys in export.cue's _modules. Typos and modules you forgot to export both land here.

error: no module named 'X' available within module 'root'

$ zig build
src/calc.zig:3:25: error: no module named 'mathlib' available within module 'root'
const mathlib = @import("mathlib");
                        ^~~~~~~~~

deps links a library. It does not register a Zig module. Export the symbols you need with pub export fn and declare them with extern fn on the other side. See deps.

Note that Zig analyses top-level declarations lazily, so an unused @import of a non-existent module compiles fine. The error appears the first time you use it.

failed to check cache: 'src/X.zig' file_hash FileNotFound

The root path in project.cue is wrong. Paths are relative to the directory containing build.zig. zig build test gives the better message:

error: 'spec_test.test.every module root exists on disk' failed: missing root for module 'mathlib': src/nope.zig

some instances are incomplete

$ cue vet
some instances are incomplete; use the -c flag to show errors or -c=false to allow incomplete instances

A required field is unset somewhere. cue vet will not say which. Run cue export -e build instead, which names it:

build.modules.app.kind: incomplete value "exe" | "static" | "shared":
    ./export.cue:10:14

field not allowed

$ cue export -e build
app.flags: field not allowed:
    ./project.cue:8:2

#Module is closed. Only kind, root, deps and profile exist. If you need something else, add it to build.zig directly.

conflicting values "X" and "Y"

An enumerated field got a value outside its disjunction. One error line per branch. The schema file:line at the end of each block tells you which disjunction it was.

dyld: Library not loaded: @rpath/libX.dylib

An executable that links a kind: "shared" module cannot find it at runtime. Zig's only rpath points into .zig-cache, relative to the current directory. Give the executable an rpath relative to itself:

if (m.kind == .exe) {
    step.root_module.addRPathSpecial(switch (target.result.os.tag) {
        .macos, .ios, .tvos, .watchos => "@loader_path/../lib",
        else => "$ORIGIN/../lib",
    });
}

examples/03-services/build.zig does this. The repo root's build.zig does not, because it has no executable that links a shared library.

Changes to project.cue seem to have no effect

build_spec.zig is generated on demand. Nothing watches for you. Run ./gen_build_spec.sh after every edit to project.cue, export.cue or schema.cue.

A Zig version other than 0.14.1 or 0.15.2

build.zig uses b.createModule with .root_module, and addLibrary with an explicit linkage. Older releases spell both differently, so expect configuration errors below 0.14. setup.sh prints a note for anything outside 0.14.x and 0.15.x but does not stop you.

Only 0.14.1 and 0.15.2 are tested.