use bindgen::callbacks::ParseCallbacks; use bindgen::{Builder, EnumVariation}; use cfg_aliases::cfg_aliases; use cmake::Config; use std::env; use std::fs::read_dir; use std::path::PathBuf; fn main() { cfg_aliases! { apple: { any(target_os = "macos", target_os = "ios", target_os = "dragonfly") }, } let cur_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); { let log_dir = cur_dir.join("log"); let mut build = Config::new(log_dir.as_path()); let lib_out = build.build(); println!( "cargo:rustc-link-search=native={}", lib_out.join("lib").display() ); println!("cargo:rustc-link-lib=static=memonitor-log"); let vk_bindings = Builder::default() .header(log_dir.join("include").join("log.h").to_string_lossy()) .allowlist_function("log_.*") .allowlist_type("log_.*") .parse_callbacks(Box::new(PrefixRemover::new("log_"))) .default_enum_style(EnumVariation::Rust { non_exhaustive: false, }) .use_core() .generate() .expect("Failed to generate Log bindings"); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); vk_bindings .write_to_file(out_path.join("log_bindings.rs")) .expect("Couldn't write bindings"); } #[cfg(feature = "vulkan")] { let vk_dir = cur_dir.join("vulkan"); let submodules_dir = vk_dir.join("thirdparty"); read_dir(submodules_dir.join("Vulkan-Headers")) .expect("Could not find Vulkan Headers. Did you forget to initialize submodules?"); read_dir(submodules_dir.join("volk")) .expect("Could not find Volk. Did you forget to initialize submodules?"); let mut build = Config::new(vk_dir.as_path()); #[cfg(debug_assertions)] { build.define("MEMONITOR_VALIDATE", "ON"); } // cmake-rs overrides the standard configured inside CMakeLists for some reason let lib_out = build.build(); println!( "cargo:rustc-link-search=native={}", lib_out.join("lib").display() ); println!("cargo:rustc-link-lib=static=volk"); println!("cargo:rustc-link-lib=static=memonitor-vk"); let vk_bindings = Builder::default() .header(vk_dir.join("include").join("memonitor.h").to_string_lossy()) .allowlist_function("vk_.*") .allowlist_type("vk_.*") .parse_callbacks(Box::new(PrefixRemover::new("vk_"))) .default_enum_style(EnumVariation::Rust { non_exhaustive: true, }) .use_core() .generate() .expect("Failed to generate Vulkan bindings"); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); vk_bindings .write_to_file(out_path.join("vk_bindings.rs")) .expect("Couldn't write bindings"); } #[cfg(all(feature = "cuda", not(apple)))] { let cuda_dir = cur_dir.join("cuda"); let mut build = Config::new(cuda_dir.as_path()); let lib_out = build.build(); println!( "cargo:rustc-link-search=native={}", lib_out.join("lib").display() ); println!("cargo:rustc-link-lib=static=memonitor-cuda"); let cuda_bindings = Builder::default() .header( cuda_dir .join("include") .join("memonitor.h") .to_string_lossy(), ) .allowlist_function("cu_.*") .allowlist_type("cu_.*") .parse_callbacks(Box::new(PrefixRemover::new("cu_"))) .default_enum_style(EnumVariation::Rust { non_exhaustive: true, }) .use_core() .generate() .expect("Failed to generate Cuda bindings"); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); cuda_bindings .write_to_file(out_path.join("cuda_bindings.rs")) .expect("Couldn't write bindings"); } } #[derive(Debug)] struct PrefixRemover { prefix: String, } impl PrefixRemover { fn new(prefix: impl ToString) -> Self { Self { prefix: prefix.to_string(), } } } impl ParseCallbacks for PrefixRemover { fn item_name(&self, original_item_name: &str) -> Option { original_item_name .strip_prefix(&self.prefix) .map(move |s| s.to_string()) } }