open-standards/wai/wai-rs/build.rs
Transaction Science c525493213 wai: the native sink core and its C ABI (wai_sink_*)
native_sink (feature native_sink): what a native host's player integration runs for
one playback session. It verifies a media playlist against its playlist receipt and
the chain of its live revisions (http-delivery §8.6), holds a WAI object to the content
hash its name or fragment states and a fragment named by its SHA-256 to that name
(packaging §7.6), and answers per object whether the host may hand it to its decoder.
It signs what stream-audit has a player sign, under a fresh session key: settlement
acknowledgements by plain SHA-256, presentation claims for marked ads, the session
record, and the bundle. And it ends a session nobody can see, or whose viewer has gone
idle.

ffi_sink: the C ABI over it, an opaque wai_sink_t with JSON in and JSON or bytes out,
include/wai.h regenerated. The corpus live-conformance/native-sink/ is written from
fixed seeds over the reference package's floor fragments.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 22:14:40 -04:00

116 lines
4.8 KiB
Rust

//! Cross-platform linker paths for the C libraries we wrap.
//!
//! Most of our codec deps (`opus`, `jpegxl-rs`, `dav1d`, `zstd`, `xz2`,
//! `libavif-sys`) already have build.rs files that probe pkg-config
//! themselves. `flac-bound` does NOT — it just links `-lflac` and
//! expects the linker to find it. On Homebrew macOS that lives under
//! `/opt/homebrew/opt/flac/lib`, which Cargo doesn't probe. We use the
//! `pkg-config` crate to discover the right path on whatever system
//! the user is on (Linux distros, macOS Homebrew, BSD ports, etc.).
//!
//! This replaces the macOS-hardcoded `.cargo/config.toml` rustflags.
#[path = "src/build_info.rs"]
mod build_info;
fn main() {
generate_c_header();
record_build();
// Only the `codecs` feature compiles flac-bound — and pkg-config's
// probe() emits a `cargo:rustc-link-lib=flac` of its own, so running
// it unconditionally makes every consumer (e.g. the wasm32 world
// build, the wai-world-relay binary) link libFLAC it never calls.
if std::env::var_os("CARGO_FEATURE_CODECS").is_some() {
link_libflac();
}
}
/// Record the build for a measurement report (`extensions/energy-measurement.md`
/// §5, §8): the profile, from cargo's `OPT_LEVEL` (`src/build_info.rs`), the
/// target triple, and the compiler's version line.
/// A part that cannot be determined is left unset and reads as `null`.
fn record_build() {
println!("cargo:rerun-if-env-changed=OPT_LEVEL");
println!("cargo:rerun-if-env-changed=TARGET");
println!("cargo:rerun-if-env-changed=RUSTC");
let var = |k: &str| std::env::var(k).unwrap_or_default();
println!(
"cargo:rustc-env=WAI_BUILD_PROFILE={}",
build_info::profile_label(&var("OPT_LEVEL"))
);
let target = var("TARGET");
if !target.is_empty() {
println!("cargo:rustc-env=WAI_BUILD_TARGET={target}");
}
let rustc = std::env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
if let Ok(out) = std::process::Command::new(rustc).arg("-V").output() {
let line = String::from_utf8_lossy(&out.stdout).trim().to_owned();
if out.status.success() && !line.is_empty() && !line.contains('\n') {
println!("cargo:rustc-env=WAI_BUILD_TOOLCHAIN={line}");
}
}
}
/// Regenerate `include/wai.h` from the FFI surface so SDK consumers can
/// always grab a typed header that matches the shipped binary. Only
/// regenerates when source files actually change (cargo handles this
/// via `rerun-if-changed` declarations).
fn generate_c_header() {
println!("cargo:rerun-if-changed=src/ffi.rs");
println!("cargo:rerun-if-changed=src/ffi_codecs.rs");
println!("cargo:rerun-if-changed=src/ffi_neural.rs");
println!("cargo:rerun-if-changed=src/ffi_sink.rs");
println!("cargo:rerun-if-changed=src/container.rs");
println!("cargo:rerun-if-changed=cbindgen.toml");
let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let out_path = std::path::Path::new(&crate_dir).join("include/wai.h");
if let Err(e) = std::fs::create_dir_all(out_path.parent().unwrap()) {
println!("cargo:warning=cbindgen: could not create include/ dir: {e}");
return;
}
match cbindgen::Builder::new()
.with_crate(&crate_dir)
.with_config(cbindgen::Config::from_file(
std::path::Path::new(&crate_dir).join("cbindgen.toml")).unwrap_or_default())
.generate()
{
Ok(bindings) => {
bindings.write_to_file(&out_path);
}
Err(e) => {
println!("cargo:warning=cbindgen failed: {e}");
}
}
}
fn link_libflac() {
if let Ok(lib) = pkg_config::Config::new()
.atleast_version("1.3")
.probe("flac")
{
for path in &lib.link_paths {
println!("cargo:rustc-link-search=native={}", path.display());
}
// pkg-config also emits the library names; flac-bound links its
// own `-lflac` directive so we only need the search path.
} else {
// Fallback: try the canonical Homebrew location on macOS so the
// common case still works without pkg-config installed.
#[cfg(target_os = "macos")]
{
let candidates = [
"/opt/homebrew/opt/flac/lib", // arm64 macOS (Homebrew)
"/usr/local/opt/flac/lib", // x86_64 macOS (Homebrew)
];
for p in candidates {
if std::path::Path::new(p).exists() {
println!("cargo:rustc-link-search=native={p}");
return;
}
}
}
// Linux/other: hope that the system linker finds -lflac on its own.
// If not, the link error will be obvious ("cannot find -lflac")
// and the user needs to install libflac-dev / equivalent.
}
}