-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathbuild.rs
More file actions
182 lines (150 loc) · 5.56 KB
/
build.rs
File metadata and controls
182 lines (150 loc) · 5.56 KB
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
use std::{
env, fs, io,
path::{Path, PathBuf},
process::Command,
str::FromStr,
};
use target_lexicon::Triple;
fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
fs::create_dir(path).or_else(|e| match e.kind() {
io::ErrorKind::AlreadyExists => Ok(()),
_ => Err(e),
})
}
fn find_python() -> Command {
// Check for pylauncher first since it is the most accurate way to get the
// newest version of python.
//
// This is more relevant on windows but it can also be installed on linux.
if let Ok(status) = Command::new("py").arg("-3").arg("-V").status() {
if status.success() {
let mut cmd = Command::new("py");
cmd.arg("-3");
return cmd;
}
}
// Next check for an explicit python3 installation.
if let Ok(status) = Command::new("python3").arg("-V").status() {
if status.success() {
return Command::new("python3");
}
}
// Finally just try and run python. If the version is
// too old (e.g. python generally means python2 on linux)
// then we'll fail later on. On windows it's generally
// likely to see python as just plain python.
if let Ok(status) = Command::new("python").arg("-V").status() {
if status.success() {
return Command::new("python");
}
}
panic!("Unable to find a working python installation. Tried `python3` and `python`.");
}
fn build_xed() {
println!("cargo:rerun-if-changed=xed/VERSION");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed-env=PROFILE");
println!("cargo:rerun-if-changed-env=CROSS_TOOLCHAIN_PREFIX");
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("Failed to read OUT_DIR"));
let cwd = env::current_dir().expect("Failed to get CWD");
let target = env::var("TARGET").expect("Failed to read TARGET");
let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_owned());
let install_dir = out_dir.join("install");
let build_dir = out_dir.join("build");
let mfile_path = cwd.join("xed/mfile.py");
create_dir(&install_dir)
.unwrap_or_else(|_| panic!("Failed to create directory '{}'", install_dir.display()));
create_dir(&build_dir)
.unwrap_or_else(|_| panic!("Failed to create directory '{}'", build_dir.display()));
// Set locale to C to avoid user language settings interference
env::set_var("LC_ALL", "C");
let num_jobs: u32 = env::var("NUM_JOBS")
.unwrap_or_else(|_| "1".to_owned())
.parse()
.unwrap_or(1);
let mut cmd = find_python();
cmd.env("PYTHONDONTWRITEBYTECODE", "x")
.current_dir(&build_dir)
// The -B flag prevents python from generating .pyc files
.arg("-B")
.arg(&mfile_path)
.arg("install")
.arg(format!("--jobs={}", num_jobs))
.arg("--silent")
.arg("--static-stripped")
.arg("--extra-ccflags=-fPIC")
.arg("--no-werror")
.arg(format!(
"--host-cpu={}",
Triple::from_str(&target)
.expect("TARGET was not a valid target triple")
.architecture
))
.arg(format!("--install-dir={}", install_dir.display()));
if let Ok(toolchain) = env::var("CROSS_TOOLCHAIN_PREFIX") {
cmd.arg(format!("--toolchain={toolchain}"));
}
if profile == "release" {
cmd.arg("--opt=3");
} else {
cmd.arg("--opt=0");
}
eprintln!("XED build command: {:?}", cmd);
let status = cmd.status().expect("Failed to start xed build");
if !status.success() {
panic!("Building xed failed");
}
let lib_dir = install_dir.join("lib");
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!("cargo:rustc-link-lib=static=xed");
}
fn build_inline_shim() {
let cwd = std::env::current_dir().unwrap();
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("Failed to read OUT_DIR"));
let mut cc = cc::Build::new();
cc.include(out_dir.join("install/include"))
.include(&cwd)
// xed-static.c contains an instance of this. It's not an error and we
// don't want to be modifying generated files so just silence the warning.
.flag_if_supported("-Wno-duplicate-decl-specifier");
if cfg!(feature = "bindgen") {
cc.file(out_dir.join("xed-static.c"));
} else {
cc.file("src/xed-static.c");
}
cc.compile("xed-shim");
}
#[cfg(feature = "bindgen")]
fn build_bindgen() {
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("Failed to read OUT_DIR"));
let dot_rs = out_dir.join("xed.rs");
let builder = bindgen::builder()
.clang_arg("-I")
.clang_arg(out_dir.join("install/include").display().to_string())
.allowlist_type("xed3?_.*")
.allowlist_function("(str2)?xed3?_.*")
.allowlist_var("(XED|xed)_.*")
.blocklist_item("XED_.*_DEFINED")
.prepend_enum_name(false)
.impl_debug(true)
.use_core()
.wrap_static_fns(true)
.wrap_static_fns_path(out_dir.join("xed-static.c"))
.wrap_static_fns_suffix("_xed_sys_inline");
let bindings = builder
.header("xed.h")
.generate()
.unwrap_or_else(|e| panic!("Could not generate bindings for xed.h: {}", e));
bindings.write_to_file(&dot_rs).unwrap_or_else(|e| {
panic!(
"Could not write generated bindings to {}: {e}",
dot_rs.display()
)
});
}
fn main() {
build_xed();
#[cfg(feature = "bindgen")]
build_bindgen();
build_inline_shim();
}