run_make_support/external_deps/
rustc.rs1use std::ffi::{OsStr, OsString};
2use std::path::{Path, PathBuf};
3use std::str::FromStr as _;
4
5use crate::command::Command;
6use crate::env::env_var;
7use crate::path_helpers::{cwd, source_root};
8use crate::util::set_host_compiler_dylib_path;
9use crate::{is_aix, is_darwin, is_windows, is_windows_msvc, target, uname};
10
11#[track_caller]
14pub fn rustc() -> Rustc {
15 Rustc::new()
16}
17
18#[track_caller]
21pub fn bare_rustc() -> Rustc {
22 Rustc::bare()
23}
24
25#[track_caller]
30pub fn stable_bare_rustc() -> Rustc {
31 Rustc::bare_stable()
32}
33
34#[track_caller]
56pub fn rustc_minicore() -> Rustc {
57 let mut builder = rustc();
58
59 let minicore_path = source_root().join("tests/auxiliary/minicore.rs");
60 builder.input(minicore_path).crate_name("minicore").crate_type("rlib");
61
62 builder
63}
64
65#[derive(Debug)]
67#[must_use]
68pub struct Rustc {
69 cmd: Command,
70 target: Option<String>,
71}
72
73crate::macros::impl_common_helpers!(Rustc, |rustc: &mut Rustc| {
75 if let Some(target) = &rustc.target {
76 rustc.cmd.arg(&format!("--target={target}"));
77 }
78});
79
80pub fn rustc_path() -> String {
81 env_var("RUSTC")
82}
83
84#[track_caller]
85fn setup_common() -> Command {
86 let mut cmd = Command::new(rustc_path());
87 set_host_compiler_dylib_path(&mut cmd);
88 cmd
89}
90
91impl Rustc {
92 #[track_caller]
99 pub fn new() -> Self {
100 let mut cmd = setup_common();
101 cmd.arg("-L").arg(cwd());
102
103 if std::env::var("IS_MUSL_HOST").is_ok_and(|i| i == "1") {
106 cmd.arg("-Ctarget-feature=-crt-static");
107 }
108
109 if let Ok(codegen_backend) = std::env::var("RUSTC_CODEGEN_BACKEND") {
110 cmd.arg(format!("-Zcodegen-backend={codegen_backend}"));
111 }
112
113 Self { cmd, target: Some(target()) }
115 }
116
117 #[track_caller]
119 pub fn bare() -> Self {
120 let cmd = setup_common();
121 Self { cmd, target: None }
122 }
123
124 #[track_caller]
126 pub fn bare_stable() -> Self {
127 let mut cmd = setup_common();
128 cmd.env("RUSTC_BOOTSTRAP", "-1");
129 Self { cmd, target: None }
130 }
131
132 pub fn cfg(&mut self, s: &str) -> &mut Self {
136 self.cmd.arg("--cfg");
137 self.cmd.arg(s);
138 self
139 }
140
141 pub fn opt(&mut self) -> &mut Self {
143 self.cmd.arg("-O");
144 self
145 }
146
147 pub fn opt_level(&mut self, option: &str) -> &mut Self {
149 self.cmd.arg(format!("-Copt-level={option}"));
150 self
151 }
152
153 pub fn metadata(&mut self, meta: &str) -> &mut Self {
155 self.cmd.arg(format!("-Cmetadata={meta}"));
156 self
157 }
158
159 pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
161 self.cmd.arg(format!("-Cextra-filename={suffix}"));
162 self
163 }
164
165 pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
167 let kinds = kinds.as_ref();
168 self.cmd.arg(format!("--emit={kinds}"));
169 self
170 }
171
172 pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
174 assert!(
175 !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
176 "crate name cannot contain whitespace or path separators"
177 );
178
179 let path = path.as_ref().to_string_lossy();
180
181 self.cmd.arg("--extern");
182 self.cmd.arg(format!("{crate_name}={path}"));
183
184 self
185 }
186
187 pub fn remap_path_prefix<P: AsRef<Path>, P2: AsRef<Path>>(
189 &mut self,
190 from: P,
191 to: P2,
192 ) -> &mut Self {
193 let from = from.as_ref().to_string_lossy();
194 let to = to.as_ref().to_string_lossy();
195
196 self.cmd.arg("--remap-path-prefix");
197 self.cmd.arg(format!("{from}={to}"));
198
199 self
200 }
201
202 pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
204 self.cmd.arg(path.as_ref());
205 self
206 }
207
208 pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
210 self.cmd.env("RUST_BACKTRACE", level);
211 self
212 }
213
214 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
216 self.cmd.arg("-o");
217 self.cmd.arg(path.as_ref());
218 self
219 }
220
221 pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
223 self.cmd.arg("--out-dir");
224 self.cmd.arg(path.as_ref());
225 self
226 }
227
228 pub fn lto(&mut self, option: &str) -> &mut Self {
230 self.cmd.arg(format!("-Clto={option}"));
231 self
232 }
233
234 pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
236 self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
237 self
238 }
239
240 pub fn panic(&mut self, option: &str) -> &mut Self {
242 self.cmd.arg(format!("-Cpanic={option}"));
243 self
244 }
245
246 pub fn codegen_units(&mut self, units: usize) -> &mut Self {
248 self.cmd.arg(format!("-Ccodegen-units={units}"));
249 self
250 }
251
252 pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
254 let mut arg = OsString::new();
255 arg.push("-Cincremental=");
256 arg.push(path.as_ref());
257 self.cmd.arg(&arg);
258 self
259 }
260
261 pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
263 let mut arg = OsString::new();
264 arg.push("-Cprofile-generate=");
265 arg.push(path.as_ref());
266 self.cmd.arg(&arg);
267 self
268 }
269
270 pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
272 let mut arg = OsString::new();
273 arg.push("-Cprofile-use=");
274 arg.push(path.as_ref());
275 self.cmd.arg(&arg);
276 self
277 }
278
279 pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
281 self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
282 self
283 }
284
285 pub fn prefer_dynamic(&mut self) -> &mut Self {
287 self.cmd.arg(format!("-Cprefer-dynamic"));
288 self
289 }
290
291 pub fn error_format(&mut self, format: &str) -> &mut Self {
293 self.cmd.arg(format!("--error-format={format}"));
294 self
295 }
296
297 pub fn json(&mut self, items: &str) -> &mut Self {
299 self.cmd.arg(format!("--json={items}"));
300 self
301 }
302
303 pub fn ui_testing(&mut self) -> &mut Self {
305 self.cmd.arg(format!("-Zui-testing"));
306 self
307 }
308
309 pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
311 self.target = Some(target.as_ref().to_string());
314 self
315 }
316
317 pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
319 let target_cpu = target_cpu.as_ref();
320 self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
321 self
322 }
323
324 pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
326 self.cmd.arg("--crate-type");
327 self.cmd.arg(crate_type);
328 self
329 }
330
331 pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
333 self.cmd.arg("-L");
334 self.cmd.arg(path.as_ref());
335 self
336 }
337
338 pub fn specific_library_search_path<P: AsRef<Path>>(
341 &mut self,
342 kind: &str,
343 path: P,
344 ) -> &mut Self {
345 assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
346 let path = path.as_ref().to_string_lossy();
347 self.cmd.arg(format!("-L{kind}={path}"));
348 self
349 }
350
351 pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
353 self.cmd.arg("--sysroot");
354 self.cmd.arg(path.as_ref());
355 self
356 }
357
358 pub fn edition(&mut self, edition: &str) -> &mut Self {
360 self.cmd.arg("--edition");
361 self.cmd.arg(edition);
362 self
363 }
364
365 pub fn print(&mut self, request: &str) -> &mut Self {
367 self.cmd.arg("--print");
368 self.cmd.arg(request);
369 self
370 }
371
372 pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
374 self.cmd.arg(format!("-Clink-arg={link_arg}"));
375 self
376 }
377
378 pub fn link_args(&mut self, link_args: &str) -> &mut Self {
380 self.cmd.arg(format!("-Clink-args={link_args}"));
381 self
382 }
383
384 pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
386 self.cmd.stdin_buf(input);
387 self
388 }
389
390 pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
392 self.cmd.arg("--crate-name");
393 self.cmd.arg(name.as_ref());
394 self
395 }
396
397 pub fn linker(&mut self, linker: &str) -> &mut Self {
399 self.cmd.arg(format!("-Clinker={linker}"));
400 self
401 }
402
403 pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
405 self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
406 self
407 }
408
409 pub fn debuginfo(&mut self, level: &str) -> &mut Self {
411 self.cmd.arg(format!("-Cdebuginfo={level}"));
412 self
413 }
414
415 pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self {
417 self.cmd.arg(format!("-Csplit-debuginfo={split_kind}"));
418 self
419 }
420
421 pub fn link_self_contained(&mut self, enabled: bool) -> &mut Self {
423 let enabled = if enabled { "y" } else { "n" };
424 self.cmd.arg(format!("-Clink-self-contained={enabled}"));
425 self
426 }
427
428 pub fn split_dwarf_out_dir(&mut self, out_dir: Option<&str>) -> &mut Self {
429 if let Some(out_dir) = out_dir {
430 self.cmd.arg(format!("-Zsplit-dwarf-out-dir={out_dir}"));
431 }
432 self
433 }
434
435 pub fn verbose(&mut self) -> &mut Self {
437 self.cmd.arg("--verbose");
438 self
439 }
440
441 pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
443 if is_windows() {
444 if !is_windows_msvc() {
460 self.cmd.arg("-lstatic:-bundle=stdc++");
461 };
462 } else if is_darwin() {
463 self.cmd.arg("-lc++");
464 } else if is_aix() {
465 self.cmd.arg("-lc++");
466 self.cmd.arg("-lc++abi");
467 } else {
468 if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
469 self.cmd.arg("-lstdc++");
470 };
471 };
472 self
473 }
474
475 pub fn codegen_source_order(&mut self) -> &mut Self {
477 self.cmd.arg("-Zcodegen-source-order");
478 self
479 }
480
481 pub fn function_sections(&mut self, enable: bool) -> &mut Self {
483 let flag = match enable {
484 true => "-Zfunction-sections=yes",
485 false => "-Zfunction-sections=no",
486 };
487 self.cmd.arg(flag);
488 self
489 }
490}
491
492#[track_caller]
494pub fn sysroot() -> PathBuf {
495 let path = rustc().print("sysroot").run().stdout_utf8();
496 PathBuf::from_str(path.trim()).unwrap()
497}