-
Notifications
You must be signed in to change notification settings - Fork 3
/
build.rs
148 lines (126 loc) · 3.47 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
#[cfg(not(windows))]
#[macro_use]
extern crate serde_derive;
#[cfg(not(windows))]
use cc;
#[cfg(not(windows))]
use handlebars as hbs;
#[cfg(not(windows))]
use std::{
convert::From,
fs::File,
io::{self, Read},
path::{Path, PathBuf},
process::exit,
env,
};
#[cfg(not(windows))]
fn main() {
let target_os = env::var("CARGO_CFG_TARGET_OS");
match target_os.as_ref().map(|x| &**x) {
Ok("windows") => return,
_ => {},
}
let in_path = Path::new("src/unix/c").join("constants.c.in");
let out_path = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("constants.c");
// Template the file.
if let Err(e) = template_file(&in_path, &out_path) {
println!("Error creating `constants.c` from template");
println!("-> {:?}", e);
exit(1);
}
// Build the final library
let mut cfg = cc::Build::new();
let helpers_path = Path::new("src/unix/c").join("helpers.c");
let ifaddrs_path = Path::new("src/unix/c").join("ifaddrs.c");
let cfg = cfg.file(&out_path).file(&helpers_path);
if env::var_os("CARGO_CFG_TARGET_OS")
.unwrap()
.to_str()
.unwrap()
== "android"
{
cfg.file(ifaddrs_path);
}
cfg.compile("libinterfaces.a");
}
#[cfg(not(windows))]
fn template_file(in_path: &PathBuf, out_path: &PathBuf) -> Result<(), Error> {
// Open and read the file.
let mut f = File::open(in_path)?;
let mut s = String::new();
f.read_to_string(&mut s)?;
let mut handlebars = hbs::Handlebars::new();
handlebars.register_template_string("template", s)?;
let mut f = File::create(out_path)?;
let data = make_data();
handlebars.renderw("template", &data, &mut f)?;
Ok(())
}
#[cfg(not(windows))]
fn make_data() -> Context {
// These constants are "dynamically" generated by compiling a C file that includes their value
// and then including that in the final build. See `constants.rs` for a function that can be
// used to retrieve them.
let names: &[&str] = &[
// IOCTLs
"SIOCGIFCONF",
"SIOCGIFHWADDR",
"SIOCGIFFLAGS",
"SIOCSIFFLAGS",
"SIOCGIFMTU",
"SIOCSIFMTU",
// Address families
"AF_LINK",
"AF_PACKET", // Only on Linux
];
// These constants are the same as above, but we don't test them for existence with #ifdef.
let anames: &[&str] = &["sizeof(struct ifreq)"];
let names = names
.into_iter()
.map(|x| String::from(*x))
.collect::<Vec<String>>();
let anames = anames
.into_iter()
.map(|x| String::from(*x))
.collect::<Vec<String>>();
Context {
test_constants: names,
always_constants: anames,
}
}
#[cfg(not(windows))]
#[derive(Serialize, Deserialize)]
struct Context {
test_constants: Vec<String>,
always_constants: Vec<String>,
}
#[cfg(not(windows))]
#[derive(Debug)]
enum Error {
IoError(io::Error),
TemplateError(hbs::TemplateError),
RenderError(hbs::RenderError),
}
#[cfg(not(windows))]
impl From<io::Error> for Error {
fn from(e: io::Error) -> Error {
Error::IoError(e)
}
}
#[cfg(not(windows))]
impl From<hbs::TemplateError> for Error {
fn from(e: hbs::TemplateError) -> Error {
Error::TemplateError(e)
}
}
#[cfg(not(windows))]
impl From<hbs::RenderError> for Error {
fn from(e: hbs::RenderError) -> Error {
Error::RenderError(e)
}
}
#[cfg(windows)]
fn main() {
// No build script required
}