Build & test
Everything runs through just; just --list shows the recipes.
just # build + check, the defaultjust build # build the crates and regenerate the C headersjust test # every suite: Rust, C++, Pythonjust check # every linter CI runsjust format # format everything| For | Tool |
|---|---|
| The crates and the C headers | Rust (stable, plus nightly for fmt), cbindgen |
| The C++ suite | a C++17 compiler; optionally mingw-w64 for the Windows cross-build |
| The Python suite | uv (the recipe creates the venv itself) |
| The documentation site | Node and pnpm; doxygen and nightly Rust for the reference; a Playwright browser for diagrams (pnpm --dir docs exec playwright install chromium) |
The Windows cross-build is skipped with a message if x86_64-w64-mingw32-g++ is absent.
The generated C artifacts
Section titled “The generated C artifacts”c/fznso_types.h and c/fznso_solver_template.c are generated by cbindgen from rust/fznso-types and rust/fznso-solver-template.
To change what a C consumer sees, change the Rust doc comment or type it comes from, then run just build.
just check-headers confirms the result still compiles as both C and C++.
The prose in each generated file’s preamble comes from the header = """…""" strings in cbindgen_types.toml and cbindgen_template.toml.
Testing against a real solver
Section titled “Testing against a real solver”The suites drive a throwaway example solver by default. Point the C++ consumer at your own library to check it against the full interface:
just test-cpp./target/test_consumer /path/to/libmysolver.soRun the Rust suite under miri before changing anything that touches handles, casts or lifetimes:
just miriThis is not optional diligence.
The interface passes handles as raw pointers that each side casts back to its own type, and every bug in that class has passed the ordinary test suite first.
rust/fznso/tests/abi.rs drives the generated entry points directly so miri covers them; miri cannot dlopen, so tests/dylib.rs skips itself.
The documentation site
Section titled “The documentation site”just docs # build the site, including the generated referencejust docs-serve # live reload while writingTwo parts of the site are generated and must not be edited in place:
docs/src/content/docs/registry/comes fromdocs/registry/*.toml— edit the TOML.docs/src/content/docs/reference/comes from the code, via rustdoc JSON, Doxygen XML and griffe — edit the doc comment.
Both run from pnpm gen, which dev and build invoke for you; the dumps they read come from just docs-api.
Doxygen and the Python toolchain are optional: a missing one skips its pages with a warning.
Diagrams are Mermaid in a ```mermaid block, rendered to inline SVG at build time, so a page ships no JavaScript to draw one and the labels stay searchable text.
That needs a browser once: pnpm --dir docs exec playwright install chromium.
Writing documentation
Section titled “Writing documentation”One rule:
Every fact has one home. Everywhere else links to it.
| Kind of fact | Lives in |
|---|---|
| A rule of the protocol | a page under docs/src/content/docs/spec/ |
| The contract of one function, type or field | its doc comment — the reference is generated from it, never hand-written |
| A common name | docs/registry/*.toml |
| Example code | a real file under rust/fznso/examples/, cpp/tests/ or python/tests/, imported with ?raw |
Pasting a paragraph into a second file is the signal to put it in the spec and link instead.
CI enforces the links: cargo doc runs with -D warnings, and docs/scripts/check-links.mjs walks the built site checking every internal link and anchor.