boxdd-sys - Low-level FFI for a pinned Box2D 3.2 snapshot
Builds the Box2D 3.2.0 development snapshot at commit
56edae79f2949d86142b03450d5d60f63bcf5a6f from third-party/box2d and exposes its C API as raw
FFI in boxdd_sys::ffi. It is not ABI-compatible with an arbitrary Box2D 3.2 checkout. High-level
wrappers live in the companion crate boxdd.
Build
- From source: builds vendored Box2D C via
cc. - System library (optional): opt into the attested
systemadapter with a caller-owned static archive, public header, pregenerated binding file, andmanifest.toml:BOXDD_SYS_PROVIDER=system BOX2D_LIB_DIR=/path/to/lib BOXDD_SYS_SYSTEM_MANIFEST=/path/to/manifest.toml. The manifest binds the exact archive/header/binding SHA-256, target, precision, CRT, SIMD, validation identity, adapter source digest, recording contract, and required adapter symbols. Dynamic/name-only linking and silentpkg-configdiscovery are rejected. - Bindings: uses pregenerated bindings by default to avoid requiring LLVM on CI.
BOXDD_SYS_LINK_KINDis accepted only asstatic(and is optional).- Force bindgen: enable the
bindgenfeature, setBOXDD_SYS_FORCE_BINDGEN=1, and ensurelibclangis available.
- Docs.rs/offline: uses pregenerated bindings and skips native C build.
Prebuilt Linking
Prebuilt archives use the same static manifest contract plus authenticated publisher provenance:
BOXDD_SYS_PROVIDER=prebuilt
BOXDD_SYS_PREBUILT_MANIFEST=/path/to/extracted/manifest.toml
BOXDD_SYS_PREBUILT_PROVENANCE=/path/to/artifact.tar.gz.provenance.toml
BOXDD_SYS_PREBUILT_BUNDLE=/path/to/artifact.tar.gz.provenance.sigstore.json
The adapter requires exact Cosign 3.0.6 (override its path with BOXDD_SYS_COSIGN) and verifies the
signature over the canonical TOML provenance statement. The statement binds the outer tar archive's
exact file name, byte size, and SHA-256; the strict complete member inventory and per-member
digests; the provider manifest and inner checksums digests; provider and ABI coordinates; and the
repository, workflow, workflow ref, source commit, release tag, run ID, and run attempt.
Repository qualification verifies the signed statement and exact outer archive before extracting
anything. boxdd-sys never downloads, extracts, or caches a package: it consumes an already-local
extracted directory, re-verifies the statement, manifest, and complete member inventory, and links
the exact verified static archive bytes. It never discovers a library by name. Missing or
inconsistent provenance fails closed. PROVIDER_PROVENANCE_SHA256 reports the SHA-256 of the
verified signed statement, not the Sigstore bundle. A caller who explicitly trusts a local package
can run xtask's native-package trust-local-system command and select the system adapter; that
manifest deliberately carries no authenticated provenance claim.
The Sigstore trust anchor is shipped in the crate and pinned by SHA-256. The optional
BOXDD_SYS_PREBUILT_TRUSTED_ROOT override is accepted only when its contents have the exact same
digest as the crate-owned anchor, so callers cannot replace the publisher trust policy.
Generate a caller-trusted artifact cohort from a compatible local archive and binding file with:
cargo run -p xtask -- native-package attest-local-system \
/boxdd-sys-out/boxdd-build-identity.toml \
/provider-root/lib/libbox2d.a \
/provider-root/include/box2d/box2d.h \
/provider-root/bindings/bindings_pregenerated.rs \
/provider-root/manifest.toml
The third argument is an output path: the command materializes the repository's reviewed effective
box2d.h there instead of trusting a header recovered from Cargo's private build directories. The
build identity must be the explicit schema-v3 marker emitted by boxdd-sys/build.rs, and its
adjacent adapter identity must match. Native markers bind the full static-archive SHA-256, so the
attestation command rejects a different archive even when its embedded ABI identity is compatible.
The archive and bindings must be regular files below the output manifest's directory. The command
creates the header and manifest without overwriting existing files. It proves exact compatibility
with this crate; it does not authenticate who produced the archive. trust-local-system performs
the same explicit trust conversion for an already verified prebuilt package manifest.
Release packaging is repository tooling, not part of the published FFI crate. It requires explicit
--sys-out, --build-identity, --output, --source-commit, and --release-tag arguments to
cargo run -p xtask -- native-package build. Package names include target, precision, static link
kind, and applicable CRT identity. Package headers come from the reviewed materialized effective
source, including public-header transformations, rather than from the unmodified submodule tree.
WASM (experimental)
- Targets
wasm32-unknown-unknown: compile-only by default; repositoryxtaskruntime and Pages entry points can build the controlled provider route that imports Box2D symbols from a browser/Emscripten provider module.wasm32-wasip1: compile-only qualification only; no WASI runtime is claimed.
- Modes
BOXDD_SYS_PROVIDER=wasm-compile-only: generate/check bindings and skip native C linkage.wasm-provider: import symbols from the precision-specificbox2d-sys-v2-singleorbox2d-sys-v2-doublemodule onwasm32-unknown-unknownonly;wasm32-wasip1and Emscripten-target Rust builds are rejected. This is a controlled final-binary route: setting onlyBOXDD_SYS_PROVIDER=wasm-provideris deliberately rejected because dependency build scripts cannot configure an arbitrary downstream final link. Use the repositoryxtaskprovider, runtime, Pages, or package-consumer entry points, which inject the versioned opt-in and complete linker arguments together and validate the final Wasm. Official provider bytes are built with the pinned Emscripten 6.0.4 SDK, but consuming them does not require that SDK.
- Notes
- There is no WASM prebuilt adapter consumed while building
boxdd-sys. Official precision-specific JavaScript/WASM runtime packages are built, authenticated, extracted, and qualified by repository-levelxtaskcommands and CI. - Emscripten builds the standalone C provider only. Rust applications target
wasm32-unknown-unknown;wasm32-unknown-emscriptenRust builds are not supported. - Provider ABI v2 uses fixed, non-overlapping memory partitions. Emscripten static data, stack,
and
emmallocstay below 64 MiB; Rust data, stack, andSystemallocation start at 64 MiB. The provider cannot grow memory or cross the partition boundary. Production allocation-driven growth belongs to Rust, up to the shared 512 MiB maximum. Final-Wasm validation checks both layouts, exact memory limits, data segments, provider growth instructions, and the Rust heap end. wasm-providerconsumes the precision-specific checked-in contract underabi/; building this crate never discovers, downloads, extracts, caches, or executes Emscripten. Repository source-provider builds, runtime smoke tests, and Pages builds use an activated Emscripten 6.0.4 toolchain; signed-package qualification consumes existing JavaScript/WASM bytes and does not use Emscripten.- Maintainers validate both checked contracts with
cargo run -p xtask -- wasm-provider-contract --checkand refresh both with--write; each output is installed atomically, while Git remains the recovery mechanism if a run stops between files. Ordinary consumers do neither. - Node and Chromium provider smoke tests verify the runtime adapter identity and all required adapter symbols in both precision modes. GitHub Pages currently qualifies single precision only and rejects
BOXDD_WASM_PRECISION=double. - The high-level
boxddcrate removes Rust callback-table entry points onwasm32. The current provider does not qualify cross-module function pointers for world callbacks, callback-backed queries/tree traversal, raw task callbacks, replay mixers, or debug draw. - Bindgen requires libclang.
- There is no WASM prebuilt adapter consumed while building
Reproducible WASM bindings
Ordinary wasm-compile-only builds use the checked-in target- and precision-specific bindings and
do not require a WASI sysroot. Forced bindgen, or a missing checked-in binding, uses Cargo's exact
TARGET; BOXDD_SYS_BINDGEN_TARGET is only an equality assertion and cannot retarget generation.
wasm32-unknown-unknown generation uses only the repository-owned
src/bindgen_headers/wasm32_unknown_unknown/math.h. Its directory must contain exactly that one
regular, non-symlink file, whose SHA-256 is
70e00e274e189af73ed321f6490ec3a0b0c58f00286e87fe7d257bb211bb367d.
wasm32-wasip1 generation instead requires BOXDD_SYS_WASI_SYSROOT to name a canonical wasi-libc
32 sysroot containing include/wasm32-wasip1/math.h. The complete header tree below that directory
is pinned to SHA-256
0e80041ea13b42db5bcd5dc92d737da7c26e4e5a60b902413a41e09924f37687.
Maintainers refreshing checked-in bindings must provide that exact sysroot:
BOXDD_SYS_WASI_SYSROOT=/path/to/wasi-libc-32/sysroot \
cargo run -p xtask -- upstream-sync --write
Features
simd-avx2: enable AVX2 on x86_64.disable-simd: disable all SIMD; overridessimd-avx2.validate: enable internal validation checks.
Notes
- Requires a C toolchain. Bindgen requires
libclangonly when forced (BOXDD_SYS_FORCE_BINDGEN=1). - Windows (MSVC) and Unix toolchains supported.
adapter::validate_snapshotverifies the linked adapter identity before invoking the native validator. ItsSnapshotValidationErrordistinguishes provider identity failures from nativeSNAPSHOT_*content-status failures.
Acknowledgments
- Thanks to the Rust Box2D bindings project for prior art and inspiration: https://github.com/Bastacyclop/rust_box2d
- Huge thanks to the upstream Box2D project by Erin Catto: https://github.com/erincatto/box2d
License
- MIT OR Apache-2.0. The pinned upstream Box2D snapshot is MIT-licensed.