]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_cranelift/build_system/utils.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / compiler / rustc_codegen_cranelift / build_system / utils.rs
CommitLineData
f2b60f7d 1use std::env;
136023e0 2use std::fs;
ed00b5ec 3use std::io;
9c376795 4use std::path::{Path, PathBuf};
ed00b5ec 5use std::process::{self, Command};
add651ee 6use std::sync::atomic::{AtomicBool, Ordering};
136023e0 7
add651ee
FG
8use crate::path::{Dirs, RelPath};
9use crate::shared_utils::rustflags_to_cmd_env;
9c376795 10
9ffffee4 11#[derive(Clone, Debug)]
9c376795
FG
12pub(crate) struct Compiler {
13 pub(crate) cargo: PathBuf,
14 pub(crate) rustc: PathBuf,
15 pub(crate) rustdoc: PathBuf,
add651ee
FG
16 pub(crate) rustflags: Vec<String>,
17 pub(crate) rustdocflags: Vec<String>,
9c376795
FG
18 pub(crate) triple: String,
19 pub(crate) runner: Vec<String>,
20}
21
22impl Compiler {
9ffffee4
FG
23 pub(crate) fn set_cross_linker_and_runner(&mut self) {
24 match self.triple.as_str() {
25 "aarch64-unknown-linux-gnu" => {
26 // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
add651ee
FG
27 self.rustflags.push("-Clinker=aarch64-linux-gnu-gcc".to_owned());
28 self.rustdocflags.push("-Clinker=aarch64-linux-gnu-gcc".to_owned());
9ffffee4
FG
29 self.runner = vec![
30 "qemu-aarch64".to_owned(),
31 "-L".to_owned(),
32 "/usr/aarch64-linux-gnu".to_owned(),
33 ];
34 }
35 "s390x-unknown-linux-gnu" => {
36 // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
add651ee
FG
37 self.rustflags.push("-Clinker=s390x-linux-gnu-gcc".to_owned());
38 self.rustdocflags.push("-Clinker=s390x-linux-gnu-gcc".to_owned());
9ffffee4
FG
39 self.runner = vec![
40 "qemu-s390x".to_owned(),
41 "-L".to_owned(),
42 "/usr/s390x-linux-gnu".to_owned(),
43 ];
44 }
ed00b5ec
FG
45 "riscv64gc-unknown-linux-gnu" => {
46 // We are cross-compiling for riscv64. Use the correct linker and run tests in qemu.
47 self.rustflags.push("-Clinker=riscv64-linux-gnu-gcc".to_owned());
48 self.rustdocflags.push("-Clinker=riscv64-linux-gnu-gcc".to_owned());
49 self.runner = vec![
50 "qemu-riscv64".to_owned(),
51 "-L".to_owned(),
52 "/usr/riscv64-linux-gnu".to_owned(),
53 ];
54 }
9ffffee4
FG
55 "x86_64-pc-windows-gnu" => {
56 // We are cross-compiling for Windows. Run tests in wine.
57 self.runner = vec!["wine".to_owned()];
58 }
59 _ => {
ed00b5ec 60 eprintln!("Unknown non-native platform");
9ffffee4 61 }
9c376795
FG
62 }
63 }
64}
65
66pub(crate) struct CargoProject {
67 source: &'static RelPath,
68 target: &'static str,
69}
70
71impl CargoProject {
72 pub(crate) const fn new(path: &'static RelPath, target: &'static str) -> CargoProject {
73 CargoProject { source: path, target }
74 }
75
76 pub(crate) fn source_dir(&self, dirs: &Dirs) -> PathBuf {
77 self.source.to_path(dirs)
78 }
79
80 pub(crate) fn manifest_path(&self, dirs: &Dirs) -> PathBuf {
81 self.source_dir(dirs).join("Cargo.toml")
82 }
83
84 pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf {
85 RelPath::BUILD.join(self.target).to_path(dirs)
86 }
2b03887a 87
9ffffee4 88 #[must_use]
9c376795
FG
89 fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
90 let mut cmd = Command::new(cargo);
91
92 cmd.arg(command)
93 .arg("--manifest-path")
94 .arg(self.manifest_path(dirs))
95 .arg("--target-dir")
9ffffee4 96 .arg(self.target_dir(dirs))
fe692bf9
FG
97 .arg("--locked");
98
99 if dirs.frozen {
100 cmd.arg("--frozen");
101 }
9c376795
FG
102
103 cmd
104 }
105
9ffffee4 106 #[must_use]
9c376795
FG
107 fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
108 let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
109
110 cmd.arg("--target").arg(&compiler.triple);
111
112 cmd.env("RUSTC", &compiler.rustc);
113 cmd.env("RUSTDOC", &compiler.rustdoc);
add651ee
FG
114 rustflags_to_cmd_env(&mut cmd, "RUSTFLAGS", &compiler.rustflags);
115 rustflags_to_cmd_env(&mut cmd, "RUSTDOCFLAGS", &compiler.rustdocflags);
9c376795
FG
116 if !compiler.runner.is_empty() {
117 cmd.env(
118 format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")),
119 compiler.runner.join(" "),
120 );
121 }
122
123 cmd
124 }
125
9ffffee4
FG
126 pub(crate) fn clean(&self, dirs: &Dirs) {
127 let _ = fs::remove_dir_all(self.target_dir(dirs));
9c376795
FG
128 }
129
130 #[must_use]
131 pub(crate) fn build(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
132 self.build_cmd("build", compiler, dirs)
133 }
134
135 #[must_use]
136 pub(crate) fn test(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
137 self.build_cmd("test", compiler, dirs)
138 }
139
140 #[must_use]
141 pub(crate) fn run(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
142 self.build_cmd("run", compiler, dirs)
143 }
2b03887a
FG
144}
145
9c376795 146#[must_use]
2b03887a
FG
147pub(crate) fn hyperfine_command(
148 warmup: u64,
149 runs: u64,
9c376795 150 prepare: Option<&str>,
add651ee
FG
151 cmds: &[(&str, &str)],
152 markdown_export: &Path,
2b03887a
FG
153) -> Command {
154 let mut bench = Command::new("hyperfine");
155
add651ee
FG
156 bench.arg("--export-markdown").arg(markdown_export);
157
2b03887a
FG
158 if warmup != 0 {
159 bench.arg("--warmup").arg(warmup.to_string());
160 }
161
162 if runs != 0 {
163 bench.arg("--runs").arg(runs.to_string());
164 }
165
166 if let Some(prepare) = prepare {
9c376795 167 bench.arg("--prepare").arg(prepare);
2b03887a
FG
168 }
169
add651ee
FG
170 for &(name, cmd) in cmds {
171 if name != "" {
172 bench.arg("-n").arg(name);
173 }
174 bench.arg(cmd);
175 }
2b03887a
FG
176
177 bench
178}
179
9ffffee4
FG
180#[must_use]
181pub(crate) fn git_command<'a>(repo_dir: impl Into<Option<&'a Path>>, cmd: &str) -> Command {
182 let mut git_cmd = Command::new("git");
183 git_cmd
184 .arg("-c")
185 .arg("user.name=Dummy")
186 .arg("-c")
187 .arg("user.email=dummy@example.com")
188 .arg("-c")
189 .arg("core.autocrlf=false")
add651ee
FG
190 .arg("-c")
191 .arg("commit.gpgSign=false")
9ffffee4
FG
192 .arg(cmd);
193 if let Some(repo_dir) = repo_dir.into() {
194 git_cmd.current_dir(repo_dir);
195 }
196 git_cmd
197}
198
136023e0
XL
199#[track_caller]
200pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
201 let src = src.as_ref();
202 let dst = dst.as_ref();
203 if let Err(_) = fs::hard_link(src, dst) {
204 fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed
205 }
206}
207
208#[track_caller]
209pub(crate) fn spawn_and_wait(mut cmd: Command) {
ed00b5ec
FG
210 let status = cmd.spawn().unwrap().wait().unwrap();
211 if !status.success() {
212 eprintln!("{cmd:?} exited with status {:?}", status);
136023e0
XL
213 process::exit(1);
214 }
215}
216
9ffffee4
FG
217// Based on the retry function in rust's src/ci/shared.sh
218#[track_caller]
219pub(crate) fn retry_spawn_and_wait(tries: u64, mut cmd: Command) {
220 for i in 1..tries + 1 {
221 if i != 1 {
ed00b5ec 222 eprintln!("Command failed. Attempt {i}/{tries}:");
9ffffee4
FG
223 }
224 if cmd.spawn().unwrap().wait().unwrap().success() {
225 return;
226 }
227 std::thread::sleep(std::time::Duration::from_secs(i * 5));
228 }
ed00b5ec 229 eprintln!("The command has failed after {tries} attempts.");
9ffffee4
FG
230 process::exit(1);
231}
232
9ffffee4
FG
233pub(crate) fn remove_dir_if_exists(path: &Path) {
234 match fs::remove_dir_all(&path) {
235 Ok(()) => {}
236 Err(err) if err.kind() == io::ErrorKind::NotFound => {}
237 Err(err) => panic!("Failed to remove {path}: {err}", path = path.display()),
238 }
239}
240
136023e0
XL
241pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
242 for entry in fs::read_dir(from).unwrap() {
243 let entry = entry.unwrap();
244 let filename = entry.file_name();
245 if filename == "." || filename == ".." {
246 continue;
247 }
248 if entry.metadata().unwrap().is_dir() {
249 fs::create_dir(to.join(&filename)).unwrap();
250 copy_dir_recursively(&from.join(&filename), &to.join(&filename));
251 } else {
252 fs::copy(from.join(&filename), to.join(&filename)).unwrap();
253 }
254 }
255}
f2b60f7d 256
add651ee
FG
257static IN_GROUP: AtomicBool = AtomicBool::new(false);
258pub(crate) struct LogGroup {
259 is_gha: bool,
260}
261
262impl LogGroup {
263 pub(crate) fn guard(name: &str) -> LogGroup {
264 let is_gha = env::var("GITHUB_ACTIONS").is_ok();
265
266 assert!(!IN_GROUP.swap(true, Ordering::SeqCst));
267 if is_gha {
268 eprintln!("::group::{name}");
269 }
270
271 LogGroup { is_gha }
272 }
273}
274
275impl Drop for LogGroup {
276 fn drop(&mut self) {
277 if self.is_gha {
278 eprintln!("::endgroup::");
279 }
280 IN_GROUP.store(false, Ordering::SeqCst);
281 }
282}