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
  • codegen or codegen rust. Writes target/codegen/azul.rs.
  • codegen c. Writes target/codegen/azul.h.
  • codegen cpp. Writes target/codegen/azul11.hpp.
  • codegen python. Writes target/codegen/python_api.rs.
  • codegen all. Every output above, plus internal C-ABI files, all six azulNN.hpp headers, 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. code carries one path per supported language. Files live under examples/.
  • 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. Expects libazul.{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:

  1. Each path in the comma-separated AZ_DLL_PATH environment variable.
  2. target/release/, then target/debug/ of the workspace root.
  3. 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

Back to guide index