// This file is auto-generated by alef. DO NOT EDIT.
/// Uppercase the alphanumerics and turn every other character into `_` -- the exact transform
/// alef applies when it fills cbindgen's `[defines]` table, so this lands on the same macro
/// name the header's `#if defined(...)` guards test.
fn feature_macro_suffix(feature: &str) -> String {
let mut name = feature.replace(|c: char| !c.is_ascii_alphanumeric(), "_");
name.make_ascii_uppercase();
name
}
fn main() {
let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
cbindgen::generate(crate_dir)
.expect("Unable to generate C bindings")
.write_to_file("include/{{ header_name }}");
{{ capsule_header_fixup }}
// Stamp the Cargo features THIS build enabled into the header, so it describes the cdylib
// sitting beside it.
//
// cbindgen wraps every `#[cfg(feature = "x")]` export in
// `#if defined({{ prefix_upper }}_FEATURE_X)` (its `[defines]` table), and it does so from
// the unparameterised source, so the guards are present no matter how the crate was built.
// Nothing ever defined those macros: every consumer that runs the C preprocessor over this
// header -- cgo, the C snippet and e2e harnesses, Zig, hand-written C -- saw every gated
// declaration deleted and failed on symbols this library really does export.
//
// The feature set is read from Cargo's own `CARGO_FEATURE_*`, not from a list baked in at
// generation time, so there is no second derivation that can drift from the artifact. A
// slim build simply emits fewer defines and its guards correctly stay false, which is what
// keeps the guards load-bearing instead of decorative.
//
// The sanitiser mirrors alef's `cbindgen_feature_defines`: alphanumerics uppercased, every
// other character to `_`. Cargo's own `-` to `_` mapping is a subset of that, so composing
// the two lands on exactly the macro cbindgen guards with, including for feature names
// carrying `.` or `+`, which Cargo leaves untouched in the variable name.
{
let header_path = "include/{{ header_name }}";
let mut header = std::fs::read_to_string(header_path).expect("read generated header");
let marker = "/* Cargo features enabled in this build. */";
if !header.contains(marker) && header.contains("{{ prefix_upper }}_FEATURE_") {
// `vars_os`, not `vars`: the latter panics if *any* variable in the environment is
// not valid Unicode, which would fail the consumer's build over something that has
// nothing to do with this crate.
let mut defines: Vec<String> = std::env::vars_os()
.filter_map(|(key, _)| {
let feature = key.to_str()?.strip_prefix("CARGO_FEATURE_")?;
let name = feature_macro_suffix(feature);
Some(format!("#define {{ prefix_upper }}_FEATURE_{name} 1"))
})
.collect();
defines.sort();
defines.dedup();
let block = format!("\n{marker}\n{}\n", defines.join("\n"));
// Anchor on the include guard cbindgen opens the file with, so the defines land
// ahead of every `#if` that tests them. Prepending is the fallback: still valid C,
// still ahead of every guard, if cbindgen ever stops emitting the guard.
let anchor = "#define {{ prefix_upper }}_H\n";
match header.find(anchor) {
Some(at) => header.insert_str(at + anchor.len(), &block),
None => header.insert_str(0, &block),
}
std::fs::write(header_path, header).expect("write header feature defines");
}
}
// Set @rpath-relative install_name on macOS so the cdylib can be relocated
// (bundled into language packages like packages/go/.lib/<rid>/, packages/
// java/src/main/resources/natives/<rid>/, etc.) and located via the consumer
// binary's rpath at runtime. Without this, the install_name embeds the CI
// runner build path (`/Users/runner/work/.../target/.../deps/lib<name>.dylib`)
// and dyld fails to load the bundled copy from its actual location.
//
// Also add `@loader_path` as an LC_RPATH so transitively-linked dylibs
// (e.g. `@rpath/libonnxruntime.<ver>.dylib` referenced by ort-bundled) can
// be resolved against the same directory the consumer ships the FFI
// cdylib in. NuGet/Maven/wheels all co-locate the bundled native deps
// alongside the cdylib, so `@loader_path` is the universally correct rpath.
// Without LC_RPATH entries, dyld reports `no LC_RPATH's found` and the
// load fails even though the sibling dylib is present.
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") {
println!("cargo:rustc-link-arg-cdylib=-Wl,-install_name,@rpath/{{ lib_name }}.dylib");
println!("cargo:rustc-link-arg-cdylib=-Wl,-rpath,@loader_path");
}
{{ go_copy_step }}}