-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.rs
122 lines (95 loc) · 3.62 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
#[path = "src/cli.rs"]
mod cli;
#[cfg(feature="pkgbuild")]
#[path = "build/pkgbuild.rs"]
mod pkgbuild;
use cli::build_cli;
#[cfg(feature="pkgbuild")]
use pkgbuild::write_pkgbuild;
use std::fs;
use std::path::PathBuf;
use std::path::Path;
use clap::{ crate_name, Shell };
//Relative to build.rs location
static C_DIRECTORY: &str = "src/c";
static HEADERS_DIRECTORY: &str = "src/c/include";
static BUILD_MODULES: &str = "build";
fn main() {
let out_path = std::env::var("OUT_DIR").unwrap();
// Use 'target' as the target dir since there is no way to know if
// the user changed it
let target_dir = String::from("target");
fs::create_dir_all(&target_dir).unwrap();
// Write the out_path to file so that it can be used out of cargo
fs::write(PathBuf::from(&target_dir).join("out_dir"), &out_path).unwrap();
// Have gcc look for libraries in out_path
println!("cargo:rustc-link-search={}", out_path);
// Tell cargo to link the project's compiled c libs in out_path
println!("cargo:rustc-link-lib=xmlparse");
// Tell cargo to tell rustc to link the libxml2 shared system library.
println!("cargo:rustc-link-lib=xml2");
// Tell cargo to invalidate the built crate whenever the c code is changed
println!("cargo:rerun-if-changed={}", C_DIRECTORY);
// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed={}", HEADERS_DIRECTORY);
// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed={}", BUILD_MODULES);
let c_files: Vec<PathBuf> = fs::read_dir(C_DIRECTORY).unwrap()
.map(|e| e.unwrap().path())
.filter(|e| e.as_path().as_os_str() != HEADERS_DIRECTORY)
.collect();
cc::Build::new()
// Suppress unused parameter warnings
.flag("-Wno-unused-parameter")
// Suppress unused function warnings
.flag("-Wno-unused-function")
// Include path to header files
.flag("-iquote").flag(HEADERS_DIRECTORY)
.include("/usr/include/libxml2")
.files(c_files)
.compile("xmlparse");
let headers = recursive_read_dir(HEADERS_DIRECTORY);
for mut header in headers {
//let mut header = header.unwrap().path();
let bindings = bindgen::Builder::default()
// Use types defined in core
.use_core()
// Use cty as the prefix of raw types
.ctypes_prefix("cty")
// Set include paths
.clang_arg("-I/usr/include/libxml2")
// The input header we would like to generate bindings for.
.header(header.to_str().unwrap())
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
header.set_extension("rs");
let header = header.file_name().unwrap();
bindings.write_to_file(PathBuf::from(&out_path).join(header)).unwrap();
}
let mut app = build_cli();
app.gen_completions(crate_name!(), Shell::Zsh, &out_path);
app.gen_completions(crate_name!(), Shell::Bash, &out_path);
app.gen_completions(crate_name!(), Shell::Fish, &out_path);
#[cfg(feature="pkgbuild")]
write_pkgbuild().unwrap();
}
fn recursive_read_dir<P: AsRef<Path>>(path: P) -> Vec<PathBuf> {
let mut entries: Vec<PathBuf> = fs::read_dir(path).unwrap().map(|e| e.unwrap().path()).collect();
let mut dirs = Vec::with_capacity(entries.len());
let mut i = 0;
while i < entries.len() {
if entries[i].is_dir() {
dirs.push(entries.remove(i));
} else {
i += 1;
}
}
let mut dirs: Vec<_> = dirs.iter().map(|d| recursive_read_dir(d)).collect();
dirs.iter_mut().for_each(|d| entries.extend(d.drain(..)));
entries
}