Development and command reference¶
Use the repository Makefile for repeatable development. make help lists common
commands; make help-all exposes specialized parity, fixture, and coverage lanes.
1. Environment¶
1.1 Host evidence¶
| Host or target | What CI proves |
|---|---|
| Ubuntu 24.04 x86-64 | Rust, smoke parity, native C, packaging, and supply chain |
| macOS 14 Apple Silicon | full exact parity, external C scorecard, and instrumented coverage using the canonical oracle host |
| macOS 15 Apple Silicon | fresh checkout, native C, layout, exports, and install tree |
| Windows Server 2025 x86-64 MSVC | native C, LLP64 layout, DLL/import library, exports, and install tree |
| Linux i686 | cross-built and QEMU-executed C consumer/layout contract |
| Linux powerpc64 | cross-built and QEMU-executed big-endian C consumer/layout contract |
wasm32-unknown-unknown on Node 22.14.0 |
raw WASM consumer plus packed and installed fontdone npm consumer |
Only Ubuntu and macOS are normal pinned-oracle development hosts. Windows and
the cross targets are claimed only to the extent recorded above.
The full source coverage job uses the same macOS host family as exact parity.
FreeType's ftcsbits.c allocates SBit nodes with FT_QNEW and initializes only
width, height, and buffer for unavailable glyphs. Linux allocation contents
produced 77 comparisons of unspecified fields in alpha.7's coverage run. Those
values are not a portable C contract; the alpha evidence is limited to the
canonical host and does not establish cross-host equality for those fields.
The alpha.9 external C audit independently reproduced three such SBit
comparisons on Ubuntu: uninitialized format, max_grays, and advance fields
differed while the documented unavailable-bitmap sentinel matched. The
aggregate scorecard therefore uses this same canonical host and still requires
fresh evidence from all five native/QEMU jobs. Cross-host equality for those
unspecified fields remains unproven.
CI validates the browser entry point through Node's standards-compatible ESM,
fetch, and WebAssembly APIs; it does not claim a named-browser version matrix.
Release evidence should add a real-browser run of the maintained HTML example
when browser behavior or asset loading changes.
1.2 Required tools¶
| Tool | Version | Used for |
|---|---|---|
| Rust | public crate MSRV 1.87; private C/WASM facade floor 1.90; repository toolchain 1.96.1 | runtime and packages |
| Rust nightly | 2026-07-16 in CI | LLVM branch and region coverage |
| cargo-llvm-cov | 0.8.7 | combined coverage report |
| cargo-deny / cargo-audit | 0.20.2 / 0.22.2 | supply-chain policy |
| GNU Make | 3.81 or newer | maintained command interface |
| Python | 3.9 or newer | audits, fixtures, consumers, releases |
| CMake | 3.20 or newer | offline FreeType oracle |
| Clang/GCC/MSVC | C11-capable | oracle and C consumers |
| Git, curl, tar, XZ | maintained OS versions | source and archive handling |
| Node.js and npm | Node 22.14.0 / npm 11.5.1 | raw Wasm, browser-wrapper, and npm archive verification |
Install the pinned supply-chain tools with make setup-tools and the coverage
frontend with make setup-coverage-tools. Font generators use one pinned
Python environment:
make setup-font-tools
2. Build boundary and generated state¶
Runtime packages are pure Rust. They do not build, link, or dynamically load
FreeType C. make setup downloads checksum-pinned FreeType 2.14.3 into ignored
freetype/, builds the offline oracle, and refreshes generated public
constants.
| Command | Purpose | Persistent output |
|---|---|---|
make build |
Build the root runtime | target/ |
cargo build --workspace --locked |
Build the one public crate and two internal facade targets | target/ |
make setup |
Fetch/build the pinned oracle and constants | ignored freetype/, target/; generated constants |
make generate-contracts |
Regenerate support, C header, WASM, and legal derivatives | tracked generated files |
make check-generated |
Reject generated drift | no intended writes |
make npm-package-verify |
Build, inspect, install, and execute the JavaScript npm tarball | target/npm-package/, release evidence |
make fresh-checkout-check |
Exercise non-parity checkout contracts | target/ |
The first oracle fetch and uncached Cargo dependency resolution need network
access. The compact Font API performs no file, network, environment, or
process I/O: callers supply font bytes. The FreeType-shaped safe facade and its
native wrapper deliberately implement path-based FT_New_Face/FT_Attach_File
and read FREETYPE_PROPERTIES for the corresponding compatibility routes.
Runtime packages perform no network access or subprocess execution.
Validation¶
| Purpose | Command | Meaning |
|---|---|---|
| Fast tests | make test-fast |
Rust tests, build checks, release/native tooling |
| Full runtime parity | make test-parity |
All runnable inputs; pending cases remain named |
| Native FFI guard | make test-ffi |
No runtime C FreeType shortcut |
| C scorecard | make c-abi-contract |
Measures all categories and reports unfinished scope |
| Complete C contract | make c-abi-contract-complete |
Requires full contract and all platform evidence |
| Format / lint | make fmt / make clippy |
Rust source quality |
| Rust documentation | make doc / make doc-test |
Strict rustdoc and executable examples |
| Per-commit CI | make ci-fast |
Required fast validation |
| Thorough review | make ci-thorough |
Adds full parity, coverage, benchmarks, packages and supply-chain checks |
| Public site | make docs-setup, make docs-build |
Install locked tools, then build checked HTML |
| Documentation | make check-docs |
Source, contracts, links, names, and evidence consistency |
Run the narrow case first, then the relevant full gate. Ordinary C-contract measurement may succeed with unfinished categories; only its complete target asserts replacement readiness. See maturity.
Diagnose a parity difference¶
Reduce to one font, glyph, size, entry point, and operation sequence. Compare C and Rust at the same pipeline stage. Check input normalization, size scaling, load flags, metrics, outline geometry, then raster bytes. Preserve error codes and observable output mutations as well as successful output.
Inspect the pinned C source as a read-only oracle. Fix the first Rust divergence;
never special-case a fixture, narrow the matrix, or edit expected values. Put
subtle reference behavior in a comment beside the implementation so the reason
survives future refactors. Permanent tracing must be guarded log::trace!.
Source coverage¶
make test-coverage-all measures the combined Rust, C-ABI, and host-compiled WASM
lanes with source/configuration-bound build state. It merges distinct raw
profiles and preserves all production-source totals. Preparation and instrumented
build caches have separate identities. A changed source or configuration must
invalidate the relevant cache. make coverage-clean removes these states.
Use legitimate public inputs to reach missing regions, including malformed files where the pinned oracle defines behavior. Fabricated pointers, invalid handles, undefined C behavior, and uncontrollable allocator failures cannot prove parity. Do not remove defensive code simply to reduce a coverage denominator.
Collect a fresh report after the source change and retain its raw profiles and identity. A selected-case hit count is not complete coverage. The complete goal still requires 100% lines, branches, functions, and regions; alpha release policy reports the actual incomplete totals. Evidence identifies retained historical measurements without rebinding them to current source.
Fixtures and provenance¶
The canonical input tree currently contains 1,336 tracked paths and no symlinks.
The Makefile exposes 26 named font-generation targets plus the deterministic
compressed-payload target, collected by make font-fixtures.
Inputs live in tests/fixtures/input/; maintained contracts live in tests/data/.
Generated matrices and raw oracle output are ignored and regeneratable. Preserve
licensed input bytes, transformations, hashes, and font provenance.
Follow the generator policy.
Run the affected generator target and make check-font-fixtures after changing
a generator or input. A new case needs a defined public oracle path and exact
comparison; signature-only or fabricated output checks do not count.
Repository retention¶
Keep source, public contracts, deterministic generators, legal/provenance files, and public guides. Superseded session logs and implementation plans are retained in Git history. The public roadmap keeps open goals visible.
make repository-inventory regenerates the complete path, size, hash, and reason
ledger. make check-generated rejects drift. The generated summary below tracks
files, not implementation coverage:
| Reason | Paths | Retained context |
|---|---|---|
| R01 | 58 | published pure-Rust runtime |
| R02 | 110 | package, build, release, and facade contracts |
| R03 | 1,761 | executable parity tests and public contracts |
| R04 | 1,336 | licensed canonical fixture inputs |
| R05 | 1 | required repository tooling alias |
| R06 | 83 | maintained tooling, examples, and benchmarks |
| R07 | 11 | durable project documentation |
| R08 | 1 | active self-cleaning roadmap |
| R09 | 7 | CI, community, and security policy |
| R10 | 2 | generated source required for offline builds |
| R11 | 1 | generated exhaustive inventory |
| Total | 3,371 | all retained paths |
Read benchmark methodology and releasing for measurement and publication workflows.
Verify the Rust integration examples¶
2.6 Maintained examples¶
cargo run --example render_mask -- tests/fixtures/input/fonts/DejaVuSans.ttf
cargo run --example load_glyph -- tests/fixtures/input/fonts/DejaVuSans.ttf
cargo run --example handle_error
make test-rust-consumer
make doc-test
make test-rust-consumer creates a temporary downstream Cargo project, uses
fontdone through a path dependency, exercises an error, and renders a
maintained fixture.
Run the complete migration walkthrough with:
cargo run --example ffi_migration -- \
tests/fixtures/input/fonts/DejaVuSans.ttf
C SDK development and verification¶
Use the public C SDK guide for application integration. Build and inspect SDK artifacts from a complete checkout:
make test-c-consumer
make check-c-exports
make c-abi-install-check
make c-abi-contract
The shared library carries a relocatable ELF SONAME or Mach-O @rpath name.
The generated headers and support map must remain synchronized. The
c-abi-contract-complete target requires all five platform bundles and all
twelve contract categories; ordinary single-host reports retain their pending rows.
Static-link system dependencies depend on the Rust target. The SDK packaging
and consumer checks determine the correct libraries for each supported host.