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;
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#[derive(Debug)]
27#[must_use]
28pub struct Rustc {
29 cmd: Command,
30 target: Option<String>,
31}
32
33crate::macros::impl_common_helpers!(Rustc, |rustc: &mut Rustc| {
35 if let Some(target) = &rustc.target {
36 rustc.cmd.arg(&format!("--target={target}"));
37 }
38});
39
40pub fn rustc_path() -> String {
41 env_var("RUSTC")
42}
43
44#[track_caller]
45fn setup_common() -> Command {
46 let mut cmd = Command::new(rustc_path());
47 set_host_compiler_dylib_path(&mut cmd);
48 cmd
49}
50
51impl Rustc {
52 #[track_caller]
59 pub fn new() -> Self {
60 let mut cmd = setup_common();
61 cmd.arg("-L").arg(cwd());
62
63 if std::env::var("IS_MUSL_HOST").is_ok_and(|i| i == "1") {
66 cmd.arg("-Ctarget-feature=-crt-static");
67 }
68
69 Self { cmd, target: Some(target()) }
71 }
72
73 #[track_caller]
75 pub fn bare() -> Self {
76 let cmd = setup_common();
77 Self { cmd, target: None }
78 }
79
80 pub fn cfg(&mut self, s: &str) -> &mut Self {
84 self.cmd.arg("--cfg");
85 self.cmd.arg(s);
86 self
87 }
88
89 pub fn opt(&mut self) -> &mut Self {
91 self.cmd.arg("-O");
92 self
93 }
94
95 pub fn opt_level(&mut self, option: &str) -> &mut Self {
97 self.cmd.arg(format!("-Copt-level={option}"));
98 self
99 }
100
101 pub fn metadata(&mut self, meta: &str) -> &mut Self {
103 self.cmd.arg(format!("-Cmetadata={meta}"));
104 self
105 }
106
107 pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
109 self.cmd.arg(format!("-Cextra-filename={suffix}"));
110 self
111 }
112
113 pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
115 let kinds = kinds.as_ref();
116 self.cmd.arg(format!("--emit={kinds}"));
117 self
118 }
119
120 pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
122 assert!(
123 !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
124 "crate name cannot contain whitespace or path separators"
125 );
126
127 let path = path.as_ref().to_string_lossy();
128
129 self.cmd.arg("--extern");
130 self.cmd.arg(format!("{crate_name}={path}"));
131
132 self
133 }
134
135 pub fn remap_path_prefix<P: AsRef<Path>, P2: AsRef<Path>>(
137 &mut self,
138 from: P,
139 to: P2,
140 ) -> &mut Self {
141 let from = from.as_ref().to_string_lossy();
142 let to = to.as_ref().to_string_lossy();
143
144 self.cmd.arg("--remap-path-prefix");
145 self.cmd.arg(format!("{from}={to}"));
146
147 self
148 }
149
150 pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
152 self.cmd.arg(path.as_ref());
153 self
154 }
155
156 pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
158 self.cmd.env("RUST_BACKTRACE", level);
159 self
160 }
161
162 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
164 self.cmd.arg("-o");
165 self.cmd.arg(path.as_ref());
166 self
167 }
168
169 pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
171 self.cmd.arg("--out-dir");
172 self.cmd.arg(path.as_ref());
173 self
174 }
175
176 pub fn lto(&mut self, option: &str) -> &mut Self {
178 self.cmd.arg(format!("-Clto={option}"));
179 self
180 }
181
182 pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
184 self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
185 self
186 }
187
188 pub fn panic(&mut self, option: &str) -> &mut Self {
190 self.cmd.arg(format!("-Cpanic={option}"));
191 self
192 }
193
194 pub fn codegen_units(&mut self, units: usize) -> &mut Self {
196 self.cmd.arg(format!("-Ccodegen-units={units}"));
197 self
198 }
199
200 pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
202 let mut arg = OsString::new();
203 arg.push("-Cincremental=");
204 arg.push(path.as_ref());
205 self.cmd.arg(&arg);
206 self
207 }
208
209 pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
211 let mut arg = OsString::new();
212 arg.push("-Cprofile-generate=");
213 arg.push(path.as_ref());
214 self.cmd.arg(&arg);
215 self
216 }
217
218 pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
220 let mut arg = OsString::new();
221 arg.push("-Cprofile-use=");
222 arg.push(path.as_ref());
223 self.cmd.arg(&arg);
224 self
225 }
226
227 pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
229 self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
230 self
231 }
232
233 pub fn prefer_dynamic(&mut self) -> &mut Self {
235 self.cmd.arg(format!("-Cprefer-dynamic"));
236 self
237 }
238
239 pub fn error_format(&mut self, format: &str) -> &mut Self {
241 self.cmd.arg(format!("--error-format={format}"));
242 self
243 }
244
245 pub fn json(&mut self, items: &str) -> &mut Self {
247 self.cmd.arg(format!("--json={items}"));
248 self
249 }
250
251 pub fn ui_testing(&mut self) -> &mut Self {
253 self.cmd.arg(format!("-Zui-testing"));
254 self
255 }
256
257 pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
259 self.target = Some(target.as_ref().to_string());
262 self
263 }
264
265 pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
267 let target_cpu = target_cpu.as_ref();
268 self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
269 self
270 }
271
272 pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
274 self.cmd.arg("--crate-type");
275 self.cmd.arg(crate_type);
276 self
277 }
278
279 pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
281 self.cmd.arg("-L");
282 self.cmd.arg(path.as_ref());
283 self
284 }
285
286 pub fn specific_library_search_path<P: AsRef<Path>>(
289 &mut self,
290 kind: &str,
291 path: P,
292 ) -> &mut Self {
293 assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
294 let path = path.as_ref().to_string_lossy();
295 self.cmd.arg(format!("-L{kind}={path}"));
296 self
297 }
298
299 pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
301 self.cmd.arg("--sysroot");
302 self.cmd.arg(path.as_ref());
303 self
304 }
305
306 pub fn edition(&mut self, edition: &str) -> &mut Self {
308 self.cmd.arg("--edition");
309 self.cmd.arg(edition);
310 self
311 }
312
313 pub fn print(&mut self, request: &str) -> &mut Self {
315 self.cmd.arg("--print");
316 self.cmd.arg(request);
317 self
318 }
319
320 pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
322 self.cmd.arg(format!("-Clink-arg={link_arg}"));
323 self
324 }
325
326 pub fn link_args(&mut self, link_args: &str) -> &mut Self {
328 self.cmd.arg(format!("-Clink-args={link_args}"));
329 self
330 }
331
332 pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
334 self.cmd.stdin_buf(input);
335 self
336 }
337
338 pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
340 self.cmd.arg("--crate-name");
341 self.cmd.arg(name.as_ref());
342 self
343 }
344
345 pub fn linker(&mut self, linker: &str) -> &mut Self {
347 self.cmd.arg(format!("-Clinker={linker}"));
348 self
349 }
350
351 pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
353 self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
354 self
355 }
356
357 pub fn debuginfo(&mut self, level: &str) -> &mut Self {
359 self.cmd.arg(format!("-Cdebuginfo={level}"));
360 self
361 }
362
363 pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self {
365 self.cmd.arg(format!("-Csplit-debuginfo={split_kind}"));
366 self
367 }
368
369 pub fn verbose(&mut self) -> &mut Self {
371 self.cmd.arg("--verbose");
372 self
373 }
374
375 pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
377 if is_windows() {
378 if !is_windows_msvc() {
394 self.cmd.arg("-lstatic:-bundle=stdc++");
395 };
396 } else if is_darwin() {
397 self.cmd.arg("-lc++");
398 } else if is_aix() {
399 self.cmd.arg("-lc++");
400 self.cmd.arg("-lc++abi");
401 } else {
402 if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
403 self.cmd.arg("-lstdc++");
404 };
405 };
406 self
407 }
408}
409
410#[track_caller]
412pub fn sysroot() -> PathBuf {
413 let path = rustc().print("sysroot").run().stdout_utf8();
414 PathBuf::from_str(path.trim()).unwrap()
415}