This repository has been archived by the owner on Sep 30, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
build.rs
149 lines (129 loc) · 4.48 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
143
144
145
146
147
148
149
extern crate bindgen;
extern crate cc;
extern crate glob;
use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks};
use glob::glob;
use std::{
collections::HashSet,
env,
fs::File,
io::{self, Error, ErrorKind, Result, Write},
path::PathBuf,
sync::{Arc, RwLock},
};
#[derive(Debug)]
struct MacroCallback {
macros: Arc<RwLock<HashSet<String>>>,
}
impl ParseCallbacks for MacroCallback {
fn will_parse_macro(&self, name: &str) -> MacroParsingBehavior {
self.macros.write().unwrap().insert(name.into());
if name == "IPPORT_RESERVED" {
return MacroParsingBehavior::Ignore;
}
MacroParsingBehavior::Default
}
}
/// We don't have luxury of using pkg-config for detecting if the library
/// is installed on the system. Try a small C program to test if the lib
/// is there.
fn find_spdk_lib(out_path: &PathBuf) -> Result<()> {
let c_file = out_path.join("test_libspdk.c");
let o_file = out_path.join("test_libspdk.o");
{
let mut file = File::create(&c_file)?;
file.write_all(b"int main() { return 0; }")?;
}
let output = cc::Build::new()
.get_compiler()
.to_command()
.arg("-o")
.arg(o_file)
.arg(c_file)
.arg("-lspdk_fat")
.output()
.expect("Failed to execute cc");
if !output.status.success() {
io::stderr().write_all(&output.stderr).unwrap();
Err(Error::new(
ErrorKind::Other,
"spdk_fat library not found
Hint: Likely you need to install it to the system at first.
Look at build.sh script in spdk-sys repo.",
))
} else {
Ok(())
}
}
/// Create a wrapper.h file containing includes for all public spdk header
/// files, which can be used as input for bindgen.
fn create_wrapper_h(out_path: &PathBuf) -> Result<String> {
// XXX just now we rely that headers in spdk submodule and headers
// installed on the system are the same. We could look directly to
// /usr/local/include/spdk but without pkg-config we don't know what
// was the installation prefix.
let headers: Vec<String> = glob("spdk/include/spdk/*.h")
.expect("wrong glob pattern")
.map(|e| {
format!(
"#include <spdk/{}>",
e.unwrap().file_name().unwrap().to_str().unwrap()
)
})
.collect();
let h_file = out_path.join("wrapper.h");
let mut file = File::create(&h_file)?;
file.write_all(headers.join("\n").as_bytes())?;
Ok(h_file.to_str().unwrap().to_string())
}
fn main() {
#![allow(unreachable_code)]
#[cfg(not(target_arch = "x86_64"))]
panic!("spdk-sys crate is only for x86_64 cpu architecture");
#[cfg(not(target_os = "linux"))]
panic!("spdk-sys crate works only on linux");
let out_dir = env::var("OUT_DIR").unwrap();
let out_path = PathBuf::from(&out_dir);
if let Err(err) = find_spdk_lib(&out_path) {
panic!("{}", err);
}
let wrapper_h = match create_wrapper_h(&out_path) {
Ok(val) => val,
Err(err) => panic!("Failed to create wrapper file with headers: {}", err),
};
let macros = Arc::new(RwLock::new(HashSet::new()));
let bindings = bindgen::Builder::default()
.header(wrapper_h)
.rustfmt_bindings(true)
.trust_clang_mangling(false)
.layout_tests(false)
.derive_default(true)
.derive_debug(true)
.prepend_enum_name(false)
.generate_inline_functions(true)
.ctypes_prefix("libc")
.parse_callbacks(Box::new(MacroCallback {
macros: macros.clone(),
}))
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out_path.join("libspdk.rs"))
.expect("Couldn't write bindings!");
// spdk lib
println!("cargo:rustc-link-lib=spdk_fat");
// OS libs
// depending on distro/version -- this search path might be needed
println!("cargo:rustc-link-search=native=/usr/lib64/iscsi");
// if you add a library here then also add it in build.sh
println!("cargo:rustc-link-lib=ibverbs");
println!("cargo:rustc-link-lib=rdmacm");
println!("cargo:rustc-link-lib=aio");
println!("cargo:rustc-link-lib=iscsi");
println!("cargo:rustc-link-lib=numa");
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=rt");
println!("cargo:rustc-link-lib=uuid");
println!("cargo:rustc-link-lib=crypto");
println!("cargo:rerun-if-changed=build.rs");
}