use std::{ collections::HashSet, env, fs, io, path::{Path, PathBuf}, }; #[derive(Debug)] struct IgnoreMacros(HashSet); impl bindgen::callbacks::ParseCallbacks for IgnoreMacros { fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroParsingBehavior { if self.0.contains(name) { bindgen::callbacks::MacroParsingBehavior::Ignore } else { bindgen::callbacks::MacroParsingBehavior::Default } } } fn main() { let zstd_root = env::var("DEP_ZSTD_ROOT") .map(PathBuf::from) .expect("missing zstd dependency"); // use cmake to configure (but not compile) the SZ3 build let mut config = cmake::Config::new("SZ3"); config.define("BUILD_SHARED_LIBS", "OFF"); config.define("BUILD_TESTING", "OFF"); config.build_arg("--version"); let sz3_root = config.build().join("build"); // copy the SZ3 source to the pre-configured build directory copy_dir_all(Path::new("SZ3").join("include"), sz3_root.join("include")) .expect("failed to copy SZ3 source"); let ignored_macros = IgnoreMacros( vec![ "FP_INFINITE".into(), "FP_NAN".into(), "FP_NORMAL".into(), "FP_SUBNORMAL".into(), "FP_ZERO".into(), ] .into_iter() .collect(), ); println!("cargo:rerun-if-changed=wrapper.hpp"); println!("cargo:rerun-if-changed=SZ3"); let cargo_callbacks = bindgen::CargoCallbacks::new(); let bindings = bindgen::Builder::default() .clang_arg("-x") .clang_arg("c++") .clang_arg("-std=c++17") .clang_arg(format!("-I{}", sz3_root.join("include").display())) .clang_arg(format!("-I{}", zstd_root.join("include").display())) .header("wrapper.hpp") .parse_callbacks(Box::new(cargo_callbacks)) .parse_callbacks(Box::new(ignored_macros)) .allowlist_type("SZ3_Config") .allowlist_type("SZ3::EB") .allowlist_type("SZ3::ALGO") .allowlist_type("SZ3::INTERP_ALGO") .allowlist_function("compress_float") .allowlist_function("compress_double") .allowlist_function("compress_int32_t") .allowlist_function("compress_int64_t") .allowlist_function("decompress_float") .allowlist_function("decompress_double") .allowlist_function("decompress_int32_t") .allowlist_function("decompress_int64_t") .allowlist_function("dealloc_result_float") .allowlist_function("dealloc_result_double") .allowlist_function("dealloc_result_int32_t") .allowlist_function("dealloc_result_int64_t") .allowlist_function("dealloc_config_dims") .allowlist_function("dealloc_result") .generate() .expect("Unable to generate bindings"); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); bindings .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); let mut build = cc::Build::new(); build .cpp(true) .warnings(false) .flag_if_supported("-std=c++17") .flag_if_supported("/std:c++17") .include(sz3_root.join("include")) .include(zstd_root.join("include")) .file("lib.cpp"); if cfg!(feature = "openmp") { env::var("DEP_OPENMP_FLAG") // set by openmp-sys .unwrap() .split(' ') .for_each(|f| { build.flag(f); }); } build.compile("sz3"); println!("cargo:rustc-link-lib=static=zstd"); if cfg!(feature = "openmp") { if let Some(link) = env::var_os("DEP_OPENMP_CARGO_LINK_INSTRUCTIONS") { for i in env::split_paths(&link) { if i.as_os_str().is_empty() { continue; } println!("cargo:{}", i.display()); } } } } // https://stackoverflow.com/a/65192210 fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { fs::create_dir_all(&dst)?; for entry in fs::read_dir(src)? { let entry = entry?; let dst = dst.as_ref().join(entry.file_name()); if entry.file_type()?.is_dir() { copy_dir_all(entry.path(), dst)?; } else { let src = fs::metadata(entry.path())?; fs::copy(entry.path(), &dst)?; // also copy over the `accessed` and `modified` timestamps fs::File::options().write(true).open(dst)?.set_times( fs::FileTimes::new() .set_accessed(src.accessed()?) .set_modified(src.modified()?), )?; } } Ok(()) }