use std::{
env, fs, io,
path::{Path, PathBuf},
};
fn main() {
let zstd_root = env::var("DEP_ZSTD_ROOT")
.map(PathBuf::from)
.expect("missing zstd dependency");
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_dir_all(Path::new("SZ3").join("include"), sz3_root.join("include"))
.expect("failed to copy SZ3 source");
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))
.enable_cxx_namespaces()
.allowlist_type("SZ3_Config")
.allowlist_type("SZ3::EB")
.allowlist_type("SZ3::ALGO")
.allowlist_type("SZ_DATA_TYPE")
.allowlist_function("dealloc_size_t")
.allowlist_function("decompress_config")
.allowlist_item("impl_.*")
.use_core()
.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)
.std("c++17")
.flag_if_supported("/bigobj") .include(sz3_root.join("include"))
.include(zstd_root.join("include"))
.file("lib.cpp")
.warnings(false);
if cfg!(feature = "openmp") {
env::var("DEP_OPENMP_FLAG") .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());
}
}
}
}
fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> 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)?;
fs::File::options().write(true).open(dst)?.set_times(
fs::FileTimes::new()
.set_accessed(src.accessed()?)
.set_modified(src.modified()?),
)?;
}
}
Ok(())
}