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
use std::env;
use std::process::Command;
use std::process::Stdio;
use std::path::Path;
fn x86_triple(os: &str) -> &'static str {
match os {
"linux" => "-felf32",
"darwin" => "-fmacho32",
"windows" => "-fwin32",
_ => ""
}
}
fn x86_64_triple(os: &str) -> &'static str {
match os {
"linux" => "-felf64",
"darwin" => "-fmacho64",
"windows" => "-fwin64",
_ => ""
}
}
fn parse_triple(trip: &str) -> &'static str {
let parts = trip.split("-").collect::<Vec<&str>>();
if parts.len() < 3 {
return ""
}
match parts[0] {
"x86_64" => x86_64_triple(&parts[2]),
"x86" => x86_triple(&parts[2]),
_ => ""
}
}
pub fn compile_library(output: &str, files: &[&str]) {
compile_library_args(output, files, &[])
}
pub fn compile_library_args(output: &str, files: &[&str], args: &[&str]) {
assert!(output.starts_with("lib"));
assert!(output.ends_with(".a"));
let target = env::var("TARGET").unwrap();
let cargo_manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let out_dir = env::var("OUT_DIR").unwrap();
let mut new_args: Vec<&str> = vec![];
new_args.push(parse_triple(&target));
if env::var_os("DEBUG").is_some() {
new_args.push("-g");
}
new_args.extend(args);
let src = Path::new(&cargo_manifest_dir);
let dst = Path::new(&out_dir);
let mut objects = Vec::new();
for file in files.iter() {
let obj = dst.join(*file).with_extension("o");
let mut cmd = Command::new("nasm");
cmd.args(&new_args[..]);
std::fs::create_dir_all(&obj.parent().unwrap()).unwrap();
run(cmd.arg(src.join(*file)).arg("-o").arg(&obj));
objects.push(obj);
}
run(Command::new(ar()).arg("crus").arg(dst.join(output)).args(&objects[..]));
println!("cargo:rustc-flags=-L {}",
dst.display());
}
fn run(cmd: &mut Command) {
println!("running: {:?}", cmd);
let status = match cmd.stdout(Stdio::inherit()).stderr(Stdio::inherit()).status() {
Ok(status) => status,
Err(e) => panic!("failed to spawn process: {}", e),
};
if !status.success() {
panic!("nonzero exit status: {}", status);
}
}
fn ar() -> String {
env::var("AR").unwrap_or("ar".to_string())
}