//! Link the vendored static libopus (UCRT MinGW ABI) + generate FFI bindings //! from the vendored opus headers via bindgen (libclang). Same vendoring //! approach as netdesk-vpx: a UCRT-ABI libopus.a so there is no vcpkg/MSYS2 or //! runtime DLL dependency, and no fragile build-from-source (audiopus_sys's //! build script mangles extended-length paths on this toolchain). use std::path::PathBuf; fn main() { let manifest = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); let tp = manifest.join("..").join("third_party").join("ucrt64"); let lib = tp.join("lib"); let inc = tp.join("include"); println!("cargo:rustc-link-search=native={}", lib.display()); println!("cargo:rustc-link-lib=static=opus"); println!("cargo:rerun-if-changed=wrapper.h"); println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed={}", lib.join("libopus.a").display()); if std::env::var("LIBCLANG_PATH").is_err() { for p in ["C:/Program Files/LLVM/bin", "C:/Program Files (x86)/LLVM/bin"] { if PathBuf::from(p).join("libclang.dll").exists() { std::env::set_var("LIBCLANG_PATH", p); break; } } } // OpusEncoder / OpusDecoder are opaque (used only through pointers), so // bindgen's default opaque representation is exactly right here — unlike // libvpx's config structs, we never set their fields. let regex = "^(opus|Opus|OPUS).*"; let bindings = bindgen::Builder::default() .header("wrapper.h") .clang_arg(format!("-I{}", inc.display())) .allowlist_type(regex) .allowlist_var(regex) .allowlist_function(regex) .rustified_enum(regex) .trust_clang_mangling(false) .layout_tests(false) .generate_comments(false) .generate() .expect("bindgen libopus"); bindings .write_to_file(PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("opus_ffi.rs")) .expect("write opus_ffi.rs"); }