]>
Commit | Line | Data |
---|---|---|
f2b60f7d | 1 | use std::env; |
136023e0 | 2 | use std::fs; |
f2b60f7d | 3 | use std::io::Write; |
6522a427 | 4 | use std::path::{Path, PathBuf}; |
f2b60f7d | 5 | use std::process::{self, Command, Stdio}; |
136023e0 | 6 | |
6522a427 EL |
7 | use super::path::{Dirs, RelPath}; |
8 | use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path}; | |
9 | ||
10 | pub(crate) struct Compiler { | |
11 | pub(crate) cargo: PathBuf, | |
12 | pub(crate) rustc: PathBuf, | |
13 | pub(crate) rustdoc: PathBuf, | |
14 | pub(crate) rustflags: String, | |
15 | pub(crate) rustdocflags: String, | |
16 | pub(crate) triple: String, | |
17 | pub(crate) runner: Vec<String>, | |
18 | } | |
19 | ||
20 | impl Compiler { | |
21 | pub(crate) fn host() -> Compiler { | |
22 | Compiler { | |
23 | cargo: get_cargo_path(), | |
24 | rustc: get_rustc_path(), | |
25 | rustdoc: get_rustdoc_path(), | |
26 | rustflags: String::new(), | |
27 | rustdocflags: String::new(), | |
28 | triple: get_host_triple(), | |
29 | runner: vec![], | |
30 | } | |
31 | } | |
32 | ||
33 | pub(crate) fn with_triple(triple: String) -> Compiler { | |
34 | Compiler { | |
35 | cargo: get_cargo_path(), | |
36 | rustc: get_rustc_path(), | |
37 | rustdoc: get_rustdoc_path(), | |
38 | rustflags: String::new(), | |
39 | rustdocflags: String::new(), | |
40 | triple, | |
41 | runner: vec![], | |
42 | } | |
43 | } | |
44 | } | |
45 | ||
46 | pub(crate) struct CargoProject { | |
47 | source: &'static RelPath, | |
48 | target: &'static str, | |
49 | } | |
50 | ||
51 | impl CargoProject { | |
52 | pub(crate) const fn new(path: &'static RelPath, target: &'static str) -> CargoProject { | |
53 | CargoProject { source: path, target } | |
54 | } | |
55 | ||
56 | pub(crate) fn source_dir(&self, dirs: &Dirs) -> PathBuf { | |
57 | self.source.to_path(dirs) | |
58 | } | |
59 | ||
60 | pub(crate) fn manifest_path(&self, dirs: &Dirs) -> PathBuf { | |
61 | self.source_dir(dirs).join("Cargo.toml") | |
62 | } | |
63 | ||
64 | pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf { | |
65 | RelPath::BUILD.join(self.target).to_path(dirs) | |
66 | } | |
2b03887a | 67 | |
6522a427 EL |
68 | fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command { |
69 | let mut cmd = Command::new(cargo); | |
70 | ||
71 | cmd.arg(command) | |
72 | .arg("--manifest-path") | |
73 | .arg(self.manifest_path(dirs)) | |
74 | .arg("--target-dir") | |
75 | .arg(self.target_dir(dirs)); | |
76 | ||
77 | cmd | |
78 | } | |
79 | ||
80 | fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command { | |
81 | let mut cmd = self.base_cmd(command, &compiler.cargo, dirs); | |
82 | ||
83 | cmd.arg("--target").arg(&compiler.triple); | |
84 | ||
85 | cmd.env("RUSTC", &compiler.rustc); | |
86 | cmd.env("RUSTDOC", &compiler.rustdoc); | |
87 | cmd.env("RUSTFLAGS", &compiler.rustflags); | |
88 | cmd.env("RUSTDOCFLAGS", &compiler.rustdocflags); | |
89 | if !compiler.runner.is_empty() { | |
90 | cmd.env( | |
91 | format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")), | |
92 | compiler.runner.join(" "), | |
93 | ); | |
94 | } | |
95 | ||
96 | cmd | |
2b03887a FG |
97 | } |
98 | ||
6522a427 EL |
99 | #[must_use] |
100 | pub(crate) fn fetch(&self, cargo: impl AsRef<Path>, dirs: &Dirs) -> Command { | |
101 | let mut cmd = Command::new(cargo.as_ref()); | |
102 | ||
103 | cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs)); | |
104 | ||
105 | cmd | |
106 | } | |
107 | ||
108 | #[must_use] | |
109 | pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command { | |
110 | self.base_cmd("clean", cargo, dirs) | |
111 | } | |
112 | ||
113 | #[must_use] | |
114 | pub(crate) fn build(&self, compiler: &Compiler, dirs: &Dirs) -> Command { | |
115 | self.build_cmd("build", compiler, dirs) | |
116 | } | |
117 | ||
118 | #[must_use] | |
119 | pub(crate) fn test(&self, compiler: &Compiler, dirs: &Dirs) -> Command { | |
120 | self.build_cmd("test", compiler, dirs) | |
121 | } | |
122 | ||
123 | #[must_use] | |
124 | pub(crate) fn run(&self, compiler: &Compiler, dirs: &Dirs) -> Command { | |
125 | self.build_cmd("run", compiler, dirs) | |
126 | } | |
2b03887a FG |
127 | } |
128 | ||
6522a427 | 129 | #[must_use] |
2b03887a FG |
130 | pub(crate) fn hyperfine_command( |
131 | warmup: u64, | |
132 | runs: u64, | |
6522a427 EL |
133 | prepare: Option<&str>, |
134 | a: &str, | |
135 | b: &str, | |
2b03887a FG |
136 | ) -> Command { |
137 | let mut bench = Command::new("hyperfine"); | |
138 | ||
139 | if warmup != 0 { | |
140 | bench.arg("--warmup").arg(warmup.to_string()); | |
141 | } | |
142 | ||
143 | if runs != 0 { | |
144 | bench.arg("--runs").arg(runs.to_string()); | |
145 | } | |
146 | ||
147 | if let Some(prepare) = prepare { | |
6522a427 | 148 | bench.arg("--prepare").arg(prepare); |
2b03887a FG |
149 | } |
150 | ||
6522a427 | 151 | bench.arg(a).arg(b); |
2b03887a FG |
152 | |
153 | bench | |
154 | } | |
155 | ||
136023e0 XL |
156 | #[track_caller] |
157 | pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) { | |
158 | let src = src.as_ref(); | |
159 | let dst = dst.as_ref(); | |
160 | if let Err(_) = fs::hard_link(src, dst) { | |
161 | fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed | |
162 | } | |
163 | } | |
164 | ||
165 | #[track_caller] | |
166 | pub(crate) fn spawn_and_wait(mut cmd: Command) { | |
167 | if !cmd.spawn().unwrap().wait().unwrap().success() { | |
168 | process::exit(1); | |
169 | } | |
170 | } | |
171 | ||
f2b60f7d FG |
172 | #[track_caller] |
173 | pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String { | |
174 | let mut child = cmd | |
175 | .stdin(Stdio::piped()) | |
176 | .stdout(Stdio::piped()) | |
177 | .spawn() | |
178 | .expect("Failed to spawn child process"); | |
179 | ||
180 | let mut stdin = child.stdin.take().expect("Failed to open stdin"); | |
181 | std::thread::spawn(move || { | |
182 | stdin.write_all(input.as_bytes()).expect("Failed to write to stdin"); | |
183 | }); | |
184 | ||
185 | let output = child.wait_with_output().expect("Failed to read stdout"); | |
186 | if !output.status.success() { | |
187 | process::exit(1); | |
188 | } | |
189 | ||
190 | String::from_utf8(output.stdout).unwrap() | |
191 | } | |
192 | ||
136023e0 XL |
193 | pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { |
194 | for entry in fs::read_dir(from).unwrap() { | |
195 | let entry = entry.unwrap(); | |
196 | let filename = entry.file_name(); | |
197 | if filename == "." || filename == ".." { | |
198 | continue; | |
199 | } | |
200 | if entry.metadata().unwrap().is_dir() { | |
201 | fs::create_dir(to.join(&filename)).unwrap(); | |
202 | copy_dir_recursively(&from.join(&filename), &to.join(&filename)); | |
203 | } else { | |
204 | fs::copy(from.join(&filename), to.join(&filename)).unwrap(); | |
205 | } | |
206 | } | |
207 | } | |
f2b60f7d FG |
208 | |
209 | pub(crate) fn is_ci() -> bool { | |
6522a427 | 210 | env::var("CI").as_deref() == Ok("true") |
f2b60f7d | 211 | } |