export DEVELOPER_DIR=/Library/Developer/CommandLineToolsAdd that to ~/.zshrc (or ~/.bashrc). Every zig build, zig build run, zig build test, and any tool that wraps them (e.g. labelle) will start working again.
On macOS 26 (Tahoe) with Zig 0.15.2 (aarch64), a fresh zig init project fails to build with a wall of undefined-symbol errors when linking the build runner itself:
error: undefined symbol: __availability_version_check
error: undefined symbol: _abort
error: undefined symbol: _arc4random_buf
error: undefined symbol: _bzero
error: undefined symbol: _clock_gettime
error: undefined symbol: _dispatch_queue_create
error: undefined symbol: _exit
error: undefined symbol: _fork
error: undefined symbol: _free
error: undefined symbol: _getcwd
error: undefined symbol: _getenv
error: undefined symbol: _isatty
error: undefined symbol: _malloc_size
error: undefined symbol: _posix_memalign
error: undefined symbol: _sigaction
error: undefined symbol: _waitpid
...
Zig auto-detects the macOS SDK via xcrun --show-sdk-path. On Tahoe, xcrun returns the full Xcode SDK:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.4.sdk
That SDK's usr/lib/libSystem.tbd declares its targets as:
targets: [ x86_64-macos, x86_64-maccatalyst, arm64e-macos, arm64e-maccatalyst ]
No arm64-macos — only arm64e-macos. Zig 0.15.2 links arm64-macos by default, so the linker loads libSystem, finds no symbols under its target, and dumps ~25 undefined-symbol errors. This affects the build.zig runner itself, so the failure happens before any project code compiles.
The Command Line Tools SDK at /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk (currently MacOSX26.2 via symlink) still ships arm64-macos in its libSystem targets and links cleanly. DEVELOPER_DIR is the env var that tells xcrun which developer installation to use; pointing it at the CLI tools makes Zig pick the working SDK.
Per-command:
DEVELOPER_DIR=/Library/Developer/CommandLineTools zig buildCurrent shell:
export DEVELOPER_DIR=/Library/Developer/CommandLineTools
zig buildPersistent (zsh):
echo 'export DEVELOPER_DIR=/Library/Developer/CommandLineTools' >> ~/.zshrcPersistent (bash):
echo 'export DEVELOPER_DIR=/Library/Developer/CommandLineTools' >> ~/.bashrcZIG_VERBOSE_LINK=1 zig build 2>&1 | grep syslibrootWorking (note the CLI tools path):
zig ld ... -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk ...
Broken (Xcode path):
zig ld ... -syslibroot /Applications/Xcode.app/.../MacOSX26.4.sdk ...
SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX15.4.sdk zig build— Zig ignoresSDKROOT; it goes throughxcrun.-Dtarget=aarch64-macos— changes the output target, not the SDK used to build the build runner itself.- Replacing Zig's bundled
lib/libc/darwin/libSystem.tbdwith a symlink to the SDK's file — Zig's self-hosted Mach-O linker uses-syslibrootfromxcrun, not the bundled stub. xcode-select --switch /Library/Developer/CommandLineTools— works in principle but is more invasive thanDEVELOPER_DIR(changes everything on the machine, not just your shell), and you'll forget you did it.
Nuke the Zig cache once to clear any stale pre-linked artifacts:
rm -rf ~/.cache/zigWhen you upgrade Zig past 0.15.2 to a version that detects Tahoe's SDK layout and prefers the CLI tools SDK automatically. Check zig version. If you're on a version newer than 0.15.2 and this workaround is no longer documented as needed in the Zig release notes, remove the export.
Tracking:
- ziglang/zig#25928 — Support TBD v5 in Mach-O linker (related upstream work)
- ziglang/zig#15963 — the macOS 14 Sonoma tracking issue, which has the same pattern of workarounds
Anything that spawns zig build as a child process, as long as it doesn't clear the environment:
- Raw
zig build/zig build run/zig build test - Build-tool wrappers like
labelle(verified: source usesstd.process.Child.runwithout touchingenv_map, so env vars inherit) - IDE integrations that inherit your shell environment
Will not work for GUI-launched apps that don't inherit shell env vars (e.g. VS Code opened from Finder instead of the terminal). For those, use launchctl setenv DEVELOPER_DIR /Library/Developer/CommandLineTools in a login hook, or just launch the IDE from the terminal.