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::time::SystemTime;
16use std::{env, fs, str};
17
18use serde_derive::Deserialize;
19#[cfg(feature = "tracing")]
20use tracing::span;
21
22use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags};
23use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
24use crate::core::build_steps::{dist, llvm};
25use crate::core::builder;
26use crate::core::builder::{
27 Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
28};
29use crate::core::config::{
30 CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
31};
32use crate::utils::build_stamp;
33use crate::utils::build_stamp::BuildStamp;
34use crate::utils::exec::command;
35use crate::utils::helpers::{
36 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
37};
38use crate::{
39 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
40 debug, trace,
41};
42
43#[derive(Debug, Clone, PartialEq, Eq, Hash)]
45pub struct Std {
46 pub target: TargetSelection,
47 pub build_compiler: Compiler,
49 crates: Vec<String>,
53 force_recompile: bool,
56 extra_rust_args: &'static [&'static str],
57 is_for_mir_opt_tests: bool,
58}
59
60impl Std {
61 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
62 Self {
63 target,
64 build_compiler,
65 crates: Default::default(),
66 force_recompile: false,
67 extra_rust_args: &[],
68 is_for_mir_opt_tests: false,
69 }
70 }
71
72 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
73 self.force_recompile = force_recompile;
74 self
75 }
76
77 #[expect(clippy::wrong_self_convention)]
78 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
79 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
80 self
81 }
82
83 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
84 self.extra_rust_args = extra_rust_args;
85 self
86 }
87
88 fn copy_extra_objects(
89 &self,
90 builder: &Builder<'_>,
91 compiler: &Compiler,
92 target: TargetSelection,
93 ) -> Vec<(PathBuf, DependencyType)> {
94 let mut deps = Vec::new();
95 if !self.is_for_mir_opt_tests {
96 deps.extend(copy_third_party_objects(builder, compiler, target));
97 deps.extend(copy_self_contained_objects(builder, compiler, target));
98 }
99 deps
100 }
101
102 pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool {
107 stage > 1 && !builder.config.full_bootstrap
108 }
109}
110
111impl Step for Std {
112 type Output = Option<BuildStamp>;
114
115 const DEFAULT: bool = true;
116
117 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
118 run.crate_or_deps("sysroot").path("library")
119 }
120
121 fn make_run(run: RunConfig<'_>) {
122 let crates = std_crates_for_run_make(&run);
123 let builder = run.builder;
124
125 let force_recompile = builder.rust_info().is_managed_git_subrepository()
129 && builder.download_rustc()
130 && builder.config.has_changes_from_upstream(&["library"]);
131
132 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
133 trace!("download_rustc: {}", builder.download_rustc());
134 trace!(force_recompile);
135
136 run.builder.ensure(Std {
137 build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target),
140 target: run.target,
141 crates,
142 force_recompile,
143 extra_rust_args: &[],
144 is_for_mir_opt_tests: false,
145 });
146 }
147
148 fn run(self, builder: &Builder<'_>) -> Self::Output {
154 let target = self.target;
155
156 if self.build_compiler.stage == 0
161 && !(builder.local_rebuild && target != builder.host_target)
162 {
163 let compiler = self.build_compiler;
164 builder.ensure(StdLink::from_std(self, compiler));
165
166 return None;
167 }
168
169 let build_compiler = if builder.download_rustc() && self.force_recompile {
170 builder
173 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
174 } else {
175 self.build_compiler
176 };
177
178 if builder.download_rustc()
181 && builder.config.is_host_target(target)
182 && !self.force_recompile
183 {
184 let sysroot =
185 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
186 cp_rustc_component_to_ci_sysroot(
187 builder,
188 &sysroot,
189 builder.config.ci_rust_std_contents(),
190 );
191 return None;
192 }
193
194 if builder.config.keep_stage.contains(&build_compiler.stage)
195 || builder.config.keep_stage_std.contains(&build_compiler.stage)
196 {
197 trace!(keep_stage = ?builder.config.keep_stage);
198 trace!(keep_stage_std = ?builder.config.keep_stage_std);
199
200 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
201
202 builder.ensure(StartupObjects { compiler: build_compiler, target });
203
204 self.copy_extra_objects(builder, &build_compiler, target);
205
206 builder.ensure(StdLink::from_std(self, build_compiler));
207 return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
208 }
209
210 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
211
212 let stage = build_compiler.stage;
214
215 if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
216 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
217 let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
218
219 let msg = if build_compiler_for_std_to_uplift.host == target {
220 format!(
221 "Uplifting library (stage{} -> stage{stage})",
222 build_compiler_for_std_to_uplift.stage
223 )
224 } else {
225 format!(
226 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
227 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
228 )
229 };
230
231 builder.info(&msg);
232
233 self.copy_extra_objects(builder, &build_compiler, target);
236
237 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
238 return stage_1_stamp;
239 }
240
241 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
242
243 let mut cargo = if self.is_for_mir_opt_tests {
247 trace!("building special sysroot for mir-opt tests");
248 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
249 builder,
250 build_compiler,
251 Mode::Std,
252 SourceType::InTree,
253 target,
254 Kind::Check,
255 );
256 cargo.rustflag("-Zalways-encode-mir");
257 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
258 cargo
259 } else {
260 trace!("building regular sysroot");
261 let mut cargo = builder::Cargo::new(
262 builder,
263 build_compiler,
264 Mode::Std,
265 SourceType::InTree,
266 target,
267 Kind::Build,
268 );
269 std_cargo(builder, target, &mut cargo);
270 for krate in &*self.crates {
271 cargo.arg("-p").arg(krate);
272 }
273 cargo
274 };
275
276 if target.is_synthetic() {
278 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
279 }
280 for rustflag in self.extra_rust_args.iter() {
281 cargo.rustflag(rustflag);
282 }
283
284 let _guard = builder.msg(
285 Kind::Build,
286 format_args!("library artifacts{}", crate_description(&self.crates)),
287 Mode::Std,
288 build_compiler,
289 target,
290 );
291
292 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
293 run_cargo(
294 builder,
295 cargo,
296 vec![],
297 &stamp,
298 target_deps,
299 self.is_for_mir_opt_tests, false,
301 );
302
303 builder.ensure(StdLink::from_std(
304 self,
305 builder.compiler(build_compiler.stage, builder.config.host_target),
306 ));
307 Some(stamp)
308 }
309
310 fn metadata(&self) -> Option<StepMetadata> {
311 Some(StepMetadata::build("std", self.target).built_by(self.build_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
434 let srcdir = if target == "wasm32-wasip3" {
438 assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now");
439 builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap()
440 } else {
441 srcdir
442 };
443 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
444 copy_and_stamp(
445 builder,
446 &libdir_self_contained,
447 &srcdir,
448 obj,
449 &mut target_deps,
450 DependencyType::TargetSelfContained,
451 );
452 }
453 } else if target.is_windows_gnu() {
454 for obj in ["crt2.o", "dllcrt2.o"].iter() {
455 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
456 let dst = libdir_self_contained.join(obj);
457 builder.copy_link(&src, &dst, FileType::NativeLibrary);
458 target_deps.push((dst, DependencyType::TargetSelfContained));
459 }
460 }
461
462 target_deps
463}
464
465pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
468 let mut crates = run.make_run_crates(builder::Alias::Library);
469
470 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
479 if target_is_no_std {
480 crates.retain(|c| c == "core" || c == "alloc");
481 }
482 crates
483}
484
485fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
491 if builder.config.llvm_from_ci {
493 builder.config.maybe_download_ci_llvm();
495 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
496 if ci_llvm_compiler_rt.exists() {
497 return ci_llvm_compiler_rt;
498 }
499 }
500
501 builder.require_submodule("src/llvm-project", {
503 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
504 });
505 builder.src.join("src/llvm-project/compiler-rt")
506}
507
508pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
511 if target.contains("apple") && !builder.config.dry_run() {
529 let mut cmd = command(builder.rustc(cargo.compiler()));
533 cmd.arg("--target").arg(target.rustc_target_arg());
534 cmd.arg("--print=deployment-target");
535 let output = cmd.run_capture_stdout(builder).stdout();
536
537 let (env_var, value) = output.split_once('=').unwrap();
538 cargo.env(env_var.trim(), value.trim());
541
542 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
552 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
553 }
554 }
555
556 if let Some(path) = builder.config.profiler_path(target) {
558 cargo.env("LLVM_PROFILER_RT_LIB", path);
559 } else if builder.config.profiler_enabled(target) {
560 let compiler_rt = compiler_rt_for_profiler(builder);
561 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
565 }
566
567 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
581 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
582 cargo.env("LLVM_COMPILER_RT_LIB", path);
583 " compiler-builtins-c"
584 }
585 CompilerBuiltins::BuildLLVMFuncs => {
586 builder.require_submodule(
596 "src/llvm-project",
597 Some(
598 "The `build.optimized-compiler-builtins` config option \
599 requires `compiler-rt` sources from LLVM.",
600 ),
601 );
602 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
603 if !builder.config.dry_run() {
604 assert!(compiler_builtins_root.exists());
607 }
608
609 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
612 " compiler-builtins-c"
613 }
614 CompilerBuiltins::BuildRustOnly => "",
615 };
616
617 if !builder.unstable_features() {
620 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
621 }
622
623 let mut features = String::new();
624
625 if builder.no_std(target) == Some(true) {
626 features += " compiler-builtins-mem";
627 if !target.starts_with("bpf") {
628 features.push_str(compiler_builtins_c_feature);
629 }
630
631 cargo
633 .args(["-p", "alloc"])
634 .arg("--manifest-path")
635 .arg(builder.src.join("library/alloc/Cargo.toml"))
636 .arg("--features")
637 .arg(features);
638 } else {
639 features += &builder.std_features(target);
640 features.push_str(compiler_builtins_c_feature);
641
642 cargo
643 .arg("--features")
644 .arg(features)
645 .arg("--manifest-path")
646 .arg(builder.src.join("library/sysroot/Cargo.toml"));
647
648 if target.contains("musl")
651 && let Some(p) = builder.musl_libdir(target)
652 {
653 let root = format!("native={}", p.to_str().unwrap());
654 cargo.rustflag("-L").rustflag(&root);
655 }
656
657 if target.contains("-wasi")
658 && let Some(dir) = builder.wasi_libdir(target)
659 {
660 let root = format!("native={}", dir.to_str().unwrap());
661 cargo.rustflag("-L").rustflag(&root);
662 }
663 }
664
665 cargo.rustflag("-Cembed-bitcode=yes");
671
672 if builder.config.rust_lto == RustcLto::Off {
673 cargo.rustflag("-Clto=off");
674 }
675
676 if target.contains("riscv") {
683 cargo.rustflag("-Cforce-unwind-tables=yes");
684 }
685
686 cargo.rustflag("-Zunstable-options");
689 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
690
691 let html_root =
692 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
693 cargo.rustflag(&html_root);
694 cargo.rustdocflag(&html_root);
695
696 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
697}
698
699#[derive(Debug, Clone, PartialEq, Eq, Hash)]
708pub struct StdLink {
709 pub compiler: Compiler,
710 pub target_compiler: Compiler,
711 pub target: TargetSelection,
712 crates: Vec<String>,
714 force_recompile: bool,
716}
717
718impl StdLink {
719 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
720 Self {
721 compiler: host_compiler,
722 target_compiler: std.build_compiler,
723 target: std.target,
724 crates: std.crates,
725 force_recompile: std.force_recompile,
726 }
727 }
728}
729
730impl Step for StdLink {
731 type Output = ();
732
733 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
734 run.never()
735 }
736
737 fn run(self, builder: &Builder<'_>) {
746 let compiler = self.compiler;
747 let target_compiler = self.target_compiler;
748 let target = self.target;
749
750 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
752 let lib = builder.sysroot_libdir_relative(self.compiler);
754 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
755 compiler: self.compiler,
756 force_recompile: self.force_recompile,
757 });
758 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
759 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
760 (libdir, hostdir)
761 } else {
762 let libdir = builder.sysroot_target_libdir(target_compiler, target);
763 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
764 (libdir, hostdir)
765 };
766
767 let is_downloaded_beta_stage0 = builder
768 .build
769 .config
770 .initial_rustc
771 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
772
773 if compiler.stage == 0 && is_downloaded_beta_stage0 {
777 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
779
780 let host = compiler.host;
781 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
782 let sysroot_bin_dir = sysroot.join("bin");
783 t!(fs::create_dir_all(&sysroot_bin_dir));
784 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
785
786 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
787 t!(fs::create_dir_all(sysroot.join("lib")));
788 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
789
790 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
792 t!(fs::create_dir_all(&sysroot_codegen_backends));
793 let stage0_codegen_backends = builder
794 .out
795 .join(host)
796 .join("stage0/lib/rustlib")
797 .join(host)
798 .join("codegen-backends");
799 if stage0_codegen_backends.exists() {
800 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
801 }
802 } else if compiler.stage == 0 {
803 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
804
805 if builder.local_rebuild {
806 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
810 }
811
812 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
813 } else {
814 if builder.download_rustc() {
815 let _ = fs::remove_dir_all(&libdir);
817 let _ = fs::remove_dir_all(&hostdir);
818 }
819
820 add_to_sysroot(
821 builder,
822 &libdir,
823 &hostdir,
824 &build_stamp::libstd_stamp(builder, compiler, target),
825 );
826 }
827 }
828}
829
830fn copy_sanitizers(
832 builder: &Builder<'_>,
833 compiler: &Compiler,
834 target: TargetSelection,
835) -> Vec<PathBuf> {
836 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
837
838 if builder.config.dry_run() {
839 return Vec::new();
840 }
841
842 let mut target_deps = Vec::new();
843 let libdir = builder.sysroot_target_libdir(*compiler, target);
844
845 for runtime in &runtimes {
846 let dst = libdir.join(&runtime.name);
847 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
848
849 if target == "x86_64-apple-darwin"
853 || target == "aarch64-apple-darwin"
854 || target == "aarch64-apple-ios"
855 || target == "aarch64-apple-ios-sim"
856 || target == "x86_64-apple-ios"
857 {
858 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
860 apple_darwin_sign_file(builder, &dst);
863 }
864
865 target_deps.push(dst);
866 }
867
868 target_deps
869}
870
871fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
872 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
873}
874
875fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
876 command("codesign")
877 .arg("-f") .arg("-s")
879 .arg("-")
880 .arg(file_path)
881 .run(builder);
882}
883
884#[derive(Debug, Clone, PartialEq, Eq, Hash)]
885pub struct StartupObjects {
886 pub compiler: Compiler,
887 pub target: TargetSelection,
888}
889
890impl Step for StartupObjects {
891 type Output = Vec<(PathBuf, DependencyType)>;
892
893 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
894 run.path("library/rtstartup")
895 }
896
897 fn make_run(run: RunConfig<'_>) {
898 run.builder.ensure(StartupObjects {
899 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
900 target: run.target,
901 });
902 }
903
904 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
911 let for_compiler = self.compiler;
912 let target = self.target;
913 if !target.is_windows_gnu() {
916 return vec![];
917 }
918
919 let mut target_deps = vec![];
920
921 let src_dir = &builder.src.join("library").join("rtstartup");
922 let dst_dir = &builder.native_dir(target).join("rtstartup");
923 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
924 t!(fs::create_dir_all(dst_dir));
925
926 for file in &["rsbegin", "rsend"] {
927 let src_file = &src_dir.join(file.to_string() + ".rs");
928 let dst_file = &dst_dir.join(file.to_string() + ".o");
929 if !up_to_date(src_file, dst_file) {
930 let mut cmd = command(&builder.initial_rustc);
931 cmd.env("RUSTC_BOOTSTRAP", "1");
932 if !builder.local_rebuild {
933 cmd.arg("--cfg").arg("bootstrap");
935 }
936 cmd.arg("--target")
937 .arg(target.rustc_target_arg())
938 .arg("--emit=obj")
939 .arg("-o")
940 .arg(dst_file)
941 .arg(src_file)
942 .run(builder);
943 }
944
945 let obj = sysroot_dir.join((*file).to_string() + ".o");
946 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
947 target_deps.push((obj, DependencyType::Target));
948 }
949
950 target_deps
951 }
952}
953
954fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
955 let ci_rustc_dir = builder.config.ci_rustc_dir();
956
957 for file in contents {
958 let src = ci_rustc_dir.join(&file);
959 let dst = sysroot.join(file);
960 if src.is_dir() {
961 t!(fs::create_dir_all(dst));
962 } else {
963 builder.copy_link(&src, &dst, FileType::Regular);
964 }
965 }
966}
967
968#[derive(Clone, Debug)]
970pub struct BuiltRustc {
971 pub build_compiler: Compiler,
975}
976
977#[derive(Debug, Clone, PartialEq, Eq, Hash)]
984pub struct Rustc {
985 pub target: TargetSelection,
987 pub build_compiler: Compiler,
989 crates: Vec<String>,
995}
996
997impl Rustc {
998 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
999 Self { target, build_compiler, crates: Default::default() }
1000 }
1001}
1002
1003impl Step for Rustc {
1004 type Output = BuiltRustc;
1005
1006 const IS_HOST: bool = true;
1007 const DEFAULT: bool = false;
1008
1009 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1010 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1011 for (i, krate) in crates.iter().enumerate() {
1012 if krate.name == "rustc-main" {
1015 crates.swap_remove(i);
1016 break;
1017 }
1018 }
1019 run.crates(crates)
1020 }
1021
1022 fn make_run(run: RunConfig<'_>) {
1023 if run.builder.paths == vec![PathBuf::from("compiler")] {
1026 return;
1027 }
1028
1029 let crates = run.cargo_crates_in_set();
1030 run.builder.ensure(Rustc {
1031 build_compiler: run
1032 .builder
1033 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1034 target: run.target,
1035 crates,
1036 });
1037 }
1038
1039 fn run(self, builder: &Builder<'_>) -> Self::Output {
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 BuiltRustc { build_compiler };
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));
1073
1074 return BuiltRustc { build_compiler };
1075 }
1076
1077 let stage = build_compiler.stage + 1;
1079
1080 if build_compiler.stage >= 2
1085 && !builder.config.full_bootstrap
1086 && target == builder.host_target
1087 {
1088 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1092
1093 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1094 builder.info(&msg);
1095
1096 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1100 uplift_build_compiler,
1102 build_compiler,
1104 target,
1105 self.crates,
1106 ));
1107
1108 return BuiltRustc { build_compiler: uplift_build_compiler };
1111 }
1112
1113 builder.std(
1119 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1120 builder.config.host_target,
1121 );
1122
1123 let mut cargo = builder::Cargo::new(
1124 builder,
1125 build_compiler,
1126 Mode::Rustc,
1127 SourceType::InTree,
1128 target,
1129 Kind::Build,
1130 );
1131
1132 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1133
1134 for krate in &*self.crates {
1138 cargo.arg("-p").arg(krate);
1139 }
1140
1141 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1142 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1144 }
1145
1146 let _guard = builder.msg(
1147 Kind::Build,
1148 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1149 Mode::Rustc,
1150 build_compiler,
1151 target,
1152 );
1153 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1154 run_cargo(
1155 builder,
1156 cargo,
1157 vec![],
1158 &stamp,
1159 vec![],
1160 false,
1161 true, );
1163
1164 let target_root_dir = stamp.path().parent().unwrap();
1165 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1171 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1172 {
1173 let rustc_driver = target_root_dir.join("librustc_driver.so");
1174 strip_debug(builder, target, &rustc_driver);
1175 }
1176
1177 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1178 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1181 }
1182
1183 builder.ensure(RustcLink::from_rustc(self));
1184 BuiltRustc { build_compiler }
1185 }
1186
1187 fn metadata(&self) -> Option<StepMetadata> {
1188 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1189 }
1190}
1191
1192pub fn rustc_cargo(
1193 builder: &Builder<'_>,
1194 cargo: &mut Cargo,
1195 target: TargetSelection,
1196 build_compiler: &Compiler,
1197 crates: &[String],
1198) {
1199 cargo
1200 .arg("--features")
1201 .arg(builder.rustc_features(builder.kind, target, crates))
1202 .arg("--manifest-path")
1203 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1204
1205 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1206
1207 cargo.rustflag("-Zon-broken-pipe=kill");
1221
1222 if builder.config.llvm_enzyme {
1225 let arch = builder.build.host_target;
1226 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1227 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1228
1229 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1230 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1231 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1232 }
1233 }
1234
1235 if builder.build.config.bootstrap_override_lld.is_used() {
1240 cargo.rustflag("-Zdefault-visibility=protected");
1241 }
1242
1243 if is_lto_stage(build_compiler) {
1244 match builder.config.rust_lto {
1245 RustcLto::Thin | RustcLto::Fat => {
1246 cargo.rustflag("-Zdylib-lto");
1249 let lto_type = match builder.config.rust_lto {
1253 RustcLto::Thin => "thin",
1254 RustcLto::Fat => "fat",
1255 _ => unreachable!(),
1256 };
1257 cargo.rustflag(&format!("-Clto={lto_type}"));
1258 cargo.rustflag("-Cembed-bitcode=yes");
1259 }
1260 RustcLto::ThinLocal => { }
1261 RustcLto::Off => {
1262 cargo.rustflag("-Clto=off");
1263 }
1264 }
1265 } else if builder.config.rust_lto == RustcLto::Off {
1266 cargo.rustflag("-Clto=off");
1267 }
1268
1269 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1277 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1278 }
1279
1280 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1281 panic!("Cannot use and generate PGO profiles at the same time");
1282 }
1283 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1284 if build_compiler.stage == 1 {
1285 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1286 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1289 true
1290 } else {
1291 false
1292 }
1293 } else if let Some(path) = &builder.config.rust_profile_use {
1294 if build_compiler.stage == 1 {
1295 cargo.rustflag(&format!("-Cprofile-use={path}"));
1296 if builder.is_verbose() {
1297 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1298 }
1299 true
1300 } else {
1301 false
1302 }
1303 } else {
1304 false
1305 };
1306 if is_collecting {
1307 cargo.rustflag(&format!(
1309 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1310 builder.config.src.components().count()
1311 ));
1312 }
1313
1314 if let Some(ref ccache) = builder.config.ccache
1319 && build_compiler.stage == 0
1320 && !builder.config.incremental
1321 {
1322 cargo.env("RUSTC_WRAPPER", ccache);
1323 }
1324
1325 rustc_cargo_env(builder, cargo, target);
1326}
1327
1328pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1329 cargo
1332 .env("CFG_RELEASE", builder.rust_release())
1333 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1334 .env("CFG_VERSION", builder.rust_version());
1335
1336 if builder.config.omit_git_hash {
1340 cargo.env("CFG_OMIT_GIT_HASH", "1");
1341 }
1342
1343 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1344
1345 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1346 let target_config = builder.config.target_config.get(&target);
1347
1348 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1349
1350 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1351 cargo.env("CFG_VER_DATE", ver_date);
1352 }
1353 if let Some(ref ver_hash) = builder.rust_info().sha() {
1354 cargo.env("CFG_VER_HASH", ver_hash);
1355 }
1356 if !builder.unstable_features() {
1357 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1358 }
1359
1360 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1363 cargo.env("CFG_DEFAULT_LINKER", s);
1364 } else if let Some(ref s) = builder.config.rustc_default_linker {
1365 cargo.env("CFG_DEFAULT_LINKER", s);
1366 }
1367
1368 if builder.config.lld_enabled {
1370 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1371 }
1372
1373 if builder.config.rust_verify_llvm_ir {
1374 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1375 }
1376
1377 if builder.config.llvm_enabled(target) {
1389 let building_llvm_is_expensive =
1390 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1391 .should_build();
1392
1393 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1394 if !skip_llvm {
1395 rustc_llvm_env(builder, cargo, target)
1396 }
1397 }
1398
1399 if builder.config.jemalloc(target) && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
1401 if target.starts_with("aarch64") {
1404 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1405 }
1406 else if target.starts_with("loongarch") {
1408 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1409 }
1410 }
1411}
1412
1413fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1419 if builder.config.is_rust_llvm(target) {
1420 cargo.env("LLVM_RUSTLLVM", "1");
1421 }
1422 if builder.config.llvm_enzyme {
1423 cargo.env("LLVM_ENZYME", "1");
1424 }
1425 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1426 cargo.env("LLVM_CONFIG", &host_llvm_config);
1427
1428 let mut llvm_linker_flags = String::new();
1438 if builder.config.llvm_profile_generate
1439 && target.is_msvc()
1440 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1441 {
1442 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1444 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1445 }
1446
1447 if let Some(ref s) = builder.config.llvm_ldflags {
1449 if !llvm_linker_flags.is_empty() {
1450 llvm_linker_flags.push(' ');
1451 }
1452 llvm_linker_flags.push_str(s);
1453 }
1454
1455 if !llvm_linker_flags.is_empty() {
1457 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1458 }
1459
1460 if builder.config.llvm_static_stdcpp
1463 && !target.contains("freebsd")
1464 && !target.is_msvc()
1465 && !target.contains("apple")
1466 && !target.contains("solaris")
1467 {
1468 let libstdcxx_name =
1469 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1470 let file = compiler_file(
1471 builder,
1472 &builder.cxx(target).unwrap(),
1473 target,
1474 CLang::Cxx,
1475 libstdcxx_name,
1476 );
1477 cargo.env("LLVM_STATIC_STDCPP", file);
1478 }
1479 if builder.llvm_link_shared() {
1480 cargo.env("LLVM_LINK_SHARED", "1");
1481 }
1482 if builder.config.llvm_use_libcxx {
1483 cargo.env("LLVM_USE_LIBCXX", "1");
1484 }
1485 if builder.config.llvm_assertions {
1486 cargo.env("LLVM_ASSERTIONS", "1");
1487 }
1488}
1489
1490#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1503struct RustcLink {
1504 build_compiler: Compiler,
1506 sysroot_compiler: Compiler,
1509 target: TargetSelection,
1510 crates: Vec<String>,
1512}
1513
1514impl RustcLink {
1515 fn from_rustc(rustc: Rustc) -> Self {
1518 Self {
1519 build_compiler: rustc.build_compiler,
1520 sysroot_compiler: rustc.build_compiler,
1521 target: rustc.target,
1522 crates: rustc.crates,
1523 }
1524 }
1525
1526 fn from_build_compiler_and_sysroot(
1528 build_compiler: Compiler,
1529 sysroot_compiler: Compiler,
1530 target: TargetSelection,
1531 crates: Vec<String>,
1532 ) -> Self {
1533 Self { build_compiler, sysroot_compiler, target, crates }
1534 }
1535}
1536
1537impl Step for RustcLink {
1538 type Output = ();
1539
1540 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1541 run.never()
1542 }
1543
1544 fn run(self, builder: &Builder<'_>) {
1546 let build_compiler = self.build_compiler;
1547 let sysroot_compiler = self.sysroot_compiler;
1548 let target = self.target;
1549 add_to_sysroot(
1550 builder,
1551 &builder.sysroot_target_libdir(sysroot_compiler, target),
1552 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1553 &build_stamp::librustc_stamp(builder, build_compiler, target),
1554 );
1555 }
1556}
1557
1558#[derive(Clone)]
1561pub struct GccCodegenBackendOutput {
1562 stamp: BuildStamp,
1563 gcc: GccOutput,
1564}
1565
1566#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1567pub struct GccCodegenBackend {
1568 compilers: RustcPrivateCompilers,
1569}
1570
1571impl Step for GccCodegenBackend {
1572 type Output = GccCodegenBackendOutput;
1573
1574 const IS_HOST: bool = true;
1575
1576 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1577 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1578 }
1579
1580 fn make_run(run: RunConfig<'_>) {
1581 run.builder.ensure(GccCodegenBackend {
1582 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1583 });
1584 }
1585
1586 fn run(self, builder: &Builder<'_>) -> Self::Output {
1587 let target = self.compilers.target();
1588 let build_compiler = self.compilers.build_compiler();
1589
1590 let stamp = build_stamp::codegen_backend_stamp(
1591 builder,
1592 build_compiler,
1593 target,
1594 &CodegenBackendKind::Gcc,
1595 );
1596
1597 let gcc = builder.ensure(Gcc { target });
1598
1599 if builder.config.keep_stage.contains(&build_compiler.stage) {
1600 trace!("`keep-stage` requested");
1601 builder.info(
1602 "WARNING: Using a potentially old codegen backend. \
1603 This may not behave well.",
1604 );
1605 return GccCodegenBackendOutput { stamp, gcc };
1608 }
1609
1610 let mut cargo = builder::Cargo::new(
1611 builder,
1612 build_compiler,
1613 Mode::Codegen,
1614 SourceType::InTree,
1615 target,
1616 Kind::Build,
1617 );
1618 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1619 rustc_cargo_env(builder, &mut cargo, target);
1620
1621 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1622
1623 let _guard =
1624 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1625 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1626
1627 GccCodegenBackendOutput {
1628 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1629 gcc,
1630 }
1631 }
1632
1633 fn metadata(&self) -> Option<StepMetadata> {
1634 Some(
1635 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1636 .built_by(self.compilers.build_compiler()),
1637 )
1638 }
1639}
1640
1641#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1642pub struct CraneliftCodegenBackend {
1643 pub compilers: RustcPrivateCompilers,
1644}
1645
1646impl Step for CraneliftCodegenBackend {
1647 type Output = BuildStamp;
1648 const IS_HOST: bool = true;
1649
1650 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1651 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1652 }
1653
1654 fn make_run(run: RunConfig<'_>) {
1655 run.builder.ensure(CraneliftCodegenBackend {
1656 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1657 });
1658 }
1659
1660 fn run(self, builder: &Builder<'_>) -> Self::Output {
1661 let target = self.compilers.target();
1662 let build_compiler = self.compilers.build_compiler();
1663
1664 let stamp = build_stamp::codegen_backend_stamp(
1665 builder,
1666 build_compiler,
1667 target,
1668 &CodegenBackendKind::Cranelift,
1669 );
1670
1671 if builder.config.keep_stage.contains(&build_compiler.stage) {
1672 trace!("`keep-stage` requested");
1673 builder.info(
1674 "WARNING: Using a potentially old codegen backend. \
1675 This may not behave well.",
1676 );
1677 return stamp;
1680 }
1681
1682 let mut cargo = builder::Cargo::new(
1683 builder,
1684 build_compiler,
1685 Mode::Codegen,
1686 SourceType::InTree,
1687 target,
1688 Kind::Build,
1689 );
1690 cargo
1691 .arg("--manifest-path")
1692 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1693 rustc_cargo_env(builder, &mut cargo, target);
1694
1695 let _guard = builder.msg(
1696 Kind::Build,
1697 "codegen backend cranelift",
1698 Mode::Codegen,
1699 build_compiler,
1700 target,
1701 );
1702 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1703 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1704 }
1705
1706 fn metadata(&self) -> Option<StepMetadata> {
1707 Some(
1708 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1709 .built_by(self.compilers.build_compiler()),
1710 )
1711 }
1712}
1713
1714fn write_codegen_backend_stamp(
1716 mut stamp: BuildStamp,
1717 files: Vec<PathBuf>,
1718 dry_run: bool,
1719) -> BuildStamp {
1720 if dry_run {
1721 return stamp;
1722 }
1723
1724 let mut files = files.into_iter().filter(|f| {
1725 let filename = f.file_name().unwrap().to_str().unwrap();
1726 is_dylib(f) && filename.contains("rustc_codegen_")
1727 });
1728 let codegen_backend = match files.next() {
1729 Some(f) => f,
1730 None => panic!("no dylibs built for codegen backend?"),
1731 };
1732 if let Some(f) = files.next() {
1733 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1734 }
1735
1736 let codegen_backend = codegen_backend.to_str().unwrap();
1737 stamp = stamp.add_stamp(codegen_backend);
1738 t!(stamp.write());
1739 stamp
1740}
1741
1742fn copy_codegen_backends_to_sysroot(
1749 builder: &Builder<'_>,
1750 stamp: BuildStamp,
1751 target_compiler: Compiler,
1752) {
1753 let dst = builder.sysroot_codegen_backends(target_compiler);
1762 t!(fs::create_dir_all(&dst), dst);
1763
1764 if builder.config.dry_run() {
1765 return;
1766 }
1767
1768 if stamp.path().exists() {
1769 let file = get_codegen_backend_file(&stamp);
1770 builder.copy_link(
1771 &file,
1772 &dst.join(normalize_codegen_backend_name(builder, &file)),
1773 FileType::NativeLibrary,
1774 );
1775 }
1776}
1777
1778pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1780 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1781}
1782
1783pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1785 let filename = path.file_name().unwrap().to_str().unwrap();
1786 let dash = filename.find('-').unwrap();
1789 let dot = filename.find('.').unwrap();
1790 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1791}
1792
1793pub fn compiler_file(
1794 builder: &Builder<'_>,
1795 compiler: &Path,
1796 target: TargetSelection,
1797 c: CLang,
1798 file: &str,
1799) -> PathBuf {
1800 if builder.config.dry_run() {
1801 return PathBuf::new();
1802 }
1803 let mut cmd = command(compiler);
1804 cmd.args(builder.cc_handled_clags(target, c));
1805 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1806 cmd.arg(format!("-print-file-name={file}"));
1807 let out = cmd.run_capture_stdout(builder).stdout();
1808 PathBuf::from(out.trim())
1809}
1810
1811#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1812pub struct Sysroot {
1813 pub compiler: Compiler,
1814 force_recompile: bool,
1816}
1817
1818impl Sysroot {
1819 pub(crate) fn new(compiler: Compiler) -> Self {
1820 Sysroot { compiler, force_recompile: false }
1821 }
1822}
1823
1824impl Step for Sysroot {
1825 type Output = PathBuf;
1826
1827 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1828 run.never()
1829 }
1830
1831 fn run(self, builder: &Builder<'_>) -> PathBuf {
1835 let compiler = self.compiler;
1836 let host_dir = builder.out.join(compiler.host);
1837
1838 let sysroot_dir = |stage| {
1839 if stage == 0 {
1840 host_dir.join("stage0-sysroot")
1841 } else if self.force_recompile && stage == compiler.stage {
1842 host_dir.join(format!("stage{stage}-test-sysroot"))
1843 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1844 host_dir.join("ci-rustc-sysroot")
1845 } else {
1846 host_dir.join(format!("stage{stage}"))
1847 }
1848 };
1849 let sysroot = sysroot_dir(compiler.stage);
1850 trace!(stage = ?compiler.stage, ?sysroot);
1851
1852 builder.do_if_verbose(|| {
1853 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1854 });
1855 let _ = fs::remove_dir_all(&sysroot);
1856 t!(fs::create_dir_all(&sysroot));
1857
1858 if compiler.stage == 0 {
1865 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1866 }
1867
1868 if builder.download_rustc() && compiler.stage != 0 {
1870 assert_eq!(
1871 builder.config.host_target, compiler.host,
1872 "Cross-compiling is not yet supported with `download-rustc`",
1873 );
1874
1875 for stage in 0..=2 {
1877 if stage != compiler.stage {
1878 let dir = sysroot_dir(stage);
1879 if !dir.ends_with("ci-rustc-sysroot") {
1880 let _ = fs::remove_dir_all(dir);
1881 }
1882 }
1883 }
1884
1885 let mut filtered_files = Vec::new();
1895 let mut add_filtered_files = |suffix, contents| {
1896 for path in contents {
1897 let path = Path::new(&path);
1898 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1899 filtered_files.push(path.file_name().unwrap().to_owned());
1900 }
1901 }
1902 };
1903 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1904 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1905 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1908
1909 let filtered_extensions = [
1910 OsStr::new("rmeta"),
1911 OsStr::new("rlib"),
1912 OsStr::new(std::env::consts::DLL_EXTENSION),
1914 ];
1915 let ci_rustc_dir = builder.config.ci_rustc_dir();
1916 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1917 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1918 return true;
1919 }
1920 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1921 return true;
1922 }
1923 filtered_files.iter().all(|f| f != path.file_name().unwrap())
1924 });
1925 }
1926
1927 if compiler.stage != 0 {
1933 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1934 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1935 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1936 if let Err(e) =
1937 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1938 {
1939 eprintln!(
1940 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1941 sysroot_lib_rustlib_src_rust.display(),
1942 builder.src.display(),
1943 e,
1944 );
1945 if builder.config.rust_remap_debuginfo {
1946 eprintln!(
1947 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1948 sysroot_lib_rustlib_src_rust.display(),
1949 );
1950 }
1951 build_helper::exit!(1);
1952 }
1953 }
1954
1955 if !builder.download_rustc() {
1957 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1958 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1959 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1960 if let Err(e) =
1961 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1962 {
1963 eprintln!(
1964 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1965 sysroot_lib_rustlib_rustcsrc_rust.display(),
1966 builder.src.display(),
1967 e,
1968 );
1969 build_helper::exit!(1);
1970 }
1971 }
1972
1973 sysroot
1974 }
1975}
1976
1977#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1984pub struct Assemble {
1985 pub target_compiler: Compiler,
1990}
1991
1992impl Step for Assemble {
1993 type Output = Compiler;
1994 const IS_HOST: bool = true;
1995
1996 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1997 run.path("compiler/rustc").path("compiler")
1998 }
1999
2000 fn make_run(run: RunConfig<'_>) {
2001 run.builder.ensure(Assemble {
2002 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2003 });
2004 }
2005
2006 fn run(self, builder: &Builder<'_>) -> Compiler {
2007 let target_compiler = self.target_compiler;
2008
2009 if target_compiler.stage == 0 {
2010 trace!("stage 0 build compiler is always available, simply returning");
2011 assert_eq!(
2012 builder.config.host_target, target_compiler.host,
2013 "Cannot obtain compiler for non-native build triple at stage 0"
2014 );
2015 return target_compiler;
2017 }
2018
2019 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2022 let libdir_bin = libdir.parent().unwrap().join("bin");
2023 t!(fs::create_dir_all(&libdir_bin));
2024
2025 if builder.config.llvm_enabled(target_compiler.host) {
2026 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2027
2028 let target = target_compiler.host;
2029 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2030 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2031 trace!("LLVM tools enabled");
2032
2033 let host_llvm_bin_dir = command(&host_llvm_config)
2034 .arg("--bindir")
2035 .cached()
2036 .run_capture_stdout(builder)
2037 .stdout()
2038 .trim()
2039 .to_string();
2040
2041 let llvm_bin_dir = if target == builder.host_target {
2042 PathBuf::from(host_llvm_bin_dir)
2043 } else {
2044 let external_llvm_config = builder
2047 .config
2048 .target_config
2049 .get(&target)
2050 .and_then(|t| t.llvm_config.clone());
2051 if let Some(external_llvm_config) = external_llvm_config {
2052 external_llvm_config.parent().unwrap().to_path_buf()
2055 } else {
2056 let host_llvm_out = builder.llvm_out(builder.host_target);
2060 let target_llvm_out = builder.llvm_out(target);
2061 if let Ok(relative_path) =
2062 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2063 {
2064 target_llvm_out.join(relative_path)
2065 } else {
2066 PathBuf::from(
2069 host_llvm_bin_dir
2070 .replace(&*builder.host_target.triple, &target.triple),
2071 )
2072 }
2073 }
2074 };
2075
2076 #[cfg(feature = "tracing")]
2083 let _llvm_tools_span =
2084 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2085 .entered();
2086 for tool in LLVM_TOOLS {
2087 trace!("installing `{tool}`");
2088 let tool_exe = exe(tool, target_compiler.host);
2089 let src_path = llvm_bin_dir.join(&tool_exe);
2090
2091 if !src_path.exists() && builder.config.llvm_from_ci {
2093 eprintln!("{} does not exist; skipping copy", src_path.display());
2094 continue;
2095 }
2096
2097 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2104 }
2105 }
2106 }
2107
2108 let maybe_install_llvm_bitcode_linker = || {
2109 if builder.config.llvm_bitcode_linker_enabled {
2110 trace!("llvm-bitcode-linker enabled, installing");
2111 let llvm_bitcode_linker = builder.ensure(
2112 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2113 builder,
2114 target_compiler,
2115 ),
2116 );
2117
2118 let bindir_self_contained = builder
2120 .sysroot(target_compiler)
2121 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2122 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2123
2124 t!(fs::create_dir_all(&bindir_self_contained));
2125 builder.copy_link(
2126 &llvm_bitcode_linker.tool_path,
2127 &bindir_self_contained.join(tool_exe),
2128 FileType::Executable,
2129 );
2130 }
2131 };
2132
2133 if builder.download_rustc() {
2135 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2136
2137 builder.std(target_compiler, target_compiler.host);
2138 let sysroot =
2139 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2140 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2143 if target_compiler.stage == builder.top_stage {
2145 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2146 }
2147
2148 maybe_install_llvm_bitcode_linker();
2151
2152 return target_compiler;
2153 }
2154
2155 debug!(
2169 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2170 target_compiler.stage - 1,
2171 builder.config.host_target,
2172 );
2173 let build_compiler =
2174 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2175
2176 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2178 debug!("`llvm_enzyme` requested");
2179 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2180 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2181 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2182 let lib_ext = std::env::consts::DLL_EXTENSION;
2183 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2184 let src_lib =
2185 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2186 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2187 let target_libdir =
2188 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2189 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2190 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2191 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2192 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2193 }
2194 }
2195
2196 debug!(
2199 ?build_compiler,
2200 "target_compiler.host" = ?target_compiler.host,
2201 "building compiler libraries to link to"
2202 );
2203
2204 let BuiltRustc { build_compiler } =
2206 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2207
2208 let stage = target_compiler.stage;
2209 let host = target_compiler.host;
2210 let (host_info, dir_name) = if build_compiler.host == host {
2211 ("".into(), "host".into())
2212 } else {
2213 (format!(" ({host})"), host.to_string())
2214 };
2215 let msg = format!(
2220 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2221 );
2222 builder.info(&msg);
2223
2224 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2226 let proc_macros = builder
2227 .read_stamp_file(&stamp)
2228 .into_iter()
2229 .filter_map(|(path, dependency_type)| {
2230 if dependency_type == DependencyType::Host {
2231 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2232 } else {
2233 None
2234 }
2235 })
2236 .collect::<HashSet<_>>();
2237
2238 let sysroot = builder.sysroot(target_compiler);
2239 let rustc_libdir = builder.rustc_libdir(target_compiler);
2240 t!(fs::create_dir_all(&rustc_libdir));
2241 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2242 for f in builder.read_dir(&src_libdir) {
2243 let filename = f.file_name().into_string().unwrap();
2244
2245 let is_proc_macro = proc_macros.contains(&filename);
2246 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2247
2248 let can_be_rustc_dynamic_dep = if builder
2252 .link_std_into_rustc_driver(target_compiler.host)
2253 && !target_compiler.host.is_windows()
2254 {
2255 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2256 !is_std
2257 } else {
2258 true
2259 };
2260
2261 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2262 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2263 }
2264 }
2265
2266 {
2267 #[cfg(feature = "tracing")]
2268 let _codegen_backend_span =
2269 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2270
2271 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2272 if builder.kind == Kind::Check && builder.top_stage == 1 {
2289 continue;
2290 }
2291
2292 let prepare_compilers = || {
2293 RustcPrivateCompilers::from_build_and_target_compiler(
2294 build_compiler,
2295 target_compiler,
2296 )
2297 };
2298
2299 match backend {
2300 CodegenBackendKind::Cranelift => {
2301 let stamp = builder
2302 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2303 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2304 }
2305 CodegenBackendKind::Gcc => {
2306 let output =
2307 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2308 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2309 output.gcc.install_to(builder, &rustc_libdir);
2312 }
2313 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2314 }
2315 }
2316 }
2317
2318 if builder.config.lld_enabled {
2319 let lld_wrapper =
2320 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2321 builder,
2322 target_compiler,
2323 ));
2324 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2325 }
2326
2327 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2328 debug!(
2329 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2330 workaround faulty homebrew `strip`s"
2331 );
2332
2333 let src_exe = exe("llvm-objcopy", target_compiler.host);
2340 let dst_exe = exe("rust-objcopy", target_compiler.host);
2341 builder.copy_link(
2342 &libdir_bin.join(src_exe),
2343 &libdir_bin.join(dst_exe),
2344 FileType::Executable,
2345 );
2346 }
2347
2348 if builder.tool_enabled("wasm-component-ld") {
2351 let wasm_component = builder.ensure(
2352 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2353 builder,
2354 target_compiler,
2355 ),
2356 );
2357 builder.copy_link(
2358 &wasm_component.tool_path,
2359 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2360 FileType::Executable,
2361 );
2362 }
2363
2364 maybe_install_llvm_bitcode_linker();
2365
2366 debug!(
2369 "target_compiler.host" = ?target_compiler.host,
2370 ?sysroot,
2371 "ensuring availability of `libLLVM.so` in compiler directory"
2372 );
2373 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2374 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2375
2376 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2378 let rustc = out_dir.join(exe("rustc-main", host));
2379 let bindir = sysroot.join("bin");
2380 t!(fs::create_dir_all(bindir));
2381 let compiler = builder.rustc(target_compiler);
2382 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2383 builder.copy_link(&rustc, &compiler, FileType::Executable);
2384
2385 target_compiler
2386 }
2387}
2388
2389#[track_caller]
2394pub fn add_to_sysroot(
2395 builder: &Builder<'_>,
2396 sysroot_dst: &Path,
2397 sysroot_host_dst: &Path,
2398 stamp: &BuildStamp,
2399) {
2400 let self_contained_dst = &sysroot_dst.join("self-contained");
2401 t!(fs::create_dir_all(sysroot_dst));
2402 t!(fs::create_dir_all(sysroot_host_dst));
2403 t!(fs::create_dir_all(self_contained_dst));
2404 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2405 let dst = match dependency_type {
2406 DependencyType::Host => sysroot_host_dst,
2407 DependencyType::Target => sysroot_dst,
2408 DependencyType::TargetSelfContained => self_contained_dst,
2409 };
2410 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2411 }
2412}
2413
2414pub fn run_cargo(
2415 builder: &Builder<'_>,
2416 cargo: Cargo,
2417 tail_args: Vec<String>,
2418 stamp: &BuildStamp,
2419 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2420 is_check: bool,
2421 rlib_only_metadata: bool,
2422) -> Vec<PathBuf> {
2423 let target_root_dir = stamp.path().parent().unwrap();
2425 let target_deps_dir = target_root_dir.join("deps");
2427 let host_root_dir = target_root_dir
2429 .parent()
2430 .unwrap() .parent()
2432 .unwrap() .join(target_root_dir.file_name().unwrap());
2434
2435 let mut deps = Vec::new();
2439 let mut toplevel = Vec::new();
2440 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2441 let (filenames_vec, crate_types) = match msg {
2442 CargoMessage::CompilerArtifact {
2443 filenames,
2444 target: CargoTarget { crate_types },
2445 ..
2446 } => {
2447 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2448 f.sort(); (f, crate_types)
2450 }
2451 _ => return,
2452 };
2453 for filename in filenames_vec {
2454 let mut keep = false;
2456 if filename.ends_with(".lib")
2457 || filename.ends_with(".a")
2458 || is_debug_info(&filename)
2459 || is_dylib(Path::new(&*filename))
2460 {
2461 keep = true;
2463 }
2464 if is_check && filename.ends_with(".rmeta") {
2465 keep = true;
2467 } else if rlib_only_metadata {
2468 if filename.contains("jemalloc_sys")
2469 || filename.contains("rustc_public_bridge")
2470 || filename.contains("rustc_public")
2471 {
2472 keep |= filename.ends_with(".rlib");
2475 } else {
2476 keep |= filename.ends_with(".rmeta");
2480 }
2481 } else {
2482 keep |= filename.ends_with(".rlib");
2484 }
2485
2486 if !keep {
2487 continue;
2488 }
2489
2490 let filename = Path::new(&*filename);
2491
2492 if filename.starts_with(&host_root_dir) {
2495 if crate_types.iter().any(|t| t == "proc-macro") {
2497 deps.push((filename.to_path_buf(), DependencyType::Host));
2498 }
2499 continue;
2500 }
2501
2502 if filename.starts_with(&target_deps_dir) {
2505 deps.push((filename.to_path_buf(), DependencyType::Target));
2506 continue;
2507 }
2508
2509 let expected_len = t!(filename.metadata()).len();
2520 let filename = filename.file_name().unwrap().to_str().unwrap();
2521 let mut parts = filename.splitn(2, '.');
2522 let file_stem = parts.next().unwrap().to_owned();
2523 let extension = parts.next().unwrap().to_owned();
2524
2525 toplevel.push((file_stem, extension, expected_len));
2526 }
2527 });
2528
2529 if !ok {
2530 crate::exit!(1);
2531 }
2532
2533 if builder.config.dry_run() {
2534 return Vec::new();
2535 }
2536
2537 let contents = target_deps_dir
2541 .read_dir()
2542 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2543 .map(|e| t!(e))
2544 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2545 .collect::<Vec<_>>();
2546 for (prefix, extension, expected_len) in toplevel {
2547 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2548 meta.len() == expected_len
2549 && filename
2550 .strip_prefix(&prefix[..])
2551 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2552 .unwrap_or(false)
2553 });
2554 let max = candidates.max_by_key(|&(_, _, metadata)| {
2555 metadata.modified().expect("mtime should be available on all relevant OSes")
2556 });
2557 let path_to_add = match max {
2558 Some(triple) => triple.0.to_str().unwrap(),
2559 None => panic!("no output generated for {prefix:?} {extension:?}"),
2560 };
2561 if is_dylib(Path::new(path_to_add)) {
2562 let candidate = format!("{path_to_add}.lib");
2563 let candidate = PathBuf::from(candidate);
2564 if candidate.exists() {
2565 deps.push((candidate, DependencyType::Target));
2566 }
2567 }
2568 deps.push((path_to_add.into(), DependencyType::Target));
2569 }
2570
2571 deps.extend(additional_target_deps);
2572 deps.sort();
2573 let mut new_contents = Vec::new();
2574 for (dep, dependency_type) in deps.iter() {
2575 new_contents.extend(match *dependency_type {
2576 DependencyType::Host => b"h",
2577 DependencyType::Target => b"t",
2578 DependencyType::TargetSelfContained => b"s",
2579 });
2580 new_contents.extend(dep.to_str().unwrap().as_bytes());
2581 new_contents.extend(b"\0");
2582 }
2583 t!(fs::write(stamp.path(), &new_contents));
2584 deps.into_iter().map(|(d, _)| d).collect()
2585}
2586
2587pub fn stream_cargo(
2588 builder: &Builder<'_>,
2589 cargo: Cargo,
2590 tail_args: Vec<String>,
2591 cb: &mut dyn FnMut(CargoMessage<'_>),
2592) -> bool {
2593 let mut cmd = cargo.into_cmd();
2594
2595 let mut message_format = if builder.config.json_output {
2598 String::from("json")
2599 } else {
2600 String::from("json-render-diagnostics")
2601 };
2602 if let Some(s) = &builder.config.rustc_error_format {
2603 message_format.push_str(",json-diagnostic-");
2604 message_format.push_str(s);
2605 }
2606 cmd.arg("--message-format").arg(message_format);
2607
2608 for arg in tail_args {
2609 cmd.arg(arg);
2610 }
2611
2612 builder.do_if_verbose(|| println!("running: {cmd:?}"));
2613
2614 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2615
2616 let Some(mut streaming_command) = streaming_command else {
2617 return true;
2618 };
2619
2620 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2624 for line in stdout.lines() {
2625 let line = t!(line);
2626 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2627 Ok(msg) => {
2628 if builder.config.json_output {
2629 println!("{line}");
2631 }
2632 cb(msg)
2633 }
2634 Err(_) => println!("{line}"),
2636 }
2637 }
2638
2639 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2641 if builder.is_verbose() && !status.success() {
2642 eprintln!(
2643 "command did not execute successfully: {cmd:?}\n\
2644 expected success, got: {status}"
2645 );
2646 }
2647
2648 status.success()
2649}
2650
2651#[derive(Deserialize)]
2652pub struct CargoTarget<'a> {
2653 crate_types: Vec<Cow<'a, str>>,
2654}
2655
2656#[derive(Deserialize)]
2657#[serde(tag = "reason", rename_all = "kebab-case")]
2658pub enum CargoMessage<'a> {
2659 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2660 BuildScriptExecuted,
2661 BuildFinished,
2662}
2663
2664pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2665 if target != "x86_64-unknown-linux-gnu"
2669 || !builder.config.is_host_target(target)
2670 || !path.exists()
2671 {
2672 return;
2673 }
2674
2675 let previous_mtime = t!(t!(path.metadata()).modified());
2676 let stamp = BuildStamp::new(path.parent().unwrap())
2677 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2678 .with_prefix("strip")
2679 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2680
2681 if !stamp.is_up_to_date() {
2684 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2685 }
2686 t!(stamp.write());
2687
2688 let file = t!(fs::File::open(path));
2689
2690 t!(file.set_modified(previous_mtime));
2703}
2704
2705pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2707 build_compiler.stage != 0
2708}