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
use std::process::{Command, ExitStatus};
use std::collections::HashMap;
use super::Error;
use super::StatusWrapper;
#[derive(Clone, Debug)]
pub enum Arch {
Aarch64,
Armv7h,
Armh,
Amd64,
I686,
}
#[derive(Clone, Debug)]
pub enum OS {
Linux,
Windows,
Mac,
}
pub struct Target {
os: OS,
arch: Arch,
native_dirs: Vec<String>,
environment: HashMap<String, String>,
}
impl Target {
pub fn new(os: OS, arch: Arch) -> Result<Self, Error> {
match (&os, &arch) {
(&OS::Linux, &Arch::Aarch64) |
(&OS::Linux, &Arch::Armv7h) |
(&OS::Linux, &Arch::Armh) |
(&OS::Linux, &Arch::Amd64) |
(&OS::Windows, &Arch::Amd64) |
(&OS::Windows, &Arch::I686) |
(&OS::Mac, &Arch::Amd64) => {
Ok(Target {
os: os,
arch: arch,
native_dirs: Vec::new(),
environment: HashMap::new(),
})
}
_ => Err(Error::InvalidTarget),
}
}
pub fn target_str(&self) -> &str {
match (&self.os, &self.arch) {
(&OS::Linux, &Arch::Aarch64) => "aarch64-unknown-linux-gnu",
(&OS::Linux, &Arch::Armv7h) => "armv7-unknown-linux-gnueabihf",
(&OS::Linux, &Arch::Armh) => "arm-unknown-linux-gnueabihf",
(&OS::Linux, &Arch::Amd64) => "x86_64-unknown-linux-gnu",
(&OS::Windows, &Arch::Amd64) => "x86_64-pc-windows-gnu",
(&OS::Windows, &Arch::I686) => "i686-pc-windows-gnu",
(&OS::Mac, &Arch::Amd64) => "x86_64-apple-darwin",
_ => "unknown",
}
}
pub fn add_libs(&mut self, libs: &[String]) {
self.native_dirs.extend_from_slice(libs);
}
pub fn add_env(&mut self, env: &HashMap<String, String>) {
for (key, value) in env {
self.environment.insert(key.clone(), value.clone());
}
}
pub fn libs(&self) -> String {
self.native_dirs
.iter()
.map(|dir| format!("-L native={}", dir))
.collect::<Vec<_>>()
.join(" ")
}
pub fn compile(&self, version: &str, status: &mut StatusWrapper) -> Result<ExitStatus, Error> {
Command::new("cargo")
.args(&["build", "--target", self.target_str(), "--release"])
.env(
"RUSTFLAGS",
&format!("-C target-feature=+crt-static {}", &self.libs()),
)
.envs(&self.environment)
.spawn()
.map_err(|e| e.into())
.and_then(|mut child| {
status.start(self.target_str(), version);
let _ = status.write();
child.wait().map_err(|e| e.into())
})
.and_then(|exit_status| {
if exit_status.success() {
status.succeed(self.target_str(), version);
} else {
status.fail(self.target_str(), version);
}
let _ = status.write();
Ok(exit_status)
})
}
}