1use std::borrow::Cow;
10use std::collections::HashSet;
11use std::ffi::OsStr;
12use std::io::BufReader;
13use std::io::prelude::*;
14use std::path::{Path, PathBuf};
15use std::process::Stdio;
16use std::{env, fs, str};
17
18use serde_derive::Deserialize;
19#[cfg(feature = "tracing")]
20use tracing::{instrument, span};
21
22use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
23use crate::core::build_steps::tool::SourceType;
24use crate::core::build_steps::{dist, llvm};
25use crate::core::builder;
26use crate::core::builder::{
27 Builder, Cargo, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath, crate_description,
28};
29use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
30use crate::utils::build_stamp;
31use crate::utils::build_stamp::BuildStamp;
32use crate::utils::exec::command;
33use crate::utils::helpers::{
34 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
35};
36use crate::{CLang, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
37
38#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct Std {
40 pub target: TargetSelection,
41 pub compiler: Compiler,
42 crates: Vec<String>,
46 force_recompile: bool,
49 extra_rust_args: &'static [&'static str],
50 is_for_mir_opt_tests: bool,
51}
52
53impl Std {
54 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
55 Self {
56 target,
57 compiler,
58 crates: Default::default(),
59 force_recompile: false,
60 extra_rust_args: &[],
61 is_for_mir_opt_tests: false,
62 }
63 }
64
65 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
66 self.force_recompile = force_recompile;
67 self
68 }
69
70 #[expect(clippy::wrong_self_convention)]
71 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
72 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
73 self
74 }
75
76 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
77 self.extra_rust_args = extra_rust_args;
78 self
79 }
80
81 fn copy_extra_objects(
82 &self,
83 builder: &Builder<'_>,
84 compiler: &Compiler,
85 target: TargetSelection,
86 ) -> Vec<(PathBuf, DependencyType)> {
87 let mut deps = Vec::new();
88 if !self.is_for_mir_opt_tests {
89 deps.extend(copy_third_party_objects(builder, compiler, target));
90 deps.extend(copy_self_contained_objects(builder, compiler, target));
91 }
92 deps
93 }
94}
95
96impl Step for Std {
97 type Output = ();
98 const DEFAULT: bool = true;
99
100 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
101 run.crate_or_deps("sysroot").path("library")
102 }
103
104 #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
105 fn make_run(run: RunConfig<'_>) {
106 let crates = std_crates_for_run_make(&run);
107 let builder = run.builder;
108
109 let force_recompile = builder.rust_info().is_managed_git_subrepository()
113 && builder.download_rustc()
114 && builder.config.has_changes_from_upstream(&["library"]);
115
116 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
117 trace!("download_rustc: {}", builder.download_rustc());
118 trace!(force_recompile);
119
120 run.builder.ensure(Std {
121 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
122 target: run.target,
123 crates,
124 force_recompile,
125 extra_rust_args: &[],
126 is_for_mir_opt_tests: false,
127 });
128 }
129
130 #[cfg_attr(
136 feature = "tracing",
137 instrument(
138 level = "debug",
139 name = "Std::run",
140 skip_all,
141 fields(
142 target = ?self.target,
143 compiler = ?self.compiler,
144 force_recompile = self.force_recompile
145 ),
146 ),
147 )]
148 fn run(self, builder: &Builder<'_>) {
149 let target = self.target;
150 let compiler = self.compiler;
151
152 if builder.download_rustc() && builder.config.is_host_target(target)
155 && compiler.stage != 0
158 && !self.force_recompile
159 {
160 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
161 cp_rustc_component_to_ci_sysroot(
162 builder,
163 &sysroot,
164 builder.config.ci_rust_std_contents(),
165 );
166 return;
167 }
168
169 if builder.config.keep_stage.contains(&compiler.stage)
170 || builder.config.keep_stage_std.contains(&compiler.stage)
171 {
172 trace!(keep_stage = ?builder.config.keep_stage);
173 trace!(keep_stage_std = ?builder.config.keep_stage_std);
174
175 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
176
177 builder.ensure(StartupObjects { compiler, target });
178
179 self.copy_extra_objects(builder, &compiler, target);
180
181 builder.ensure(StdLink::from_std(self, compiler));
182 return;
183 }
184
185 builder.require_submodule("library/stdarch", None);
186
187 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
188
189 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
190 trace!(?compiler_to_use);
191
192 if compiler_to_use != compiler {
193 trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
194
195 builder.ensure(Std::new(compiler_to_use, target));
196 let msg = if compiler_to_use.host == target {
197 format!(
198 "Uplifting library (stage{} -> stage{})",
199 compiler_to_use.stage, compiler.stage
200 )
201 } else {
202 format!(
203 "Uplifting library (stage{}:{} -> stage{}:{})",
204 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
205 )
206 };
207 builder.info(&msg);
208
209 self.copy_extra_objects(builder, &compiler, target);
212
213 builder.ensure(StdLink::from_std(self, compiler_to_use));
214 return;
215 }
216
217 trace!(
218 ?compiler_to_use,
219 ?compiler,
220 "compiler == compiler_to_use, handling not-cross-compile scenario"
221 );
222
223 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
224
225 if compiler.stage == 0 && builder.config.is_host_target(compiler.host) {
229 trace!(
230 "(build == host) copying linking components to `stage0-sysroot` for bootstrapping"
231 );
232 let src_sysroot_bin = builder
234 .rustc_snapshot_sysroot()
235 .join("lib")
236 .join("rustlib")
237 .join(compiler.host)
238 .join("bin");
239 if src_sysroot_bin.exists() {
240 let target_sysroot_bin = builder.sysroot_target_bindir(compiler, target);
241 t!(fs::create_dir_all(&target_sysroot_bin));
242 builder.cp_link_r(&src_sysroot_bin, &target_sysroot_bin);
243 }
244 }
245
246 let mut cargo = if self.is_for_mir_opt_tests {
250 trace!("building special sysroot for mir-opt tests");
251 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
252 builder,
253 compiler,
254 Mode::Std,
255 SourceType::InTree,
256 target,
257 Kind::Check,
258 );
259 cargo.rustflag("-Zalways-encode-mir");
260 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
261 cargo
262 } else {
263 trace!("building regular sysroot");
264 let mut cargo = builder::Cargo::new(
265 builder,
266 compiler,
267 Mode::Std,
268 SourceType::InTree,
269 target,
270 Kind::Build,
271 );
272 std_cargo(builder, target, compiler.stage, &mut cargo);
273 for krate in &*self.crates {
274 cargo.arg("-p").arg(krate);
275 }
276 cargo
277 };
278
279 if target.is_synthetic() {
281 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
282 }
283 for rustflag in self.extra_rust_args.iter() {
284 cargo.rustflag(rustflag);
285 }
286
287 let _guard = builder.msg(
288 Kind::Build,
289 compiler.stage,
290 format_args!("library artifacts{}", crate_description(&self.crates)),
291 compiler.host,
292 target,
293 );
294 run_cargo(
295 builder,
296 cargo,
297 vec![],
298 &build_stamp::libstd_stamp(builder, compiler, target),
299 target_deps,
300 self.is_for_mir_opt_tests, false,
302 );
303
304 builder.ensure(StdLink::from_std(
305 self,
306 builder.compiler(compiler.stage, builder.config.build),
307 ));
308 }
309}
310
311fn copy_and_stamp(
312 builder: &Builder<'_>,
313 libdir: &Path,
314 sourcedir: &Path,
315 name: &str,
316 target_deps: &mut Vec<(PathBuf, DependencyType)>,
317 dependency_type: DependencyType,
318) {
319 let target = libdir.join(name);
320 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
321
322 target_deps.push((target, dependency_type));
323}
324
325fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
326 let libunwind_path = builder.ensure(llvm::Libunwind { target });
327 let libunwind_source = libunwind_path.join("libunwind.a");
328 let libunwind_target = libdir.join("libunwind.a");
329 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
330 libunwind_target
331}
332
333fn copy_third_party_objects(
335 builder: &Builder<'_>,
336 compiler: &Compiler,
337 target: TargetSelection,
338) -> Vec<(PathBuf, DependencyType)> {
339 let mut target_deps = vec![];
340
341 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
342 target_deps.extend(
345 copy_sanitizers(builder, compiler, target)
346 .into_iter()
347 .map(|d| (d, DependencyType::Target)),
348 );
349 }
350
351 if target == "x86_64-fortanix-unknown-sgx"
352 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
353 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
354 {
355 let libunwind_path =
356 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
357 target_deps.push((libunwind_path, DependencyType::Target));
358 }
359
360 target_deps
361}
362
363fn copy_self_contained_objects(
365 builder: &Builder<'_>,
366 compiler: &Compiler,
367 target: TargetSelection,
368) -> Vec<(PathBuf, DependencyType)> {
369 let libdir_self_contained =
370 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
371 t!(fs::create_dir_all(&libdir_self_contained));
372 let mut target_deps = vec![];
373
374 if target.needs_crt_begin_end() {
382 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
383 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
384 });
385 if !target.starts_with("wasm32") {
386 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
387 copy_and_stamp(
388 builder,
389 &libdir_self_contained,
390 &srcdir,
391 obj,
392 &mut target_deps,
393 DependencyType::TargetSelfContained,
394 );
395 }
396 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
397 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
398 let src = crt_path.join(obj);
399 let target = libdir_self_contained.join(obj);
400 builder.copy_link(&src, &target, FileType::NativeLibrary);
401 target_deps.push((target, DependencyType::TargetSelfContained));
402 }
403 } else {
404 for &obj in &["libc.a", "crt1-command.o"] {
407 copy_and_stamp(
408 builder,
409 &libdir_self_contained,
410 &srcdir,
411 obj,
412 &mut target_deps,
413 DependencyType::TargetSelfContained,
414 );
415 }
416 }
417 if !target.starts_with("s390x") {
418 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
419 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
420 }
421 } else if target.contains("-wasi") {
422 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
423 panic!(
424 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
425 or `$WASI_SDK_PATH` set",
426 target.triple
427 )
428 });
429 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
430 copy_and_stamp(
431 builder,
432 &libdir_self_contained,
433 &srcdir,
434 obj,
435 &mut target_deps,
436 DependencyType::TargetSelfContained,
437 );
438 }
439 } else if target.is_windows_gnu() {
440 for obj in ["crt2.o", "dllcrt2.o"].iter() {
441 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
442 let dst = libdir_self_contained.join(obj);
443 builder.copy_link(&src, &dst, FileType::NativeLibrary);
444 target_deps.push((dst, DependencyType::TargetSelfContained));
445 }
446 }
447
448 target_deps
449}
450
451pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
453 if cfg!(test) {
455 return vec![];
456 }
457
458 let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
459 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
460
461 if target_is_no_std {
463 vec![]
464 }
465 else if has_alias {
467 run.make_run_crates(builder::Alias::Library)
468 } else {
469 run.cargo_crates_in_set()
470 }
471}
472
473fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
479 if builder.config.llvm_from_ci {
481 builder.config.maybe_download_ci_llvm();
483 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
484 if ci_llvm_compiler_rt.exists() {
485 return ci_llvm_compiler_rt;
486 }
487 }
488
489 builder.require_submodule("src/llvm-project", {
491 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
492 });
493 builder.src.join("src/llvm-project/compiler-rt")
494}
495
496pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
499 if target.contains("apple") && !builder.config.dry_run() {
517 let mut cmd = command(builder.rustc(cargo.compiler()));
521 cmd.arg("--target").arg(target.rustc_target_arg());
522 cmd.arg("--print=deployment-target");
523 let output = cmd.run_capture_stdout(builder).stdout();
524
525 let (env_var, value) = output.split_once('=').unwrap();
526 cargo.env(env_var.trim(), value.trim());
529
530 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
540 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
541 }
542 }
543
544 if let Some(path) = builder.config.profiler_path(target) {
546 cargo.env("LLVM_PROFILER_RT_LIB", path);
547 } else if builder.config.profiler_enabled(target) {
548 let compiler_rt = compiler_rt_for_profiler(builder);
549 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
553 }
554
555 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
569 builder.require_submodule(
577 "src/llvm-project",
578 Some(
579 "The `build.optimized-compiler-builtins` config option \
580 requires `compiler-rt` sources from LLVM.",
581 ),
582 );
583 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
584 assert!(compiler_builtins_root.exists());
585 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
588 " compiler-builtins-c"
589 } else {
590 ""
591 };
592
593 if !builder.unstable_features() {
596 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
597 }
598
599 let mut features = String::new();
600
601 if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
602 {
603 features += "compiler-builtins-no-f16-f128 ";
604 }
605
606 if builder.no_std(target) == Some(true) {
607 features += " compiler-builtins-mem";
608 if !target.starts_with("bpf") {
609 features.push_str(compiler_builtins_c_feature);
610 }
611
612 cargo
614 .args(["-p", "alloc"])
615 .arg("--manifest-path")
616 .arg(builder.src.join("library/alloc/Cargo.toml"))
617 .arg("--features")
618 .arg(features);
619 } else {
620 features += &builder.std_features(target);
621 features.push_str(compiler_builtins_c_feature);
622
623 cargo
624 .arg("--features")
625 .arg(features)
626 .arg("--manifest-path")
627 .arg(builder.src.join("library/sysroot/Cargo.toml"));
628
629 if target.contains("musl") {
632 if let Some(p) = builder.musl_libdir(target) {
633 let root = format!("native={}", p.to_str().unwrap());
634 cargo.rustflag("-L").rustflag(&root);
635 }
636 }
637
638 if target.contains("-wasi") {
639 if let Some(dir) = builder.wasi_libdir(target) {
640 let root = format!("native={}", dir.to_str().unwrap());
641 cargo.rustflag("-L").rustflag(&root);
642 }
643 }
644 }
645
646 if stage >= 1 {
655 cargo.rustflag("-Cembed-bitcode=yes");
656 }
657 if builder.config.rust_lto == RustcLto::Off {
658 cargo.rustflag("-Clto=off");
659 }
660
661 if target.contains("riscv") {
668 cargo.rustflag("-Cforce-unwind-tables=yes");
669 }
670
671 cargo.rustflag("-Cforce-frame-pointers=yes");
674
675 let html_root =
676 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
677 cargo.rustflag(&html_root);
678 cargo.rustdocflag(&html_root);
679
680 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
681}
682
683#[derive(Debug, Clone, PartialEq, Eq, Hash)]
684struct StdLink {
685 pub compiler: Compiler,
686 pub target_compiler: Compiler,
687 pub target: TargetSelection,
688 crates: Vec<String>,
690 force_recompile: bool,
692}
693
694impl StdLink {
695 fn from_std(std: Std, host_compiler: Compiler) -> Self {
696 Self {
697 compiler: host_compiler,
698 target_compiler: std.compiler,
699 target: std.target,
700 crates: std.crates,
701 force_recompile: std.force_recompile,
702 }
703 }
704}
705
706impl Step for StdLink {
707 type Output = ();
708
709 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
710 run.never()
711 }
712
713 #[cfg_attr(
722 feature = "tracing",
723 instrument(
724 level = "trace",
725 name = "StdLink::run",
726 skip_all,
727 fields(
728 compiler = ?self.compiler,
729 target_compiler = ?self.target_compiler,
730 target = ?self.target
731 ),
732 ),
733 )]
734 fn run(self, builder: &Builder<'_>) {
735 let compiler = self.compiler;
736 let target_compiler = self.target_compiler;
737 let target = self.target;
738
739 let (libdir, hostdir) = if self.force_recompile && builder.download_rustc() {
741 let lib = builder.sysroot_libdir_relative(self.compiler);
743 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
744 compiler: self.compiler,
745 force_recompile: self.force_recompile,
746 });
747 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
748 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
749 (libdir, hostdir)
750 } else {
751 let libdir = builder.sysroot_target_libdir(target_compiler, target);
752 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
753 (libdir, hostdir)
754 };
755
756 add_to_sysroot(
757 builder,
758 &libdir,
759 &hostdir,
760 &build_stamp::libstd_stamp(builder, compiler, target),
761 );
762
763 if compiler.stage == 0
767 && builder
768 .build
769 .config
770 .initial_rustc
771 .starts_with(builder.out.join(compiler.host).join("stage0/bin"))
772 {
773 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
775
776 let host = compiler.host;
777 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
778 let sysroot_bin_dir = sysroot.join("bin");
779 t!(fs::create_dir_all(&sysroot_bin_dir));
780 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
781
782 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
784 if let Ok(files) = fs::read_dir(stage0_lib_dir) {
785 for file in files {
786 let file = t!(file);
787 let path = file.path();
788 if path.is_file() {
789 builder.copy_link(
790 &path,
791 &sysroot.join("lib").join(path.file_name().unwrap()),
792 FileType::Regular,
793 );
794 }
795 }
796 }
797
798 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
800 t!(fs::create_dir_all(&sysroot_codegen_backends));
801 let stage0_codegen_backends = builder
802 .out
803 .join(host)
804 .join("stage0/lib/rustlib")
805 .join(host)
806 .join("codegen-backends");
807 if stage0_codegen_backends.exists() {
808 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
809 }
810 }
811 }
812}
813
814fn copy_sanitizers(
816 builder: &Builder<'_>,
817 compiler: &Compiler,
818 target: TargetSelection,
819) -> Vec<PathBuf> {
820 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
821
822 if builder.config.dry_run() {
823 return Vec::new();
824 }
825
826 let mut target_deps = Vec::new();
827 let libdir = builder.sysroot_target_libdir(*compiler, target);
828
829 for runtime in &runtimes {
830 let dst = libdir.join(&runtime.name);
831 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
832
833 if target == "x86_64-apple-darwin"
837 || target == "aarch64-apple-darwin"
838 || target == "aarch64-apple-ios"
839 || target == "aarch64-apple-ios-sim"
840 || target == "x86_64-apple-ios"
841 {
842 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
844 apple_darwin_sign_file(builder, &dst);
847 }
848
849 target_deps.push(dst);
850 }
851
852 target_deps
853}
854
855fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
856 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
857}
858
859fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
860 command("codesign")
861 .arg("-f") .arg("-s")
863 .arg("-")
864 .arg(file_path)
865 .run(builder);
866}
867
868#[derive(Debug, Clone, PartialEq, Eq, Hash)]
869pub struct StartupObjects {
870 pub compiler: Compiler,
871 pub target: TargetSelection,
872}
873
874impl Step for StartupObjects {
875 type Output = Vec<(PathBuf, DependencyType)>;
876
877 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
878 run.path("library/rtstartup")
879 }
880
881 fn make_run(run: RunConfig<'_>) {
882 run.builder.ensure(StartupObjects {
883 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
884 target: run.target,
885 });
886 }
887
888 #[cfg_attr(
895 feature = "tracing",
896 instrument(
897 level = "trace",
898 name = "StartupObjects::run",
899 skip_all,
900 fields(compiler = ?self.compiler, target = ?self.target),
901 ),
902 )]
903 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
904 let for_compiler = self.compiler;
905 let target = self.target;
906 if !target.is_windows_gnu() {
907 return vec![];
908 }
909
910 let mut target_deps = vec![];
911
912 let src_dir = &builder.src.join("library").join("rtstartup");
913 let dst_dir = &builder.native_dir(target).join("rtstartup");
914 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
915 t!(fs::create_dir_all(dst_dir));
916
917 for file in &["rsbegin", "rsend"] {
918 let src_file = &src_dir.join(file.to_string() + ".rs");
919 let dst_file = &dst_dir.join(file.to_string() + ".o");
920 if !up_to_date(src_file, dst_file) {
921 let mut cmd = command(&builder.initial_rustc);
922 cmd.env("RUSTC_BOOTSTRAP", "1");
923 if !builder.local_rebuild {
924 cmd.arg("--cfg").arg("bootstrap");
926 }
927 cmd.arg("--target")
928 .arg(target.rustc_target_arg())
929 .arg("--emit=obj")
930 .arg("-o")
931 .arg(dst_file)
932 .arg(src_file)
933 .run(builder);
934 }
935
936 let obj = sysroot_dir.join((*file).to_string() + ".o");
937 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
938 target_deps.push((obj, DependencyType::Target));
939 }
940
941 target_deps
942 }
943}
944
945fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
946 let ci_rustc_dir = builder.config.ci_rustc_dir();
947
948 for file in contents {
949 let src = ci_rustc_dir.join(&file);
950 let dst = sysroot.join(file);
951 if src.is_dir() {
952 t!(fs::create_dir_all(dst));
953 } else {
954 builder.copy_link(&src, &dst, FileType::Regular);
955 }
956 }
957}
958
959#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
960pub struct Rustc {
961 pub target: TargetSelection,
962 pub compiler: Compiler,
964 crates: Vec<String>,
970}
971
972impl Rustc {
973 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
974 Self { target, compiler, crates: Default::default() }
975 }
976}
977
978impl Step for Rustc {
979 type Output = u32;
987 const ONLY_HOSTS: bool = true;
988 const DEFAULT: bool = false;
989
990 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
991 let mut crates = run.builder.in_tree_crates("rustc-main", None);
992 for (i, krate) in crates.iter().enumerate() {
993 if krate.name == "rustc-main" {
996 crates.swap_remove(i);
997 break;
998 }
999 }
1000 run.crates(crates)
1001 }
1002
1003 fn make_run(run: RunConfig<'_>) {
1004 let crates = run.cargo_crates_in_set();
1005 run.builder.ensure(Rustc {
1006 compiler: run
1007 .builder
1008 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1009 target: run.target,
1010 crates,
1011 });
1012 }
1013
1014 #[cfg_attr(
1020 feature = "tracing",
1021 instrument(
1022 level = "debug",
1023 name = "Rustc::run",
1024 skip_all,
1025 fields(previous_compiler = ?self.compiler, target = ?self.target),
1026 ),
1027 )]
1028 fn run(self, builder: &Builder<'_>) -> u32 {
1029 let compiler = self.compiler;
1030 let target = self.target;
1031
1032 if builder.download_rustc() && compiler.stage != 0 {
1035 trace!(stage = compiler.stage, "`download_rustc` requested");
1036
1037 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
1038 cp_rustc_component_to_ci_sysroot(
1039 builder,
1040 &sysroot,
1041 builder.config.ci_rustc_dev_contents(),
1042 );
1043 return compiler.stage;
1044 }
1045
1046 builder.ensure(Std::new(compiler, target));
1047
1048 if builder.config.keep_stage.contains(&compiler.stage) {
1049 trace!(stage = compiler.stage, "`keep-stage` requested");
1050
1051 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1052 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1053 builder.ensure(RustcLink::from_rustc(self, compiler));
1054
1055 return compiler.stage;
1056 }
1057
1058 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1059 if compiler_to_use != compiler {
1060 builder.ensure(Rustc::new(compiler_to_use, target));
1061 let msg = if compiler_to_use.host == target {
1062 format!(
1063 "Uplifting rustc (stage{} -> stage{})",
1064 compiler_to_use.stage,
1065 compiler.stage + 1
1066 )
1067 } else {
1068 format!(
1069 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1070 compiler_to_use.stage,
1071 compiler_to_use.host,
1072 compiler.stage + 1,
1073 target
1074 )
1075 };
1076 builder.info(&msg);
1077 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1078 return compiler_to_use.stage;
1079 }
1080
1081 builder.ensure(Std::new(
1083 builder.compiler(self.compiler.stage, builder.config.build),
1084 builder.config.build,
1085 ));
1086
1087 let mut cargo = builder::Cargo::new(
1088 builder,
1089 compiler,
1090 Mode::Rustc,
1091 SourceType::InTree,
1092 target,
1093 Kind::Build,
1094 );
1095
1096 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
1097
1098 for krate in &*self.crates {
1102 cargo.arg("-p").arg(krate);
1103 }
1104
1105 if builder.build.config.enable_bolt_settings && compiler.stage == 1 {
1106 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1108 }
1109
1110 let _guard = builder.msg_sysroot_tool(
1111 Kind::Build,
1112 compiler.stage,
1113 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1114 compiler.host,
1115 target,
1116 );
1117 let stamp = build_stamp::librustc_stamp(builder, compiler, target);
1118 run_cargo(
1119 builder,
1120 cargo,
1121 vec![],
1122 &stamp,
1123 vec![],
1124 false,
1125 true, );
1127
1128 let target_root_dir = stamp.path().parent().unwrap();
1129 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1135 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1136 {
1137 let rustc_driver = target_root_dir.join("librustc_driver.so");
1138 strip_debug(builder, target, &rustc_driver);
1139 }
1140
1141 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1142 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1145 }
1146
1147 builder.ensure(RustcLink::from_rustc(
1148 self,
1149 builder.compiler(compiler.stage, builder.config.build),
1150 ));
1151
1152 compiler.stage
1153 }
1154}
1155
1156pub fn rustc_cargo(
1157 builder: &Builder<'_>,
1158 cargo: &mut Cargo,
1159 target: TargetSelection,
1160 compiler: &Compiler,
1161 crates: &[String],
1162) {
1163 cargo
1164 .arg("--features")
1165 .arg(builder.rustc_features(builder.kind, target, crates))
1166 .arg("--manifest-path")
1167 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1168
1169 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1170
1171 cargo.rustflag("-Zon-broken-pipe=kill");
1185
1186 if builder.config.llvm_enzyme {
1189 let arch = builder.build.build;
1190 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1191 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1192
1193 if let Some(llvm_config) = builder.llvm_config(builder.config.build) {
1194 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1195 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1196 }
1197 }
1198
1199 if builder.build.config.lld_mode.is_used() {
1204 cargo.rustflag("-Zdefault-visibility=protected");
1205 }
1206
1207 if is_lto_stage(compiler) {
1208 match builder.config.rust_lto {
1209 RustcLto::Thin | RustcLto::Fat => {
1210 cargo.rustflag("-Zdylib-lto");
1213 let lto_type = match builder.config.rust_lto {
1217 RustcLto::Thin => "thin",
1218 RustcLto::Fat => "fat",
1219 _ => unreachable!(),
1220 };
1221 cargo.rustflag(&format!("-Clto={lto_type}"));
1222 cargo.rustflag("-Cembed-bitcode=yes");
1223 }
1224 RustcLto::ThinLocal => { }
1225 RustcLto::Off => {
1226 cargo.rustflag("-Clto=off");
1227 }
1228 }
1229 } else if builder.config.rust_lto == RustcLto::Off {
1230 cargo.rustflag("-Clto=off");
1231 }
1232
1233 if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
1241 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1242 }
1243
1244 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1245 panic!("Cannot use and generate PGO profiles at the same time");
1246 }
1247 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1248 if compiler.stage == 1 {
1249 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1250 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1253 true
1254 } else {
1255 false
1256 }
1257 } else if let Some(path) = &builder.config.rust_profile_use {
1258 if compiler.stage == 1 {
1259 cargo.rustflag(&format!("-Cprofile-use={path}"));
1260 if builder.is_verbose() {
1261 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1262 }
1263 true
1264 } else {
1265 false
1266 }
1267 } else {
1268 false
1269 };
1270 if is_collecting {
1271 cargo.rustflag(&format!(
1273 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1274 builder.config.src.components().count()
1275 ));
1276 }
1277
1278 rustc_cargo_env(builder, cargo, target, compiler.stage);
1279}
1280
1281pub fn rustc_cargo_env(
1282 builder: &Builder<'_>,
1283 cargo: &mut Cargo,
1284 target: TargetSelection,
1285 stage: u32,
1286) {
1287 cargo
1290 .env("CFG_RELEASE", builder.rust_release())
1291 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1292 .env("CFG_VERSION", builder.rust_version());
1293
1294 if builder.config.omit_git_hash {
1298 cargo.env("CFG_OMIT_GIT_HASH", "1");
1299 }
1300
1301 if let Some(backend) = builder.config.default_codegen_backend(target) {
1302 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1303 }
1304
1305 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1306 let target_config = builder.config.target_config.get(&target);
1307
1308 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1309
1310 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1311 cargo.env("CFG_VER_DATE", ver_date);
1312 }
1313 if let Some(ref ver_hash) = builder.rust_info().sha() {
1314 cargo.env("CFG_VER_HASH", ver_hash);
1315 }
1316 if !builder.unstable_features() {
1317 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1318 }
1319
1320 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1323 cargo.env("CFG_DEFAULT_LINKER", s);
1324 } else if let Some(ref s) = builder.config.rustc_default_linker {
1325 cargo.env("CFG_DEFAULT_LINKER", s);
1326 }
1327
1328 if builder.config.lld_enabled
1330 && (builder.config.channel == "dev" || builder.config.channel == "nightly")
1331 {
1332 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1333 }
1334
1335 if builder.config.rust_verify_llvm_ir {
1336 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1337 }
1338
1339 if builder.config.llvm_enzyme {
1340 cargo.rustflag("--cfg=llvm_enzyme");
1341 }
1342
1343 if builder.config.llvm_enabled(target) {
1348 let building_is_expensive =
1349 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1350 .should_build();
1351 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage;
1353 let should_skip_build = building_is_expensive && can_skip_build;
1354 if !should_skip_build {
1355 rustc_llvm_env(builder, cargo, target)
1356 }
1357 }
1358
1359 if builder.config.jemalloc(target)
1362 && target.starts_with("aarch64")
1363 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1364 {
1365 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1366 }
1367}
1368
1369fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1372 if builder.config.is_rust_llvm(target) {
1373 cargo.env("LLVM_RUSTLLVM", "1");
1374 }
1375 if builder.config.llvm_enzyme {
1376 cargo.env("LLVM_ENZYME", "1");
1377 }
1378 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1379 cargo.env("LLVM_CONFIG", &llvm_config);
1380
1381 let mut llvm_linker_flags = String::new();
1391 if builder.config.llvm_profile_generate && target.is_msvc() {
1392 if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
1393 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1395 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1396 }
1397 }
1398
1399 if let Some(ref s) = builder.config.llvm_ldflags {
1401 if !llvm_linker_flags.is_empty() {
1402 llvm_linker_flags.push(' ');
1403 }
1404 llvm_linker_flags.push_str(s);
1405 }
1406
1407 if !llvm_linker_flags.is_empty() {
1409 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1410 }
1411
1412 if builder.config.llvm_static_stdcpp
1415 && !target.contains("freebsd")
1416 && !target.is_msvc()
1417 && !target.contains("apple")
1418 && !target.contains("solaris")
1419 {
1420 let libstdcxx_name =
1421 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1422 let file = compiler_file(
1423 builder,
1424 &builder.cxx(target).unwrap(),
1425 target,
1426 CLang::Cxx,
1427 libstdcxx_name,
1428 );
1429 cargo.env("LLVM_STATIC_STDCPP", file);
1430 }
1431 if builder.llvm_link_shared() {
1432 cargo.env("LLVM_LINK_SHARED", "1");
1433 }
1434 if builder.config.llvm_use_libcxx {
1435 cargo.env("LLVM_USE_LIBCXX", "1");
1436 }
1437 if builder.config.llvm_assertions {
1438 cargo.env("LLVM_ASSERTIONS", "1");
1439 }
1440}
1441
1442#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1448struct RustcLink {
1449 pub compiler: Compiler,
1451 pub previous_stage_compiler: Compiler,
1453 pub target: TargetSelection,
1454 crates: Vec<String>,
1456}
1457
1458impl RustcLink {
1459 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1460 Self {
1461 compiler: host_compiler,
1462 previous_stage_compiler: rustc.compiler,
1463 target: rustc.target,
1464 crates: rustc.crates,
1465 }
1466 }
1467}
1468
1469impl Step for RustcLink {
1470 type Output = ();
1471
1472 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1473 run.never()
1474 }
1475
1476 #[cfg_attr(
1478 feature = "tracing",
1479 instrument(
1480 level = "trace",
1481 name = "RustcLink::run",
1482 skip_all,
1483 fields(
1484 compiler = ?self.compiler,
1485 previous_stage_compiler = ?self.previous_stage_compiler,
1486 target = ?self.target,
1487 ),
1488 ),
1489 )]
1490 fn run(self, builder: &Builder<'_>) {
1491 let compiler = self.compiler;
1492 let previous_stage_compiler = self.previous_stage_compiler;
1493 let target = self.target;
1494 add_to_sysroot(
1495 builder,
1496 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1497 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1498 &build_stamp::librustc_stamp(builder, compiler, target),
1499 );
1500 }
1501}
1502
1503#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1504pub struct CodegenBackend {
1505 pub target: TargetSelection,
1506 pub compiler: Compiler,
1507 pub backend: String,
1508}
1509
1510fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1511 let mut needs_codegen_cfg = false;
1512 for path_set in &run.paths {
1513 needs_codegen_cfg = match path_set {
1514 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1515 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1516 }
1517 }
1518 needs_codegen_cfg
1519}
1520
1521pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1522
1523fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1524 let path = path.path.to_str().unwrap();
1525
1526 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1527 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1528
1529 if path.contains(CODEGEN_BACKEND_PREFIX) {
1530 let mut needs_codegen_backend_config = true;
1531 for backend in run.builder.config.codegen_backends(run.target) {
1532 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1533 needs_codegen_backend_config = false;
1534 }
1535 }
1536 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1537 && needs_codegen_backend_config
1538 {
1539 run.builder.info(
1540 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1541 HELP: add backend to codegen-backends in bootstrap.toml.",
1542 );
1543 return true;
1544 }
1545 }
1546
1547 false
1548}
1549
1550impl Step for CodegenBackend {
1551 type Output = ();
1552 const ONLY_HOSTS: bool = true;
1553 const DEFAULT: bool = true;
1555
1556 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1557 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1558 }
1559
1560 fn make_run(run: RunConfig<'_>) {
1561 if needs_codegen_config(&run) {
1562 return;
1563 }
1564
1565 for backend in run.builder.config.codegen_backends(run.target) {
1566 if backend == "llvm" {
1567 continue; }
1569
1570 run.builder.ensure(CodegenBackend {
1571 target: run.target,
1572 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1573 backend: backend.clone(),
1574 });
1575 }
1576 }
1577
1578 #[cfg_attr(
1579 feature = "tracing",
1580 instrument(
1581 level = "debug",
1582 name = "CodegenBackend::run",
1583 skip_all,
1584 fields(
1585 compiler = ?self.compiler,
1586 target = ?self.target,
1587 backend = ?self.target,
1588 ),
1589 ),
1590 )]
1591 fn run(self, builder: &Builder<'_>) {
1592 let compiler = self.compiler;
1593 let target = self.target;
1594 let backend = self.backend;
1595
1596 builder.ensure(Rustc::new(compiler, target));
1597
1598 if builder.config.keep_stage.contains(&compiler.stage) {
1599 trace!("`keep-stage` requested");
1600 builder.info(
1601 "WARNING: Using a potentially old codegen backend. \
1602 This may not behave well.",
1603 );
1604 return;
1607 }
1608
1609 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1610 if compiler_to_use != compiler {
1611 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1612 return;
1613 }
1614
1615 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1616
1617 let mut cargo = builder::Cargo::new(
1618 builder,
1619 compiler,
1620 Mode::Codegen,
1621 SourceType::InTree,
1622 target,
1623 Kind::Build,
1624 );
1625 cargo
1626 .arg("--manifest-path")
1627 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1628 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1629
1630 if backend == "gcc" {
1634 let gcc = builder.ensure(Gcc { target });
1635 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1636 }
1637
1638 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1639
1640 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1641 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1642 if builder.config.dry_run() {
1643 return;
1644 }
1645 let mut files = files.into_iter().filter(|f| {
1646 let filename = f.file_name().unwrap().to_str().unwrap();
1647 is_dylib(f) && filename.contains("rustc_codegen_")
1648 });
1649 let codegen_backend = match files.next() {
1650 Some(f) => f,
1651 None => panic!("no dylibs built for codegen backend?"),
1652 };
1653 if let Some(f) = files.next() {
1654 panic!(
1655 "codegen backend built two dylibs:\n{}\n{}",
1656 codegen_backend.display(),
1657 f.display()
1658 );
1659 }
1660 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1661 let codegen_backend = codegen_backend.to_str().unwrap();
1662 t!(stamp.add_stamp(codegen_backend).write());
1663 }
1664}
1665
1666fn copy_codegen_backends_to_sysroot(
1673 builder: &Builder<'_>,
1674 compiler: Compiler,
1675 target_compiler: Compiler,
1676) {
1677 let target = target_compiler.host;
1678
1679 let dst = builder.sysroot_codegen_backends(target_compiler);
1688 t!(fs::create_dir_all(&dst), dst);
1689
1690 if builder.config.dry_run() {
1691 return;
1692 }
1693
1694 for backend in builder.config.codegen_backends(target) {
1695 if backend == "llvm" {
1696 continue; }
1698
1699 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1700 let dylib = t!(fs::read_to_string(stamp.path()));
1701 let file = Path::new(&dylib);
1702 let filename = file.file_name().unwrap().to_str().unwrap();
1703 let target_filename = {
1706 let dash = filename.find('-').unwrap();
1707 let dot = filename.find('.').unwrap();
1708 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1709 };
1710 builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
1711 }
1712}
1713
1714pub fn compiler_file(
1715 builder: &Builder<'_>,
1716 compiler: &Path,
1717 target: TargetSelection,
1718 c: CLang,
1719 file: &str,
1720) -> PathBuf {
1721 if builder.config.dry_run() {
1722 return PathBuf::new();
1723 }
1724 let mut cmd = command(compiler);
1725 cmd.args(builder.cc_handled_clags(target, c));
1726 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1727 cmd.arg(format!("-print-file-name={file}"));
1728 let out = cmd.run_capture_stdout(builder).stdout();
1729 PathBuf::from(out.trim())
1730}
1731
1732#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1733pub struct Sysroot {
1734 pub compiler: Compiler,
1735 force_recompile: bool,
1737}
1738
1739impl Sysroot {
1740 pub(crate) fn new(compiler: Compiler) -> Self {
1741 Sysroot { compiler, force_recompile: false }
1742 }
1743}
1744
1745impl Step for Sysroot {
1746 type Output = PathBuf;
1747
1748 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1749 run.never()
1750 }
1751
1752 #[cfg_attr(
1756 feature = "tracing",
1757 instrument(
1758 level = "debug",
1759 name = "Sysroot::run",
1760 skip_all,
1761 fields(compiler = ?self.compiler),
1762 ),
1763 )]
1764 fn run(self, builder: &Builder<'_>) -> PathBuf {
1765 let compiler = self.compiler;
1766 let host_dir = builder.out.join(compiler.host);
1767
1768 let sysroot_dir = |stage| {
1769 if stage == 0 {
1770 host_dir.join("stage0-sysroot")
1771 } else if self.force_recompile && stage == compiler.stage {
1772 host_dir.join(format!("stage{stage}-test-sysroot"))
1773 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1774 host_dir.join("ci-rustc-sysroot")
1775 } else {
1776 host_dir.join(format!("stage{stage}"))
1777 }
1778 };
1779 let sysroot = sysroot_dir(compiler.stage);
1780 trace!(stage = ?compiler.stage, ?sysroot);
1781
1782 builder
1783 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1784 let _ = fs::remove_dir_all(&sysroot);
1785 t!(fs::create_dir_all(&sysroot));
1786
1787 if compiler.stage == 0 {
1794 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1795 }
1796
1797 if builder.download_rustc() && compiler.stage != 0 {
1799 assert_eq!(
1800 builder.config.build, compiler.host,
1801 "Cross-compiling is not yet supported with `download-rustc`",
1802 );
1803
1804 for stage in 0..=2 {
1806 if stage != compiler.stage {
1807 let dir = sysroot_dir(stage);
1808 if !dir.ends_with("ci-rustc-sysroot") {
1809 let _ = fs::remove_dir_all(dir);
1810 }
1811 }
1812 }
1813
1814 let mut filtered_files = Vec::new();
1824 let mut add_filtered_files = |suffix, contents| {
1825 for path in contents {
1826 let path = Path::new(&path);
1827 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1828 filtered_files.push(path.file_name().unwrap().to_owned());
1829 }
1830 }
1831 };
1832 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1833 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1834 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1837
1838 let filtered_extensions = [
1839 OsStr::new("rmeta"),
1840 OsStr::new("rlib"),
1841 OsStr::new(std::env::consts::DLL_EXTENSION),
1843 ];
1844 let ci_rustc_dir = builder.config.ci_rustc_dir();
1845 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1846 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1847 return true;
1848 }
1849 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1850 return true;
1851 }
1852 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1853 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1854 false
1855 } else {
1856 true
1857 }
1858 });
1859 }
1860
1861 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1867 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1868 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1869 if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
1870 eprintln!(
1871 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1872 sysroot_lib_rustlib_src_rust.display(),
1873 builder.src.display(),
1874 e,
1875 );
1876 if builder.config.rust_remap_debuginfo {
1877 eprintln!(
1878 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1879 sysroot_lib_rustlib_src_rust.display(),
1880 );
1881 }
1882 build_helper::exit!(1);
1883 }
1884
1885 if !builder.download_rustc() {
1887 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1888 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1889 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1890 if let Err(e) =
1891 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1892 {
1893 eprintln!(
1894 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1895 sysroot_lib_rustlib_rustcsrc_rust.display(),
1896 builder.src.display(),
1897 e,
1898 );
1899 build_helper::exit!(1);
1900 }
1901 }
1902
1903 sysroot
1904 }
1905}
1906
1907#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1908pub struct Assemble {
1909 pub target_compiler: Compiler,
1914}
1915
1916impl Step for Assemble {
1917 type Output = Compiler;
1918 const ONLY_HOSTS: bool = true;
1919
1920 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1921 run.path("compiler/rustc").path("compiler")
1922 }
1923
1924 fn make_run(run: RunConfig<'_>) {
1925 run.builder.ensure(Assemble {
1926 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1927 });
1928 }
1929
1930 #[cfg_attr(
1936 feature = "tracing",
1937 instrument(
1938 level = "debug",
1939 name = "Assemble::run",
1940 skip_all,
1941 fields(target_compiler = ?self.target_compiler),
1942 ),
1943 )]
1944 fn run(self, builder: &Builder<'_>) -> Compiler {
1945 let target_compiler = self.target_compiler;
1946
1947 if target_compiler.stage == 0 {
1948 trace!("stage 0 build compiler is always available, simply returning");
1949 assert_eq!(
1950 builder.config.build, target_compiler.host,
1951 "Cannot obtain compiler for non-native build triple at stage 0"
1952 );
1953 return target_compiler;
1955 }
1956
1957 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
1960 let libdir_bin = libdir.parent().unwrap().join("bin");
1961 t!(fs::create_dir_all(&libdir_bin));
1962
1963 if builder.config.llvm_enabled(target_compiler.host) {
1964 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
1965
1966 let llvm::LlvmResult { llvm_config, .. } =
1967 builder.ensure(llvm::Llvm { target: target_compiler.host });
1968 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
1969 trace!("LLVM tools enabled");
1970
1971 let llvm_bin_dir =
1972 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
1973 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
1974
1975 #[cfg(feature = "tracing")]
1982 let _llvm_tools_span =
1983 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
1984 .entered();
1985 for tool in LLVM_TOOLS {
1986 trace!("installing `{tool}`");
1987 let tool_exe = exe(tool, target_compiler.host);
1988 let src_path = llvm_bin_dir.join(&tool_exe);
1989
1990 if !src_path.exists() && builder.config.llvm_from_ci {
1992 eprintln!("{} does not exist; skipping copy", src_path.display());
1993 continue;
1994 }
1995
1996 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2003 }
2004 }
2005 }
2006
2007 let maybe_install_llvm_bitcode_linker = |compiler| {
2008 if builder.config.llvm_bitcode_linker_enabled {
2009 trace!("llvm-bitcode-linker enabled, installing");
2010 let llvm_bitcode_linker =
2011 builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
2012 compiler,
2013 target: target_compiler.host,
2014 extra_features: vec![],
2015 });
2016 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2017 builder.copy_link(
2018 &llvm_bitcode_linker.tool_path,
2019 &libdir_bin.join(tool_exe),
2020 FileType::Executable,
2021 );
2022 }
2023 };
2024
2025 if builder.download_rustc() {
2027 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2028
2029 builder.ensure(Std::new(target_compiler, target_compiler.host));
2030 let sysroot =
2031 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2032 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2035 if target_compiler.stage == builder.top_stage {
2037 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage=target_compiler.stage));
2038 }
2039
2040 let mut precompiled_compiler = target_compiler;
2041 precompiled_compiler.forced_compiler(true);
2042 maybe_install_llvm_bitcode_linker(precompiled_compiler);
2043
2044 return target_compiler;
2045 }
2046
2047 debug!(
2061 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2062 target_compiler.stage - 1,
2063 builder.config.build,
2064 );
2065 let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
2066
2067 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2069 debug!("`llvm_enzyme` requested");
2070 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2071 let llvm_config = builder.llvm_config(builder.config.build).unwrap();
2072 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2073 let lib_ext = std::env::consts::DLL_EXTENSION;
2074 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2075 let src_lib =
2076 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2077 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2078 let target_libdir =
2079 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2080 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2081 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2082 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2083 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2084 }
2085
2086 debug!(
2092 ?build_compiler,
2093 "target_compiler.host" = ?target_compiler.host,
2094 "building compiler libraries to link to"
2095 );
2096 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2097 debug!(
2100 "(old) build_compiler.stage" = build_compiler.stage,
2101 "(adjusted) build_compiler.stage" = actual_stage,
2102 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2103 );
2104 build_compiler.stage = actual_stage;
2105
2106 #[cfg(feature = "tracing")]
2107 let _codegen_backend_span =
2108 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2109 for backend in builder.config.codegen_backends(target_compiler.host) {
2110 if backend == "llvm" {
2111 debug!("llvm codegen backend is already built as part of rustc");
2112 continue; }
2114
2115 builder.ensure(CodegenBackend {
2116 compiler: build_compiler,
2117 target: target_compiler.host,
2118 backend: backend.clone(),
2119 });
2120 }
2121 #[cfg(feature = "tracing")]
2122 drop(_codegen_backend_span);
2123
2124 let stage = target_compiler.stage;
2125 let host = target_compiler.host;
2126 let (host_info, dir_name) = if build_compiler.host == host {
2127 ("".into(), "host".into())
2128 } else {
2129 (format!(" ({host})"), host.to_string())
2130 };
2131 let msg = format!(
2136 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2137 );
2138 builder.info(&msg);
2139
2140 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2142 let proc_macros = builder
2143 .read_stamp_file(&stamp)
2144 .into_iter()
2145 .filter_map(|(path, dependency_type)| {
2146 if dependency_type == DependencyType::Host {
2147 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2148 } else {
2149 None
2150 }
2151 })
2152 .collect::<HashSet<_>>();
2153
2154 let sysroot = builder.sysroot(target_compiler);
2155 let rustc_libdir = builder.rustc_libdir(target_compiler);
2156 t!(fs::create_dir_all(&rustc_libdir));
2157 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2158 for f in builder.read_dir(&src_libdir) {
2159 let filename = f.file_name().into_string().unwrap();
2160
2161 let is_proc_macro = proc_macros.contains(&filename);
2162 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2163
2164 let can_be_rustc_dynamic_dep = if builder
2168 .link_std_into_rustc_driver(target_compiler.host)
2169 && !target_compiler.host.is_windows()
2170 {
2171 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2172 !is_std
2173 } else {
2174 true
2175 };
2176
2177 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2178 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2179 }
2180 }
2181
2182 debug!("copying codegen backends to sysroot");
2183 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2184
2185 if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) {
2186 builder.ensure(crate::core::build_steps::tool::LldWrapper {
2187 build_compiler,
2188 target_compiler,
2189 });
2190 }
2191
2192 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2193 debug!(
2194 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2195 workaround faulty homebrew `strip`s"
2196 );
2197
2198 let src_exe = exe("llvm-objcopy", target_compiler.host);
2205 let dst_exe = exe("rust-objcopy", target_compiler.host);
2206 builder.copy_link(
2207 &libdir_bin.join(src_exe),
2208 &libdir_bin.join(dst_exe),
2209 FileType::Executable,
2210 );
2211 }
2212
2213 if builder.tool_enabled("wasm-component-ld") {
2219 let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
2220 compiler: build_compiler,
2221 target: target_compiler.host,
2222 });
2223 builder.copy_link(
2224 &wasm_component.tool_path,
2225 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2226 FileType::Executable,
2227 );
2228 }
2229
2230 maybe_install_llvm_bitcode_linker(target_compiler);
2231
2232 debug!(
2235 "target_compiler.host" = ?target_compiler.host,
2236 ?sysroot,
2237 "ensuring availability of `libLLVM.so` in compiler directory"
2238 );
2239 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2240 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2241
2242 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2244 let rustc = out_dir.join(exe("rustc-main", host));
2245 let bindir = sysroot.join("bin");
2246 t!(fs::create_dir_all(bindir));
2247 let compiler = builder.rustc(target_compiler);
2248 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2249 builder.copy_link(&rustc, &compiler, FileType::Executable);
2250
2251 target_compiler
2252 }
2253}
2254
2255pub fn add_to_sysroot(
2260 builder: &Builder<'_>,
2261 sysroot_dst: &Path,
2262 sysroot_host_dst: &Path,
2263 stamp: &BuildStamp,
2264) {
2265 let self_contained_dst = &sysroot_dst.join("self-contained");
2266 t!(fs::create_dir_all(sysroot_dst));
2267 t!(fs::create_dir_all(sysroot_host_dst));
2268 t!(fs::create_dir_all(self_contained_dst));
2269 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2270 let dst = match dependency_type {
2271 DependencyType::Host => sysroot_host_dst,
2272 DependencyType::Target => sysroot_dst,
2273 DependencyType::TargetSelfContained => self_contained_dst,
2274 };
2275 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2276 }
2277}
2278
2279pub fn run_cargo(
2280 builder: &Builder<'_>,
2281 cargo: Cargo,
2282 tail_args: Vec<String>,
2283 stamp: &BuildStamp,
2284 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2285 is_check: bool,
2286 rlib_only_metadata: bool,
2287) -> Vec<PathBuf> {
2288 let target_root_dir = stamp.path().parent().unwrap();
2290 let target_deps_dir = target_root_dir.join("deps");
2292 let host_root_dir = target_root_dir
2294 .parent()
2295 .unwrap() .parent()
2297 .unwrap() .join(target_root_dir.file_name().unwrap());
2299
2300 let mut deps = Vec::new();
2304 let mut toplevel = Vec::new();
2305 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2306 let (filenames, crate_types) = match msg {
2307 CargoMessage::CompilerArtifact {
2308 filenames,
2309 target: CargoTarget { crate_types },
2310 ..
2311 } => (filenames, crate_types),
2312 _ => return,
2313 };
2314 for filename in filenames {
2315 let mut keep = false;
2317 if filename.ends_with(".lib")
2318 || filename.ends_with(".a")
2319 || is_debug_info(&filename)
2320 || is_dylib(Path::new(&*filename))
2321 {
2322 keep = true;
2324 }
2325 if is_check && filename.ends_with(".rmeta") {
2326 keep = true;
2328 } else if rlib_only_metadata {
2329 if filename.contains("jemalloc_sys")
2330 || filename.contains("rustc_smir")
2331 || filename.contains("stable_mir")
2332 {
2333 keep |= filename.ends_with(".rlib");
2336 } else {
2337 keep |= filename.ends_with(".rmeta");
2341 }
2342 } else {
2343 keep |= filename.ends_with(".rlib");
2345 }
2346
2347 if !keep {
2348 continue;
2349 }
2350
2351 let filename = Path::new(&*filename);
2352
2353 if filename.starts_with(&host_root_dir) {
2356 if crate_types.iter().any(|t| t == "proc-macro") {
2358 deps.push((filename.to_path_buf(), DependencyType::Host));
2359 }
2360 continue;
2361 }
2362
2363 if filename.starts_with(&target_deps_dir) {
2366 deps.push((filename.to_path_buf(), DependencyType::Target));
2367 continue;
2368 }
2369
2370 let expected_len = t!(filename.metadata()).len();
2381 let filename = filename.file_name().unwrap().to_str().unwrap();
2382 let mut parts = filename.splitn(2, '.');
2383 let file_stem = parts.next().unwrap().to_owned();
2384 let extension = parts.next().unwrap().to_owned();
2385
2386 toplevel.push((file_stem, extension, expected_len));
2387 }
2388 });
2389
2390 if !ok {
2391 crate::exit!(1);
2392 }
2393
2394 if builder.config.dry_run() {
2395 return Vec::new();
2396 }
2397
2398 let contents = target_deps_dir
2402 .read_dir()
2403 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2404 .map(|e| t!(e))
2405 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2406 .collect::<Vec<_>>();
2407 for (prefix, extension, expected_len) in toplevel {
2408 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2409 meta.len() == expected_len
2410 && filename
2411 .strip_prefix(&prefix[..])
2412 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2413 .unwrap_or(false)
2414 });
2415 let max = candidates.max_by_key(|&(_, _, metadata)| {
2416 metadata.modified().expect("mtime should be available on all relevant OSes")
2417 });
2418 let path_to_add = match max {
2419 Some(triple) => triple.0.to_str().unwrap(),
2420 None => panic!("no output generated for {prefix:?} {extension:?}"),
2421 };
2422 if is_dylib(Path::new(path_to_add)) {
2423 let candidate = format!("{path_to_add}.lib");
2424 let candidate = PathBuf::from(candidate);
2425 if candidate.exists() {
2426 deps.push((candidate, DependencyType::Target));
2427 }
2428 }
2429 deps.push((path_to_add.into(), DependencyType::Target));
2430 }
2431
2432 deps.extend(additional_target_deps);
2433 deps.sort();
2434 let mut new_contents = Vec::new();
2435 for (dep, dependency_type) in deps.iter() {
2436 new_contents.extend(match *dependency_type {
2437 DependencyType::Host => b"h",
2438 DependencyType::Target => b"t",
2439 DependencyType::TargetSelfContained => b"s",
2440 });
2441 new_contents.extend(dep.to_str().unwrap().as_bytes());
2442 new_contents.extend(b"\0");
2443 }
2444 t!(fs::write(stamp.path(), &new_contents));
2445 deps.into_iter().map(|(d, _)| d).collect()
2446}
2447
2448pub fn stream_cargo(
2449 builder: &Builder<'_>,
2450 cargo: Cargo,
2451 tail_args: Vec<String>,
2452 cb: &mut dyn FnMut(CargoMessage<'_>),
2453) -> bool {
2454 let mut cmd = cargo.into_cmd();
2455
2456 #[cfg(feature = "tracing")]
2457 let _run_span = crate::trace_cmd!(cmd);
2458
2459 let cargo = cmd.as_command_mut();
2460 let mut message_format = if builder.config.json_output {
2463 String::from("json")
2464 } else {
2465 String::from("json-render-diagnostics")
2466 };
2467 if let Some(s) = &builder.config.rustc_error_format {
2468 message_format.push_str(",json-diagnostic-");
2469 message_format.push_str(s);
2470 }
2471 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
2472
2473 for arg in tail_args {
2474 cargo.arg(arg);
2475 }
2476
2477 builder.verbose(|| println!("running: {cargo:?}"));
2478
2479 if builder.config.dry_run() {
2480 return true;
2481 }
2482
2483 let mut child = match cargo.spawn() {
2484 Ok(child) => child,
2485 Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"),
2486 };
2487
2488 let stdout = BufReader::new(child.stdout.take().unwrap());
2492 for line in stdout.lines() {
2493 let line = t!(line);
2494 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2495 Ok(msg) => {
2496 if builder.config.json_output {
2497 println!("{line}");
2499 }
2500 cb(msg)
2501 }
2502 Err(_) => println!("{line}"),
2504 }
2505 }
2506
2507 let status = t!(child.wait());
2509 if builder.is_verbose() && !status.success() {
2510 eprintln!(
2511 "command did not execute successfully: {cargo:?}\n\
2512 expected success, got: {status}"
2513 );
2514 }
2515 status.success()
2516}
2517
2518#[derive(Deserialize)]
2519pub struct CargoTarget<'a> {
2520 crate_types: Vec<Cow<'a, str>>,
2521}
2522
2523#[derive(Deserialize)]
2524#[serde(tag = "reason", rename_all = "kebab-case")]
2525pub enum CargoMessage<'a> {
2526 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2527 BuildScriptExecuted,
2528 BuildFinished,
2529}
2530
2531pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2532 if target != "x86_64-unknown-linux-gnu"
2536 || !builder.config.is_host_target(target)
2537 || !path.exists()
2538 {
2539 return;
2540 }
2541
2542 let previous_mtime = t!(t!(path.metadata()).modified());
2543 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2544
2545 let file = t!(fs::File::open(path));
2546
2547 t!(file.set_modified(previous_mtime));
2560}
2561
2562pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2564 build_compiler.stage != 0
2565}