run_make_support/external_deps/
rustc.rs
1use 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_rpath;
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#[track_caller]
27pub fn aux_build() -> Rustc {
28 Rustc::new_aux_build()
29}
30
31#[derive(Debug)]
33#[must_use]
34pub struct Rustc {
35 cmd: Command,
36}
37
38crate::macros::impl_common_helpers!(Rustc);
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_rpath(&mut cmd);
48 cmd
49}
50
51impl Rustc {
52 #[track_caller]
57 pub fn new() -> Self {
58 let mut cmd = setup_common();
59 cmd.arg("-L").arg(cwd());
60 Self { cmd }
61 }
62
63 #[track_caller]
65 pub fn bare() -> Self {
66 let cmd = setup_common();
67 Self { cmd }
68 }
69
70 #[track_caller]
72 pub fn new_aux_build() -> Self {
73 let mut cmd = setup_common();
74 cmd.arg("--crate-type=lib");
75 Self { cmd }
76 }
77
78 pub fn cfg(&mut self, s: &str) -> &mut Self {
82 self.cmd.arg("--cfg");
83 self.cmd.arg(s);
84 self
85 }
86
87 pub fn opt(&mut self) -> &mut Self {
89 self.cmd.arg("-O");
90 self
91 }
92
93 pub fn opt_level(&mut self, option: &str) -> &mut Self {
95 self.cmd.arg(format!("-Copt-level={option}"));
96 self
97 }
98
99 pub fn metadata(&mut self, meta: &str) -> &mut Self {
101 self.cmd.arg(format!("-Cmetadata={meta}"));
102 self
103 }
104
105 pub fn extra_filename(&mut self, suffix: &str) -> &mut Self {
107 self.cmd.arg(format!("-Cextra-filename={suffix}"));
108 self
109 }
110
111 pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
113 let kinds = kinds.as_ref();
114 self.cmd.arg(format!("--emit={kinds}"));
115 self
116 }
117
118 pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
120 assert!(
121 !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
122 "crate name cannot contain whitespace or path separators"
123 );
124
125 let path = path.as_ref().to_string_lossy();
126
127 self.cmd.arg("--extern");
128 self.cmd.arg(format!("{crate_name}={path}"));
129
130 self
131 }
132
133 pub fn remap_path_prefix<P: AsRef<Path>, P2: AsRef<Path>>(
135 &mut self,
136 from: P,
137 to: P2,
138 ) -> &mut Self {
139 let from = from.as_ref().to_string_lossy();
140 let to = to.as_ref().to_string_lossy();
141
142 self.cmd.arg("--remap-path-prefix");
143 self.cmd.arg(format!("{from}={to}"));
144
145 self
146 }
147
148 pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
150 self.cmd.arg(path.as_ref());
151 self
152 }
153
154 pub fn set_backtrace_level<R: AsRef<OsStr>>(&mut self, level: R) -> &mut Self {
156 self.cmd.env("RUST_BACKTRACE", level);
157 self
158 }
159
160 pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
162 self.cmd.arg("-o");
163 self.cmd.arg(path.as_ref());
164 self
165 }
166
167 pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
169 self.cmd.arg("--out-dir");
170 self.cmd.arg(path.as_ref());
171 self
172 }
173
174 pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
176 self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
177 self
178 }
179
180 pub fn panic(&mut self, option: &str) -> &mut Self {
182 self.cmd.arg(format!("-Cpanic={option}"));
183 self
184 }
185
186 pub fn codegen_units(&mut self, units: usize) -> &mut Self {
188 self.cmd.arg(format!("-Ccodegen-units={units}"));
189 self
190 }
191
192 pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
194 let mut arg = OsString::new();
195 arg.push("-Cincremental=");
196 arg.push(path.as_ref());
197 self.cmd.arg(&arg);
198 self
199 }
200
201 pub fn profile_generate<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
203 let mut arg = OsString::new();
204 arg.push("-Cprofile-generate=");
205 arg.push(path.as_ref());
206 self.cmd.arg(&arg);
207 self
208 }
209
210 pub fn profile_use<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
212 let mut arg = OsString::new();
213 arg.push("-Cprofile-use=");
214 arg.push(path.as_ref());
215 self.cmd.arg(&arg);
216 self
217 }
218
219 pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
221 self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
222 self
223 }
224
225 pub fn prefer_dynamic(&mut self) -> &mut Self {
227 self.cmd.arg(format!("-Cprefer-dynamic"));
228 self
229 }
230
231 pub fn error_format(&mut self, format: &str) -> &mut Self {
233 self.cmd.arg(format!("--error-format={format}"));
234 self
235 }
236
237 pub fn json(&mut self, items: &str) -> &mut Self {
239 self.cmd.arg(format!("--json={items}"));
240 self
241 }
242
243 pub fn ui_testing(&mut self) -> &mut Self {
245 self.cmd.arg(format!("-Zui-testing"));
246 self
247 }
248
249 pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
251 let target = target.as_ref();
252 self.cmd.arg(format!("--target={target}"));
253 self
254 }
255
256 pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
258 self.cmd.arg("--crate-type");
259 self.cmd.arg(crate_type);
260 self
261 }
262
263 pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
265 self.cmd.arg("-L");
266 self.cmd.arg(path.as_ref());
267 self
268 }
269
270 pub fn specific_library_search_path<P: AsRef<Path>>(
273 &mut self,
274 kind: &str,
275 path: P,
276 ) -> &mut Self {
277 assert!(["dependency", "native", "all", "framework", "crate"].contains(&kind));
278 let path = path.as_ref().to_string_lossy();
279 self.cmd.arg(format!("-L{kind}={path}"));
280 self
281 }
282
283 pub fn sysroot<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
285 self.cmd.arg("--sysroot");
286 self.cmd.arg(path.as_ref());
287 self
288 }
289
290 pub fn edition(&mut self, edition: &str) -> &mut Self {
292 self.cmd.arg("--edition");
293 self.cmd.arg(edition);
294 self
295 }
296
297 pub fn print(&mut self, request: &str) -> &mut Self {
299 self.cmd.arg("--print");
300 self.cmd.arg(request);
301 self
302 }
303
304 pub fn link_arg(&mut self, link_arg: &str) -> &mut Self {
306 self.cmd.arg(format!("-Clink-arg={link_arg}"));
307 self
308 }
309
310 pub fn link_args(&mut self, link_args: &str) -> &mut Self {
312 self.cmd.arg(format!("-Clink-args={link_args}"));
313 self
314 }
315
316 pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
318 self.cmd.stdin_buf(input);
319 self
320 }
321
322 pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
324 self.cmd.arg("--crate-name");
325 self.cmd.arg(name.as_ref());
326 self
327 }
328
329 pub fn linker(&mut self, linker: &str) -> &mut Self {
331 self.cmd.arg(format!("-Clinker={linker}"));
332 self
333 }
334
335 pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
337 self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
338 self
339 }
340
341 pub fn debuginfo(&mut self, level: &str) -> &mut Self {
343 self.cmd.arg(format!("-Cdebuginfo={level}"));
344 self
345 }
346
347 pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self {
349 self.cmd.arg(format!("-Csplit-debuginfo={split_kind}"));
350 self
351 }
352
353 pub fn verbose(&mut self) -> &mut Self {
355 self.cmd.arg("--verbose");
356 self
357 }
358
359 pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
361 if is_windows() {
387 if !is_msvc() {
403 self.cmd.arg("-lstatic:-bundle=stdc++");
404 };
405 } else if is_darwin() {
406 self.cmd.arg("-lc++");
407 } else if is_aix() {
408 self.cmd.arg("-lc++");
409 self.cmd.arg("-lc++abi");
410 } else {
411 if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
412 self.cmd.arg("-lstdc++");
413 };
414 };
415 self
416 }
417}
418
419#[track_caller]
421pub fn sysroot() -> PathBuf {
422 let path = rustc().print("sysroot").run().stdout_utf8();
423 PathBuf::from_str(path.trim()).unwrap()
424}