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::{env, fs, str};
16
17use serde_derive::Deserialize;
18#[cfg(feature = "tracing")]
19use tracing::{instrument, span};
20
21use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
22use crate::core::build_steps::tool::{SourceType, copy_lld_artifacts};
23use crate::core::build_steps::{dist, llvm};
24use crate::core::builder;
25use crate::core::builder::{
26 Builder, Cargo, Kind, PathSet, RunConfig, ShouldRun, Step, StepMetadata, TaskPath,
27 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::{
37 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
38 debug, trace,
39};
40
41#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
43pub struct Std {
44 pub target: TargetSelection,
45 pub compiler: Compiler,
46 crates: Vec<String>,
50 force_recompile: bool,
53 extra_rust_args: &'static [&'static str],
54 is_for_mir_opt_tests: bool,
55}
56
57impl Std {
58 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
59 Self {
60 target,
61 compiler,
62 crates: Default::default(),
63 force_recompile: false,
64 extra_rust_args: &[],
65 is_for_mir_opt_tests: false,
66 }
67 }
68
69 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
70 self.force_recompile = force_recompile;
71 self
72 }
73
74 #[expect(clippy::wrong_self_convention)]
75 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
76 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
77 self
78 }
79
80 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
81 self.extra_rust_args = extra_rust_args;
82 self
83 }
84
85 fn copy_extra_objects(
86 &self,
87 builder: &Builder<'_>,
88 compiler: &Compiler,
89 target: TargetSelection,
90 ) -> Vec<(PathBuf, DependencyType)> {
91 let mut deps = Vec::new();
92 if !self.is_for_mir_opt_tests {
93 deps.extend(copy_third_party_objects(builder, compiler, target));
94 deps.extend(copy_self_contained_objects(builder, compiler, target));
95 }
96 deps
97 }
98}
99
100impl Step for Std {
101 type Output = ();
102 const DEFAULT: bool = true;
103
104 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
105 run.crate_or_deps("sysroot").path("library")
106 }
107
108 #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
109 fn make_run(run: RunConfig<'_>) {
110 let crates = std_crates_for_run_make(&run);
111 let builder = run.builder;
112
113 let force_recompile = builder.rust_info().is_managed_git_subrepository()
117 && builder.download_rustc()
118 && builder.config.has_changes_from_upstream(&["library"]);
119
120 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
121 trace!("download_rustc: {}", builder.download_rustc());
122 trace!(force_recompile);
123
124 run.builder.ensure(Std {
125 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
126 target: run.target,
127 crates,
128 force_recompile,
129 extra_rust_args: &[],
130 is_for_mir_opt_tests: false,
131 });
132 }
133
134 #[cfg_attr(
140 feature = "tracing",
141 instrument(
142 level = "debug",
143 name = "Std::run",
144 skip_all,
145 fields(
146 target = ?self.target,
147 compiler = ?self.compiler,
148 force_recompile = self.force_recompile
149 ),
150 ),
151 )]
152 fn run(self, builder: &Builder<'_>) {
153 let target = self.target;
154
155 if self.compiler.stage == 0 {
157 let compiler = self.compiler;
158 builder.ensure(StdLink::from_std(self, compiler));
159
160 return;
161 }
162
163 let compiler = if builder.download_rustc() && self.force_recompile {
164 builder.compiler(self.compiler.stage.saturating_sub(1), builder.config.host_target)
167 } else {
168 self.compiler
169 };
170
171 if builder.download_rustc()
174 && builder.config.is_host_target(target)
175 && !self.force_recompile
176 {
177 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
178 cp_rustc_component_to_ci_sysroot(
179 builder,
180 &sysroot,
181 builder.config.ci_rust_std_contents(),
182 );
183 return;
184 }
185
186 if builder.config.keep_stage.contains(&compiler.stage)
187 || builder.config.keep_stage_std.contains(&compiler.stage)
188 {
189 trace!(keep_stage = ?builder.config.keep_stage);
190 trace!(keep_stage_std = ?builder.config.keep_stage_std);
191
192 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
193
194 builder.ensure(StartupObjects { compiler, target });
195
196 self.copy_extra_objects(builder, &compiler, target);
197
198 builder.ensure(StdLink::from_std(self, compiler));
199 return;
200 }
201
202 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
203
204 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
205 trace!(?compiler_to_use);
206
207 if compiler_to_use != compiler
208 && compiler.stage > 1
213 {
214 trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
215
216 builder.std(compiler_to_use, target);
217 let msg = if compiler_to_use.host == target {
218 format!(
219 "Uplifting library (stage{} -> stage{})",
220 compiler_to_use.stage, compiler.stage
221 )
222 } else {
223 format!(
224 "Uplifting library (stage{}:{} -> stage{}:{})",
225 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
226 )
227 };
228 builder.info(&msg);
229
230 self.copy_extra_objects(builder, &compiler, target);
233
234 builder.ensure(StdLink::from_std(self, compiler_to_use));
235 return;
236 }
237
238 trace!(
239 ?compiler_to_use,
240 ?compiler,
241 "compiler == compiler_to_use, handling not-cross-compile scenario"
242 );
243
244 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
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.host_target),
307 ));
308 }
309
310 fn metadata(&self) -> Option<StepMetadata> {
311 Some(StepMetadata::build("std", self.target).built_by(self.compiler))
312 }
313}
314
315fn copy_and_stamp(
316 builder: &Builder<'_>,
317 libdir: &Path,
318 sourcedir: &Path,
319 name: &str,
320 target_deps: &mut Vec<(PathBuf, DependencyType)>,
321 dependency_type: DependencyType,
322) {
323 let target = libdir.join(name);
324 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
325
326 target_deps.push((target, dependency_type));
327}
328
329fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
330 let libunwind_path = builder.ensure(llvm::Libunwind { target });
331 let libunwind_source = libunwind_path.join("libunwind.a");
332 let libunwind_target = libdir.join("libunwind.a");
333 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
334 libunwind_target
335}
336
337fn copy_third_party_objects(
339 builder: &Builder<'_>,
340 compiler: &Compiler,
341 target: TargetSelection,
342) -> Vec<(PathBuf, DependencyType)> {
343 let mut target_deps = vec![];
344
345 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
346 target_deps.extend(
349 copy_sanitizers(builder, compiler, target)
350 .into_iter()
351 .map(|d| (d, DependencyType::Target)),
352 );
353 }
354
355 if target == "x86_64-fortanix-unknown-sgx"
356 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
357 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
358 {
359 let libunwind_path =
360 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
361 target_deps.push((libunwind_path, DependencyType::Target));
362 }
363
364 target_deps
365}
366
367fn copy_self_contained_objects(
369 builder: &Builder<'_>,
370 compiler: &Compiler,
371 target: TargetSelection,
372) -> Vec<(PathBuf, DependencyType)> {
373 let libdir_self_contained =
374 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
375 t!(fs::create_dir_all(&libdir_self_contained));
376 let mut target_deps = vec![];
377
378 if target.needs_crt_begin_end() {
386 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
387 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
388 });
389 if !target.starts_with("wasm32") {
390 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
391 copy_and_stamp(
392 builder,
393 &libdir_self_contained,
394 &srcdir,
395 obj,
396 &mut target_deps,
397 DependencyType::TargetSelfContained,
398 );
399 }
400 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
401 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
402 let src = crt_path.join(obj);
403 let target = libdir_self_contained.join(obj);
404 builder.copy_link(&src, &target, FileType::NativeLibrary);
405 target_deps.push((target, DependencyType::TargetSelfContained));
406 }
407 } else {
408 for &obj in &["libc.a", "crt1-command.o"] {
411 copy_and_stamp(
412 builder,
413 &libdir_self_contained,
414 &srcdir,
415 obj,
416 &mut target_deps,
417 DependencyType::TargetSelfContained,
418 );
419 }
420 }
421 if !target.starts_with("s390x") {
422 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
423 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
424 }
425 } else if target.contains("-wasi") {
426 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
427 panic!(
428 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
429 or `$WASI_SDK_PATH` set",
430 target.triple
431 )
432 });
433 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
434 copy_and_stamp(
435 builder,
436 &libdir_self_contained,
437 &srcdir,
438 obj,
439 &mut target_deps,
440 DependencyType::TargetSelfContained,
441 );
442 }
443 } else if target.is_windows_gnu() {
444 for obj in ["crt2.o", "dllcrt2.o"].iter() {
445 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
446 let dst = libdir_self_contained.join(obj);
447 builder.copy_link(&src, &dst, FileType::NativeLibrary);
448 target_deps.push((dst, DependencyType::TargetSelfContained));
449 }
450 }
451
452 target_deps
453}
454
455pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
458 let mut crates = run.make_run_crates(builder::Alias::Library);
459
460 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
469 if target_is_no_std {
470 crates.retain(|c| c == "core" || c == "alloc");
471 }
472 crates
473}
474
475fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
481 if builder.config.llvm_from_ci {
483 builder.config.maybe_download_ci_llvm();
485 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
486 if ci_llvm_compiler_rt.exists() {
487 return ci_llvm_compiler_rt;
488 }
489 }
490
491 builder.require_submodule("src/llvm-project", {
493 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
494 });
495 builder.src.join("src/llvm-project/compiler-rt")
496}
497
498pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
501 if target.contains("apple") && !builder.config.dry_run() {
519 let mut cmd = command(builder.rustc(cargo.compiler()));
523 cmd.arg("--target").arg(target.rustc_target_arg());
524 cmd.arg("--print=deployment-target");
525 let output = cmd.run_capture_stdout(builder).stdout();
526
527 let (env_var, value) = output.split_once('=').unwrap();
528 cargo.env(env_var.trim(), value.trim());
531
532 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
542 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
543 }
544 }
545
546 if let Some(path) = builder.config.profiler_path(target) {
548 cargo.env("LLVM_PROFILER_RT_LIB", path);
549 } else if builder.config.profiler_enabled(target) {
550 let compiler_rt = compiler_rt_for_profiler(builder);
551 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
555 }
556
557 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
571 builder.require_submodule(
579 "src/llvm-project",
580 Some(
581 "The `build.optimized-compiler-builtins` config option \
582 requires `compiler-rt` sources from LLVM.",
583 ),
584 );
585 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
586 assert!(compiler_builtins_root.exists());
587 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
590 " compiler-builtins-c"
591 } else {
592 ""
593 };
594
595 if !builder.unstable_features() {
598 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
599 }
600
601 let mut features = String::new();
602
603 if builder.no_std(target) == Some(true) {
604 features += " compiler-builtins-mem";
605 if !target.starts_with("bpf") {
606 features.push_str(compiler_builtins_c_feature);
607 }
608
609 cargo
611 .args(["-p", "alloc"])
612 .arg("--manifest-path")
613 .arg(builder.src.join("library/alloc/Cargo.toml"))
614 .arg("--features")
615 .arg(features);
616 } else {
617 features += &builder.std_features(target);
618 features.push_str(compiler_builtins_c_feature);
619
620 cargo
621 .arg("--features")
622 .arg(features)
623 .arg("--manifest-path")
624 .arg(builder.src.join("library/sysroot/Cargo.toml"));
625
626 if target.contains("musl")
629 && let Some(p) = builder.musl_libdir(target)
630 {
631 let root = format!("native={}", p.to_str().unwrap());
632 cargo.rustflag("-L").rustflag(&root);
633 }
634
635 if target.contains("-wasi")
636 && let Some(dir) = builder.wasi_libdir(target)
637 {
638 let root = format!("native={}", dir.to_str().unwrap());
639 cargo.rustflag("-L").rustflag(&root);
640 }
641 }
642
643 if stage >= 1 {
652 cargo.rustflag("-Cembed-bitcode=yes");
653 }
654 if builder.config.rust_lto == RustcLto::Off {
655 cargo.rustflag("-Clto=off");
656 }
657
658 if target.contains("riscv") {
665 cargo.rustflag("-Cforce-unwind-tables=yes");
666 }
667
668 cargo.rustflag("-Zunstable-options");
671 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
672
673 let html_root =
674 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
675 cargo.rustflag(&html_root);
676 cargo.rustdocflag(&html_root);
677
678 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
679}
680
681#[derive(Debug, Clone, PartialEq, Eq, Hash)]
682pub struct StdLink {
683 pub compiler: Compiler,
684 pub target_compiler: Compiler,
685 pub target: TargetSelection,
686 crates: Vec<String>,
688 force_recompile: bool,
690}
691
692impl StdLink {
693 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
694 Self {
695 compiler: host_compiler,
696 target_compiler: std.compiler,
697 target: std.target,
698 crates: std.crates,
699 force_recompile: std.force_recompile,
700 }
701 }
702}
703
704impl Step for StdLink {
705 type Output = ();
706
707 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
708 run.never()
709 }
710
711 #[cfg_attr(
720 feature = "tracing",
721 instrument(
722 level = "trace",
723 name = "StdLink::run",
724 skip_all,
725 fields(
726 compiler = ?self.compiler,
727 target_compiler = ?self.target_compiler,
728 target = ?self.target
729 ),
730 ),
731 )]
732 fn run(self, builder: &Builder<'_>) {
733 let compiler = self.compiler;
734 let target_compiler = self.target_compiler;
735 let target = self.target;
736
737 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
739 let lib = builder.sysroot_libdir_relative(self.compiler);
741 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
742 compiler: self.compiler,
743 force_recompile: self.force_recompile,
744 });
745 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
746 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
747 (libdir, hostdir)
748 } else {
749 let libdir = builder.sysroot_target_libdir(target_compiler, target);
750 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
751 (libdir, hostdir)
752 };
753
754 let is_downloaded_beta_stage0 = builder
755 .build
756 .config
757 .initial_rustc
758 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
759
760 if compiler.stage == 0 && is_downloaded_beta_stage0 {
764 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
766
767 let host = compiler.host;
768 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
769 let sysroot_bin_dir = sysroot.join("bin");
770 t!(fs::create_dir_all(&sysroot_bin_dir));
771 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
772
773 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
774 t!(fs::create_dir_all(sysroot.join("lib")));
775 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
776
777 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
779 t!(fs::create_dir_all(&sysroot_codegen_backends));
780 let stage0_codegen_backends = builder
781 .out
782 .join(host)
783 .join("stage0/lib/rustlib")
784 .join(host)
785 .join("codegen-backends");
786 if stage0_codegen_backends.exists() {
787 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
788 }
789 } else if compiler.stage == 0 {
790 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
791
792 if builder.local_rebuild {
793 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
797 }
798
799 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
800 } else {
801 if builder.download_rustc() {
802 let _ = fs::remove_dir_all(&libdir);
804 let _ = fs::remove_dir_all(&hostdir);
805 }
806
807 add_to_sysroot(
808 builder,
809 &libdir,
810 &hostdir,
811 &build_stamp::libstd_stamp(builder, compiler, target),
812 );
813 }
814 }
815}
816
817fn copy_sanitizers(
819 builder: &Builder<'_>,
820 compiler: &Compiler,
821 target: TargetSelection,
822) -> Vec<PathBuf> {
823 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
824
825 if builder.config.dry_run() {
826 return Vec::new();
827 }
828
829 let mut target_deps = Vec::new();
830 let libdir = builder.sysroot_target_libdir(*compiler, target);
831
832 for runtime in &runtimes {
833 let dst = libdir.join(&runtime.name);
834 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
835
836 if target == "x86_64-apple-darwin"
840 || target == "aarch64-apple-darwin"
841 || target == "aarch64-apple-ios"
842 || target == "aarch64-apple-ios-sim"
843 || target == "x86_64-apple-ios"
844 {
845 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
847 apple_darwin_sign_file(builder, &dst);
850 }
851
852 target_deps.push(dst);
853 }
854
855 target_deps
856}
857
858fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
859 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
860}
861
862fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
863 command("codesign")
864 .arg("-f") .arg("-s")
866 .arg("-")
867 .arg(file_path)
868 .run(builder);
869}
870
871#[derive(Debug, Clone, PartialEq, Eq, Hash)]
872pub struct StartupObjects {
873 pub compiler: Compiler,
874 pub target: TargetSelection,
875}
876
877impl Step for StartupObjects {
878 type Output = Vec<(PathBuf, DependencyType)>;
879
880 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
881 run.path("library/rtstartup")
882 }
883
884 fn make_run(run: RunConfig<'_>) {
885 run.builder.ensure(StartupObjects {
886 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
887 target: run.target,
888 });
889 }
890
891 #[cfg_attr(
898 feature = "tracing",
899 instrument(
900 level = "trace",
901 name = "StartupObjects::run",
902 skip_all,
903 fields(compiler = ?self.compiler, target = ?self.target),
904 ),
905 )]
906 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
907 let for_compiler = self.compiler;
908 let target = self.target;
909 if !target.is_windows_gnu() {
910 return vec![];
911 }
912
913 let mut target_deps = vec![];
914
915 let src_dir = &builder.src.join("library").join("rtstartup");
916 let dst_dir = &builder.native_dir(target).join("rtstartup");
917 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
918 t!(fs::create_dir_all(dst_dir));
919
920 for file in &["rsbegin", "rsend"] {
921 let src_file = &src_dir.join(file.to_string() + ".rs");
922 let dst_file = &dst_dir.join(file.to_string() + ".o");
923 if !up_to_date(src_file, dst_file) {
924 let mut cmd = command(&builder.initial_rustc);
925 cmd.env("RUSTC_BOOTSTRAP", "1");
926 if !builder.local_rebuild {
927 cmd.arg("--cfg").arg("bootstrap");
929 }
930 cmd.arg("--target")
931 .arg(target.rustc_target_arg())
932 .arg("--emit=obj")
933 .arg("-o")
934 .arg(dst_file)
935 .arg(src_file)
936 .run(builder);
937 }
938
939 let obj = sysroot_dir.join((*file).to_string() + ".o");
940 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
941 target_deps.push((obj, DependencyType::Target));
942 }
943
944 target_deps
945 }
946}
947
948fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
949 let ci_rustc_dir = builder.config.ci_rustc_dir();
950
951 for file in contents {
952 let src = ci_rustc_dir.join(&file);
953 let dst = sysroot.join(file);
954 if src.is_dir() {
955 t!(fs::create_dir_all(dst));
956 } else {
957 builder.copy_link(&src, &dst, FileType::Regular);
958 }
959 }
960}
961
962#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
969pub struct Rustc {
970 pub target: TargetSelection,
972 pub build_compiler: Compiler,
974 crates: Vec<String>,
980}
981
982impl Rustc {
983 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
984 Self { target, build_compiler, crates: Default::default() }
985 }
986}
987
988impl Step for Rustc {
989 type Output = u32;
997 const ONLY_HOSTS: bool = true;
998 const DEFAULT: bool = false;
999
1000 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1001 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1002 for (i, krate) in crates.iter().enumerate() {
1003 if krate.name == "rustc-main" {
1006 crates.swap_remove(i);
1007 break;
1008 }
1009 }
1010 run.crates(crates)
1011 }
1012
1013 fn make_run(run: RunConfig<'_>) {
1014 if run.builder.paths == vec![PathBuf::from("compiler")] {
1017 return;
1018 }
1019
1020 let crates = run.cargo_crates_in_set();
1021 run.builder.ensure(Rustc {
1022 build_compiler: run
1023 .builder
1024 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1025 target: run.target,
1026 crates,
1027 });
1028 }
1029
1030 #[cfg_attr(
1036 feature = "tracing",
1037 instrument(
1038 level = "debug",
1039 name = "Rustc::run",
1040 skip_all,
1041 fields(previous_compiler = ?self.build_compiler, target = ?self.target),
1042 ),
1043 )]
1044 fn run(self, builder: &Builder<'_>) -> u32 {
1045 let build_compiler = self.build_compiler;
1046 let target = self.target;
1047
1048 if builder.download_rustc() && build_compiler.stage != 0 {
1051 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1052
1053 let sysroot =
1054 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1055 cp_rustc_component_to_ci_sysroot(
1056 builder,
1057 &sysroot,
1058 builder.config.ci_rustc_dev_contents(),
1059 );
1060 return build_compiler.stage;
1061 }
1062
1063 builder.std(build_compiler, target);
1066
1067 if builder.config.keep_stage.contains(&build_compiler.stage) {
1068 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1069
1070 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1071 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1072 builder.ensure(RustcLink::from_rustc(self, build_compiler));
1073
1074 return build_compiler.stage;
1075 }
1076
1077 let compiler_to_use =
1078 builder.compiler_for(build_compiler.stage, build_compiler.host, target);
1079 if compiler_to_use != build_compiler {
1080 builder.ensure(Rustc::new(compiler_to_use, target));
1081 let msg = if compiler_to_use.host == target {
1082 format!(
1083 "Uplifting rustc (stage{} -> stage{})",
1084 compiler_to_use.stage,
1085 build_compiler.stage + 1
1086 )
1087 } else {
1088 format!(
1089 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1090 compiler_to_use.stage,
1091 compiler_to_use.host,
1092 build_compiler.stage + 1,
1093 target
1094 )
1095 };
1096 builder.info(&msg);
1097 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1098 return compiler_to_use.stage;
1099 }
1100
1101 builder.std(
1107 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1108 builder.config.host_target,
1109 );
1110
1111 let mut cargo = builder::Cargo::new(
1112 builder,
1113 build_compiler,
1114 Mode::Rustc,
1115 SourceType::InTree,
1116 target,
1117 Kind::Build,
1118 );
1119
1120 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1121
1122 for krate in &*self.crates {
1126 cargo.arg("-p").arg(krate);
1127 }
1128
1129 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1130 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1132 }
1133
1134 let _guard = builder.msg_sysroot_tool(
1135 Kind::Build,
1136 build_compiler.stage,
1137 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1138 build_compiler.host,
1139 target,
1140 );
1141 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1142 run_cargo(
1143 builder,
1144 cargo,
1145 vec![],
1146 &stamp,
1147 vec![],
1148 false,
1149 true, );
1151
1152 let target_root_dir = stamp.path().parent().unwrap();
1153 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1159 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1160 {
1161 let rustc_driver = target_root_dir.join("librustc_driver.so");
1162 strip_debug(builder, target, &rustc_driver);
1163 }
1164
1165 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1166 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1169 }
1170
1171 builder.ensure(RustcLink::from_rustc(
1172 self,
1173 builder.compiler(build_compiler.stage, builder.config.host_target),
1174 ));
1175
1176 build_compiler.stage
1177 }
1178
1179 fn metadata(&self) -> Option<StepMetadata> {
1180 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1181 }
1182}
1183
1184pub fn rustc_cargo(
1185 builder: &Builder<'_>,
1186 cargo: &mut Cargo,
1187 target: TargetSelection,
1188 build_compiler: &Compiler,
1189 crates: &[String],
1190) {
1191 cargo
1192 .arg("--features")
1193 .arg(builder.rustc_features(builder.kind, target, crates))
1194 .arg("--manifest-path")
1195 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1196
1197 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1198
1199 cargo.rustflag("-Zon-broken-pipe=kill");
1213
1214 if builder.config.llvm_enzyme {
1217 let arch = builder.build.host_target;
1218 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1219 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1220
1221 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1222 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1223 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1224 }
1225 }
1226
1227 if builder.build.config.lld_mode.is_used() {
1232 cargo.rustflag("-Zdefault-visibility=protected");
1233 }
1234
1235 if is_lto_stage(build_compiler) {
1236 match builder.config.rust_lto {
1237 RustcLto::Thin | RustcLto::Fat => {
1238 cargo.rustflag("-Zdylib-lto");
1241 let lto_type = match builder.config.rust_lto {
1245 RustcLto::Thin => "thin",
1246 RustcLto::Fat => "fat",
1247 _ => unreachable!(),
1248 };
1249 cargo.rustflag(&format!("-Clto={lto_type}"));
1250 cargo.rustflag("-Cembed-bitcode=yes");
1251 }
1252 RustcLto::ThinLocal => { }
1253 RustcLto::Off => {
1254 cargo.rustflag("-Clto=off");
1255 }
1256 }
1257 } else if builder.config.rust_lto == RustcLto::Off {
1258 cargo.rustflag("-Clto=off");
1259 }
1260
1261 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1269 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1270 }
1271
1272 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1273 panic!("Cannot use and generate PGO profiles at the same time");
1274 }
1275 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1276 if build_compiler.stage == 1 {
1277 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1278 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1281 true
1282 } else {
1283 false
1284 }
1285 } else if let Some(path) = &builder.config.rust_profile_use {
1286 if build_compiler.stage == 1 {
1287 cargo.rustflag(&format!("-Cprofile-use={path}"));
1288 if builder.is_verbose() {
1289 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1290 }
1291 true
1292 } else {
1293 false
1294 }
1295 } else {
1296 false
1297 };
1298 if is_collecting {
1299 cargo.rustflag(&format!(
1301 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1302 builder.config.src.components().count()
1303 ));
1304 }
1305
1306 if let Some(ref ccache) = builder.config.ccache
1311 && build_compiler.stage == 0
1312 && !builder.config.incremental
1313 {
1314 cargo.env("RUSTC_WRAPPER", ccache);
1315 }
1316
1317 rustc_cargo_env(builder, cargo, target);
1318}
1319
1320pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1321 cargo
1324 .env("CFG_RELEASE", builder.rust_release())
1325 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1326 .env("CFG_VERSION", builder.rust_version());
1327
1328 if builder.config.omit_git_hash {
1332 cargo.env("CFG_OMIT_GIT_HASH", "1");
1333 }
1334
1335 if let Some(backend) = builder.config.default_codegen_backend(target) {
1336 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
1337 }
1338
1339 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1340 let target_config = builder.config.target_config.get(&target);
1341
1342 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1343
1344 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1345 cargo.env("CFG_VER_DATE", ver_date);
1346 }
1347 if let Some(ref ver_hash) = builder.rust_info().sha() {
1348 cargo.env("CFG_VER_HASH", ver_hash);
1349 }
1350 if !builder.unstable_features() {
1351 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1352 }
1353
1354 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1357 cargo.env("CFG_DEFAULT_LINKER", s);
1358 } else if let Some(ref s) = builder.config.rustc_default_linker {
1359 cargo.env("CFG_DEFAULT_LINKER", s);
1360 }
1361
1362 if builder.config.lld_enabled {
1364 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1365 }
1366
1367 if builder.config.rust_verify_llvm_ir {
1368 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1369 }
1370
1371 if builder.config.llvm_enzyme {
1372 cargo.rustflag("--cfg=llvm_enzyme");
1373 }
1374
1375 if builder.config.llvm_enabled(target) {
1387 let building_llvm_is_expensive =
1388 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1389 .should_build();
1390
1391 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1392 if !skip_llvm {
1393 rustc_llvm_env(builder, cargo, target)
1394 }
1395 }
1396
1397 if builder.config.jemalloc(target)
1400 && target.starts_with("aarch64")
1401 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1402 {
1403 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1404 }
1405}
1406
1407fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1413 if builder.config.is_rust_llvm(target) {
1414 cargo.env("LLVM_RUSTLLVM", "1");
1415 }
1416 if builder.config.llvm_enzyme {
1417 cargo.env("LLVM_ENZYME", "1");
1418 }
1419 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1420 cargo.env("LLVM_CONFIG", &host_llvm_config);
1421
1422 let mut llvm_linker_flags = String::new();
1432 if builder.config.llvm_profile_generate
1433 && target.is_msvc()
1434 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1435 {
1436 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1438 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1439 }
1440
1441 if let Some(ref s) = builder.config.llvm_ldflags {
1443 if !llvm_linker_flags.is_empty() {
1444 llvm_linker_flags.push(' ');
1445 }
1446 llvm_linker_flags.push_str(s);
1447 }
1448
1449 if !llvm_linker_flags.is_empty() {
1451 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1452 }
1453
1454 if builder.config.llvm_static_stdcpp
1457 && !target.contains("freebsd")
1458 && !target.is_msvc()
1459 && !target.contains("apple")
1460 && !target.contains("solaris")
1461 {
1462 let libstdcxx_name =
1463 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1464 let file = compiler_file(
1465 builder,
1466 &builder.cxx(target).unwrap(),
1467 target,
1468 CLang::Cxx,
1469 libstdcxx_name,
1470 );
1471 cargo.env("LLVM_STATIC_STDCPP", file);
1472 }
1473 if builder.llvm_link_shared() {
1474 cargo.env("LLVM_LINK_SHARED", "1");
1475 }
1476 if builder.config.llvm_use_libcxx {
1477 cargo.env("LLVM_USE_LIBCXX", "1");
1478 }
1479 if builder.config.llvm_assertions {
1480 cargo.env("LLVM_ASSERTIONS", "1");
1481 }
1482}
1483
1484#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1490struct RustcLink {
1491 pub compiler: Compiler,
1493 pub previous_stage_compiler: Compiler,
1495 pub target: TargetSelection,
1496 crates: Vec<String>,
1498}
1499
1500impl RustcLink {
1501 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1502 Self {
1503 compiler: host_compiler,
1504 previous_stage_compiler: rustc.build_compiler,
1505 target: rustc.target,
1506 crates: rustc.crates,
1507 }
1508 }
1509}
1510
1511impl Step for RustcLink {
1512 type Output = ();
1513
1514 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1515 run.never()
1516 }
1517
1518 #[cfg_attr(
1520 feature = "tracing",
1521 instrument(
1522 level = "trace",
1523 name = "RustcLink::run",
1524 skip_all,
1525 fields(
1526 compiler = ?self.compiler,
1527 previous_stage_compiler = ?self.previous_stage_compiler,
1528 target = ?self.target,
1529 ),
1530 ),
1531 )]
1532 fn run(self, builder: &Builder<'_>) {
1533 let compiler = self.compiler;
1534 let previous_stage_compiler = self.previous_stage_compiler;
1535 let target = self.target;
1536 add_to_sysroot(
1537 builder,
1538 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1539 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1540 &build_stamp::librustc_stamp(builder, compiler, target),
1541 );
1542 }
1543}
1544
1545#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1546pub struct CodegenBackend {
1547 pub target: TargetSelection,
1548 pub compiler: Compiler,
1549 pub backend: CodegenBackendKind,
1550}
1551
1552fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1553 let mut needs_codegen_cfg = false;
1554 for path_set in &run.paths {
1555 needs_codegen_cfg = match path_set {
1556 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1557 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1558 }
1559 }
1560 needs_codegen_cfg
1561}
1562
1563pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1564
1565fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1566 let path = path.path.to_str().unwrap();
1567
1568 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1569 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1570
1571 if path.contains(CODEGEN_BACKEND_PREFIX) {
1572 let mut needs_codegen_backend_config = true;
1573 for backend in run.builder.config.codegen_backends(run.target) {
1574 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend.name())) {
1575 needs_codegen_backend_config = false;
1576 }
1577 }
1578 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1579 && needs_codegen_backend_config
1580 {
1581 run.builder.info(
1582 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1583 HELP: add backend to codegen-backends in bootstrap.toml.",
1584 );
1585 return true;
1586 }
1587 }
1588
1589 false
1590}
1591
1592impl Step for CodegenBackend {
1593 type Output = ();
1594 const ONLY_HOSTS: bool = true;
1595 const DEFAULT: bool = true;
1597
1598 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1599 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1600 }
1601
1602 fn make_run(run: RunConfig<'_>) {
1603 if needs_codegen_config(&run) {
1604 return;
1605 }
1606
1607 for backend in run.builder.config.codegen_backends(run.target) {
1608 if backend.is_llvm() {
1609 continue; }
1611
1612 run.builder.ensure(CodegenBackend {
1613 target: run.target,
1614 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1615 backend: backend.clone(),
1616 });
1617 }
1618 }
1619
1620 #[cfg_attr(
1621 feature = "tracing",
1622 instrument(
1623 level = "debug",
1624 name = "CodegenBackend::run",
1625 skip_all,
1626 fields(
1627 compiler = ?self.compiler,
1628 target = ?self.target,
1629 backend = ?self.target,
1630 ),
1631 ),
1632 )]
1633 fn run(self, builder: &Builder<'_>) {
1634 let compiler = self.compiler;
1635 let target = self.target;
1636 let backend = self.backend;
1637
1638 builder.ensure(Rustc::new(compiler, target));
1639
1640 if builder.config.keep_stage.contains(&compiler.stage) {
1641 trace!("`keep-stage` requested");
1642 builder.info(
1643 "WARNING: Using a potentially old codegen backend. \
1644 This may not behave well.",
1645 );
1646 return;
1649 }
1650
1651 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1652 if compiler_to_use != compiler {
1653 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1654 return;
1655 }
1656
1657 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1658
1659 let mut cargo = builder::Cargo::new(
1660 builder,
1661 compiler,
1662 Mode::Codegen,
1663 SourceType::InTree,
1664 target,
1665 Kind::Build,
1666 );
1667 cargo
1668 .arg("--manifest-path")
1669 .arg(builder.src.join(format!("compiler/{}/Cargo.toml", backend.crate_name())));
1670 rustc_cargo_env(builder, &mut cargo, target);
1671
1672 if backend.is_gcc() {
1676 let gcc = builder.ensure(Gcc { target });
1677 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1678 }
1679
1680 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1681
1682 let _guard =
1683 builder.msg_build(compiler, format_args!("codegen backend {}", backend.name()), target);
1684 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1685 if builder.config.dry_run() {
1686 return;
1687 }
1688 let mut files = files.into_iter().filter(|f| {
1689 let filename = f.file_name().unwrap().to_str().unwrap();
1690 is_dylib(f) && filename.contains("rustc_codegen_")
1691 });
1692 let codegen_backend = match files.next() {
1693 Some(f) => f,
1694 None => panic!("no dylibs built for codegen backend?"),
1695 };
1696 if let Some(f) = files.next() {
1697 panic!(
1698 "codegen backend built two dylibs:\n{}\n{}",
1699 codegen_backend.display(),
1700 f.display()
1701 );
1702 }
1703 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1704 let codegen_backend = codegen_backend.to_str().unwrap();
1705 t!(stamp.add_stamp(codegen_backend).write());
1706 }
1707}
1708
1709fn copy_codegen_backends_to_sysroot(
1716 builder: &Builder<'_>,
1717 compiler: Compiler,
1718 target_compiler: Compiler,
1719) {
1720 let target = target_compiler.host;
1721
1722 let dst = builder.sysroot_codegen_backends(target_compiler);
1731 t!(fs::create_dir_all(&dst), dst);
1732
1733 if builder.config.dry_run() {
1734 return;
1735 }
1736
1737 for backend in builder.config.codegen_backends(target) {
1738 if backend.is_llvm() {
1739 continue; }
1741
1742 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1743 if stamp.path().exists() {
1744 let dylib = t!(fs::read_to_string(stamp.path()));
1745 let file = Path::new(&dylib);
1746 let filename = file.file_name().unwrap().to_str().unwrap();
1747 let target_filename = {
1750 let dash = filename.find('-').unwrap();
1751 let dot = filename.find('.').unwrap();
1752 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1753 };
1754 builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
1755 }
1756 }
1757}
1758
1759pub fn compiler_file(
1760 builder: &Builder<'_>,
1761 compiler: &Path,
1762 target: TargetSelection,
1763 c: CLang,
1764 file: &str,
1765) -> PathBuf {
1766 if builder.config.dry_run() {
1767 return PathBuf::new();
1768 }
1769 let mut cmd = command(compiler);
1770 cmd.args(builder.cc_handled_clags(target, c));
1771 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1772 cmd.arg(format!("-print-file-name={file}"));
1773 let out = cmd.run_capture_stdout(builder).stdout();
1774 PathBuf::from(out.trim())
1775}
1776
1777#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1778pub struct Sysroot {
1779 pub compiler: Compiler,
1780 force_recompile: bool,
1782}
1783
1784impl Sysroot {
1785 pub(crate) fn new(compiler: Compiler) -> Self {
1786 Sysroot { compiler, force_recompile: false }
1787 }
1788}
1789
1790impl Step for Sysroot {
1791 type Output = PathBuf;
1792
1793 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1794 run.never()
1795 }
1796
1797 #[cfg_attr(
1801 feature = "tracing",
1802 instrument(
1803 level = "debug",
1804 name = "Sysroot::run",
1805 skip_all,
1806 fields(compiler = ?self.compiler),
1807 ),
1808 )]
1809 fn run(self, builder: &Builder<'_>) -> PathBuf {
1810 let compiler = self.compiler;
1811 let host_dir = builder.out.join(compiler.host);
1812
1813 let sysroot_dir = |stage| {
1814 if stage == 0 {
1815 host_dir.join("stage0-sysroot")
1816 } else if self.force_recompile && stage == compiler.stage {
1817 host_dir.join(format!("stage{stage}-test-sysroot"))
1818 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1819 host_dir.join("ci-rustc-sysroot")
1820 } else {
1821 host_dir.join(format!("stage{stage}"))
1822 }
1823 };
1824 let sysroot = sysroot_dir(compiler.stage);
1825 trace!(stage = ?compiler.stage, ?sysroot);
1826
1827 builder
1828 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1829 let _ = fs::remove_dir_all(&sysroot);
1830 t!(fs::create_dir_all(&sysroot));
1831
1832 if compiler.stage == 0 {
1839 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1840 }
1841
1842 if builder.download_rustc() && compiler.stage != 0 {
1844 assert_eq!(
1845 builder.config.host_target, compiler.host,
1846 "Cross-compiling is not yet supported with `download-rustc`",
1847 );
1848
1849 for stage in 0..=2 {
1851 if stage != compiler.stage {
1852 let dir = sysroot_dir(stage);
1853 if !dir.ends_with("ci-rustc-sysroot") {
1854 let _ = fs::remove_dir_all(dir);
1855 }
1856 }
1857 }
1858
1859 let mut filtered_files = Vec::new();
1869 let mut add_filtered_files = |suffix, contents| {
1870 for path in contents {
1871 let path = Path::new(&path);
1872 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1873 filtered_files.push(path.file_name().unwrap().to_owned());
1874 }
1875 }
1876 };
1877 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1878 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1879 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1882
1883 let filtered_extensions = [
1884 OsStr::new("rmeta"),
1885 OsStr::new("rlib"),
1886 OsStr::new(std::env::consts::DLL_EXTENSION),
1888 ];
1889 let ci_rustc_dir = builder.config.ci_rustc_dir();
1890 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1891 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1892 return true;
1893 }
1894 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1895 return true;
1896 }
1897 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1898 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1899 false
1900 } else {
1901 true
1902 }
1903 });
1904 }
1905
1906 if compiler.stage != 0 {
1912 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1913 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1914 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1915 if let Err(e) =
1916 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1917 {
1918 eprintln!(
1919 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1920 sysroot_lib_rustlib_src_rust.display(),
1921 builder.src.display(),
1922 e,
1923 );
1924 if builder.config.rust_remap_debuginfo {
1925 eprintln!(
1926 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1927 sysroot_lib_rustlib_src_rust.display(),
1928 );
1929 }
1930 build_helper::exit!(1);
1931 }
1932 }
1933
1934 if !builder.download_rustc() {
1936 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1937 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1938 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1939 if let Err(e) =
1940 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1941 {
1942 eprintln!(
1943 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1944 sysroot_lib_rustlib_rustcsrc_rust.display(),
1945 builder.src.display(),
1946 e,
1947 );
1948 build_helper::exit!(1);
1949 }
1950 }
1951
1952 sysroot
1953 }
1954}
1955
1956#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1957pub struct Assemble {
1958 pub target_compiler: Compiler,
1963}
1964
1965impl Step for Assemble {
1966 type Output = Compiler;
1967 const ONLY_HOSTS: bool = true;
1968
1969 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1970 run.path("compiler/rustc").path("compiler")
1971 }
1972
1973 fn make_run(run: RunConfig<'_>) {
1974 run.builder.ensure(Assemble {
1975 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1976 });
1977 }
1978
1979 #[cfg_attr(
1985 feature = "tracing",
1986 instrument(
1987 level = "debug",
1988 name = "Assemble::run",
1989 skip_all,
1990 fields(target_compiler = ?self.target_compiler),
1991 ),
1992 )]
1993 fn run(self, builder: &Builder<'_>) -> Compiler {
1994 let target_compiler = self.target_compiler;
1995
1996 if target_compiler.stage == 0 {
1997 trace!("stage 0 build compiler is always available, simply returning");
1998 assert_eq!(
1999 builder.config.host_target, target_compiler.host,
2000 "Cannot obtain compiler for non-native build triple at stage 0"
2001 );
2002 return target_compiler;
2004 }
2005
2006 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2009 let libdir_bin = libdir.parent().unwrap().join("bin");
2010 t!(fs::create_dir_all(&libdir_bin));
2011
2012 if builder.config.llvm_enabled(target_compiler.host) {
2013 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2014
2015 let target = target_compiler.host;
2016 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2017 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2018 trace!("LLVM tools enabled");
2019
2020 let host_llvm_bin_dir = command(&host_llvm_config)
2021 .arg("--bindir")
2022 .run_capture_stdout(builder)
2023 .stdout()
2024 .trim()
2025 .to_string();
2026
2027 let llvm_bin_dir = if target == builder.host_target {
2028 PathBuf::from(host_llvm_bin_dir)
2029 } else {
2030 let external_llvm_config = builder
2033 .config
2034 .target_config
2035 .get(&target)
2036 .and_then(|t| t.llvm_config.clone());
2037 if let Some(external_llvm_config) = external_llvm_config {
2038 external_llvm_config.parent().unwrap().to_path_buf()
2041 } else {
2042 let host_llvm_out = builder.llvm_out(builder.host_target);
2046 let target_llvm_out = builder.llvm_out(target);
2047 if let Ok(relative_path) =
2048 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2049 {
2050 target_llvm_out.join(relative_path)
2051 } else {
2052 PathBuf::from(
2055 host_llvm_bin_dir
2056 .replace(&*builder.host_target.triple, &target.triple),
2057 )
2058 }
2059 }
2060 };
2061
2062 #[cfg(feature = "tracing")]
2069 let _llvm_tools_span =
2070 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2071 .entered();
2072 for tool in LLVM_TOOLS {
2073 trace!("installing `{tool}`");
2074 let tool_exe = exe(tool, target_compiler.host);
2075 let src_path = llvm_bin_dir.join(&tool_exe);
2076
2077 if !src_path.exists() && builder.config.llvm_from_ci {
2079 eprintln!("{} does not exist; skipping copy", src_path.display());
2080 continue;
2081 }
2082
2083 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2090 }
2091 }
2092 }
2093
2094 let maybe_install_llvm_bitcode_linker = || {
2095 if builder.config.llvm_bitcode_linker_enabled {
2096 trace!("llvm-bitcode-linker enabled, installing");
2097 let llvm_bitcode_linker = builder.ensure(
2098 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2099 builder,
2100 target_compiler,
2101 ),
2102 );
2103
2104 let bindir_self_contained = builder
2106 .sysroot(target_compiler)
2107 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2108 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2109
2110 t!(fs::create_dir_all(&bindir_self_contained));
2111 builder.copy_link(
2112 &llvm_bitcode_linker.tool_path,
2113 &bindir_self_contained.join(tool_exe),
2114 FileType::Executable,
2115 );
2116 }
2117 };
2118
2119 if builder.download_rustc() {
2121 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2122
2123 builder.std(target_compiler, target_compiler.host);
2124 let sysroot =
2125 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2126 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2129 if target_compiler.stage == builder.top_stage {
2131 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2132 }
2133
2134 maybe_install_llvm_bitcode_linker();
2137
2138 return target_compiler;
2139 }
2140
2141 debug!(
2155 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2156 target_compiler.stage - 1,
2157 builder.config.host_target,
2158 );
2159 let mut build_compiler =
2160 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2161
2162 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2164 debug!("`llvm_enzyme` requested");
2165 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2166 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2167 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2168 let lib_ext = std::env::consts::DLL_EXTENSION;
2169 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2170 let src_lib =
2171 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2172 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2173 let target_libdir =
2174 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2175 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2176 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2177 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2178 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2179 }
2180 }
2181
2182 debug!(
2188 ?build_compiler,
2189 "target_compiler.host" = ?target_compiler.host,
2190 "building compiler libraries to link to"
2191 );
2192 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2193 debug!(
2196 "(old) build_compiler.stage" = build_compiler.stage,
2197 "(adjusted) build_compiler.stage" = actual_stage,
2198 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2199 );
2200 build_compiler.stage = actual_stage;
2201
2202 #[cfg(feature = "tracing")]
2203 let _codegen_backend_span =
2204 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2205 for backend in builder.config.codegen_backends(target_compiler.host) {
2206 if backend.is_llvm() {
2207 debug!("llvm codegen backend is already built as part of rustc");
2208 continue; }
2210
2211 if builder.kind == Kind::Check && builder.top_stage == 1 {
2228 continue;
2229 }
2230 builder.ensure(CodegenBackend {
2231 compiler: build_compiler,
2232 target: target_compiler.host,
2233 backend: backend.clone(),
2234 });
2235 }
2236 #[cfg(feature = "tracing")]
2237 drop(_codegen_backend_span);
2238
2239 let stage = target_compiler.stage;
2240 let host = target_compiler.host;
2241 let (host_info, dir_name) = if build_compiler.host == host {
2242 ("".into(), "host".into())
2243 } else {
2244 (format!(" ({host})"), host.to_string())
2245 };
2246 let msg = format!(
2251 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2252 );
2253 builder.info(&msg);
2254
2255 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2257 let proc_macros = builder
2258 .read_stamp_file(&stamp)
2259 .into_iter()
2260 .filter_map(|(path, dependency_type)| {
2261 if dependency_type == DependencyType::Host {
2262 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2263 } else {
2264 None
2265 }
2266 })
2267 .collect::<HashSet<_>>();
2268
2269 let sysroot = builder.sysroot(target_compiler);
2270 let rustc_libdir = builder.rustc_libdir(target_compiler);
2271 t!(fs::create_dir_all(&rustc_libdir));
2272 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2273 for f in builder.read_dir(&src_libdir) {
2274 let filename = f.file_name().into_string().unwrap();
2275
2276 let is_proc_macro = proc_macros.contains(&filename);
2277 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2278
2279 let can_be_rustc_dynamic_dep = if builder
2283 .link_std_into_rustc_driver(target_compiler.host)
2284 && !target_compiler.host.is_windows()
2285 {
2286 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2287 !is_std
2288 } else {
2289 true
2290 };
2291
2292 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2293 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2294 }
2295 }
2296
2297 debug!("copying codegen backends to sysroot");
2298 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2299
2300 if builder.config.lld_enabled {
2301 let lld_wrapper =
2302 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2303 builder,
2304 target_compiler,
2305 ));
2306 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2307 }
2308
2309 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2310 debug!(
2311 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2312 workaround faulty homebrew `strip`s"
2313 );
2314
2315 let src_exe = exe("llvm-objcopy", target_compiler.host);
2322 let dst_exe = exe("rust-objcopy", target_compiler.host);
2323 builder.copy_link(
2324 &libdir_bin.join(src_exe),
2325 &libdir_bin.join(dst_exe),
2326 FileType::Executable,
2327 );
2328 }
2329
2330 if builder.tool_enabled("wasm-component-ld") {
2333 let wasm_component = builder.ensure(
2334 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2335 builder,
2336 target_compiler,
2337 ),
2338 );
2339 builder.copy_link(
2340 &wasm_component.tool_path,
2341 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2342 FileType::Executable,
2343 );
2344 }
2345
2346 maybe_install_llvm_bitcode_linker();
2347
2348 debug!(
2351 "target_compiler.host" = ?target_compiler.host,
2352 ?sysroot,
2353 "ensuring availability of `libLLVM.so` in compiler directory"
2354 );
2355 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2356 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2357
2358 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2360 let rustc = out_dir.join(exe("rustc-main", host));
2361 let bindir = sysroot.join("bin");
2362 t!(fs::create_dir_all(bindir));
2363 let compiler = builder.rustc(target_compiler);
2364 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2365 builder.copy_link(&rustc, &compiler, FileType::Executable);
2366
2367 target_compiler
2368 }
2369}
2370
2371pub fn add_to_sysroot(
2376 builder: &Builder<'_>,
2377 sysroot_dst: &Path,
2378 sysroot_host_dst: &Path,
2379 stamp: &BuildStamp,
2380) {
2381 let self_contained_dst = &sysroot_dst.join("self-contained");
2382 t!(fs::create_dir_all(sysroot_dst));
2383 t!(fs::create_dir_all(sysroot_host_dst));
2384 t!(fs::create_dir_all(self_contained_dst));
2385 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2386 let dst = match dependency_type {
2387 DependencyType::Host => sysroot_host_dst,
2388 DependencyType::Target => sysroot_dst,
2389 DependencyType::TargetSelfContained => self_contained_dst,
2390 };
2391 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2392 }
2393}
2394
2395pub fn run_cargo(
2396 builder: &Builder<'_>,
2397 cargo: Cargo,
2398 tail_args: Vec<String>,
2399 stamp: &BuildStamp,
2400 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2401 is_check: bool,
2402 rlib_only_metadata: bool,
2403) -> Vec<PathBuf> {
2404 let target_root_dir = stamp.path().parent().unwrap();
2406 let target_deps_dir = target_root_dir.join("deps");
2408 let host_root_dir = target_root_dir
2410 .parent()
2411 .unwrap() .parent()
2413 .unwrap() .join(target_root_dir.file_name().unwrap());
2415
2416 let mut deps = Vec::new();
2420 let mut toplevel = Vec::new();
2421 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2422 let (filenames, crate_types) = match msg {
2423 CargoMessage::CompilerArtifact {
2424 filenames,
2425 target: CargoTarget { crate_types },
2426 ..
2427 } => (filenames, crate_types),
2428 _ => return,
2429 };
2430 for filename in filenames {
2431 let mut keep = false;
2433 if filename.ends_with(".lib")
2434 || filename.ends_with(".a")
2435 || is_debug_info(&filename)
2436 || is_dylib(Path::new(&*filename))
2437 {
2438 keep = true;
2440 }
2441 if is_check && filename.ends_with(".rmeta") {
2442 keep = true;
2444 } else if rlib_only_metadata {
2445 if filename.contains("jemalloc_sys")
2446 || filename.contains("rustc_public_bridge")
2447 || filename.contains("rustc_public")
2448 {
2449 keep |= filename.ends_with(".rlib");
2452 } else {
2453 keep |= filename.ends_with(".rmeta");
2457 }
2458 } else {
2459 keep |= filename.ends_with(".rlib");
2461 }
2462
2463 if !keep {
2464 continue;
2465 }
2466
2467 let filename = Path::new(&*filename);
2468
2469 if filename.starts_with(&host_root_dir) {
2472 if crate_types.iter().any(|t| t == "proc-macro") {
2474 deps.push((filename.to_path_buf(), DependencyType::Host));
2475 }
2476 continue;
2477 }
2478
2479 if filename.starts_with(&target_deps_dir) {
2482 deps.push((filename.to_path_buf(), DependencyType::Target));
2483 continue;
2484 }
2485
2486 let expected_len = t!(filename.metadata()).len();
2497 let filename = filename.file_name().unwrap().to_str().unwrap();
2498 let mut parts = filename.splitn(2, '.');
2499 let file_stem = parts.next().unwrap().to_owned();
2500 let extension = parts.next().unwrap().to_owned();
2501
2502 toplevel.push((file_stem, extension, expected_len));
2503 }
2504 });
2505
2506 if !ok {
2507 crate::exit!(1);
2508 }
2509
2510 if builder.config.dry_run() {
2511 return Vec::new();
2512 }
2513
2514 let contents = target_deps_dir
2518 .read_dir()
2519 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2520 .map(|e| t!(e))
2521 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2522 .collect::<Vec<_>>();
2523 for (prefix, extension, expected_len) in toplevel {
2524 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2525 meta.len() == expected_len
2526 && filename
2527 .strip_prefix(&prefix[..])
2528 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2529 .unwrap_or(false)
2530 });
2531 let max = candidates.max_by_key(|&(_, _, metadata)| {
2532 metadata.modified().expect("mtime should be available on all relevant OSes")
2533 });
2534 let path_to_add = match max {
2535 Some(triple) => triple.0.to_str().unwrap(),
2536 None => panic!("no output generated for {prefix:?} {extension:?}"),
2537 };
2538 if is_dylib(Path::new(path_to_add)) {
2539 let candidate = format!("{path_to_add}.lib");
2540 let candidate = PathBuf::from(candidate);
2541 if candidate.exists() {
2542 deps.push((candidate, DependencyType::Target));
2543 }
2544 }
2545 deps.push((path_to_add.into(), DependencyType::Target));
2546 }
2547
2548 deps.extend(additional_target_deps);
2549 deps.sort();
2550 let mut new_contents = Vec::new();
2551 for (dep, dependency_type) in deps.iter() {
2552 new_contents.extend(match *dependency_type {
2553 DependencyType::Host => b"h",
2554 DependencyType::Target => b"t",
2555 DependencyType::TargetSelfContained => b"s",
2556 });
2557 new_contents.extend(dep.to_str().unwrap().as_bytes());
2558 new_contents.extend(b"\0");
2559 }
2560 t!(fs::write(stamp.path(), &new_contents));
2561 deps.into_iter().map(|(d, _)| d).collect()
2562}
2563
2564pub fn stream_cargo(
2565 builder: &Builder<'_>,
2566 cargo: Cargo,
2567 tail_args: Vec<String>,
2568 cb: &mut dyn FnMut(CargoMessage<'_>),
2569) -> bool {
2570 let mut cmd = cargo.into_cmd();
2571
2572 #[cfg(feature = "tracing")]
2573 let _run_span = crate::trace_cmd!(cmd);
2574
2575 let mut message_format = if builder.config.json_output {
2578 String::from("json")
2579 } else {
2580 String::from("json-render-diagnostics")
2581 };
2582 if let Some(s) = &builder.config.rustc_error_format {
2583 message_format.push_str(",json-diagnostic-");
2584 message_format.push_str(s);
2585 }
2586 cmd.arg("--message-format").arg(message_format);
2587
2588 for arg in tail_args {
2589 cmd.arg(arg);
2590 }
2591
2592 builder.verbose(|| println!("running: {cmd:?}"));
2593
2594 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2595
2596 let Some(mut streaming_command) = streaming_command else {
2597 return true;
2598 };
2599
2600 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2604 for line in stdout.lines() {
2605 let line = t!(line);
2606 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2607 Ok(msg) => {
2608 if builder.config.json_output {
2609 println!("{line}");
2611 }
2612 cb(msg)
2613 }
2614 Err(_) => println!("{line}"),
2616 }
2617 }
2618
2619 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2621 if builder.is_verbose() && !status.success() {
2622 eprintln!(
2623 "command did not execute successfully: {cmd:?}\n\
2624 expected success, got: {status}"
2625 );
2626 }
2627
2628 status.success()
2629}
2630
2631#[derive(Deserialize)]
2632pub struct CargoTarget<'a> {
2633 crate_types: Vec<Cow<'a, str>>,
2634}
2635
2636#[derive(Deserialize)]
2637#[serde(tag = "reason", rename_all = "kebab-case")]
2638pub enum CargoMessage<'a> {
2639 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2640 BuildScriptExecuted,
2641 BuildFinished,
2642}
2643
2644pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2645 if target != "x86_64-unknown-linux-gnu"
2649 || !builder.config.is_host_target(target)
2650 || !path.exists()
2651 {
2652 return;
2653 }
2654
2655 let previous_mtime = t!(t!(path.metadata()).modified());
2656 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2657
2658 let file = t!(fs::File::open(path));
2659
2660 t!(file.set_modified(previous_mtime));
2673}
2674
2675pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2677 build_compiler.stage != 0
2678}