-
Notifications
You must be signed in to change notification settings - Fork 4
/
build.rs
142 lines (120 loc) · 4.13 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
135
136
137
138
139
140
141
142
extern crate bindgen;
extern crate pkg_config;
#[macro_use]
extern crate cfg_if;
use std::env;
use std::path::PathBuf;
use std::process::Command;
cfg_if! {
if #[cfg(target_os = "linux")] {
const LIBS: [&'static str; 2] = [
"static=ReadStat",
"dylib=z",
];
} else {
const LIBS: [&'static str; 3] = [
"static=ReadStat",
"dylib=iconv",
"dylib=z",
];
}
}
const LIB_SEARCH_PATHS: [&'static str; 1] = ["/usr/lib"];
const READSTAT_URL: &'static str = "https://github.com/WizardMac/ReadStat.git";
const READSTAT_DIR: &'static str = "ReadStat/";
macro_rules! get(($name:expr) => (env::var($name).unwrap()));
macro_rules! log {
($fmt:expr) => (println!(concat!("qamd/build.rs:{}: ", $fmt), line!()));
($fmt:expr, $($arg:tt)*) => (println!(concat!("qamd/build.rs:{}: ", $fmt),
line!(), $($arg)*));
}
macro_rules! log_var(($var:ident) =>
(log!(concat!(stringify!($var), " = {:?}"), $var)));
/// Setup the rustc link search directories & library
fn main() {
LIBS.iter()
.map(|lib| {
if cfg!(target_os = "windows") {
lib.replace("dylib", "static")
} else {
lib.to_string()
}
})
.for_each(|lib| println!("cargo:rustc-link-lib={}", lib));
LIB_SEARCH_PATHS
.iter()
.for_each(|lib| println!("cargo:rustc-link-search={}", lib));
let out_path = PathBuf::from(&get!("OUT_DIR"));
log_var!(out_path);
let mut readstat_search_path = out_path.join(&READSTAT_DIR);
readstat_search_path.push("src");
println!(
"cargo:rustc-link-search={}",
&readstat_search_path.display()
);
get_readstat();
make_readstat(&out_path);
generate_bindings();
}
/// Clone the readstat directory if it isn't already present.
fn get_readstat() {
let out_path = PathBuf::from(&get!("OUT_DIR"));
let clone_dir = out_path.join(&READSTAT_DIR);
// Clone repo
if !&clone_dir.exists() {
run("git", |command| {
command
.current_dir(&out_path)
.arg("clone")
.arg(&READSTAT_URL)
});
}
run("cp", |command| command.arg("Makefile").arg(&out_path));
}
/// Use bindgen to generate the rust code required to interact with the C code.
fn generate_bindings() {
let out_path = PathBuf::from(&get!("OUT_DIR"));
let bindings_file = out_path.join("bindings.rs");
let header_file = out_path.join("ReadStat/src/readstat.h");
if !&bindings_file.exists() {
log!("Attempting to generate bindings via bindgen.");
let bindings = bindgen::Builder::default()
.header(header_file.to_str().expect("Failed to convert path to str"))
.whitelisted_function(r"readstat_[a-z0-9_]+")
.whitelisted_type(r"readstat_[a-z]+_t")
.whitelisted_var(r"READSTAT_HANDLER_[A-Z]+")
.generate()
.expect("Unable to generate bindings");
log!("Bindings generated bindings.");
log!("Attempting to write to file {:?}", &bindings_file);
bindings
.write_to_file(&bindings_file)
.expect("Couldn't write bindings!");
log!("Successfully written bindings to {:?}", &bindings_file);
} else {
log!("Bindings already generated. Skipping.");
}
}
/// Build ReadStat with make to get a statically linkable library
fn make_readstat(out_path: &PathBuf) {
if cfg!(target_os = "windows") {
run("make", |command| {
command.current_dir(&out_path).arg("windows")
});
} else {
run("make", |command| command.current_dir(&out_path));
}
}
/// Build and run a Command and log the result.
fn run<F>(name: &str, mut configure: F)
where
F: FnMut(&mut Command) -> &mut Command,
{
let mut command = Command::new(name);
let configured = configure(&mut command);
log!("Executing {:?}", configured);
if !configured.status().unwrap().success() {
panic!("Failed to execute {:?}", configured);
}
log!("Command {:?} finished sucessfully.", configured);
}