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]
47pub fn rustc_minicore() -> Rustc {
48 let mut builder = rustc();
49
50 let minicore_path = source_root().join("tests/auxiliary/minicore.rs");
51 builder.input(minicore_path).crate_name("minicore").crate_type("rlib");
52
53 builder
54}
55
56#[derive(Debug)]
58#[must_use]
59pub struct Rustc {
60 cmd: Command,
61 target: Option<String>,
62}
63
64crate::macros::impl_common_helpers!(Rustc, |rustc: &mut Rustc| {
66 if let Some(target) = &rustc.target {
67 rustc.cmd.arg(&format!("--target={target}"));
68 }
69});
70
71pub fn rustc_path() -> String {
72 env_var("RUSTC")
73}
74
75#[track_caller]
76fn setup_common() -> Command {
77 let mut cmd = Command::new(rustc_path());
78 set_host_compiler_dylib_path(&mut cmd);
79 if let Ok(codegen_backend) = std::env::var("RUSTC_CODEGEN_BACKEND") {
80 cmd.arg(format!("-Zcodegen-backend={codegen_backend}"));
81 }
82 cmd
83}
84
85impl Rustc {
86 #[track_caller]
93 pub fn new() -> Self {
94 let mut cmd = setup_common();
95 cmd.arg("-L").arg(cwd());
96
97 if std::env::var("IS_MUSL_HOST").is_ok_and(|i| i == "1") {
100 cmd.arg("-Ctarget-feature=-crt-static");
101 }
102
103 Self { cmd, target: Some(target()) }
105 }
106
107 #[track_caller]
109 pub fn bare() -> Self {
110 let cmd = setup_common();
111 Self { cmd, target: None }
112 }
113
114 pub fn cfg(&mut self, s: &str) -> &mut Self {
118 self.cmd.arg("--cfg");
119 self.cmd.arg(s);
120 self
121 }
122
123 pub fn opt(&mut self) -> &mut Self {
125 self.cmd.arg("-O");
126 self
127 }
128
129 pub fn opt_level(&mut self, option: &str) -> &mut Self {
131 self.cmd.arg(format!("-Copt-level={option}"));
132 self
133 }
134
135 pub fn metadata(&mut self, meta: &str) -> &mut Self {
137 self.cmd.arg(format!("-Cmetadata={meta}"));
138 self
139 }
140
141 pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
143 self.cmd.arg(format!("-Cextra-filename={suffix}"));
144 self
145 }
146
147 pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
149 let kinds = kinds.as_ref();
150 self.cmd.arg(format!("--emit={kinds}"));
151 self
152 }
153
154 pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
156 assert!(
157 !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
158 "crate name cannot contain whitespace or path separators"
159 );
160
161 let path = path.as_ref().to_string_lossy();
162
163 self.cmd.arg("--extern");
164 self.cmd.arg(format!("{crate_name}={path}"));
165
166 self
167 }
168
169 pub fn remap_path_prefix<P: AsRef<Path>, P2: AsRef<Path>>(
171 &mut self,
172 from: P,
173 to: P2,
174 ) -> &mut Self {
175 let from = from.as_ref().to_string_lossy();
176 let to = to.as_ref().to_string_lossy();
177
178 self.cmd.arg("--remap-path-prefix");
179 self.cmd.arg(format!("{from}={to}"));
180
181 self
182 }
183
184 pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
186 self.cmd.arg(path.as_ref());
187 self
188 }
189
190 pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
192 self.cmd.env("RUST_BACKTRACE", level);
193 self
194 }
195
196 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
198 self.cmd.arg("-o");
199 self.cmd.arg(path.as_ref());
200 self
201 }
202
203 pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
205 self.cmd.arg("--out-dir");
206 self.cmd.arg(path.as_ref());
207 self
208 }
209
210 pub fn lto(&mut self, option: &str) -> &mut Self {
212 self.cmd.arg(format!("-Clto={option}"));
213 self
214 }
215
216 pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
218 self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
219 self
220 }
221
222 pub fn panic(&mut self, option: &str) -> &mut Self {
224 self.cmd.arg(format!("-Cpanic={option}"));
225 self
226 }
227
228 pub fn codegen_units(&mut self, units: usize) -> &mut Self {
230 self.cmd.arg(format!("-Ccodegen-units={units}"));
231 self
232 }
233
234 pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
236 let mut arg = OsString::new();
237 arg.push("-Cincremental=");
238 arg.push(path.as_ref());
239 self.cmd.arg(&arg);
240 self
241 }
242
243 pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
245 let mut arg = OsString::new();
246 arg.push("-Cprofile-generate=");
247 arg.push(path.as_ref());
248 self.cmd.arg(&arg);
249 self
250 }
251
252 pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
254 let mut arg = OsString::new();
255 arg.push("-Cprofile-use=");
256 arg.push(path.as_ref());
257 self.cmd.arg(&arg);
258 self
259 }
260
261 pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
263 self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
264 self
265 }
266
267 pub fn prefer_dynamic(&mut self) -> &mut Self {
269 self.cmd.arg(format!("-Cprefer-dynamic"));
270 self
271 }
272
273 pub fn error_format(&mut self, format: &str) -> &mut Self {
275 self.cmd.arg(format!("--error-format={format}"));
276 self
277 }
278
279 pub fn json(&mut self, items: &str) -> &mut Self {
281 self.cmd.arg(format!("--json={items}"));
282 self
283 }
284
285 pub fn ui_testing(&mut self) -> &mut Self {
287 self.cmd.arg(format!("-Zui-testing"));
288 self
289 }
290
291 pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
293 self.target = Some(target.as_ref().to_string());
296 self
297 }
298
299 pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
301 let target_cpu = target_cpu.as_ref();
302 self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
303 self
304 }
305
306 pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
308 self.cmd.arg("--crate-type");
309 self.cmd.arg(crate_type);
310 self
311 }
312
313 pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
315 self.cmd.arg("-L");
316 self.cmd.arg(path.as_ref());
317 self
318 }
319
320 pub fn specific_library_search_path<P: AsRef<Path>>(
323 &mut self,
324 kind: &str,
325 path: P,
326 ) -> &mut Self {
327 assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
328 let path = path.as_ref().to_string_lossy();
329 self.cmd.arg(format!("-L{kind}={path}"));
330 self
331 }
332
333 pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
335 self.cmd.arg("--sysroot");
336 self.cmd.arg(path.as_ref());
337 self
338 }
339
340 pub fn edition(&mut self, edition: &str) -> &mut Self {
342 self.cmd.arg("--edition");
343 self.cmd.arg(edition);
344 self
345 }
346
347 pub fn print(&mut self, request: &str) -> &mut Self {
349 self.cmd.arg("--print");
350 self.cmd.arg(request);
351 self
352 }
353
354 pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
356 self.cmd.arg(format!("-Clink-arg={link_arg}"));
357 self
358 }
359
360 pub fn link_args(&mut self, link_args: &str) -> &mut Self {
362 self.cmd.arg(format!("-Clink-args={link_args}"));
363 self
364 }
365
366 pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
368 self.cmd.stdin_buf(input);
369 self
370 }
371
372 pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
374 self.cmd.arg("--crate-name");
375 self.cmd.arg(name.as_ref());
376 self
377 }
378
379 pub fn linker(&mut self, linker: &str) -> &mut Self {
381 self.cmd.arg(format!("-Clinker={linker}"));
382 self
383 }
384
385 pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
387 self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
388 self
389 }
390
391 pub fn debuginfo(&mut self, level: &str) -> &mut Self {
393 self.cmd.arg(format!("-Cdebuginfo={level}"));
394 self
395 }
396
397 pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self {
399 self.cmd.arg(format!("-Csplit-debuginfo={split_kind}"));
400 self
401 }
402
403 pub fn link_self_contained(&mut self, enabled: bool) -> &mut Self {
405 let enabled = if enabled { "y" } else { "n" };
406 self.cmd.arg(format!("-Clink-self-contained={enabled}"));
407 self
408 }
409
410 pub fn split_dwarf_out_dir(&mut self, out_dir: Option<&str>) -> &mut Self {
411 if let Some(out_dir) = out_dir {
412 self.cmd.arg(format!("-Zsplit-dwarf-out-dir={out_dir}"));
413 }
414 self
415 }
416
417 pub fn verbose(&mut self) -> &mut Self {
419 self.cmd.arg("--verbose");
420 self
421 }
422
423 pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
425 if is_windows() {
426 if !is_windows_msvc() {
442 self.cmd.arg("-lstatic:-bundle=stdc++");
443 };
444 } else if is_darwin() {
445 self.cmd.arg("-lc++");
446 } else if is_aix() {
447 self.cmd.arg("-lc++");
448 self.cmd.arg("-lc++abi");
449 } else {
450 if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
451 self.cmd.arg("-lstdc++");
452 };
453 };
454 self
455 }
456
457 pub fn codegen_source_order(&mut self) -> &mut Self {
459 self.cmd.arg("-Zcodegen-source-order");
460 self
461 }
462
463 pub fn function_sections(&mut self, enable: bool) -> &mut Self {
465 let flag = match enable {
466 true => "-Zfunction-sections=yes",
467 false => "-Zfunction-sections=no",
468 };
469 self.cmd.arg(flag);
470 self
471 }
472}
473
474#[track_caller]
476pub fn sysroot() -> PathBuf {
477 let path = rustc().print("sysroot").run().stdout_utf8();
478 PathBuf::from_str(path.trim()).unwrap()
479}