extern crate cmake;
extern crate bindgen;
use std::{path::PathBuf, env};
fn main() {
let target = env::var("TARGET").expect("TARGET was not set");
let mut features = std::collections::HashSet::<String>::default();
if let Ok(rustflags) = env::var("CARGO_CFG_TARGET_FEATURE") {
for v in rustflags.split(',') {
features.insert(v.to_string());
}
}
let dst = cmake::Config::new("sleef")
.very_verbose(true)
.define("BUILD_DFT", "FALSE")
.define("BUILD_TESTS", "FALSE")
.define("BUILD_SHARED_LIBS", "TRUE")
.build();
println!("cargo:rustc-link-lib=sleef");
println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
let out_dir = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR was not set"));
let sleef_header = out_dir.join("include").join("sleef.h");
assert!(sleef_header.exists(),
"error sleef.h header not found in OUT_DIR={}",
out_dir.display());
let mut bindings = bindgen::Builder::default()
.header(sleef_header.to_str().expect("failed to convert header path to string"))
.opaque_type("Sleef_longdouble2")
.use_core()
.ctypes_prefix("::libc")
.generate_inline_functions(true)
.rust_target(bindgen::RustTarget::Nightly);
if target.contains("86") && (features.contains("sse") || features.contains("avx")) {
let vs = [
"__m64",
"__m128", "__m128i", "__m128d",
"__m256", "__m256i", "__m256d",
];
for v in &vs {
bindings = bindings.blacklist_type(v).opaque_type(v);
}
let x86_features = {
let mut features = std::collections::HashMap::<String, String>::default();
features.insert("sse2".to_string(), "__SSE2__".to_string());
features.insert("avx".to_string(), "__AVX__".to_string());
features
};
for f in &features {
if let Some(def) = x86_features.get(f) {
bindings = bindings.clang_arg(format!("-D{}", def));
}
}
} else if target.contains("aarch") && features.contains("neon") {
let vs = [
"int8x8_t", "uint8x8_t", "poly8x8_t", "int16x4_t", "uint16x4_t",
"poly16x4_t", "int32x2_t", "uint32x2_t", "float32x2_t", "int64x1_t", "uint64x1_t",
"float64x1_t", "int8x16_t", "uint8x16_t", "poly8x16_t", "int16x8_t",
"uint16x8_t", "poly16x8_t", "int32x4_t", "uint32x4_t", "float32x4_t", "int64x2_t",
"uint64x2_t", "float64x2_t"
];
for v in &vs {
bindings = bindings.blacklist_type(v).opaque_type(v);
}
} else if target.contains("powerpc64") && features.contains("vsx") {
let vs = [
"vector_signed_char", "vector_unsigned_char",
"vector_signed_short", "vector_unsigned_short", "vector_signed_int",
"vector_unsigned_int", "vector_float", "vector_signed_long",
"vector_unsigned_long", "vector_double", "vector_bool_char",
"vector_bool_short", "vector_bool_int", "vector_bool_long"
];
for v in &vs {
bindings = bindings.blacklist_type(v).opaque_type(v);
}
} else {
eprintln!("unsupported target: \"{}\" features: \"{:?}\"", target, features);
std::process::abort();
}
let bindings = bindings
.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!");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=sleef");
}