-
Notifications
You must be signed in to change notification settings - Fork 8
/
build.rs
129 lines (115 loc) · 4.91 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Builds the sleef library from source.
extern crate cmake;
extern crate bindgen;
extern crate env_logger;
use std::{path::PathBuf, env};
fn main() {
env_logger::init();
let target = env::var("TARGET").expect("TARGET was not set");
// Parse target features, this is required for ABI compatibility.
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)
// no DFT libraries (should be behind a feature flag):
.define("BUILD_DFT", "FALSE")
// no tests (should build and run the tests behind a feature flag):
.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());
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let mut bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header(sleef_header.to_str().expect("failed to convert header path to string"))
// Rust does not support 80-bit precision floats:
.opaque_type("Sleef_longdouble2")
// The bindings should be no_std:
.use_core()
// The bindings should use the ctypes from libc, not std::os::raw:
.ctypes_prefix("libc")
// Generate inline functions:
.generate_inline_functions(true)
// Only target nightly Rust for the time being:
.rust_target(bindgen::RustTarget::Nightly);
// Blacklist vector types:
if target.contains("86") && (features.contains("sse") || features.contains("avx")) {
// x86 targets: i386,i586,i686,x86,x86_64
let vs = [
// MMX:
"__m64",
// SSE:
"__m128", "__m128i", "__m128d",
// AVX
"__m256", "__m256i", "__m256d",
// FIXME: AVX-512
//"__m512", "__m512i", "__m512d",
];
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());
// FIXME: AVX-512
// features.insert("avx512f".to_string(), "__AVX512F__".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
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
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");
}