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 cmd
80}
81
82impl Rustc {
83 #[track_caller]
90 pub fn new() -> Self {
91 let mut cmd = setup_common();
92 cmd.arg("-L").arg(cwd());
93
94 if std::env::var("IS_MUSL_HOST").is_ok_and(|i| i == "1") {
97 cmd.arg("-Ctarget-feature=-crt-static");
98 }
99
100 Self { cmd, target: Some(target()) }
102 }
103
104 #[track_caller]
106 pub fn bare() -> Self {
107 let cmd = setup_common();
108 Self { cmd, target: None }
109 }
110
111 pub fn cfg(&mut self, s: &str) -> &mut Self {
115 self.cmd.arg("--cfg");
116 self.cmd.arg(s);
117 self
118 }
119
120 pub fn opt(&mut self) -> &mut Self {
122 self.cmd.arg("-O");
123 self
124 }
125
126 pub fn opt_level(&mut self, option: &str) -> &mut Self {
128 self.cmd.arg(format!("-Copt-level={option}"));
129 self
130 }
131
132 pub fn metadata(&mut self, meta: &str) -> &mut Self {
134 self.cmd.arg(format!("-Cmetadata={meta}"));
135 self
136 }
137
138 pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
140 self.cmd.arg(format!("-Cextra-filename={suffix}"));
141 self
142 }
143
144 pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
146 let kinds = kinds.as_ref();
147 self.cmd.arg(format!("--emit={kinds}"));
148 self
149 }
150
151 pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
153 assert!(
154 !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
155 "crate name cannot contain whitespace or path separators"
156 );
157
158 let path = path.as_ref().to_string_lossy();
159
160 self.cmd.arg("--extern");
161 self.cmd.arg(format!("{crate_name}={path}"));
162
163 self
164 }
165
166 pub fn remap_path_prefix<P: AsRef<Path>, P2: AsRef<Path>>(
168 &mut self,
169 from: P,
170 to: P2,
171 ) -> &mut Self {
172 let from = from.as_ref().to_string_lossy();
173 let to = to.as_ref().to_string_lossy();
174
175 self.cmd.arg("--remap-path-prefix");
176 self.cmd.arg(format!("{from}={to}"));
177
178 self
179 }
180
181 pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
183 self.cmd.arg(path.as_ref());
184 self
185 }
186
187 pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
189 self.cmd.env("RUST_BACKTRACE", level);
190 self
191 }
192
193 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
195 self.cmd.arg("-o");
196 self.cmd.arg(path.as_ref());
197 self
198 }
199
200 pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
202 self.cmd.arg("--out-dir");
203 self.cmd.arg(path.as_ref());
204 self
205 }
206
207 pub fn lto(&mut self, option: &str) -> &mut Self {
209 self.cmd.arg(format!("-Clto={option}"));
210 self
211 }
212
213 pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
215 self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
216 self
217 }
218
219 pub fn panic(&mut self, option: &str) -> &mut Self {
221 self.cmd.arg(format!("-Cpanic={option}"));
222 self
223 }
224
225 pub fn codegen_units(&mut self, units: usize) -> &mut Self {
227 self.cmd.arg(format!("-Ccodegen-units={units}"));
228 self
229 }
230
231 pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
233 let mut arg = OsString::new();
234 arg.push("-Cincremental=");
235 arg.push(path.as_ref());
236 self.cmd.arg(&arg);
237 self
238 }
239
240 pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
242 let mut arg = OsString::new();
243 arg.push("-Cprofile-generate=");
244 arg.push(path.as_ref());
245 self.cmd.arg(&arg);
246 self
247 }
248
249 pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
251 let mut arg = OsString::new();
252 arg.push("-Cprofile-use=");
253 arg.push(path.as_ref());
254 self.cmd.arg(&arg);
255 self
256 }
257
258 pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
260 self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
261 self
262 }
263
264 pub fn prefer_dynamic(&mut self) -> &mut Self {
266 self.cmd.arg(format!("-Cprefer-dynamic"));
267 self
268 }
269
270 pub fn error_format(&mut self, format: &str) -> &mut Self {
272 self.cmd.arg(format!("--error-format={format}"));
273 self
274 }
275
276 pub fn json(&mut self, items: &str) -> &mut Self {
278 self.cmd.arg(format!("--json={items}"));
279 self
280 }
281
282 pub fn ui_testing(&mut self) -> &mut Self {
284 self.cmd.arg(format!("-Zui-testing"));
285 self
286 }
287
288 pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
290 self.target = Some(target.as_ref().to_string());
293 self
294 }
295
296 pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
298 let target_cpu = target_cpu.as_ref();
299 self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
300 self
301 }
302
303 pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
305 self.cmd.arg("--crate-type");
306 self.cmd.arg(crate_type);
307 self
308 }
309
310 pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
312 self.cmd.arg("-L");
313 self.cmd.arg(path.as_ref());
314 self
315 }
316
317 pub fn specific_library_search_path<P: AsRef<Path>>(
320 &mut self,
321 kind: &str,
322 path: P,
323 ) -> &mut Self {
324 assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
325 let path = path.as_ref().to_string_lossy();
326 self.cmd.arg(format!("-L{kind}={path}"));
327 self
328 }
329
330 pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
332 self.cmd.arg("--sysroot");
333 self.cmd.arg(path.as_ref());
334 self
335 }
336
337 pub fn edition(&mut self, edition: &str) -> &mut Self {
339 self.cmd.arg("--edition");
340 self.cmd.arg(edition);
341 self
342 }
343
344 pub fn print(&mut self, request: &str) -> &mut Self {
346 self.cmd.arg("--print");
347 self.cmd.arg(request);
348 self
349 }
350
351 pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
353 self.cmd.arg(format!("-Clink-arg={link_arg}"));
354 self
355 }
356
357 pub fn link_args(&mut self, link_args: &str) -> &mut Self {
359 self.cmd.arg(format!("-Clink-args={link_args}"));
360 self
361 }
362
363 pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
365 self.cmd.stdin_buf(input);
366 self
367 }
368
369 pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
371 self.cmd.arg("--crate-name");
372 self.cmd.arg(name.as_ref());
373 self
374 }
375
376 pub fn linker(&mut self, linker: &str) -> &mut Self {
378 self.cmd.arg(format!("-Clinker={linker}"));
379 self
380 }
381
382 pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
384 self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
385 self
386 }
387
388 pub fn debuginfo(&mut self, level: &str) -> &mut Self {
390 self.cmd.arg(format!("-Cdebuginfo={level}"));
391 self
392 }
393
394 pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self {
396 self.cmd.arg(format!("-Csplit-debuginfo={split_kind}"));
397 self
398 }
399
400 pub fn split_dwarf_out_dir(&mut self, out_dir: Option<&str>) -> &mut Self {
401 if let Some(out_dir) = out_dir {
402 self.cmd.arg(format!("-Zsplit-dwarf-out-dir={out_dir}"));
403 }
404 self
405 }
406
407 pub fn verbose(&mut self) -> &mut Self {
409 self.cmd.arg("--verbose");
410 self
411 }
412
413 pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
415 if is_windows() {
416 if !is_windows_msvc() {
432 self.cmd.arg("-lstatic:-bundle=stdc++");
433 };
434 } else if is_darwin() {
435 self.cmd.arg("-lc++");
436 } else if is_aix() {
437 self.cmd.arg("-lc++");
438 self.cmd.arg("-lc++abi");
439 } else {
440 if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
441 self.cmd.arg("-lstdc++");
442 };
443 };
444 self
445 }
446
447 pub fn codegen_source_order(&mut self) -> &mut Self {
449 self.cmd.arg("-Zcodegen-source-order");
450 self
451 }
452}
453
454#[track_caller]
456pub fn sysroot() -> PathBuf {
457 let path = rustc().print("sysroot").run().stdout_utf8();
458 PathBuf::from_str(path.trim()).unwrap()
459}