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, 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}
31
32crate::macros::impl_common_helpers!(Rustc);
33
34pub fn rustc_path() -> String {
35 env_var("RUSTC")
36}
37
38#[track_caller]
39fn setup_common() -> Command {
40 let mut cmd = Command::new(rustc_path());
41 set_host_compiler_dylib_path(&mut cmd);
42 cmd
43}
44
45impl Rustc {
46 #[track_caller]
51 pub fn new() -> Self {
52 let mut cmd = setup_common();
53 cmd.arg("-L").arg(cwd());
54 Self { cmd }
55 }
56
57 #[track_caller]
59 pub fn bare() -> Self {
60 let cmd = setup_common();
61 Self { cmd }
62 }
63
64 pub fn cfg(&mut self, s: &str) -> &mut Self {
68 self.cmd.arg("--cfg");
69 self.cmd.arg(s);
70 self
71 }
72
73 pub fn opt(&mut self) -> &mut Self {
75 self.cmd.arg("-O");
76 self
77 }
78
79 pub fn opt_level(&mut self, option: &str) -> &mut Self {
81 self.cmd.arg(format!("-Copt-level={option}"));
82 self
83 }
84
85 pub fn metadata(&mut self, meta: &str) -> &mut Self {
87 self.cmd.arg(format!("-Cmetadata={meta}"));
88 self
89 }
90
91 pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
93 self.cmd.arg(format!("-Cextra-filename={suffix}"));
94 self
95 }
96
97 pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
99 let kinds = kinds.as_ref();
100 self.cmd.arg(format!("--emit={kinds}"));
101 self
102 }
103
104 pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
106 assert!(
107 !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
108 "crate name cannot contain whitespace or path separators"
109 );
110
111 let path = path.as_ref().to_string_lossy();
112
113 self.cmd.arg("--extern");
114 self.cmd.arg(format!("{crate_name}={path}"));
115
116 self
117 }
118
119 pub fn remap_path_prefix<P: AsRef<Path>, P2: AsRef<Path>>(
121 &mut self,
122 from: P,
123 to: P2,
124 ) -> &mut Self {
125 let from = from.as_ref().to_string_lossy();
126 let to = to.as_ref().to_string_lossy();
127
128 self.cmd.arg("--remap-path-prefix");
129 self.cmd.arg(format!("{from}={to}"));
130
131 self
132 }
133
134 pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
136 self.cmd.arg(path.as_ref());
137 self
138 }
139
140 pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
142 self.cmd.env("RUST_BACKTRACE", level);
143 self
144 }
145
146 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
148 self.cmd.arg("-o");
149 self.cmd.arg(path.as_ref());
150 self
151 }
152
153 pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
155 self.cmd.arg("--out-dir");
156 self.cmd.arg(path.as_ref());
157 self
158 }
159
160 pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
162 self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
163 self
164 }
165
166 pub fn panic(&mut self, option: &str) -> &mut Self {
168 self.cmd.arg(format!("-Cpanic={option}"));
169 self
170 }
171
172 pub fn codegen_units(&mut self, units: usize) -> &mut Self {
174 self.cmd.arg(format!("-Ccodegen-units={units}"));
175 self
176 }
177
178 pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
180 let mut arg = OsString::new();
181 arg.push("-Cincremental=");
182 arg.push(path.as_ref());
183 self.cmd.arg(&arg);
184 self
185 }
186
187 pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
189 let mut arg = OsString::new();
190 arg.push("-Cprofile-generate=");
191 arg.push(path.as_ref());
192 self.cmd.arg(&arg);
193 self
194 }
195
196 pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
198 let mut arg = OsString::new();
199 arg.push("-Cprofile-use=");
200 arg.push(path.as_ref());
201 self.cmd.arg(&arg);
202 self
203 }
204
205 pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
207 self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
208 self
209 }
210
211 pub fn prefer_dynamic(&mut self) -> &mut Self {
213 self.cmd.arg(format!("-Cprefer-dynamic"));
214 self
215 }
216
217 pub fn error_format(&mut self, format: &str) -> &mut Self {
219 self.cmd.arg(format!("--error-format={format}"));
220 self
221 }
222
223 pub fn json(&mut self, items: &str) -> &mut Self {
225 self.cmd.arg(format!("--json={items}"));
226 self
227 }
228
229 pub fn ui_testing(&mut self) -> &mut Self {
231 self.cmd.arg(format!("-Zui-testing"));
232 self
233 }
234
235 pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
237 let target = target.as_ref();
238 self.cmd.arg(format!("--target={target}"));
239 self
240 }
241
242 pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
244 let target_cpu = target_cpu.as_ref();
245 self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
246 self
247 }
248
249 pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
251 self.cmd.arg("--crate-type");
252 self.cmd.arg(crate_type);
253 self
254 }
255
256 pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
258 self.cmd.arg("-L");
259 self.cmd.arg(path.as_ref());
260 self
261 }
262
263 pub fn specific_library_search_path<P: AsRef<Path>>(
266 &mut self,
267 kind: &str,
268 path: P,
269 ) -> &mut Self {
270 assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
271 let path = path.as_ref().to_string_lossy();
272 self.cmd.arg(format!("-L{kind}={path}"));
273 self
274 }
275
276 pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
278 self.cmd.arg("--sysroot");
279 self.cmd.arg(path.as_ref());
280 self
281 }
282
283 pub fn edition(&mut self, edition: &str) -> &mut Self {
285 self.cmd.arg("--edition");
286 self.cmd.arg(edition);
287 self
288 }
289
290 pub fn print(&mut self, request: &str) -> &mut Self {
292 self.cmd.arg("--print");
293 self.cmd.arg(request);
294 self
295 }
296
297 pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
299 self.cmd.arg(format!("-Clink-arg={link_arg}"));
300 self
301 }
302
303 pub fn link_args(&mut self, link_args: &str) -> &mut Self {
305 self.cmd.arg(format!("-Clink-args={link_args}"));
306 self
307 }
308
309 pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
311 self.cmd.stdin_buf(input);
312 self
313 }
314
315 pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
317 self.cmd.arg("--crate-name");
318 self.cmd.arg(name.as_ref());
319 self
320 }
321
322 pub fn linker(&mut self, linker: &str) -> &mut Self {
324 self.cmd.arg(format!("-Clinker={linker}"));
325 self
326 }
327
328 pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
330 self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
331 self
332 }
333
334 pub fn debuginfo(&mut self, level: &str) -> &mut Self {
336 self.cmd.arg(format!("-Cdebuginfo={level}"));
337 self
338 }
339
340 pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self {
342 self.cmd.arg(format!("-Csplit-debuginfo={split_kind}"));
343 self
344 }
345
346 pub fn verbose(&mut self) -> &mut Self {
348 self.cmd.arg("--verbose");
349 self
350 }
351
352 pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
354 if is_windows() {
355 if !is_msvc() {
371 self.cmd.arg("-lstatic:-bundle=stdc++");
372 };
373 } else if is_darwin() {
374 self.cmd.arg("-lc++");
375 } else if is_aix() {
376 self.cmd.arg("-lc++");
377 self.cmd.arg("-lc++abi");
378 } else {
379 if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
380 self.cmd.arg("-lstdc++");
381 };
382 };
383 self
384 }
385}
386
387#[track_caller]
389pub fn sysroot() -> PathBuf {
390 let path = rustc().print("sysroot").run().stdout_utf8();
391 PathBuf::from_str(path.trim()).unwrap()
392}