use std::{ env, path::{Path, PathBuf}, }; fn find_package(name: &str) -> Vec { let vcpkg_root = std::env::var("VCPKG_ROOT").unwrap(); let mut path: PathBuf = vcpkg_root.into(); let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); let mut target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); if target_arch == "x86_64" { target_arch = "x64".to_owned(); } else if target_arch == "aarch64" { target_arch = "arm64".to_owned(); } else { target_arch = "arm".to_owned(); } let target = if target_os == "macos" { "x64-osx".to_owned() } else if target_os == "windows" { "x64-windows-static".to_owned() } else if target_os == "android" { format!("{}-android-static", target_arch) } else { "x64-linux".to_owned() }; println!("cargo:info={}", target); path.push("installed"); path.push(target); println!( "{}", format!("cargo:rustc-link-lib={}", name.trim_start_matches("lib")) ); println!( "{}", format!( "cargo:rustc-link-search={}", path.join("lib").to_str().unwrap() ) ); let include = path.join("include"); println!("{}", format!("cargo:include={}", include.to_str().unwrap())); vec![include] } fn generate_bindings(ffi_header: &Path, include_paths: &[PathBuf], ffi_rs: &Path) { #[derive(Debug)] struct ParseCallbacks; impl bindgen::callbacks::ParseCallbacks for ParseCallbacks { fn int_macro(&self, name: &str, _value: i64) -> Option { if name.starts_with("OPUS") { Some(bindgen::callbacks::IntKind::Int) } else { None } } } let mut b = bindgen::Builder::default() .header(ffi_header.to_str().unwrap()) .parse_callbacks(Box::new(ParseCallbacks)) .generate_comments(false); for dir in include_paths { b = b.clang_arg(format!("-I{}", dir.display())); } b.generate().unwrap().write_to_file(ffi_rs).unwrap(); } fn gen_opus() { let includes = find_package("opus"); let src_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); let src_dir = Path::new(&src_dir); let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); let ffi_header = src_dir.join("opus_ffi.h"); println!("rerun-if-changed={}", ffi_header.display()); for dir in &includes { println!("rerun-if-changed={}", dir.display()); } let ffi_rs = out_dir.join("opus_ffi.rs"); generate_bindings(&ffi_header, &includes, &ffi_rs); } fn main() { gen_opus() }