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)
1390 && target.starts_with("aarch64")
1391 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1392 {
1393 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1394 }
1395}
1396
1397fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1403 if builder.config.is_rust_llvm(target) {
1404 cargo.env("LLVM_RUSTLLVM", "1");
1405 }
1406 if builder.config.llvm_enzyme {
1407 cargo.env("LLVM_ENZYME", "1");
1408 }
1409 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1410 cargo.env("LLVM_CONFIG", &host_llvm_config);
1411
1412 let mut llvm_linker_flags = String::new();
1422 if builder.config.llvm_profile_generate
1423 && target.is_msvc()
1424 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1425 {
1426 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1428 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1429 }
1430
1431 if let Some(ref s) = builder.config.llvm_ldflags {
1433 if !llvm_linker_flags.is_empty() {
1434 llvm_linker_flags.push(' ');
1435 }
1436 llvm_linker_flags.push_str(s);
1437 }
1438
1439 if !llvm_linker_flags.is_empty() {
1441 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1442 }
1443
1444 if builder.config.llvm_static_stdcpp
1447 && !target.contains("freebsd")
1448 && !target.is_msvc()
1449 && !target.contains("apple")
1450 && !target.contains("solaris")
1451 {
1452 let libstdcxx_name =
1453 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1454 let file = compiler_file(
1455 builder,
1456 &builder.cxx(target).unwrap(),
1457 target,
1458 CLang::Cxx,
1459 libstdcxx_name,
1460 );
1461 cargo.env("LLVM_STATIC_STDCPP", file);
1462 }
1463 if builder.llvm_link_shared() {
1464 cargo.env("LLVM_LINK_SHARED", "1");
1465 }
1466 if builder.config.llvm_use_libcxx {
1467 cargo.env("LLVM_USE_LIBCXX", "1");
1468 }
1469 if builder.config.llvm_assertions {
1470 cargo.env("LLVM_ASSERTIONS", "1");
1471 }
1472}
1473
1474#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1487struct RustcLink {
1488 build_compiler: Compiler,
1490 sysroot_compiler: Compiler,
1493 target: TargetSelection,
1494 crates: Vec<String>,
1496}
1497
1498impl RustcLink {
1499 fn from_rustc(rustc: Rustc) -> Self {
1502 Self {
1503 build_compiler: rustc.build_compiler,
1504 sysroot_compiler: rustc.build_compiler,
1505 target: rustc.target,
1506 crates: rustc.crates,
1507 }
1508 }
1509
1510 fn from_build_compiler_and_sysroot(
1512 build_compiler: Compiler,
1513 sysroot_compiler: Compiler,
1514 target: TargetSelection,
1515 crates: Vec<String>,
1516 ) -> Self {
1517 Self { build_compiler, sysroot_compiler, target, crates }
1518 }
1519}
1520
1521impl Step for RustcLink {
1522 type Output = ();
1523
1524 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1525 run.never()
1526 }
1527
1528 fn run(self, builder: &Builder<'_>) {
1530 let build_compiler = self.build_compiler;
1531 let sysroot_compiler = self.sysroot_compiler;
1532 let target = self.target;
1533 add_to_sysroot(
1534 builder,
1535 &builder.sysroot_target_libdir(sysroot_compiler, target),
1536 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1537 &build_stamp::librustc_stamp(builder, build_compiler, target),
1538 );
1539 }
1540}
1541
1542#[derive(Clone)]
1545pub struct GccCodegenBackendOutput {
1546 stamp: BuildStamp,
1547 gcc: GccOutput,
1548}
1549
1550#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1551pub struct GccCodegenBackend {
1552 compilers: RustcPrivateCompilers,
1553}
1554
1555impl Step for GccCodegenBackend {
1556 type Output = GccCodegenBackendOutput;
1557
1558 const IS_HOST: bool = true;
1559
1560 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1561 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1562 }
1563
1564 fn make_run(run: RunConfig<'_>) {
1565 run.builder.ensure(GccCodegenBackend {
1566 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1567 });
1568 }
1569
1570 fn run(self, builder: &Builder<'_>) -> Self::Output {
1571 let target = self.compilers.target();
1572 let build_compiler = self.compilers.build_compiler();
1573
1574 let stamp = build_stamp::codegen_backend_stamp(
1575 builder,
1576 build_compiler,
1577 target,
1578 &CodegenBackendKind::Gcc,
1579 );
1580
1581 let gcc = builder.ensure(Gcc { target });
1582
1583 if builder.config.keep_stage.contains(&build_compiler.stage) {
1584 trace!("`keep-stage` requested");
1585 builder.info(
1586 "WARNING: Using a potentially old codegen backend. \
1587 This may not behave well.",
1588 );
1589 return GccCodegenBackendOutput { stamp, gcc };
1592 }
1593
1594 let mut cargo = builder::Cargo::new(
1595 builder,
1596 build_compiler,
1597 Mode::Codegen,
1598 SourceType::InTree,
1599 target,
1600 Kind::Build,
1601 );
1602 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1603 rustc_cargo_env(builder, &mut cargo, target);
1604
1605 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1606
1607 let _guard =
1608 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1609 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1610
1611 GccCodegenBackendOutput {
1612 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1613 gcc,
1614 }
1615 }
1616
1617 fn metadata(&self) -> Option<StepMetadata> {
1618 Some(
1619 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1620 .built_by(self.compilers.build_compiler()),
1621 )
1622 }
1623}
1624
1625#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1626pub struct CraneliftCodegenBackend {
1627 pub compilers: RustcPrivateCompilers,
1628}
1629
1630impl Step for CraneliftCodegenBackend {
1631 type Output = BuildStamp;
1632 const IS_HOST: bool = true;
1633
1634 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1635 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1636 }
1637
1638 fn make_run(run: RunConfig<'_>) {
1639 run.builder.ensure(CraneliftCodegenBackend {
1640 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1641 });
1642 }
1643
1644 fn run(self, builder: &Builder<'_>) -> Self::Output {
1645 let target = self.compilers.target();
1646 let build_compiler = self.compilers.build_compiler();
1647
1648 let stamp = build_stamp::codegen_backend_stamp(
1649 builder,
1650 build_compiler,
1651 target,
1652 &CodegenBackendKind::Cranelift,
1653 );
1654
1655 if builder.config.keep_stage.contains(&build_compiler.stage) {
1656 trace!("`keep-stage` requested");
1657 builder.info(
1658 "WARNING: Using a potentially old codegen backend. \
1659 This may not behave well.",
1660 );
1661 return stamp;
1664 }
1665
1666 let mut cargo = builder::Cargo::new(
1667 builder,
1668 build_compiler,
1669 Mode::Codegen,
1670 SourceType::InTree,
1671 target,
1672 Kind::Build,
1673 );
1674 cargo
1675 .arg("--manifest-path")
1676 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1677 rustc_cargo_env(builder, &mut cargo, target);
1678
1679 let _guard = builder.msg(
1680 Kind::Build,
1681 "codegen backend cranelift",
1682 Mode::Codegen,
1683 build_compiler,
1684 target,
1685 );
1686 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1687 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1688 }
1689
1690 fn metadata(&self) -> Option<StepMetadata> {
1691 Some(
1692 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1693 .built_by(self.compilers.build_compiler()),
1694 )
1695 }
1696}
1697
1698fn write_codegen_backend_stamp(
1700 mut stamp: BuildStamp,
1701 files: Vec<PathBuf>,
1702 dry_run: bool,
1703) -> BuildStamp {
1704 if dry_run {
1705 return stamp;
1706 }
1707
1708 let mut files = files.into_iter().filter(|f| {
1709 let filename = f.file_name().unwrap().to_str().unwrap();
1710 is_dylib(f) && filename.contains("rustc_codegen_")
1711 });
1712 let codegen_backend = match files.next() {
1713 Some(f) => f,
1714 None => panic!("no dylibs built for codegen backend?"),
1715 };
1716 if let Some(f) = files.next() {
1717 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1718 }
1719
1720 let codegen_backend = codegen_backend.to_str().unwrap();
1721 stamp = stamp.add_stamp(codegen_backend);
1722 t!(stamp.write());
1723 stamp
1724}
1725
1726fn copy_codegen_backends_to_sysroot(
1733 builder: &Builder<'_>,
1734 stamp: BuildStamp,
1735 target_compiler: Compiler,
1736) {
1737 let dst = builder.sysroot_codegen_backends(target_compiler);
1746 t!(fs::create_dir_all(&dst), dst);
1747
1748 if builder.config.dry_run() {
1749 return;
1750 }
1751
1752 if stamp.path().exists() {
1753 let file = get_codegen_backend_file(&stamp);
1754 builder.copy_link(
1755 &file,
1756 &dst.join(normalize_codegen_backend_name(builder, &file)),
1757 FileType::NativeLibrary,
1758 );
1759 }
1760}
1761
1762pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1764 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1765}
1766
1767pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1769 let filename = path.file_name().unwrap().to_str().unwrap();
1770 let dash = filename.find('-').unwrap();
1773 let dot = filename.find('.').unwrap();
1774 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1775}
1776
1777pub fn compiler_file(
1778 builder: &Builder<'_>,
1779 compiler: &Path,
1780 target: TargetSelection,
1781 c: CLang,
1782 file: &str,
1783) -> PathBuf {
1784 if builder.config.dry_run() {
1785 return PathBuf::new();
1786 }
1787 let mut cmd = command(compiler);
1788 cmd.args(builder.cc_handled_clags(target, c));
1789 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1790 cmd.arg(format!("-print-file-name={file}"));
1791 let out = cmd.run_capture_stdout(builder).stdout();
1792 PathBuf::from(out.trim())
1793}
1794
1795#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1796pub struct Sysroot {
1797 pub compiler: Compiler,
1798 force_recompile: bool,
1800}
1801
1802impl Sysroot {
1803 pub(crate) fn new(compiler: Compiler) -> Self {
1804 Sysroot { compiler, force_recompile: false }
1805 }
1806}
1807
1808impl Step for Sysroot {
1809 type Output = PathBuf;
1810
1811 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1812 run.never()
1813 }
1814
1815 fn run(self, builder: &Builder<'_>) -> PathBuf {
1819 let compiler = self.compiler;
1820 let host_dir = builder.out.join(compiler.host);
1821
1822 let sysroot_dir = |stage| {
1823 if stage == 0 {
1824 host_dir.join("stage0-sysroot")
1825 } else if self.force_recompile && stage == compiler.stage {
1826 host_dir.join(format!("stage{stage}-test-sysroot"))
1827 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1828 host_dir.join("ci-rustc-sysroot")
1829 } else {
1830 host_dir.join(format!("stage{stage}"))
1831 }
1832 };
1833 let sysroot = sysroot_dir(compiler.stage);
1834 trace!(stage = ?compiler.stage, ?sysroot);
1835
1836 builder
1837 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1838 let _ = fs::remove_dir_all(&sysroot);
1839 t!(fs::create_dir_all(&sysroot));
1840
1841 if compiler.stage == 0 {
1848 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1849 }
1850
1851 if builder.download_rustc() && compiler.stage != 0 {
1853 assert_eq!(
1854 builder.config.host_target, compiler.host,
1855 "Cross-compiling is not yet supported with `download-rustc`",
1856 );
1857
1858 for stage in 0..=2 {
1860 if stage != compiler.stage {
1861 let dir = sysroot_dir(stage);
1862 if !dir.ends_with("ci-rustc-sysroot") {
1863 let _ = fs::remove_dir_all(dir);
1864 }
1865 }
1866 }
1867
1868 let mut filtered_files = Vec::new();
1878 let mut add_filtered_files = |suffix, contents| {
1879 for path in contents {
1880 let path = Path::new(&path);
1881 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1882 filtered_files.push(path.file_name().unwrap().to_owned());
1883 }
1884 }
1885 };
1886 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1887 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1888 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1891
1892 let filtered_extensions = [
1893 OsStr::new("rmeta"),
1894 OsStr::new("rlib"),
1895 OsStr::new(std::env::consts::DLL_EXTENSION),
1897 ];
1898 let ci_rustc_dir = builder.config.ci_rustc_dir();
1899 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1900 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1901 return true;
1902 }
1903 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1904 return true;
1905 }
1906 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1907 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1908 false
1909 } else {
1910 true
1911 }
1912 });
1913 }
1914
1915 if compiler.stage != 0 {
1921 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1922 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1923 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1924 if let Err(e) =
1925 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1926 {
1927 eprintln!(
1928 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1929 sysroot_lib_rustlib_src_rust.display(),
1930 builder.src.display(),
1931 e,
1932 );
1933 if builder.config.rust_remap_debuginfo {
1934 eprintln!(
1935 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1936 sysroot_lib_rustlib_src_rust.display(),
1937 );
1938 }
1939 build_helper::exit!(1);
1940 }
1941 }
1942
1943 if !builder.download_rustc() {
1945 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1946 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1947 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1948 if let Err(e) =
1949 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1950 {
1951 eprintln!(
1952 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1953 sysroot_lib_rustlib_rustcsrc_rust.display(),
1954 builder.src.display(),
1955 e,
1956 );
1957 build_helper::exit!(1);
1958 }
1959 }
1960
1961 sysroot
1962 }
1963}
1964
1965#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1972pub struct Assemble {
1973 pub target_compiler: Compiler,
1978}
1979
1980impl Step for Assemble {
1981 type Output = Compiler;
1982 const IS_HOST: bool = true;
1983
1984 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1985 run.path("compiler/rustc").path("compiler")
1986 }
1987
1988 fn make_run(run: RunConfig<'_>) {
1989 run.builder.ensure(Assemble {
1990 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1991 });
1992 }
1993
1994 fn run(self, builder: &Builder<'_>) -> Compiler {
1995 let target_compiler = self.target_compiler;
1996
1997 if target_compiler.stage == 0 {
1998 trace!("stage 0 build compiler is always available, simply returning");
1999 assert_eq!(
2000 builder.config.host_target, target_compiler.host,
2001 "Cannot obtain compiler for non-native build triple at stage 0"
2002 );
2003 return target_compiler;
2005 }
2006
2007 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2010 let libdir_bin = libdir.parent().unwrap().join("bin");
2011 t!(fs::create_dir_all(&libdir_bin));
2012
2013 if builder.config.llvm_enabled(target_compiler.host) {
2014 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2015
2016 let target = target_compiler.host;
2017 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2018 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2019 trace!("LLVM tools enabled");
2020
2021 let host_llvm_bin_dir = command(&host_llvm_config)
2022 .arg("--bindir")
2023 .cached()
2024 .run_capture_stdout(builder)
2025 .stdout()
2026 .trim()
2027 .to_string();
2028
2029 let llvm_bin_dir = if target == builder.host_target {
2030 PathBuf::from(host_llvm_bin_dir)
2031 } else {
2032 let external_llvm_config = builder
2035 .config
2036 .target_config
2037 .get(&target)
2038 .and_then(|t| t.llvm_config.clone());
2039 if let Some(external_llvm_config) = external_llvm_config {
2040 external_llvm_config.parent().unwrap().to_path_buf()
2043 } else {
2044 let host_llvm_out = builder.llvm_out(builder.host_target);
2048 let target_llvm_out = builder.llvm_out(target);
2049 if let Ok(relative_path) =
2050 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2051 {
2052 target_llvm_out.join(relative_path)
2053 } else {
2054 PathBuf::from(
2057 host_llvm_bin_dir
2058 .replace(&*builder.host_target.triple, &target.triple),
2059 )
2060 }
2061 }
2062 };
2063
2064 #[cfg(feature = "tracing")]
2071 let _llvm_tools_span =
2072 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2073 .entered();
2074 for tool in LLVM_TOOLS {
2075 trace!("installing `{tool}`");
2076 let tool_exe = exe(tool, target_compiler.host);
2077 let src_path = llvm_bin_dir.join(&tool_exe);
2078
2079 if !src_path.exists() && builder.config.llvm_from_ci {
2081 eprintln!("{} does not exist; skipping copy", src_path.display());
2082 continue;
2083 }
2084
2085 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2092 }
2093 }
2094 }
2095
2096 let maybe_install_llvm_bitcode_linker = || {
2097 if builder.config.llvm_bitcode_linker_enabled {
2098 trace!("llvm-bitcode-linker enabled, installing");
2099 let llvm_bitcode_linker = builder.ensure(
2100 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2101 builder,
2102 target_compiler,
2103 ),
2104 );
2105
2106 let bindir_self_contained = builder
2108 .sysroot(target_compiler)
2109 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2110 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2111
2112 t!(fs::create_dir_all(&bindir_self_contained));
2113 builder.copy_link(
2114 &llvm_bitcode_linker.tool_path,
2115 &bindir_self_contained.join(tool_exe),
2116 FileType::Executable,
2117 );
2118 }
2119 };
2120
2121 if builder.download_rustc() {
2123 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2124
2125 builder.std(target_compiler, target_compiler.host);
2126 let sysroot =
2127 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2128 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2131 if target_compiler.stage == builder.top_stage {
2133 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2134 }
2135
2136 maybe_install_llvm_bitcode_linker();
2139
2140 return target_compiler;
2141 }
2142
2143 debug!(
2157 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2158 target_compiler.stage - 1,
2159 builder.config.host_target,
2160 );
2161 let build_compiler =
2162 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2163
2164 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2166 debug!("`llvm_enzyme` requested");
2167 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2168 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2169 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2170 let lib_ext = std::env::consts::DLL_EXTENSION;
2171 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2172 let src_lib =
2173 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2174 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2175 let target_libdir =
2176 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2177 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2178 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2179 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2180 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2181 }
2182 }
2183
2184 debug!(
2187 ?build_compiler,
2188 "target_compiler.host" = ?target_compiler.host,
2189 "building compiler libraries to link to"
2190 );
2191
2192 let BuiltRustc { build_compiler } =
2194 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2195
2196 let stage = target_compiler.stage;
2197 let host = target_compiler.host;
2198 let (host_info, dir_name) = if build_compiler.host == host {
2199 ("".into(), "host".into())
2200 } else {
2201 (format!(" ({host})"), host.to_string())
2202 };
2203 let msg = format!(
2208 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2209 );
2210 builder.info(&msg);
2211
2212 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2214 let proc_macros = builder
2215 .read_stamp_file(&stamp)
2216 .into_iter()
2217 .filter_map(|(path, dependency_type)| {
2218 if dependency_type == DependencyType::Host {
2219 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2220 } else {
2221 None
2222 }
2223 })
2224 .collect::<HashSet<_>>();
2225
2226 let sysroot = builder.sysroot(target_compiler);
2227 let rustc_libdir = builder.rustc_libdir(target_compiler);
2228 t!(fs::create_dir_all(&rustc_libdir));
2229 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2230 for f in builder.read_dir(&src_libdir) {
2231 let filename = f.file_name().into_string().unwrap();
2232
2233 let is_proc_macro = proc_macros.contains(&filename);
2234 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2235
2236 let can_be_rustc_dynamic_dep = if builder
2240 .link_std_into_rustc_driver(target_compiler.host)
2241 && !target_compiler.host.is_windows()
2242 {
2243 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2244 !is_std
2245 } else {
2246 true
2247 };
2248
2249 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2250 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2251 }
2252 }
2253
2254 {
2255 #[cfg(feature = "tracing")]
2256 let _codegen_backend_span =
2257 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2258
2259 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2260 if builder.kind == Kind::Check && builder.top_stage == 1 {
2277 continue;
2278 }
2279
2280 let prepare_compilers = || {
2281 RustcPrivateCompilers::from_build_and_target_compiler(
2282 build_compiler,
2283 target_compiler,
2284 )
2285 };
2286
2287 match backend {
2288 CodegenBackendKind::Cranelift => {
2289 let stamp = builder
2290 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2291 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2292 }
2293 CodegenBackendKind::Gcc => {
2294 let output =
2295 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2296 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2297 output.gcc.install_to(builder, &rustc_libdir);
2300 }
2301 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2302 }
2303 }
2304 }
2305
2306 if builder.config.lld_enabled {
2307 let lld_wrapper =
2308 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2309 builder,
2310 target_compiler,
2311 ));
2312 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2313 }
2314
2315 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2316 debug!(
2317 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2318 workaround faulty homebrew `strip`s"
2319 );
2320
2321 let src_exe = exe("llvm-objcopy", target_compiler.host);
2328 let dst_exe = exe("rust-objcopy", target_compiler.host);
2329 builder.copy_link(
2330 &libdir_bin.join(src_exe),
2331 &libdir_bin.join(dst_exe),
2332 FileType::Executable,
2333 );
2334 }
2335
2336 if builder.tool_enabled("wasm-component-ld") {
2339 let wasm_component = builder.ensure(
2340 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2341 builder,
2342 target_compiler,
2343 ),
2344 );
2345 builder.copy_link(
2346 &wasm_component.tool_path,
2347 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2348 FileType::Executable,
2349 );
2350 }
2351
2352 maybe_install_llvm_bitcode_linker();
2353
2354 debug!(
2357 "target_compiler.host" = ?target_compiler.host,
2358 ?sysroot,
2359 "ensuring availability of `libLLVM.so` in compiler directory"
2360 );
2361 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2362 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2363
2364 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2366 let rustc = out_dir.join(exe("rustc-main", host));
2367 let bindir = sysroot.join("bin");
2368 t!(fs::create_dir_all(bindir));
2369 let compiler = builder.rustc(target_compiler);
2370 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2371 builder.copy_link(&rustc, &compiler, FileType::Executable);
2372
2373 target_compiler
2374 }
2375}
2376
2377#[track_caller]
2382pub fn add_to_sysroot(
2383 builder: &Builder<'_>,
2384 sysroot_dst: &Path,
2385 sysroot_host_dst: &Path,
2386 stamp: &BuildStamp,
2387) {
2388 let self_contained_dst = &sysroot_dst.join("self-contained");
2389 t!(fs::create_dir_all(sysroot_dst));
2390 t!(fs::create_dir_all(sysroot_host_dst));
2391 t!(fs::create_dir_all(self_contained_dst));
2392 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2393 let dst = match dependency_type {
2394 DependencyType::Host => sysroot_host_dst,
2395 DependencyType::Target => sysroot_dst,
2396 DependencyType::TargetSelfContained => self_contained_dst,
2397 };
2398 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2399 }
2400}
2401
2402pub fn run_cargo(
2403 builder: &Builder<'_>,
2404 cargo: Cargo,
2405 tail_args: Vec<String>,
2406 stamp: &BuildStamp,
2407 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2408 is_check: bool,
2409 rlib_only_metadata: bool,
2410) -> Vec<PathBuf> {
2411 let target_root_dir = stamp.path().parent().unwrap();
2413 let target_deps_dir = target_root_dir.join("deps");
2415 let host_root_dir = target_root_dir
2417 .parent()
2418 .unwrap() .parent()
2420 .unwrap() .join(target_root_dir.file_name().unwrap());
2422
2423 let mut deps = Vec::new();
2427 let mut toplevel = Vec::new();
2428 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2429 let (filenames_vec, crate_types) = match msg {
2430 CargoMessage::CompilerArtifact {
2431 filenames,
2432 target: CargoTarget { crate_types },
2433 ..
2434 } => {
2435 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2436 f.sort(); (f, crate_types)
2438 }
2439 _ => return,
2440 };
2441 for filename in filenames_vec {
2442 let mut keep = false;
2444 if filename.ends_with(".lib")
2445 || filename.ends_with(".a")
2446 || is_debug_info(&filename)
2447 || is_dylib(Path::new(&*filename))
2448 {
2449 keep = true;
2451 }
2452 if is_check && filename.ends_with(".rmeta") {
2453 keep = true;
2455 } else if rlib_only_metadata {
2456 if filename.contains("jemalloc_sys")
2457 || filename.contains("rustc_public_bridge")
2458 || filename.contains("rustc_public")
2459 {
2460 keep |= filename.ends_with(".rlib");
2463 } else {
2464 keep |= filename.ends_with(".rmeta");
2468 }
2469 } else {
2470 keep |= filename.ends_with(".rlib");
2472 }
2473
2474 if !keep {
2475 continue;
2476 }
2477
2478 let filename = Path::new(&*filename);
2479
2480 if filename.starts_with(&host_root_dir) {
2483 if crate_types.iter().any(|t| t == "proc-macro") {
2485 deps.push((filename.to_path_buf(), DependencyType::Host));
2486 }
2487 continue;
2488 }
2489
2490 if filename.starts_with(&target_deps_dir) {
2493 deps.push((filename.to_path_buf(), DependencyType::Target));
2494 continue;
2495 }
2496
2497 let expected_len = t!(filename.metadata()).len();
2508 let filename = filename.file_name().unwrap().to_str().unwrap();
2509 let mut parts = filename.splitn(2, '.');
2510 let file_stem = parts.next().unwrap().to_owned();
2511 let extension = parts.next().unwrap().to_owned();
2512
2513 toplevel.push((file_stem, extension, expected_len));
2514 }
2515 });
2516
2517 if !ok {
2518 crate::exit!(1);
2519 }
2520
2521 if builder.config.dry_run() {
2522 return Vec::new();
2523 }
2524
2525 let contents = target_deps_dir
2529 .read_dir()
2530 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2531 .map(|e| t!(e))
2532 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2533 .collect::<Vec<_>>();
2534 for (prefix, extension, expected_len) in toplevel {
2535 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2536 meta.len() == expected_len
2537 && filename
2538 .strip_prefix(&prefix[..])
2539 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2540 .unwrap_or(false)
2541 });
2542 let max = candidates.max_by_key(|&(_, _, metadata)| {
2543 metadata.modified().expect("mtime should be available on all relevant OSes")
2544 });
2545 let path_to_add = match max {
2546 Some(triple) => triple.0.to_str().unwrap(),
2547 None => panic!("no output generated for {prefix:?} {extension:?}"),
2548 };
2549 if is_dylib(Path::new(path_to_add)) {
2550 let candidate = format!("{path_to_add}.lib");
2551 let candidate = PathBuf::from(candidate);
2552 if candidate.exists() {
2553 deps.push((candidate, DependencyType::Target));
2554 }
2555 }
2556 deps.push((path_to_add.into(), DependencyType::Target));
2557 }
2558
2559 deps.extend(additional_target_deps);
2560 deps.sort();
2561 let mut new_contents = Vec::new();
2562 for (dep, dependency_type) in deps.iter() {
2563 new_contents.extend(match *dependency_type {
2564 DependencyType::Host => b"h",
2565 DependencyType::Target => b"t",
2566 DependencyType::TargetSelfContained => b"s",
2567 });
2568 new_contents.extend(dep.to_str().unwrap().as_bytes());
2569 new_contents.extend(b"\0");
2570 }
2571 t!(fs::write(stamp.path(), &new_contents));
2572 deps.into_iter().map(|(d, _)| d).collect()
2573}
2574
2575pub fn stream_cargo(
2576 builder: &Builder<'_>,
2577 cargo: Cargo,
2578 tail_args: Vec<String>,
2579 cb: &mut dyn FnMut(CargoMessage<'_>),
2580) -> bool {
2581 let mut cmd = cargo.into_cmd();
2582
2583 let mut message_format = if builder.config.json_output {
2586 String::from("json")
2587 } else {
2588 String::from("json-render-diagnostics")
2589 };
2590 if let Some(s) = &builder.config.rustc_error_format {
2591 message_format.push_str(",json-diagnostic-");
2592 message_format.push_str(s);
2593 }
2594 cmd.arg("--message-format").arg(message_format);
2595
2596 for arg in tail_args {
2597 cmd.arg(arg);
2598 }
2599
2600 builder.verbose(|| println!("running: {cmd:?}"));
2601
2602 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2603
2604 let Some(mut streaming_command) = streaming_command else {
2605 return true;
2606 };
2607
2608 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2612 for line in stdout.lines() {
2613 let line = t!(line);
2614 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2615 Ok(msg) => {
2616 if builder.config.json_output {
2617 println!("{line}");
2619 }
2620 cb(msg)
2621 }
2622 Err(_) => println!("{line}"),
2624 }
2625 }
2626
2627 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2629 if builder.is_verbose() && !status.success() {
2630 eprintln!(
2631 "command did not execute successfully: {cmd:?}\n\
2632 expected success, got: {status}"
2633 );
2634 }
2635
2636 status.success()
2637}
2638
2639#[derive(Deserialize)]
2640pub struct CargoTarget<'a> {
2641 crate_types: Vec<Cow<'a, str>>,
2642}
2643
2644#[derive(Deserialize)]
2645#[serde(tag = "reason", rename_all = "kebab-case")]
2646pub enum CargoMessage<'a> {
2647 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2648 BuildScriptExecuted,
2649 BuildFinished,
2650}
2651
2652pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2653 if target != "x86_64-unknown-linux-gnu"
2657 || !builder.config.is_host_target(target)
2658 || !path.exists()
2659 {
2660 return;
2661 }
2662
2663 let previous_mtime = t!(t!(path.metadata()).modified());
2664 let stamp = BuildStamp::new(path.parent().unwrap())
2665 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2666 .with_prefix("strip")
2667 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2668
2669 if !stamp.is_up_to_date() {
2672 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2673 }
2674 t!(stamp.write());
2675
2676 let file = t!(fs::File::open(path));
2677
2678 t!(file.set_modified(previous_mtime));
2691}
2692
2693pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2695 build_compiler.stage != 0
2696}