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_msvc, is_windows, 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]
58 pub fn new() -> Self {
59 let mut cmd = setup_common();
60 cmd.arg("-L").arg(cwd());
61
62 Self { cmd, target: Some(target()) }
64 }
65
66 #[track_caller]
68 pub fn bare() -> Self {
69 let cmd = setup_common();
70 Self { cmd, target: None }
71 }
72
73 pub fn cfg(&mut self, s: &str) -> &mut Self {
77 self.cmd.arg("--cfg");
78 self.cmd.arg(s);
79 self
80 }
81
82 pub fn opt(&mut self) -> &mut Self {
84 self.cmd.arg("-O");
85 self
86 }
87
88 pub fn opt_level(&mut self, option: &str) -> &mut Self {
90 self.cmd.arg(format!("-Copt-level={option}"));
91 self
92 }
93
94 pub fn metadata(&mut self, meta: &str) -> &mut Self {
96 self.cmd.arg(format!("-Cmetadata={meta}"));
97 self
98 }
99
100 pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
102 self.cmd.arg(format!("-Cextra-filename={suffix}"));
103 self
104 }
105
106 pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
108 let kinds = kinds.as_ref();
109 self.cmd.arg(format!("--emit={kinds}"));
110 self
111 }
112
113 pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
115 assert!(
116 !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
117 "crate name cannot contain whitespace or path separators"
118 );
119
120 let path = path.as_ref().to_string_lossy();
121
122 self.cmd.arg("--extern");
123 self.cmd.arg(format!("{crate_name}={path}"));
124
125 self
126 }
127
128 pub fn remap_path_prefix<P: AsRef<Path>, P2: AsRef<Path>>(
130 &mut self,
131 from: P,
132 to: P2,
133 ) -> &mut Self {
134 let from = from.as_ref().to_string_lossy();
135 let to = to.as_ref().to_string_lossy();
136
137 self.cmd.arg("--remap-path-prefix");
138 self.cmd.arg(format!("{from}={to}"));
139
140 self
141 }
142
143 pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
145 self.cmd.arg(path.as_ref());
146 self
147 }
148
149 pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
151 self.cmd.env("RUST_BACKTRACE", level);
152 self
153 }
154
155 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
157 self.cmd.arg("-o");
158 self.cmd.arg(path.as_ref());
159 self
160 }
161
162 pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
164 self.cmd.arg("--out-dir");
165 self.cmd.arg(path.as_ref());
166 self
167 }
168
169 pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
171 self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
172 self
173 }
174
175 pub fn panic(&mut self, option: &str) -> &mut Self {
177 self.cmd.arg(format!("-Cpanic={option}"));
178 self
179 }
180
181 pub fn codegen_units(&mut self, units: usize) -> &mut Self {
183 self.cmd.arg(format!("-Ccodegen-units={units}"));
184 self
185 }
186
187 pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
189 let mut arg = OsString::new();
190 arg.push("-Cincremental=");
191 arg.push(path.as_ref());
192 self.cmd.arg(&arg);
193 self
194 }
195
196 pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
198 let mut arg = OsString::new();
199 arg.push("-Cprofile-generate=");
200 arg.push(path.as_ref());
201 self.cmd.arg(&arg);
202 self
203 }
204
205 pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
207 let mut arg = OsString::new();
208 arg.push("-Cprofile-use=");
209 arg.push(path.as_ref());
210 self.cmd.arg(&arg);
211 self
212 }
213
214 pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
216 self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
217 self
218 }
219
220 pub fn prefer_dynamic(&mut self) -> &mut Self {
222 self.cmd.arg(format!("-Cprefer-dynamic"));
223 self
224 }
225
226 pub fn error_format(&mut self, format: &str) -> &mut Self {
228 self.cmd.arg(format!("--error-format={format}"));
229 self
230 }
231
232 pub fn json(&mut self, items: &str) -> &mut Self {
234 self.cmd.arg(format!("--json={items}"));
235 self
236 }
237
238 pub fn ui_testing(&mut self) -> &mut Self {
240 self.cmd.arg(format!("-Zui-testing"));
241 self
242 }
243
244 pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
246 self.target = Some(target.as_ref().to_string());
249 self
250 }
251
252 pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
254 let target_cpu = target_cpu.as_ref();
255 self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
256 self
257 }
258
259 pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
261 self.cmd.arg("--crate-type");
262 self.cmd.arg(crate_type);
263 self
264 }
265
266 pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
268 self.cmd.arg("-L");
269 self.cmd.arg(path.as_ref());
270 self
271 }
272
273 pub fn specific_library_search_path<P: AsRef<Path>>(
276 &mut self,
277 kind: &str,
278 path: P,
279 ) -> &mut Self {
280 assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
281 let path = path.as_ref().to_string_lossy();
282 self.cmd.arg(format!("-L{kind}={path}"));
283 self
284 }
285
286 pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
288 self.cmd.arg("--sysroot");
289 self.cmd.arg(path.as_ref());
290 self
291 }
292
293 pub fn edition(&mut self, edition: &str) -> &mut Self {
295 self.cmd.arg("--edition");
296 self.cmd.arg(edition);
297 self
298 }
299
300 pub fn print(&mut self, request: &str) -> &mut Self {
302 self.cmd.arg("--print");
303 self.cmd.arg(request);
304 self
305 }
306
307 pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
309 self.cmd.arg(format!("-Clink-arg={link_arg}"));
310 self
311 }
312
313 pub fn link_args(&mut self, link_args: &str) -> &mut Self {
315 self.cmd.arg(format!("-Clink-args={link_args}"));
316 self
317 }
318
319 pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
321 self.cmd.stdin_buf(input);
322 self
323 }
324
325 pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
327 self.cmd.arg("--crate-name");
328 self.cmd.arg(name.as_ref());
329 self
330 }
331
332 pub fn linker(&mut self, linker: &str) -> &mut Self {
334 self.cmd.arg(format!("-Clinker={linker}"));
335 self
336 }
337
338 pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
340 self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
341 self
342 }
343
344 pub fn debuginfo(&mut self, level: &str) -> &mut Self {
346 self.cmd.arg(format!("-Cdebuginfo={level}"));
347 self
348 }
349
350 pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self {
352 self.cmd.arg(format!("-Csplit-debuginfo={split_kind}"));
353 self
354 }
355
356 pub fn verbose(&mut self) -> &mut Self {
358 self.cmd.arg("--verbose");
359 self
360 }
361
362 pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
364 if is_windows() {
365 if !is_msvc() {
381 self.cmd.arg("-lstatic:-bundle=stdc++");
382 };
383 } else if is_darwin() {
384 self.cmd.arg("-lc++");
385 } else if is_aix() {
386 self.cmd.arg("-lc++");
387 self.cmd.arg("-lc++abi");
388 } else {
389 if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
390 self.cmd.arg("-lstdc++");
391 };
392 };
393 self
394 }
395}
396
397#[track_caller]
399pub fn sysroot() -> PathBuf {
400 let path = rustc().print("sysroot").run().stdout_utf8();
401 PathBuf::from_str(path.trim()).unwrap()
402}