-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbuild.rs
134 lines (119 loc) · 3.97 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
130
131
132
133
134
extern crate bindgen;
extern crate cc;
use std::{
env::{self, VarError},
ffi::OsStr,
iter,
path::PathBuf,
};
fn main() {
println!("cargo:rustc-link-lib=SFCGAL");
let mut cargo_metadata = Vec::with_capacity(64);
let link_libs_opt = env_var("SFCGAL_LINK_LIBS");
let link_paths_opt = env_var("SFCGAL_LINK_PATHS");
let include_paths_opt = env_var("SFCGAL_INCLUDE_PATHS");
if let Some(link_paths) = link_paths_opt {
let meta = link_paths
.split(',')
.map(str::trim)
.filter(|x| !x.is_empty())
.flat_map(|path| {
let out = iter::once(format!("cargo:rustc-link-search={}", path));
#[cfg(target_os = "macos")]
{
out.chain(iter::once(format!(
"cargo:rustc-link-search=framework={}",
path
)))
}
#[cfg(not(target_os = "macos"))]
{
out
}
});
cargo_metadata.extend(meta);
}
if let Some(link_libs) = link_libs_opt {
cargo_metadata.extend(
process_library_list(
link_libs
.split(',')
.map(str::trim)
.filter(|x| !x.is_empty()),
)
.map(|l| format!("cargo:rustc-link-lib={}", l)),
);
}
let include_paths: Vec<_> = match include_paths_opt {
Some(include_paths) => include_paths
.split(',')
.map(str::trim)
.filter(|x| !x.is_empty())
.map(PathBuf::from)
.collect(),
None => vec![PathBuf::from("/usr/include")],
};
{
let mut build = cc::Build::new();
build.file("src/wrapper.c");
for include_path in include_paths.iter() {
build.include(include_path);
}
build.compile("sfcgalwrapper");
}
let bindings = bindgen::Builder::default()
.rust_target(bindgen::RustTarget::Stable_1_33)
.header("src/wrapper.h")
.clang_args(
include_paths
.iter()
.map(|path| format!("-I{}", path.display())),
)
.allowlist_type("sfcgal_.*$")
.allowlist_var("sfcgal_.*$")
.allowlist_function("sfcgal_.*$")
.allowlist_type("w_sfcgal_.*$")
.allowlist_var("w_sfcgal_.*$")
.allowlist_function("w_sfcgal_.*$")
.size_t_is_usize(true)
.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!");
for meta in cargo_metadata.into_iter() {
println!("{}", meta);
}
}
fn process_library_list(
libs: impl IntoIterator<Item = impl Into<PathBuf>>,
) -> impl Iterator<Item = String> {
libs.into_iter().map(|x| {
let mut path: PathBuf = x.into();
let extension = path.extension().and_then(OsStr::to_str).unwrap_or_default();
let is_framework = extension.eq_ignore_ascii_case("framework");
const LIB_EXTS: [&str; 7] = ["so", "a", "dll", "lib", "dylib", "framework", "tbd"];
if is_framework || LIB_EXTS.iter().any(|e| e.eq_ignore_ascii_case(extension)) {
path.set_extension("");
}
path.file_name()
.and_then(|f| {
f.to_str().map(|f| {
if is_framework {
format!("framework={}", f)
} else {
f.to_owned()
}
})
})
.expect("Invalid library name")
})
}
fn env_var<K: AsRef<OsStr>>(key: K) -> Option<String> {
match env::var(key) {
Ok(val) => Some(val),
Err(VarError::NotPresent) => None,
Err(VarError::NotUnicode(_)) => panic!("the value of environment variable is not Unicode"),
}
}