Code Generation
Introduction
WIP. The per-language defaults are stable, but pin to a specific commit if you embed the generator in your own build.
api.json at the repository root is the single source of truth for the public surface of azul. Every binding (Rust, C, C++03–23, Python) is a deterministic transform of that file. The transform is exposed through the azul-doc binary's codegen subcommand.
Running the generator
cargo run --release -p azul-doc -- codegen all
codegenorcodegen rust. Writestarget/codegen/azul.rs.codegen c. Writestarget/codegen/azul.h.codegen cpp. Writestarget/codegen/azul11.hpp.codegen python. Writestarget/codegen/python_api.rs.codegen all. Every output above, plus internal C-ABI files, all sixazulNN.hppheaders, and brotli-compressed asset blobs.
codegen all is what dll/build.rs expects. Run it after editing api.json or after a fresh checkout, then build the DLL.
The generated files land under target/codegen/. Nothing in that directory is committed. The build script re-runs the generator if any required file is missing.
Anatomy of api.json
The file is a top-level map of version strings ("0.2.0", …) to version data. Within a version the relevant keys are:
apiversion— integer, bumped when the FFI ABI breaks.git— short SHA pinned to that release.installation.languages— per-language install commands shown in the docs.examples— list of{name, code, screenshot, description}entries.codecarries one path per supported language. Files live underexamples/.classes(one per module) — the type list. Each class declares its layout, derived traits, and method set.
Adding a type or method to api.json and re-running codegen all is the only step needed to expose it through every binding.
Build-time integration
The DLL crate's build script gates each generated file behind a Cargo feature. If a feature is enabled and the matching file is missing, the build aborts with:
Missing generated file: dll_api_internal.rs
Run: cargo run --release -p azul-doc -- codegen all
Editing api.json and re-running codegen all triggers a downstream rebuild without cargo clean.
Three link modes
Generated outputs pair with three Cargo feature combinations:
build-dll. The shared library itself (libazul.{so,dylib,dll}) with exported symbols.link-static. Static linking from a Rust binary. The full crate stack is compiled in.link-dynamic. Extern declarations only. Expectslibazul.{so,dylib,dll}at runtime.
The C, C++, and Python bindings are downstream of build-dll: they consume the produced shared library plus the matching header. The Rust binding can use any of the three modes.
Locating the library at link time
dll/build.rs searches for libazul.{so,dylib,dll} in this order when dynamic linking is active:
- Each path in the comma-separated
AZ_DLL_PATHenvironment variable. target/release/, thentarget/debug/of the workspace root.- System paths —
/opt/homebrew/lib,/usr/local/lib,/usr/lib(skipped on Windows).
If a local match is found, the dylib is copied next to the build artifacts so the binary loads it without DYLD_LIBRARY_PATH.
Determinism
A given (api.json + azul-doc + cargo lockfile) triple regenerates byte-identical headers and Rust bindings. Binary artifacts depend on the target triple and host toolchain; pin both in CI to keep release archives reproducible.
Coming Up Next
- Web Deployment — Building for the browser via WASM
- Headless Rendering — Running the pipeline without a window
- Debugging — Debug overlays, the inspector, and structured logging