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 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, 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 = match builder.config.optimized_compiler_builtins(target) {
571 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
572 cargo.env("LLVM_COMPILER_RT_LIB", path);
573 " compiler-builtins-c"
574 }
575 CompilerBuiltins::BuildLLVMFuncs => {
576 builder.require_submodule(
586 "src/llvm-project",
587 Some(
588 "The `build.optimized-compiler-builtins` config option \
589 requires `compiler-rt` sources from LLVM.",
590 ),
591 );
592 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
593 assert!(compiler_builtins_root.exists());
594 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
597 " compiler-builtins-c"
598 }
599 CompilerBuiltins::BuildRustOnly => "",
600 };
601
602 if !builder.unstable_features() {
605 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
606 }
607
608 let mut features = String::new();
609
610 if builder.no_std(target) == Some(true) {
611 features += " compiler-builtins-mem";
612 if !target.starts_with("bpf") {
613 features.push_str(compiler_builtins_c_feature);
614 }
615
616 cargo
618 .args(["-p", "alloc"])
619 .arg("--manifest-path")
620 .arg(builder.src.join("library/alloc/Cargo.toml"))
621 .arg("--features")
622 .arg(features);
623 } else {
624 features += &builder.std_features(target);
625 features.push_str(compiler_builtins_c_feature);
626
627 cargo
628 .arg("--features")
629 .arg(features)
630 .arg("--manifest-path")
631 .arg(builder.src.join("library/sysroot/Cargo.toml"));
632
633 if target.contains("musl")
636 && let Some(p) = builder.musl_libdir(target)
637 {
638 let root = format!("native={}", p.to_str().unwrap());
639 cargo.rustflag("-L").rustflag(&root);
640 }
641
642 if target.contains("-wasi")
643 && let Some(dir) = builder.wasi_libdir(target)
644 {
645 let root = format!("native={}", dir.to_str().unwrap());
646 cargo.rustflag("-L").rustflag(&root);
647 }
648 }
649
650 cargo.rustflag("-Cembed-bitcode=yes");
656
657 if builder.config.rust_lto == RustcLto::Off {
658 cargo.rustflag("-Clto=off");
659 }
660
661 if target.contains("riscv") {
668 cargo.rustflag("-Cforce-unwind-tables=yes");
669 }
670
671 cargo.rustflag("-Zunstable-options");
674 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
675
676 let html_root =
677 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
678 cargo.rustflag(&html_root);
679 cargo.rustdocflag(&html_root);
680
681 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
682}
683
684#[derive(Debug, Clone, PartialEq, Eq, Hash)]
693pub struct StdLink {
694 pub compiler: Compiler,
695 pub target_compiler: Compiler,
696 pub target: TargetSelection,
697 crates: Vec<String>,
699 force_recompile: bool,
701}
702
703impl StdLink {
704 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
705 Self {
706 compiler: host_compiler,
707 target_compiler: std.build_compiler,
708 target: std.target,
709 crates: std.crates,
710 force_recompile: std.force_recompile,
711 }
712 }
713}
714
715impl Step for StdLink {
716 type Output = ();
717
718 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
719 run.never()
720 }
721
722 fn run(self, builder: &Builder<'_>) {
731 let compiler = self.compiler;
732 let target_compiler = self.target_compiler;
733 let target = self.target;
734
735 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
737 let lib = builder.sysroot_libdir_relative(self.compiler);
739 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
740 compiler: self.compiler,
741 force_recompile: self.force_recompile,
742 });
743 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
744 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
745 (libdir, hostdir)
746 } else {
747 let libdir = builder.sysroot_target_libdir(target_compiler, target);
748 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
749 (libdir, hostdir)
750 };
751
752 let is_downloaded_beta_stage0 = builder
753 .build
754 .config
755 .initial_rustc
756 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
757
758 if compiler.stage == 0 && is_downloaded_beta_stage0 {
762 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
764
765 let host = compiler.host;
766 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
767 let sysroot_bin_dir = sysroot.join("bin");
768 t!(fs::create_dir_all(&sysroot_bin_dir));
769 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
770
771 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
772 t!(fs::create_dir_all(sysroot.join("lib")));
773 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
774
775 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
777 t!(fs::create_dir_all(&sysroot_codegen_backends));
778 let stage0_codegen_backends = builder
779 .out
780 .join(host)
781 .join("stage0/lib/rustlib")
782 .join(host)
783 .join("codegen-backends");
784 if stage0_codegen_backends.exists() {
785 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
786 }
787 } else if compiler.stage == 0 {
788 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
789
790 if builder.local_rebuild {
791 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
795 }
796
797 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
798 } else {
799 if builder.download_rustc() {
800 let _ = fs::remove_dir_all(&libdir);
802 let _ = fs::remove_dir_all(&hostdir);
803 }
804
805 add_to_sysroot(
806 builder,
807 &libdir,
808 &hostdir,
809 &build_stamp::libstd_stamp(builder, compiler, target),
810 );
811 }
812 }
813}
814
815fn copy_sanitizers(
817 builder: &Builder<'_>,
818 compiler: &Compiler,
819 target: TargetSelection,
820) -> Vec<PathBuf> {
821 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
822
823 if builder.config.dry_run() {
824 return Vec::new();
825 }
826
827 let mut target_deps = Vec::new();
828 let libdir = builder.sysroot_target_libdir(*compiler, target);
829
830 for runtime in &runtimes {
831 let dst = libdir.join(&runtime.name);
832 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
833
834 if target == "x86_64-apple-darwin"
838 || target == "aarch64-apple-darwin"
839 || target == "aarch64-apple-ios"
840 || target == "aarch64-apple-ios-sim"
841 || target == "x86_64-apple-ios"
842 {
843 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
845 apple_darwin_sign_file(builder, &dst);
848 }
849
850 target_deps.push(dst);
851 }
852
853 target_deps
854}
855
856fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
857 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
858}
859
860fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
861 command("codesign")
862 .arg("-f") .arg("-s")
864 .arg("-")
865 .arg(file_path)
866 .run(builder);
867}
868
869#[derive(Debug, Clone, PartialEq, Eq, Hash)]
870pub struct StartupObjects {
871 pub compiler: Compiler,
872 pub target: TargetSelection,
873}
874
875impl Step for StartupObjects {
876 type Output = Vec<(PathBuf, DependencyType)>;
877
878 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
879 run.path("library/rtstartup")
880 }
881
882 fn make_run(run: RunConfig<'_>) {
883 run.builder.ensure(StartupObjects {
884 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
885 target: run.target,
886 });
887 }
888
889 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
896 let for_compiler = self.compiler;
897 let target = self.target;
898 if !target.is_windows_gnu() {
899 return vec![];
900 }
901
902 let mut target_deps = vec![];
903
904 let src_dir = &builder.src.join("library").join("rtstartup");
905 let dst_dir = &builder.native_dir(target).join("rtstartup");
906 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
907 t!(fs::create_dir_all(dst_dir));
908
909 for file in &["rsbegin", "rsend"] {
910 let src_file = &src_dir.join(file.to_string() + ".rs");
911 let dst_file = &dst_dir.join(file.to_string() + ".o");
912 if !up_to_date(src_file, dst_file) {
913 let mut cmd = command(&builder.initial_rustc);
914 cmd.env("RUSTC_BOOTSTRAP", "1");
915 if !builder.local_rebuild {
916 cmd.arg("--cfg").arg("bootstrap");
918 }
919 cmd.arg("--target")
920 .arg(target.rustc_target_arg())
921 .arg("--emit=obj")
922 .arg("-o")
923 .arg(dst_file)
924 .arg(src_file)
925 .run(builder);
926 }
927
928 let obj = sysroot_dir.join((*file).to_string() + ".o");
929 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
930 target_deps.push((obj, DependencyType::Target));
931 }
932
933 target_deps
934 }
935}
936
937fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
938 let ci_rustc_dir = builder.config.ci_rustc_dir();
939
940 for file in contents {
941 let src = ci_rustc_dir.join(&file);
942 let dst = sysroot.join(file);
943 if src.is_dir() {
944 t!(fs::create_dir_all(dst));
945 } else {
946 builder.copy_link(&src, &dst, FileType::Regular);
947 }
948 }
949}
950
951#[derive(Clone, Debug)]
953pub struct BuiltRustc {
954 pub build_compiler: Compiler,
958}
959
960#[derive(Debug, Clone, PartialEq, Eq, Hash)]
967pub struct Rustc {
968 pub target: TargetSelection,
970 pub build_compiler: Compiler,
972 crates: Vec<String>,
978}
979
980impl Rustc {
981 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
982 Self { target, build_compiler, crates: Default::default() }
983 }
984}
985
986impl Step for Rustc {
987 type Output = BuiltRustc;
988
989 const IS_HOST: bool = true;
990 const DEFAULT: bool = false;
991
992 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
993 let mut crates = run.builder.in_tree_crates("rustc-main", None);
994 for (i, krate) in crates.iter().enumerate() {
995 if krate.name == "rustc-main" {
998 crates.swap_remove(i);
999 break;
1000 }
1001 }
1002 run.crates(crates)
1003 }
1004
1005 fn make_run(run: RunConfig<'_>) {
1006 if run.builder.paths == vec![PathBuf::from("compiler")] {
1009 return;
1010 }
1011
1012 let crates = run.cargo_crates_in_set();
1013 run.builder.ensure(Rustc {
1014 build_compiler: run
1015 .builder
1016 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1017 target: run.target,
1018 crates,
1019 });
1020 }
1021
1022 fn run(self, builder: &Builder<'_>) -> Self::Output {
1028 let build_compiler = self.build_compiler;
1029 let target = self.target;
1030
1031 if builder.download_rustc() && build_compiler.stage != 0 {
1034 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1035
1036 let sysroot =
1037 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1038 cp_rustc_component_to_ci_sysroot(
1039 builder,
1040 &sysroot,
1041 builder.config.ci_rustc_dev_contents(),
1042 );
1043 return BuiltRustc { build_compiler };
1044 }
1045
1046 builder.std(build_compiler, target);
1049
1050 if builder.config.keep_stage.contains(&build_compiler.stage) {
1051 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1052
1053 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1054 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1055 builder.ensure(RustcLink::from_rustc(self));
1056
1057 return BuiltRustc { build_compiler };
1058 }
1059
1060 let stage = build_compiler.stage + 1;
1062
1063 if build_compiler.stage >= 2
1068 && !builder.config.full_bootstrap
1069 && target == builder.host_target
1070 {
1071 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1075
1076 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1077 builder.info(&msg);
1078
1079 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1083 uplift_build_compiler,
1085 build_compiler,
1087 target,
1088 self.crates,
1089 ));
1090
1091 return BuiltRustc { build_compiler: uplift_build_compiler };
1094 }
1095
1096 builder.std(
1102 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1103 builder.config.host_target,
1104 );
1105
1106 let mut cargo = builder::Cargo::new(
1107 builder,
1108 build_compiler,
1109 Mode::Rustc,
1110 SourceType::InTree,
1111 target,
1112 Kind::Build,
1113 );
1114
1115 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1116
1117 for krate in &*self.crates {
1121 cargo.arg("-p").arg(krate);
1122 }
1123
1124 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1125 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1127 }
1128
1129 let _guard = builder.msg(
1130 Kind::Build,
1131 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1132 Mode::Rustc,
1133 build_compiler,
1134 target,
1135 );
1136 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1137 run_cargo(
1138 builder,
1139 cargo,
1140 vec![],
1141 &stamp,
1142 vec![],
1143 false,
1144 true, );
1146
1147 let target_root_dir = stamp.path().parent().unwrap();
1148 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1154 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1155 {
1156 let rustc_driver = target_root_dir.join("librustc_driver.so");
1157 strip_debug(builder, target, &rustc_driver);
1158 }
1159
1160 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1161 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1164 }
1165
1166 builder.ensure(RustcLink::from_rustc(self));
1167 BuiltRustc { build_compiler }
1168 }
1169
1170 fn metadata(&self) -> Option<StepMetadata> {
1171 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1172 }
1173}
1174
1175pub fn rustc_cargo(
1176 builder: &Builder<'_>,
1177 cargo: &mut Cargo,
1178 target: TargetSelection,
1179 build_compiler: &Compiler,
1180 crates: &[String],
1181) {
1182 cargo
1183 .arg("--features")
1184 .arg(builder.rustc_features(builder.kind, target, crates))
1185 .arg("--manifest-path")
1186 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1187
1188 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1189
1190 cargo.rustflag("-Zon-broken-pipe=kill");
1204
1205 if builder.config.llvm_enzyme {
1208 let arch = builder.build.host_target;
1209 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1210 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1211
1212 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1213 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1214 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1215 }
1216 }
1217
1218 if builder.build.config.lld_mode.is_used() {
1223 cargo.rustflag("-Zdefault-visibility=protected");
1224 }
1225
1226 if is_lto_stage(build_compiler) {
1227 match builder.config.rust_lto {
1228 RustcLto::Thin | RustcLto::Fat => {
1229 cargo.rustflag("-Zdylib-lto");
1232 let lto_type = match builder.config.rust_lto {
1236 RustcLto::Thin => "thin",
1237 RustcLto::Fat => "fat",
1238 _ => unreachable!(),
1239 };
1240 cargo.rustflag(&format!("-Clto={lto_type}"));
1241 cargo.rustflag("-Cembed-bitcode=yes");
1242 }
1243 RustcLto::ThinLocal => { }
1244 RustcLto::Off => {
1245 cargo.rustflag("-Clto=off");
1246 }
1247 }
1248 } else if builder.config.rust_lto == RustcLto::Off {
1249 cargo.rustflag("-Clto=off");
1250 }
1251
1252 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1260 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1261 }
1262
1263 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1264 panic!("Cannot use and generate PGO profiles at the same time");
1265 }
1266 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1267 if build_compiler.stage == 1 {
1268 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1269 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1272 true
1273 } else {
1274 false
1275 }
1276 } else if let Some(path) = &builder.config.rust_profile_use {
1277 if build_compiler.stage == 1 {
1278 cargo.rustflag(&format!("-Cprofile-use={path}"));
1279 if builder.is_verbose() {
1280 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1281 }
1282 true
1283 } else {
1284 false
1285 }
1286 } else {
1287 false
1288 };
1289 if is_collecting {
1290 cargo.rustflag(&format!(
1292 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1293 builder.config.src.components().count()
1294 ));
1295 }
1296
1297 if let Some(ref ccache) = builder.config.ccache
1302 && build_compiler.stage == 0
1303 && !builder.config.incremental
1304 {
1305 cargo.env("RUSTC_WRAPPER", ccache);
1306 }
1307
1308 rustc_cargo_env(builder, cargo, target);
1309}
1310
1311pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1312 cargo
1315 .env("CFG_RELEASE", builder.rust_release())
1316 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1317 .env("CFG_VERSION", builder.rust_version());
1318
1319 if builder.config.omit_git_hash {
1323 cargo.env("CFG_OMIT_GIT_HASH", "1");
1324 }
1325
1326 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1327
1328 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1329 let target_config = builder.config.target_config.get(&target);
1330
1331 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1332
1333 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1334 cargo.env("CFG_VER_DATE", ver_date);
1335 }
1336 if let Some(ref ver_hash) = builder.rust_info().sha() {
1337 cargo.env("CFG_VER_HASH", ver_hash);
1338 }
1339 if !builder.unstable_features() {
1340 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1341 }
1342
1343 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1346 cargo.env("CFG_DEFAULT_LINKER", s);
1347 } else if let Some(ref s) = builder.config.rustc_default_linker {
1348 cargo.env("CFG_DEFAULT_LINKER", s);
1349 }
1350
1351 if builder.config.lld_enabled {
1353 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1354 }
1355
1356 if builder.config.rust_verify_llvm_ir {
1357 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1358 }
1359
1360 if builder.config.llvm_enzyme {
1361 cargo.rustflag("--cfg=llvm_enzyme");
1362 }
1363
1364 if builder.config.llvm_enabled(target) {
1376 let building_llvm_is_expensive =
1377 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1378 .should_build();
1379
1380 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1381 if !skip_llvm {
1382 rustc_llvm_env(builder, cargo, target)
1383 }
1384 }
1385
1386 if builder.config.jemalloc(target) && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
1388 if target.starts_with("aarch64") {
1391 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1392 }
1393 else if target.starts_with("loongarch") {
1395 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1396 }
1397 }
1398}
1399
1400fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1406 if builder.config.is_rust_llvm(target) {
1407 cargo.env("LLVM_RUSTLLVM", "1");
1408 }
1409 if builder.config.llvm_enzyme {
1410 cargo.env("LLVM_ENZYME", "1");
1411 }
1412 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1413 cargo.env("LLVM_CONFIG", &host_llvm_config);
1414
1415 let mut llvm_linker_flags = String::new();
1425 if builder.config.llvm_profile_generate
1426 && target.is_msvc()
1427 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1428 {
1429 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1431 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1432 }
1433
1434 if let Some(ref s) = builder.config.llvm_ldflags {
1436 if !llvm_linker_flags.is_empty() {
1437 llvm_linker_flags.push(' ');
1438 }
1439 llvm_linker_flags.push_str(s);
1440 }
1441
1442 if !llvm_linker_flags.is_empty() {
1444 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1445 }
1446
1447 if builder.config.llvm_static_stdcpp
1450 && !target.contains("freebsd")
1451 && !target.is_msvc()
1452 && !target.contains("apple")
1453 && !target.contains("solaris")
1454 {
1455 let libstdcxx_name =
1456 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1457 let file = compiler_file(
1458 builder,
1459 &builder.cxx(target).unwrap(),
1460 target,
1461 CLang::Cxx,
1462 libstdcxx_name,
1463 );
1464 cargo.env("LLVM_STATIC_STDCPP", file);
1465 }
1466 if builder.llvm_link_shared() {
1467 cargo.env("LLVM_LINK_SHARED", "1");
1468 }
1469 if builder.config.llvm_use_libcxx {
1470 cargo.env("LLVM_USE_LIBCXX", "1");
1471 }
1472 if builder.config.llvm_assertions {
1473 cargo.env("LLVM_ASSERTIONS", "1");
1474 }
1475}
1476
1477#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1490struct RustcLink {
1491 build_compiler: Compiler,
1493 sysroot_compiler: Compiler,
1496 target: TargetSelection,
1497 crates: Vec<String>,
1499}
1500
1501impl RustcLink {
1502 fn from_rustc(rustc: Rustc) -> Self {
1505 Self {
1506 build_compiler: rustc.build_compiler,
1507 sysroot_compiler: rustc.build_compiler,
1508 target: rustc.target,
1509 crates: rustc.crates,
1510 }
1511 }
1512
1513 fn from_build_compiler_and_sysroot(
1515 build_compiler: Compiler,
1516 sysroot_compiler: Compiler,
1517 target: TargetSelection,
1518 crates: Vec<String>,
1519 ) -> Self {
1520 Self { build_compiler, sysroot_compiler, target, crates }
1521 }
1522}
1523
1524impl Step for RustcLink {
1525 type Output = ();
1526
1527 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1528 run.never()
1529 }
1530
1531 fn run(self, builder: &Builder<'_>) {
1533 let build_compiler = self.build_compiler;
1534 let sysroot_compiler = self.sysroot_compiler;
1535 let target = self.target;
1536 add_to_sysroot(
1537 builder,
1538 &builder.sysroot_target_libdir(sysroot_compiler, target),
1539 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1540 &build_stamp::librustc_stamp(builder, build_compiler, target),
1541 );
1542 }
1543}
1544
1545#[derive(Clone)]
1548pub struct GccCodegenBackendOutput {
1549 stamp: BuildStamp,
1550 gcc: GccOutput,
1551}
1552
1553#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1554pub struct GccCodegenBackend {
1555 compilers: RustcPrivateCompilers,
1556}
1557
1558impl Step for GccCodegenBackend {
1559 type Output = GccCodegenBackendOutput;
1560
1561 const IS_HOST: bool = true;
1562
1563 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1564 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1565 }
1566
1567 fn make_run(run: RunConfig<'_>) {
1568 run.builder.ensure(GccCodegenBackend {
1569 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1570 });
1571 }
1572
1573 fn run(self, builder: &Builder<'_>) -> Self::Output {
1574 let target = self.compilers.target();
1575 let build_compiler = self.compilers.build_compiler();
1576
1577 let stamp = build_stamp::codegen_backend_stamp(
1578 builder,
1579 build_compiler,
1580 target,
1581 &CodegenBackendKind::Gcc,
1582 );
1583
1584 let gcc = builder.ensure(Gcc { target });
1585
1586 if builder.config.keep_stage.contains(&build_compiler.stage) {
1587 trace!("`keep-stage` requested");
1588 builder.info(
1589 "WARNING: Using a potentially old codegen backend. \
1590 This may not behave well.",
1591 );
1592 return GccCodegenBackendOutput { stamp, gcc };
1595 }
1596
1597 let mut cargo = builder::Cargo::new(
1598 builder,
1599 build_compiler,
1600 Mode::Codegen,
1601 SourceType::InTree,
1602 target,
1603 Kind::Build,
1604 );
1605 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1606 rustc_cargo_env(builder, &mut cargo, target);
1607
1608 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1609
1610 let _guard =
1611 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1612 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1613
1614 GccCodegenBackendOutput {
1615 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1616 gcc,
1617 }
1618 }
1619
1620 fn metadata(&self) -> Option<StepMetadata> {
1621 Some(
1622 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1623 .built_by(self.compilers.build_compiler()),
1624 )
1625 }
1626}
1627
1628#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1629pub struct CraneliftCodegenBackend {
1630 pub compilers: RustcPrivateCompilers,
1631}
1632
1633impl Step for CraneliftCodegenBackend {
1634 type Output = BuildStamp;
1635 const IS_HOST: bool = true;
1636
1637 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1638 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1639 }
1640
1641 fn make_run(run: RunConfig<'_>) {
1642 run.builder.ensure(CraneliftCodegenBackend {
1643 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1644 });
1645 }
1646
1647 fn run(self, builder: &Builder<'_>) -> Self::Output {
1648 let target = self.compilers.target();
1649 let build_compiler = self.compilers.build_compiler();
1650
1651 let stamp = build_stamp::codegen_backend_stamp(
1652 builder,
1653 build_compiler,
1654 target,
1655 &CodegenBackendKind::Cranelift,
1656 );
1657
1658 if builder.config.keep_stage.contains(&build_compiler.stage) {
1659 trace!("`keep-stage` requested");
1660 builder.info(
1661 "WARNING: Using a potentially old codegen backend. \
1662 This may not behave well.",
1663 );
1664 return stamp;
1667 }
1668
1669 let mut cargo = builder::Cargo::new(
1670 builder,
1671 build_compiler,
1672 Mode::Codegen,
1673 SourceType::InTree,
1674 target,
1675 Kind::Build,
1676 );
1677 cargo
1678 .arg("--manifest-path")
1679 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1680 rustc_cargo_env(builder, &mut cargo, target);
1681
1682 let _guard = builder.msg(
1683 Kind::Build,
1684 "codegen backend cranelift",
1685 Mode::Codegen,
1686 build_compiler,
1687 target,
1688 );
1689 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1690 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1691 }
1692
1693 fn metadata(&self) -> Option<StepMetadata> {
1694 Some(
1695 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1696 .built_by(self.compilers.build_compiler()),
1697 )
1698 }
1699}
1700
1701fn write_codegen_backend_stamp(
1703 mut stamp: BuildStamp,
1704 files: Vec<PathBuf>,
1705 dry_run: bool,
1706) -> BuildStamp {
1707 if dry_run {
1708 return stamp;
1709 }
1710
1711 let mut files = files.into_iter().filter(|f| {
1712 let filename = f.file_name().unwrap().to_str().unwrap();
1713 is_dylib(f) && filename.contains("rustc_codegen_")
1714 });
1715 let codegen_backend = match files.next() {
1716 Some(f) => f,
1717 None => panic!("no dylibs built for codegen backend?"),
1718 };
1719 if let Some(f) = files.next() {
1720 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1721 }
1722
1723 let codegen_backend = codegen_backend.to_str().unwrap();
1724 stamp = stamp.add_stamp(codegen_backend);
1725 t!(stamp.write());
1726 stamp
1727}
1728
1729fn copy_codegen_backends_to_sysroot(
1736 builder: &Builder<'_>,
1737 stamp: BuildStamp,
1738 target_compiler: Compiler,
1739) {
1740 let dst = builder.sysroot_codegen_backends(target_compiler);
1749 t!(fs::create_dir_all(&dst), dst);
1750
1751 if builder.config.dry_run() {
1752 return;
1753 }
1754
1755 if stamp.path().exists() {
1756 let file = get_codegen_backend_file(&stamp);
1757 builder.copy_link(
1758 &file,
1759 &dst.join(normalize_codegen_backend_name(builder, &file)),
1760 FileType::NativeLibrary,
1761 );
1762 }
1763}
1764
1765pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1767 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1768}
1769
1770pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1772 let filename = path.file_name().unwrap().to_str().unwrap();
1773 let dash = filename.find('-').unwrap();
1776 let dot = filename.find('.').unwrap();
1777 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1778}
1779
1780pub fn compiler_file(
1781 builder: &Builder<'_>,
1782 compiler: &Path,
1783 target: TargetSelection,
1784 c: CLang,
1785 file: &str,
1786) -> PathBuf {
1787 if builder.config.dry_run() {
1788 return PathBuf::new();
1789 }
1790 let mut cmd = command(compiler);
1791 cmd.args(builder.cc_handled_clags(target, c));
1792 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1793 cmd.arg(format!("-print-file-name={file}"));
1794 let out = cmd.run_capture_stdout(builder).stdout();
1795 PathBuf::from(out.trim())
1796}
1797
1798#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1799pub struct Sysroot {
1800 pub compiler: Compiler,
1801 force_recompile: bool,
1803}
1804
1805impl Sysroot {
1806 pub(crate) fn new(compiler: Compiler) -> Self {
1807 Sysroot { compiler, force_recompile: false }
1808 }
1809}
1810
1811impl Step for Sysroot {
1812 type Output = PathBuf;
1813
1814 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1815 run.never()
1816 }
1817
1818 fn run(self, builder: &Builder<'_>) -> PathBuf {
1822 let compiler = self.compiler;
1823 let host_dir = builder.out.join(compiler.host);
1824
1825 let sysroot_dir = |stage| {
1826 if stage == 0 {
1827 host_dir.join("stage0-sysroot")
1828 } else if self.force_recompile && stage == compiler.stage {
1829 host_dir.join(format!("stage{stage}-test-sysroot"))
1830 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1831 host_dir.join("ci-rustc-sysroot")
1832 } else {
1833 host_dir.join(format!("stage{stage}"))
1834 }
1835 };
1836 let sysroot = sysroot_dir(compiler.stage);
1837 trace!(stage = ?compiler.stage, ?sysroot);
1838
1839 builder
1840 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1841 let _ = fs::remove_dir_all(&sysroot);
1842 t!(fs::create_dir_all(&sysroot));
1843
1844 if compiler.stage == 0 {
1851 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1852 }
1853
1854 if builder.download_rustc() && compiler.stage != 0 {
1856 assert_eq!(
1857 builder.config.host_target, compiler.host,
1858 "Cross-compiling is not yet supported with `download-rustc`",
1859 );
1860
1861 for stage in 0..=2 {
1863 if stage != compiler.stage {
1864 let dir = sysroot_dir(stage);
1865 if !dir.ends_with("ci-rustc-sysroot") {
1866 let _ = fs::remove_dir_all(dir);
1867 }
1868 }
1869 }
1870
1871 let mut filtered_files = Vec::new();
1881 let mut add_filtered_files = |suffix, contents| {
1882 for path in contents {
1883 let path = Path::new(&path);
1884 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1885 filtered_files.push(path.file_name().unwrap().to_owned());
1886 }
1887 }
1888 };
1889 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1890 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1891 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1894
1895 let filtered_extensions = [
1896 OsStr::new("rmeta"),
1897 OsStr::new("rlib"),
1898 OsStr::new(std::env::consts::DLL_EXTENSION),
1900 ];
1901 let ci_rustc_dir = builder.config.ci_rustc_dir();
1902 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1903 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1904 return true;
1905 }
1906 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1907 return true;
1908 }
1909 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1910 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1911 false
1912 } else {
1913 true
1914 }
1915 });
1916 }
1917
1918 if compiler.stage != 0 {
1924 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1925 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1926 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1927 if let Err(e) =
1928 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1929 {
1930 eprintln!(
1931 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1932 sysroot_lib_rustlib_src_rust.display(),
1933 builder.src.display(),
1934 e,
1935 );
1936 if builder.config.rust_remap_debuginfo {
1937 eprintln!(
1938 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1939 sysroot_lib_rustlib_src_rust.display(),
1940 );
1941 }
1942 build_helper::exit!(1);
1943 }
1944 }
1945
1946 if !builder.download_rustc() {
1948 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1949 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1950 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1951 if let Err(e) =
1952 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1953 {
1954 eprintln!(
1955 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1956 sysroot_lib_rustlib_rustcsrc_rust.display(),
1957 builder.src.display(),
1958 e,
1959 );
1960 build_helper::exit!(1);
1961 }
1962 }
1963
1964 sysroot
1965 }
1966}
1967
1968#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1975pub struct Assemble {
1976 pub target_compiler: Compiler,
1981}
1982
1983impl Step for Assemble {
1984 type Output = Compiler;
1985 const IS_HOST: bool = true;
1986
1987 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1988 run.path("compiler/rustc").path("compiler")
1989 }
1990
1991 fn make_run(run: RunConfig<'_>) {
1992 run.builder.ensure(Assemble {
1993 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1994 });
1995 }
1996
1997 fn run(self, builder: &Builder<'_>) -> Compiler {
1998 let target_compiler = self.target_compiler;
1999
2000 if target_compiler.stage == 0 {
2001 trace!("stage 0 build compiler is always available, simply returning");
2002 assert_eq!(
2003 builder.config.host_target, target_compiler.host,
2004 "Cannot obtain compiler for non-native build triple at stage 0"
2005 );
2006 return target_compiler;
2008 }
2009
2010 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2013 let libdir_bin = libdir.parent().unwrap().join("bin");
2014 t!(fs::create_dir_all(&libdir_bin));
2015
2016 if builder.config.llvm_enabled(target_compiler.host) {
2017 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2018
2019 let target = target_compiler.host;
2020 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2021 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2022 trace!("LLVM tools enabled");
2023
2024 let host_llvm_bin_dir = command(&host_llvm_config)
2025 .arg("--bindir")
2026 .cached()
2027 .run_capture_stdout(builder)
2028 .stdout()
2029 .trim()
2030 .to_string();
2031
2032 let llvm_bin_dir = if target == builder.host_target {
2033 PathBuf::from(host_llvm_bin_dir)
2034 } else {
2035 let external_llvm_config = builder
2038 .config
2039 .target_config
2040 .get(&target)
2041 .and_then(|t| t.llvm_config.clone());
2042 if let Some(external_llvm_config) = external_llvm_config {
2043 external_llvm_config.parent().unwrap().to_path_buf()
2046 } else {
2047 let host_llvm_out = builder.llvm_out(builder.host_target);
2051 let target_llvm_out = builder.llvm_out(target);
2052 if let Ok(relative_path) =
2053 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2054 {
2055 target_llvm_out.join(relative_path)
2056 } else {
2057 PathBuf::from(
2060 host_llvm_bin_dir
2061 .replace(&*builder.host_target.triple, &target.triple),
2062 )
2063 }
2064 }
2065 };
2066
2067 #[cfg(feature = "tracing")]
2074 let _llvm_tools_span =
2075 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2076 .entered();
2077 for tool in LLVM_TOOLS {
2078 trace!("installing `{tool}`");
2079 let tool_exe = exe(tool, target_compiler.host);
2080 let src_path = llvm_bin_dir.join(&tool_exe);
2081
2082 if !src_path.exists() && builder.config.llvm_from_ci {
2084 eprintln!("{} does not exist; skipping copy", src_path.display());
2085 continue;
2086 }
2087
2088 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2095 }
2096 }
2097 }
2098
2099 let maybe_install_llvm_bitcode_linker = || {
2100 if builder.config.llvm_bitcode_linker_enabled {
2101 trace!("llvm-bitcode-linker enabled, installing");
2102 let llvm_bitcode_linker = builder.ensure(
2103 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2104 builder,
2105 target_compiler,
2106 ),
2107 );
2108
2109 let bindir_self_contained = builder
2111 .sysroot(target_compiler)
2112 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2113 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2114
2115 t!(fs::create_dir_all(&bindir_self_contained));
2116 builder.copy_link(
2117 &llvm_bitcode_linker.tool_path,
2118 &bindir_self_contained.join(tool_exe),
2119 FileType::Executable,
2120 );
2121 }
2122 };
2123
2124 if builder.download_rustc() {
2126 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2127
2128 builder.std(target_compiler, target_compiler.host);
2129 let sysroot =
2130 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2131 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2134 if target_compiler.stage == builder.top_stage {
2136 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2137 }
2138
2139 maybe_install_llvm_bitcode_linker();
2142
2143 return target_compiler;
2144 }
2145
2146 debug!(
2160 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2161 target_compiler.stage - 1,
2162 builder.config.host_target,
2163 );
2164 let build_compiler =
2165 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2166
2167 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2169 debug!("`llvm_enzyme` requested");
2170 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2171 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2172 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2173 let lib_ext = std::env::consts::DLL_EXTENSION;
2174 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2175 let src_lib =
2176 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2177 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2178 let target_libdir =
2179 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2180 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2181 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2182 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2183 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2184 }
2185 }
2186
2187 debug!(
2190 ?build_compiler,
2191 "target_compiler.host" = ?target_compiler.host,
2192 "building compiler libraries to link to"
2193 );
2194
2195 let BuiltRustc { build_compiler } =
2197 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2198
2199 let stage = target_compiler.stage;
2200 let host = target_compiler.host;
2201 let (host_info, dir_name) = if build_compiler.host == host {
2202 ("".into(), "host".into())
2203 } else {
2204 (format!(" ({host})"), host.to_string())
2205 };
2206 let msg = format!(
2211 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2212 );
2213 builder.info(&msg);
2214
2215 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2217 let proc_macros = builder
2218 .read_stamp_file(&stamp)
2219 .into_iter()
2220 .filter_map(|(path, dependency_type)| {
2221 if dependency_type == DependencyType::Host {
2222 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2223 } else {
2224 None
2225 }
2226 })
2227 .collect::<HashSet<_>>();
2228
2229 let sysroot = builder.sysroot(target_compiler);
2230 let rustc_libdir = builder.rustc_libdir(target_compiler);
2231 t!(fs::create_dir_all(&rustc_libdir));
2232 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2233 for f in builder.read_dir(&src_libdir) {
2234 let filename = f.file_name().into_string().unwrap();
2235
2236 let is_proc_macro = proc_macros.contains(&filename);
2237 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2238
2239 let can_be_rustc_dynamic_dep = if builder
2243 .link_std_into_rustc_driver(target_compiler.host)
2244 && !target_compiler.host.is_windows()
2245 {
2246 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2247 !is_std
2248 } else {
2249 true
2250 };
2251
2252 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2253 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2254 }
2255 }
2256
2257 {
2258 #[cfg(feature = "tracing")]
2259 let _codegen_backend_span =
2260 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2261
2262 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2263 if builder.kind == Kind::Check && builder.top_stage == 1 {
2280 continue;
2281 }
2282
2283 let prepare_compilers = || {
2284 RustcPrivateCompilers::from_build_and_target_compiler(
2285 build_compiler,
2286 target_compiler,
2287 )
2288 };
2289
2290 match backend {
2291 CodegenBackendKind::Cranelift => {
2292 let stamp = builder
2293 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2294 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2295 }
2296 CodegenBackendKind::Gcc => {
2297 let output =
2298 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2299 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2300 output.gcc.install_to(builder, &rustc_libdir);
2303 }
2304 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2305 }
2306 }
2307 }
2308
2309 if builder.config.lld_enabled {
2310 let lld_wrapper =
2311 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2312 builder,
2313 target_compiler,
2314 ));
2315 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2316 }
2317
2318 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2319 debug!(
2320 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2321 workaround faulty homebrew `strip`s"
2322 );
2323
2324 let src_exe = exe("llvm-objcopy", target_compiler.host);
2331 let dst_exe = exe("rust-objcopy", target_compiler.host);
2332 builder.copy_link(
2333 &libdir_bin.join(src_exe),
2334 &libdir_bin.join(dst_exe),
2335 FileType::Executable,
2336 );
2337 }
2338
2339 if builder.tool_enabled("wasm-component-ld") {
2342 let wasm_component = builder.ensure(
2343 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2344 builder,
2345 target_compiler,
2346 ),
2347 );
2348 builder.copy_link(
2349 &wasm_component.tool_path,
2350 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2351 FileType::Executable,
2352 );
2353 }
2354
2355 maybe_install_llvm_bitcode_linker();
2356
2357 debug!(
2360 "target_compiler.host" = ?target_compiler.host,
2361 ?sysroot,
2362 "ensuring availability of `libLLVM.so` in compiler directory"
2363 );
2364 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2365 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2366
2367 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2369 let rustc = out_dir.join(exe("rustc-main", host));
2370 let bindir = sysroot.join("bin");
2371 t!(fs::create_dir_all(bindir));
2372 let compiler = builder.rustc(target_compiler);
2373 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2374 builder.copy_link(&rustc, &compiler, FileType::Executable);
2375
2376 target_compiler
2377 }
2378}
2379
2380#[track_caller]
2385pub fn add_to_sysroot(
2386 builder: &Builder<'_>,
2387 sysroot_dst: &Path,
2388 sysroot_host_dst: &Path,
2389 stamp: &BuildStamp,
2390) {
2391 let self_contained_dst = &sysroot_dst.join("self-contained");
2392 t!(fs::create_dir_all(sysroot_dst));
2393 t!(fs::create_dir_all(sysroot_host_dst));
2394 t!(fs::create_dir_all(self_contained_dst));
2395 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2396 let dst = match dependency_type {
2397 DependencyType::Host => sysroot_host_dst,
2398 DependencyType::Target => sysroot_dst,
2399 DependencyType::TargetSelfContained => self_contained_dst,
2400 };
2401 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2402 }
2403}
2404
2405pub fn run_cargo(
2406 builder: &Builder<'_>,
2407 cargo: Cargo,
2408 tail_args: Vec<String>,
2409 stamp: &BuildStamp,
2410 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2411 is_check: bool,
2412 rlib_only_metadata: bool,
2413) -> Vec<PathBuf> {
2414 let target_root_dir = stamp.path().parent().unwrap();
2416 let target_deps_dir = target_root_dir.join("deps");
2418 let host_root_dir = target_root_dir
2420 .parent()
2421 .unwrap() .parent()
2423 .unwrap() .join(target_root_dir.file_name().unwrap());
2425
2426 let mut deps = Vec::new();
2430 let mut toplevel = Vec::new();
2431 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2432 let (filenames_vec, crate_types) = match msg {
2433 CargoMessage::CompilerArtifact {
2434 filenames,
2435 target: CargoTarget { crate_types },
2436 ..
2437 } => {
2438 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2439 f.sort(); (f, crate_types)
2441 }
2442 _ => return,
2443 };
2444 for filename in filenames_vec {
2445 let mut keep = false;
2447 if filename.ends_with(".lib")
2448 || filename.ends_with(".a")
2449 || is_debug_info(&filename)
2450 || is_dylib(Path::new(&*filename))
2451 {
2452 keep = true;
2454 }
2455 if is_check && filename.ends_with(".rmeta") {
2456 keep = true;
2458 } else if rlib_only_metadata {
2459 if filename.contains("jemalloc_sys")
2460 || filename.contains("rustc_public_bridge")
2461 || filename.contains("rustc_public")
2462 {
2463 keep |= filename.ends_with(".rlib");
2466 } else {
2467 keep |= filename.ends_with(".rmeta");
2471 }
2472 } else {
2473 keep |= filename.ends_with(".rlib");
2475 }
2476
2477 if !keep {
2478 continue;
2479 }
2480
2481 let filename = Path::new(&*filename);
2482
2483 if filename.starts_with(&host_root_dir) {
2486 if crate_types.iter().any(|t| t == "proc-macro") {
2488 deps.push((filename.to_path_buf(), DependencyType::Host));
2489 }
2490 continue;
2491 }
2492
2493 if filename.starts_with(&target_deps_dir) {
2496 deps.push((filename.to_path_buf(), DependencyType::Target));
2497 continue;
2498 }
2499
2500 let expected_len = t!(filename.metadata()).len();
2511 let filename = filename.file_name().unwrap().to_str().unwrap();
2512 let mut parts = filename.splitn(2, '.');
2513 let file_stem = parts.next().unwrap().to_owned();
2514 let extension = parts.next().unwrap().to_owned();
2515
2516 toplevel.push((file_stem, extension, expected_len));
2517 }
2518 });
2519
2520 if !ok {
2521 crate::exit!(1);
2522 }
2523
2524 if builder.config.dry_run() {
2525 return Vec::new();
2526 }
2527
2528 let contents = target_deps_dir
2532 .read_dir()
2533 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2534 .map(|e| t!(e))
2535 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2536 .collect::<Vec<_>>();
2537 for (prefix, extension, expected_len) in toplevel {
2538 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2539 meta.len() == expected_len
2540 && filename
2541 .strip_prefix(&prefix[..])
2542 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2543 .unwrap_or(false)
2544 });
2545 let max = candidates.max_by_key(|&(_, _, metadata)| {
2546 metadata.modified().expect("mtime should be available on all relevant OSes")
2547 });
2548 let path_to_add = match max {
2549 Some(triple) => triple.0.to_str().unwrap(),
2550 None => panic!("no output generated for {prefix:?} {extension:?}"),
2551 };
2552 if is_dylib(Path::new(path_to_add)) {
2553 let candidate = format!("{path_to_add}.lib");
2554 let candidate = PathBuf::from(candidate);
2555 if candidate.exists() {
2556 deps.push((candidate, DependencyType::Target));
2557 }
2558 }
2559 deps.push((path_to_add.into(), DependencyType::Target));
2560 }
2561
2562 deps.extend(additional_target_deps);
2563 deps.sort();
2564 let mut new_contents = Vec::new();
2565 for (dep, dependency_type) in deps.iter() {
2566 new_contents.extend(match *dependency_type {
2567 DependencyType::Host => b"h",
2568 DependencyType::Target => b"t",
2569 DependencyType::TargetSelfContained => b"s",
2570 });
2571 new_contents.extend(dep.to_str().unwrap().as_bytes());
2572 new_contents.extend(b"\0");
2573 }
2574 t!(fs::write(stamp.path(), &new_contents));
2575 deps.into_iter().map(|(d, _)| d).collect()
2576}
2577
2578pub fn stream_cargo(
2579 builder: &Builder<'_>,
2580 cargo: Cargo,
2581 tail_args: Vec<String>,
2582 cb: &mut dyn FnMut(CargoMessage<'_>),
2583) -> bool {
2584 let mut cmd = cargo.into_cmd();
2585
2586 let mut message_format = if builder.config.json_output {
2589 String::from("json")
2590 } else {
2591 String::from("json-render-diagnostics")
2592 };
2593 if let Some(s) = &builder.config.rustc_error_format {
2594 message_format.push_str(",json-diagnostic-");
2595 message_format.push_str(s);
2596 }
2597 cmd.arg("--message-format").arg(message_format);
2598
2599 for arg in tail_args {
2600 cmd.arg(arg);
2601 }
2602
2603 builder.verbose(|| println!("running: {cmd:?}"));
2604
2605 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2606
2607 let Some(mut streaming_command) = streaming_command else {
2608 return true;
2609 };
2610
2611 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2615 for line in stdout.lines() {
2616 let line = t!(line);
2617 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2618 Ok(msg) => {
2619 if builder.config.json_output {
2620 println!("{line}");
2622 }
2623 cb(msg)
2624 }
2625 Err(_) => println!("{line}"),
2627 }
2628 }
2629
2630 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2632 if builder.is_verbose() && !status.success() {
2633 eprintln!(
2634 "command did not execute successfully: {cmd:?}\n\
2635 expected success, got: {status}"
2636 );
2637 }
2638
2639 status.success()
2640}
2641
2642#[derive(Deserialize)]
2643pub struct CargoTarget<'a> {
2644 crate_types: Vec<Cow<'a, str>>,
2645}
2646
2647#[derive(Deserialize)]
2648#[serde(tag = "reason", rename_all = "kebab-case")]
2649pub enum CargoMessage<'a> {
2650 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2651 BuildScriptExecuted,
2652 BuildFinished,
2653}
2654
2655pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2656 if target != "x86_64-unknown-linux-gnu"
2660 || !builder.config.is_host_target(target)
2661 || !path.exists()
2662 {
2663 return;
2664 }
2665
2666 let previous_mtime = t!(t!(path.metadata()).modified());
2667 let stamp = BuildStamp::new(path.parent().unwrap())
2668 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2669 .with_prefix("strip")
2670 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2671
2672 if !stamp.is_up_to_date() {
2675 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2676 }
2677 t!(stamp.write());
2678
2679 let file = t!(fs::File::open(path));
2680
2681 t!(file.set_modified(previous_mtime));
2694}
2695
2696pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2698 build_compiler.stage != 0
2699}