Building Zynx
Build targets, LLVM modes, test tiers, SDK knobs, and cleanup commands.
Zynx uses CMake and Ninja for the real build graph. The public developer
interface is still make, so normal work starts with:
make
make test
The default build configures build/cmake, builds ./zynx, builds the runtime
archive, and bootstraps the standard library archive plus .zxm module headers
with the freshly built compiler.
Install CMake 3.20 or newer, Ninja, Python 3, a C23-capable Clang toolchain, LLVM development packages with CMake package files, and libclang development headers for bindgen support.
On Debian or Ubuntu, matching packages such as llvm-18-dev, clang-18,
libclang-18-dev, and lld-18 usually provide the expected layout.
make # Configure and build using system LLVM/shared libclang.
make configure # Regenerate CMake/Ninja build files.
make test # Run core and tooling tests.
make install # Install under PREFIX, default /usr/local.
make uninstall # Remove installed Zynx files and SDKs from PREFIX.
make libs # Build compiler, runtime, and standard library archives.
make lint # Run clang-tidy through compile_commands.json.
make static # Build with bundled LLVM and static LLVM/Clang/libclang.
make deps-llvm # Download/build/install the bundled LLVM dependency.
make sdk # Build default SDK targets.
make clean # Remove Zynx build outputs, preserving expensive deps.
make distclean # Remove Zynx outputs plus build/deps and build/sdk.
Install locations can be changed with PREFIX:
make install PREFIX=/tmp/zynx-install
The default test suite is hermetic by policy. Tests that require host
facilities declare a .requires file with capability names such as loopback,
filesystem-write, dynamic-linking, subprocess, or network-external.
Run the default compiler and tooling tiers with:
python3 tests/run.py
python3 tests/tooling/run.py
python3 tests/tooling/test_docs_examples.py
Loopback socket tests are a separate required host-capability tier:
python3 tests/run.py --require-capability loopback --only-requiring-capability loopback
network-external is not part of the default tier. It must be explicitly
allowed when a platform-specific run really needs it.
| Option | Default | Meaning |
|---|---|---|
BUILDTYPE | debug | debug maps to CMake Debug; release maps to MinSizeRel. |
PREFIX | /usr/local | Install prefix used by make install and make uninstall. |
CC / CXX / AR | toolchain default | C compiler, C++ linker/compiler, and archive tool. |
LLVM_PROVIDER | system | Use installed LLVM or bundled LLVM under build/deps. |
LLVM_LINK | shared | Link shared or static LLVM/Clang/libclang. |
LLVM_VERSION | 22.1.5 | Bundled LLVM release; changing it needs a matching pinned hash. |
LLVM_TARGETS | Native | LLVM targets built for bundled LLVM. |
LLVM_CONFIG | llvm-config | Used to derive system LLVM package paths. |
ZYNX_USE_LLD | auto | Use lld on ELF executable links. |
ZYNX_LINK_ICF | safe | Identical code folding mode for static ELF links. |
ZYNX_LINK_MAP | OFF | Write a linker map for size inspection. |
EXTRA_CFLAGS | empty | Extra C compiler flags. |
EXTRA_LDFLAGS | empty | Extra executable linker flags. |
The normal default uses system LLVM and a shared build-time libclang link:
make LLVM_PROVIDER=system LLVM_LINK=shared
Bindgen links to the Clang C API at build time. There is no runtime
LIBCLANG_PATH discovery or dlopen path for bindgen.
Static compiler builds are explicit:
make static
That target forces bundled LLVM and static LLVM/Clang/libclang linkage into the
zynx executable. Platform libraries such as libc, libm, pthreads, or macOS
frameworks may still be dynamic.
Useful system LLVM overrides:
make LLVM_CONFIG=/opt/homebrew/opt/llvm/bin/llvm-config
make LLVM_DIR=/path/to/lib/cmake/llvm Clang_DIR=/path/to/lib/cmake/clang
make LIBCLANG_LIBRARY=/path/to/libclang.so
make CLANG_C_INCLUDE_DIR=/path/to/include
make deps-llvm builds the pinned bundled LLVM dependency into
build/deps/llvm/install. The bundled build uses LLVM 22.1.5 from the release
tarball with a pinned SHA-256 hash in the repository CMake files.
Useful bundled dependency knobs:
make deps-llvm LLVM_JOBS=8
make deps-llvm LLVM_BUILDTYPE=MinSizeRel
make deps-llvm LLVM_CCACHE=on
make deps-llvm LLVM_BUNDLED_PREFIX=/opt/zynx-llvm
LLVM_CCACHE=auto uses ccache when it is installed. LLVM_CCACHE=on requires
it.
The SDK is optional and is covered in detail on the Zynx SDK page. The build wrapper exposes these common selectors:
make sdk
make sdk TARGET=x86_64-linux-musl
make sdk SDK_TARGETS="x86_64-darwin-macho aarch64-darwin-macho"
make sdk-clean TARGET=x86_64-linux-musl
SDK source pins can be overridden for local experiments:
| Option | Default | Meaning |
|---|---|---|
SDK_MUSL_VERSION | 1.2.6 | musl source release for default Linux SDK targets. |
SDK_LINUX_KERNEL_VERSION | 6.12.9 | Linux UAPI headers release. |
SDK_ZLIB_VERSION | 1.3.2 | zlib source release for SDK sysroots. |
DARWIN_SDK_PROVIDER | auto | Darwin provider: auto, xcode, zig, or portable. |
DARWIN_MIN_VERSION | 11.0 | Minimum macOS deployment version for Darwin targets. |
SDK targets are static executable targets in the current SDK contract. Dynamic runtime-loadable modules remain host/system mode only.
The shared build stays small because LLVM and libclang come from system shared
libraries. Static mode is larger because libclang.a pulls in substantial
Clang and LLVM code.
On Linux, static mode uses size-oriented options when available:
make static ZYNX_USE_LLD=on
make static ZYNX_USE_LLD=on ZYNX_LINK_ICF=safe
make static ZYNX_LINK_MAP=ON
Check dynamic dependencies after a static build with:
otool -L ./zynx # macOS
ldd ./zynx # Linux
Static mode should not show dynamic libLLVM, libclang, or libclang-cpp
dependencies.
make clean removes Zynx build products but keeps expensive dependency and SDK
trees. Use make distclean when build/deps, build/sdk, and SDK driver
outputs should be removed too.
Generate or refresh the compilation database with:
make compile_commands.json
make refresh-compile-commands