1use std::borrow::Cow;
10use std::collections::{BTreeMap, HashMap, 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, GccTargetPair, 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::toml::target::DefaultLinuxLinkerOverride;
30use crate::core::config::{
31 CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
32};
33use crate::utils::build_stamp;
34use crate::utils::build_stamp::BuildStamp;
35use crate::utils::exec::command;
36use crate::utils::helpers::{
37 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
38};
39use crate::{
40 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
41 debug, trace,
42};
43
44#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub struct Std {
47 pub target: TargetSelection,
48 pub build_compiler: Compiler,
50 crates: Vec<String>,
54 force_recompile: bool,
57 extra_rust_args: &'static [&'static str],
58 is_for_mir_opt_tests: bool,
59}
60
61impl Std {
62 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
63 Self {
64 target,
65 build_compiler,
66 crates: Default::default(),
67 force_recompile: false,
68 extra_rust_args: &[],
69 is_for_mir_opt_tests: false,
70 }
71 }
72
73 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
74 self.force_recompile = force_recompile;
75 self
76 }
77
78 #[expect(clippy::wrong_self_convention)]
79 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
80 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
81 self
82 }
83
84 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
85 self.extra_rust_args = extra_rust_args;
86 self
87 }
88
89 fn copy_extra_objects(
90 &self,
91 builder: &Builder<'_>,
92 compiler: &Compiler,
93 target: TargetSelection,
94 ) -> Vec<(PathBuf, DependencyType)> {
95 let mut deps = Vec::new();
96 if !self.is_for_mir_opt_tests {
97 deps.extend(copy_third_party_objects(builder, compiler, target));
98 deps.extend(copy_self_contained_objects(builder, compiler, target));
99 }
100 deps
101 }
102
103 pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool {
108 stage > 1 && !builder.config.full_bootstrap
109 }
110}
111
112impl Step for Std {
113 type Output = Option<BuildStamp>;
115
116 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
117 run.crate_or_deps("sysroot").path("library")
118 }
119
120 fn is_default_step(_builder: &Builder<'_>) -> bool {
121 true
122 }
123
124 fn make_run(run: RunConfig<'_>) {
125 let crates = std_crates_for_run_make(&run);
126 let builder = run.builder;
127
128 let force_recompile = builder.rust_info().is_managed_git_subrepository()
132 && builder.download_rustc()
133 && builder.config.has_changes_from_upstream(&["library"]);
134
135 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
136 trace!("download_rustc: {}", builder.download_rustc());
137 trace!(force_recompile);
138
139 run.builder.ensure(Std {
140 build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target),
143 target: run.target,
144 crates,
145 force_recompile,
146 extra_rust_args: &[],
147 is_for_mir_opt_tests: false,
148 });
149 }
150
151 fn run(self, builder: &Builder<'_>) -> Self::Output {
157 let target = self.target;
158
159 if self.build_compiler.stage == 0
164 && !(builder.local_rebuild && target != builder.host_target)
165 {
166 let compiler = self.build_compiler;
167 builder.ensure(StdLink::from_std(self, compiler));
168
169 return None;
170 }
171
172 let build_compiler = if builder.download_rustc() && self.force_recompile {
173 builder
176 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
177 } else {
178 self.build_compiler
179 };
180
181 if builder.download_rustc()
184 && builder.config.is_host_target(target)
185 && !self.force_recompile
186 {
187 let sysroot =
188 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
189 cp_rustc_component_to_ci_sysroot(
190 builder,
191 &sysroot,
192 builder.config.ci_rust_std_contents(),
193 );
194 return None;
195 }
196
197 if builder.config.keep_stage.contains(&build_compiler.stage)
198 || builder.config.keep_stage_std.contains(&build_compiler.stage)
199 {
200 trace!(keep_stage = ?builder.config.keep_stage);
201 trace!(keep_stage_std = ?builder.config.keep_stage_std);
202
203 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
204
205 builder.ensure(StartupObjects { compiler: build_compiler, target });
206
207 self.copy_extra_objects(builder, &build_compiler, target);
208
209 builder.ensure(StdLink::from_std(self, build_compiler));
210 return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
211 }
212
213 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
214
215 let stage = build_compiler.stage;
217
218 if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
219 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
220 let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
221
222 let msg = if build_compiler_for_std_to_uplift.host == target {
223 format!(
224 "Uplifting library (stage{} -> stage{stage})",
225 build_compiler_for_std_to_uplift.stage
226 )
227 } else {
228 format!(
229 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
230 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
231 )
232 };
233
234 builder.info(&msg);
235
236 self.copy_extra_objects(builder, &build_compiler, target);
239
240 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
241 return stage_1_stamp;
242 }
243
244 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
245
246 let mut cargo = if self.is_for_mir_opt_tests {
250 trace!("building special sysroot for mir-opt tests");
251 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
252 builder,
253 build_compiler,
254 Mode::Std,
255 SourceType::InTree,
256 target,
257 Kind::Check,
258 );
259 cargo.rustflag("-Zalways-encode-mir");
260 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
261 cargo
262 } else {
263 trace!("building regular sysroot");
264 let mut cargo = builder::Cargo::new(
265 builder,
266 build_compiler,
267 Mode::Std,
268 SourceType::InTree,
269 target,
270 Kind::Build,
271 );
272 std_cargo(builder, target, &mut cargo, &self.crates);
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")
358 || target.contains("fuchsia")
359 || target.contains("aix")
360 || target.contains("hexagon"))
361 {
362 let libunwind_path =
363 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
364 target_deps.push((libunwind_path, DependencyType::Target));
365 }
366
367 target_deps
368}
369
370fn copy_self_contained_objects(
372 builder: &Builder<'_>,
373 compiler: &Compiler,
374 target: TargetSelection,
375) -> Vec<(PathBuf, DependencyType)> {
376 let libdir_self_contained =
377 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
378 t!(fs::create_dir_all(&libdir_self_contained));
379 let mut target_deps = vec![];
380
381 if target.needs_crt_begin_end() {
389 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
390 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
391 });
392 if !target.starts_with("wasm32") {
393 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
394 copy_and_stamp(
395 builder,
396 &libdir_self_contained,
397 &srcdir,
398 obj,
399 &mut target_deps,
400 DependencyType::TargetSelfContained,
401 );
402 }
403 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
404 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
405 let src = crt_path.join(obj);
406 let target = libdir_self_contained.join(obj);
407 builder.copy_link(&src, &target, FileType::NativeLibrary);
408 target_deps.push((target, DependencyType::TargetSelfContained));
409 }
410 } else {
411 for &obj in &["libc.a", "crt1-command.o"] {
414 copy_and_stamp(
415 builder,
416 &libdir_self_contained,
417 &srcdir,
418 obj,
419 &mut target_deps,
420 DependencyType::TargetSelfContained,
421 );
422 }
423 }
424 if !target.starts_with("s390x") {
425 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
426 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
427 }
428 } else if target.contains("-wasi") {
429 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
430 panic!(
431 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
432 or `$WASI_SDK_PATH` set",
433 target.triple
434 )
435 });
436
437 let srcdir = if target == "wasm32-wasip3" {
441 assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now");
442 builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap()
443 } else {
444 srcdir
445 };
446 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
447 copy_and_stamp(
448 builder,
449 &libdir_self_contained,
450 &srcdir,
451 obj,
452 &mut target_deps,
453 DependencyType::TargetSelfContained,
454 );
455 }
456 } else if target.is_windows_gnu() || target.is_windows_gnullvm() {
457 for obj in ["crt2.o", "dllcrt2.o"].iter() {
458 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
459 let dst = libdir_self_contained.join(obj);
460 builder.copy_link(&src, &dst, FileType::NativeLibrary);
461 target_deps.push((dst, DependencyType::TargetSelfContained));
462 }
463 }
464
465 target_deps
466}
467
468pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
471 let mut crates = run.make_run_crates(builder::Alias::Library);
472
473 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
482 if target_is_no_std {
483 crates.retain(|c| c == "core" || c == "alloc");
484 }
485 crates
486}
487
488fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
494 if builder.config.llvm_from_ci {
496 builder.config.maybe_download_ci_llvm();
498 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
499 if ci_llvm_compiler_rt.exists() {
500 return ci_llvm_compiler_rt;
501 }
502 }
503
504 builder.require_submodule("src/llvm-project", {
506 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
507 });
508 builder.src.join("src/llvm-project/compiler-rt")
509}
510
511pub fn std_cargo(
514 builder: &Builder<'_>,
515 target: TargetSelection,
516 cargo: &mut Cargo,
517 crates: &[String],
518) {
519 if target.contains("apple") && !builder.config.dry_run() {
537 let mut cmd = builder.rustc_cmd(cargo.compiler());
541 cmd.arg("--target").arg(target.rustc_target_arg());
542 cmd.arg("--print=deployment-target");
543 let output = cmd.run_capture_stdout(builder).stdout();
544
545 let (env_var, value) = output.split_once('=').unwrap();
546 cargo.env(env_var.trim(), value.trim());
549
550 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
560 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
561 }
562 }
563
564 if let Some(path) = builder.config.profiler_path(target) {
566 cargo.env("LLVM_PROFILER_RT_LIB", path);
567 } else if builder.config.profiler_enabled(target) {
568 let compiler_rt = compiler_rt_for_profiler(builder);
569 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
573 }
574
575 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
589 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
590 cargo.env("LLVM_COMPILER_RT_LIB", path);
591 " compiler-builtins-c"
592 }
593 CompilerBuiltins::BuildLLVMFuncs => {
594 builder.require_submodule(
604 "src/llvm-project",
605 Some(
606 "The `build.optimized-compiler-builtins` config option \
607 requires `compiler-rt` sources from LLVM.",
608 ),
609 );
610 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
611 if !builder.config.dry_run() {
612 assert!(compiler_builtins_root.exists());
615 }
616
617 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
620 " compiler-builtins-c"
621 }
622 CompilerBuiltins::BuildRustOnly => "",
623 };
624
625 if !builder.unstable_features() {
628 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
629 }
630
631 for krate in crates {
632 cargo.args(["-p", krate]);
633 }
634
635 let mut features = String::new();
636
637 if builder.no_std(target) == Some(true) {
638 features += " compiler-builtins-mem";
639 if !target.starts_with("bpf") {
640 features.push_str(compiler_builtins_c_feature);
641 }
642
643 if crates.is_empty() {
645 cargo.args(["-p", "alloc"]);
646 }
647 cargo
648 .arg("--manifest-path")
649 .arg(builder.src.join("library/alloc/Cargo.toml"))
650 .arg("--features")
651 .arg(features);
652 } else {
653 features += &builder.std_features(target);
654 features.push_str(compiler_builtins_c_feature);
655
656 cargo
657 .arg("--features")
658 .arg(features)
659 .arg("--manifest-path")
660 .arg(builder.src.join("library/sysroot/Cargo.toml"));
661
662 if target.contains("musl")
665 && let Some(p) = builder.musl_libdir(target)
666 {
667 let root = format!("native={}", p.to_str().unwrap());
668 cargo.rustflag("-L").rustflag(&root);
669 }
670
671 if target.contains("-wasi")
672 && let Some(dir) = builder.wasi_libdir(target)
673 {
674 let root = format!("native={}", dir.to_str().unwrap());
675 cargo.rustflag("-L").rustflag(&root);
676 }
677 }
678
679 cargo.rustflag("-Cembed-bitcode=yes");
685
686 if builder.config.rust_lto == RustcLto::Off {
687 cargo.rustflag("-Clto=off");
688 }
689
690 if target.contains("riscv") {
697 cargo.rustflag("-Cforce-unwind-tables=yes");
698 }
699
700 cargo.rustflag("-Zunstable-options");
703 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
704
705 let html_root =
706 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
707 cargo.rustflag(&html_root);
708 cargo.rustdocflag(&html_root);
709
710 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
711}
712
713#[derive(Debug, Clone, PartialEq, Eq, Hash)]
722pub struct StdLink {
723 pub compiler: Compiler,
724 pub target_compiler: Compiler,
725 pub target: TargetSelection,
726 crates: Vec<String>,
728 force_recompile: bool,
730}
731
732impl StdLink {
733 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
734 Self {
735 compiler: host_compiler,
736 target_compiler: std.build_compiler,
737 target: std.target,
738 crates: std.crates,
739 force_recompile: std.force_recompile,
740 }
741 }
742}
743
744impl Step for StdLink {
745 type Output = ();
746
747 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
748 run.never()
749 }
750
751 fn run(self, builder: &Builder<'_>) {
760 let compiler = self.compiler;
761 let target_compiler = self.target_compiler;
762 let target = self.target;
763
764 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
766 let lib = builder.sysroot_libdir_relative(self.compiler);
768 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
769 compiler: self.compiler,
770 force_recompile: self.force_recompile,
771 });
772 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
773 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
774 (libdir, hostdir)
775 } else {
776 let libdir = builder.sysroot_target_libdir(target_compiler, target);
777 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
778 (libdir, hostdir)
779 };
780
781 let is_downloaded_beta_stage0 = builder
782 .build
783 .config
784 .initial_rustc
785 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
786
787 if compiler.stage == 0 && is_downloaded_beta_stage0 {
791 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
793
794 let host = compiler.host;
795 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
796 let sysroot_bin_dir = sysroot.join("bin");
797 t!(fs::create_dir_all(&sysroot_bin_dir));
798 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
799
800 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
801 t!(fs::create_dir_all(sysroot.join("lib")));
802 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
803
804 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
806 t!(fs::create_dir_all(&sysroot_codegen_backends));
807 let stage0_codegen_backends = builder
808 .out
809 .join(host)
810 .join("stage0/lib/rustlib")
811 .join(host)
812 .join("codegen-backends");
813 if stage0_codegen_backends.exists() {
814 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
815 }
816 } else if compiler.stage == 0 {
817 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
818
819 if builder.local_rebuild {
820 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
824 }
825
826 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
827 } else {
828 if builder.download_rustc() {
829 let _ = fs::remove_dir_all(&libdir);
831 let _ = fs::remove_dir_all(&hostdir);
832 }
833
834 add_to_sysroot(
835 builder,
836 &libdir,
837 &hostdir,
838 &build_stamp::libstd_stamp(builder, compiler, target),
839 );
840 }
841 }
842}
843
844fn copy_sanitizers(
846 builder: &Builder<'_>,
847 compiler: &Compiler,
848 target: TargetSelection,
849) -> Vec<PathBuf> {
850 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
851
852 if builder.config.dry_run() {
853 return Vec::new();
854 }
855
856 let mut target_deps = Vec::new();
857 let libdir = builder.sysroot_target_libdir(*compiler, target);
858
859 for runtime in &runtimes {
860 let dst = libdir.join(&runtime.name);
861 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
862
863 if target == "x86_64-apple-darwin"
867 || target == "aarch64-apple-darwin"
868 || target == "aarch64-apple-ios"
869 || target == "aarch64-apple-ios-sim"
870 || target == "x86_64-apple-ios"
871 {
872 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
874 apple_darwin_sign_file(builder, &dst);
877 }
878
879 target_deps.push(dst);
880 }
881
882 target_deps
883}
884
885fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
886 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
887}
888
889fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
890 command("codesign")
891 .arg("-f") .arg("-s")
893 .arg("-")
894 .arg(file_path)
895 .run(builder);
896}
897
898#[derive(Debug, Clone, PartialEq, Eq, Hash)]
899pub struct StartupObjects {
900 pub compiler: Compiler,
901 pub target: TargetSelection,
902}
903
904impl Step for StartupObjects {
905 type Output = Vec<(PathBuf, DependencyType)>;
906
907 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
908 run.path("library/rtstartup")
909 }
910
911 fn make_run(run: RunConfig<'_>) {
912 run.builder.ensure(StartupObjects {
913 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
914 target: run.target,
915 });
916 }
917
918 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
925 let for_compiler = self.compiler;
926 let target = self.target;
927 if !target.is_windows_gnu() {
930 return vec![];
931 }
932
933 let mut target_deps = vec![];
934
935 let src_dir = &builder.src.join("library").join("rtstartup");
936 let dst_dir = &builder.native_dir(target).join("rtstartup");
937 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
938 t!(fs::create_dir_all(dst_dir));
939
940 for file in &["rsbegin", "rsend"] {
941 let src_file = &src_dir.join(file.to_string() + ".rs");
942 let dst_file = &dst_dir.join(file.to_string() + ".o");
943 if !up_to_date(src_file, dst_file) {
944 let mut cmd = command(&builder.initial_rustc);
945 cmd.env("RUSTC_BOOTSTRAP", "1");
946 if !builder.local_rebuild {
947 cmd.arg("--cfg").arg("bootstrap");
949 }
950 cmd.arg("--target")
951 .arg(target.rustc_target_arg())
952 .arg("--emit=obj")
953 .arg("-o")
954 .arg(dst_file)
955 .arg(src_file)
956 .run(builder);
957 }
958
959 let obj = sysroot_dir.join((*file).to_string() + ".o");
960 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
961 target_deps.push((obj, DependencyType::Target));
962 }
963
964 target_deps
965 }
966}
967
968fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
969 let ci_rustc_dir = builder.config.ci_rustc_dir();
970
971 for file in contents {
972 let src = ci_rustc_dir.join(&file);
973 let dst = sysroot.join(file);
974 if src.is_dir() {
975 t!(fs::create_dir_all(dst));
976 } else {
977 builder.copy_link(&src, &dst, FileType::Regular);
978 }
979 }
980}
981
982#[derive(Clone, Debug)]
984pub struct BuiltRustc {
985 pub build_compiler: Compiler,
989}
990
991#[derive(Debug, Clone, PartialEq, Eq, Hash)]
998pub struct Rustc {
999 pub target: TargetSelection,
1001 pub build_compiler: Compiler,
1003 crates: Vec<String>,
1009}
1010
1011impl Rustc {
1012 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
1013 Self { target, build_compiler, crates: Default::default() }
1014 }
1015}
1016
1017impl Step for Rustc {
1018 type Output = BuiltRustc;
1019 const IS_HOST: bool = true;
1020
1021 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1022 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1023 for (i, krate) in crates.iter().enumerate() {
1024 if krate.name == "rustc-main" {
1027 crates.swap_remove(i);
1028 break;
1029 }
1030 }
1031 run.crates(crates)
1032 }
1033
1034 fn is_default_step(_builder: &Builder<'_>) -> bool {
1035 false
1036 }
1037
1038 fn make_run(run: RunConfig<'_>) {
1039 if run.builder.paths == vec![PathBuf::from("compiler")] {
1042 return;
1043 }
1044
1045 let crates = run.cargo_crates_in_set();
1046 run.builder.ensure(Rustc {
1047 build_compiler: run
1048 .builder
1049 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1050 target: run.target,
1051 crates,
1052 });
1053 }
1054
1055 fn run(self, builder: &Builder<'_>) -> Self::Output {
1061 let build_compiler = self.build_compiler;
1062 let target = self.target;
1063
1064 if builder.download_rustc() && build_compiler.stage != 0 {
1067 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1068
1069 let sysroot =
1070 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1071 cp_rustc_component_to_ci_sysroot(
1072 builder,
1073 &sysroot,
1074 builder.config.ci_rustc_dev_contents(),
1075 );
1076 return BuiltRustc { build_compiler };
1077 }
1078
1079 builder.std(build_compiler, target);
1082
1083 if builder.config.keep_stage.contains(&build_compiler.stage) {
1084 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1085
1086 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1087 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1088 builder.ensure(RustcLink::from_rustc(self));
1089
1090 return BuiltRustc { build_compiler };
1091 }
1092
1093 let stage = build_compiler.stage + 1;
1095
1096 if build_compiler.stage >= 2
1101 && !builder.config.full_bootstrap
1102 && target == builder.host_target
1103 {
1104 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1108
1109 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1110 builder.info(&msg);
1111
1112 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1116 uplift_build_compiler,
1118 build_compiler,
1120 target,
1121 self.crates,
1122 ));
1123
1124 return BuiltRustc { build_compiler: uplift_build_compiler };
1127 }
1128
1129 builder.std(
1135 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1136 builder.config.host_target,
1137 );
1138
1139 let mut cargo = builder::Cargo::new(
1140 builder,
1141 build_compiler,
1142 Mode::Rustc,
1143 SourceType::InTree,
1144 target,
1145 Kind::Build,
1146 );
1147
1148 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1149
1150 for krate in &*self.crates {
1154 cargo.arg("-p").arg(krate);
1155 }
1156
1157 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1158 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1160 }
1161
1162 let _guard = builder.msg(
1163 Kind::Build,
1164 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1165 Mode::Rustc,
1166 build_compiler,
1167 target,
1168 );
1169 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1170 run_cargo(
1171 builder,
1172 cargo,
1173 vec![],
1174 &stamp,
1175 vec![],
1176 false,
1177 true, );
1179
1180 let target_root_dir = stamp.path().parent().unwrap();
1181 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1187 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1188 {
1189 let rustc_driver = target_root_dir.join("librustc_driver.so");
1190 strip_debug(builder, target, &rustc_driver);
1191 }
1192
1193 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1194 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1197 }
1198
1199 builder.ensure(RustcLink::from_rustc(self));
1200 BuiltRustc { build_compiler }
1201 }
1202
1203 fn metadata(&self) -> Option<StepMetadata> {
1204 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1205 }
1206}
1207
1208pub fn rustc_cargo(
1209 builder: &Builder<'_>,
1210 cargo: &mut Cargo,
1211 target: TargetSelection,
1212 build_compiler: &Compiler,
1213 crates: &[String],
1214) {
1215 cargo
1216 .arg("--features")
1217 .arg(builder.rustc_features(builder.kind, target, crates))
1218 .arg("--manifest-path")
1219 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1220
1221 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1222
1223 cargo.rustflag("-Zon-broken-pipe=kill");
1237
1238 if builder.build.config.bootstrap_override_lld.is_used() {
1243 cargo.rustflag("-Zdefault-visibility=protected");
1244 }
1245
1246 if is_lto_stage(build_compiler) {
1247 match builder.config.rust_lto {
1248 RustcLto::Thin | RustcLto::Fat => {
1249 cargo.rustflag("-Zdylib-lto");
1252 let lto_type = match builder.config.rust_lto {
1256 RustcLto::Thin => "thin",
1257 RustcLto::Fat => "fat",
1258 _ => unreachable!(),
1259 };
1260 cargo.rustflag(&format!("-Clto={lto_type}"));
1261 cargo.rustflag("-Cembed-bitcode=yes");
1262 }
1263 RustcLto::ThinLocal => { }
1264 RustcLto::Off => {
1265 cargo.rustflag("-Clto=off");
1266 }
1267 }
1268 } else if builder.config.rust_lto == RustcLto::Off {
1269 cargo.rustflag("-Clto=off");
1270 }
1271
1272 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1280 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1281 }
1282
1283 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1284 panic!("Cannot use and generate PGO profiles at the same time");
1285 }
1286 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1287 if build_compiler.stage == 1 {
1288 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1289 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1292 true
1293 } else {
1294 false
1295 }
1296 } else if let Some(path) = &builder.config.rust_profile_use {
1297 if build_compiler.stage == 1 {
1298 cargo.rustflag(&format!("-Cprofile-use={path}"));
1299 if builder.is_verbose() {
1300 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1301 }
1302 true
1303 } else {
1304 false
1305 }
1306 } else {
1307 false
1308 };
1309 if is_collecting {
1310 cargo.rustflag(&format!(
1312 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1313 builder.config.src.components().count()
1314 ));
1315 }
1316
1317 if let Some(ref ccache) = builder.config.ccache
1322 && build_compiler.stage == 0
1323 && !builder.config.incremental
1324 {
1325 cargo.env("RUSTC_WRAPPER", ccache);
1326 }
1327
1328 rustc_cargo_env(builder, cargo, target);
1329}
1330
1331pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1332 cargo
1335 .env("CFG_RELEASE", builder.rust_release())
1336 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1337 .env("CFG_VERSION", builder.rust_version());
1338
1339 if builder.config.omit_git_hash {
1343 cargo.env("CFG_OMIT_GIT_HASH", "1");
1344 }
1345
1346 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1347
1348 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1349 let target_config = builder.config.target_config.get(&target);
1350
1351 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1352
1353 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1354 cargo.env("CFG_VER_DATE", ver_date);
1355 }
1356 if let Some(ref ver_hash) = builder.rust_info().sha() {
1357 cargo.env("CFG_VER_HASH", ver_hash);
1358 }
1359 if !builder.unstable_features() {
1360 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1361 }
1362
1363 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1366 cargo.env("CFG_DEFAULT_LINKER", s);
1367 } else if let Some(ref s) = builder.config.rustc_default_linker {
1368 cargo.env("CFG_DEFAULT_LINKER", s);
1369 }
1370
1371 if let Some(linker) = target_config.map(|c| c.default_linker_linux_override) {
1373 match linker {
1374 DefaultLinuxLinkerOverride::Off => {}
1375 DefaultLinuxLinkerOverride::SelfContainedLldCc => {
1376 cargo.env("CFG_DEFAULT_LINKER_SELF_CONTAINED_LLD_CC", "1");
1377 }
1378 }
1379 }
1380
1381 if builder.config.rust_verify_llvm_ir {
1382 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1383 }
1384
1385 if builder.config.llvm_enabled(target) {
1397 let building_llvm_is_expensive =
1398 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1399 .should_build();
1400
1401 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1402 if !skip_llvm {
1403 rustc_llvm_env(builder, cargo, target)
1404 }
1405 }
1406
1407 if builder.config.jemalloc(target) && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
1409 if target.starts_with("aarch64") {
1412 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1413 }
1414 else if target.starts_with("loongarch") {
1416 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1417 }
1418 }
1419}
1420
1421fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1427 if builder.config.is_rust_llvm(target) {
1428 cargo.env("LLVM_RUSTLLVM", "1");
1429 }
1430 if builder.config.llvm_enzyme {
1431 cargo.env("LLVM_ENZYME", "1");
1432 }
1433 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1434 if builder.config.llvm_offload {
1435 builder.ensure(llvm::OmpOffload { target });
1436 cargo.env("LLVM_OFFLOAD", "1");
1437 }
1438
1439 cargo.env("LLVM_CONFIG", &host_llvm_config);
1440
1441 let mut llvm_linker_flags = String::new();
1451 if builder.config.llvm_profile_generate
1452 && target.is_msvc()
1453 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1454 {
1455 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1457 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1458 }
1459
1460 if let Some(ref s) = builder.config.llvm_ldflags {
1462 if !llvm_linker_flags.is_empty() {
1463 llvm_linker_flags.push(' ');
1464 }
1465 llvm_linker_flags.push_str(s);
1466 }
1467
1468 if !llvm_linker_flags.is_empty() {
1470 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1471 }
1472
1473 if builder.config.llvm_static_stdcpp
1476 && !target.contains("freebsd")
1477 && !target.is_msvc()
1478 && !target.contains("apple")
1479 && !target.contains("solaris")
1480 {
1481 let libstdcxx_name =
1482 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1483 let file = compiler_file(
1484 builder,
1485 &builder.cxx(target).unwrap(),
1486 target,
1487 CLang::Cxx,
1488 libstdcxx_name,
1489 );
1490 cargo.env("LLVM_STATIC_STDCPP", file);
1491 }
1492 if builder.llvm_link_shared() {
1493 cargo.env("LLVM_LINK_SHARED", "1");
1494 }
1495 if builder.config.llvm_use_libcxx {
1496 cargo.env("LLVM_USE_LIBCXX", "1");
1497 }
1498 if builder.config.llvm_assertions {
1499 cargo.env("LLVM_ASSERTIONS", "1");
1500 }
1501}
1502
1503#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1516struct RustcLink {
1517 build_compiler: Compiler,
1519 sysroot_compiler: Compiler,
1522 target: TargetSelection,
1523 crates: Vec<String>,
1525}
1526
1527impl RustcLink {
1528 fn from_rustc(rustc: Rustc) -> Self {
1531 Self {
1532 build_compiler: rustc.build_compiler,
1533 sysroot_compiler: rustc.build_compiler,
1534 target: rustc.target,
1535 crates: rustc.crates,
1536 }
1537 }
1538
1539 fn from_build_compiler_and_sysroot(
1541 build_compiler: Compiler,
1542 sysroot_compiler: Compiler,
1543 target: TargetSelection,
1544 crates: Vec<String>,
1545 ) -> Self {
1546 Self { build_compiler, sysroot_compiler, target, crates }
1547 }
1548}
1549
1550impl Step for RustcLink {
1551 type Output = ();
1552
1553 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1554 run.never()
1555 }
1556
1557 fn run(self, builder: &Builder<'_>) {
1559 let build_compiler = self.build_compiler;
1560 let sysroot_compiler = self.sysroot_compiler;
1561 let target = self.target;
1562 add_to_sysroot(
1563 builder,
1564 &builder.sysroot_target_libdir(sysroot_compiler, target),
1565 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1566 &build_stamp::librustc_stamp(builder, build_compiler, target),
1567 );
1568 }
1569}
1570
1571#[derive(Clone)]
1573pub struct GccDylibSet {
1574 dylibs: BTreeMap<GccTargetPair, GccOutput>,
1575 host_pair: GccTargetPair,
1576}
1577
1578impl GccDylibSet {
1579 fn host_dylib(&self) -> &GccOutput {
1584 self.dylibs.get(&self.host_pair).unwrap_or_else(|| {
1585 panic!("libgccjit.so was not built for host target {}", self.host_pair)
1586 })
1587 }
1588
1589 pub fn install_to(&self, builder: &Builder<'_>, compiler: Compiler) {
1593 if builder.config.dry_run() {
1594 return;
1595 }
1596
1597 let cg_sysroot = builder.sysroot_codegen_backends(compiler);
1599
1600 for (target_pair, libgccjit) in &self.dylibs {
1601 assert_eq!(
1602 target_pair.host(),
1603 compiler.host,
1604 "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",
1605 compiler.host
1606 );
1607 let libgccjit = libgccjit.libgccjit();
1608 let target_filename = libgccjit.file_name().unwrap().to_str().unwrap();
1609
1610 let actual_libgccjit_path = t!(
1614 libgccjit.canonicalize(),
1615 format!("Cannot find libgccjit at {}", libgccjit.display())
1616 );
1617
1618 let dest_dir = cg_sysroot.join("lib").join(target_pair.target());
1620 t!(fs::create_dir_all(&dest_dir));
1621 let dst = dest_dir.join(target_filename);
1622 builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
1623 }
1624 }
1625}
1626
1627#[derive(Clone)]
1631pub struct GccCodegenBackendOutput {
1632 stamp: BuildStamp,
1633 dylib_set: GccDylibSet,
1634}
1635
1636#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1647pub struct GccCodegenBackend {
1648 compilers: RustcPrivateCompilers,
1649 targets: Vec<TargetSelection>,
1650}
1651
1652impl GccCodegenBackend {
1653 pub fn for_targets(
1656 compilers: RustcPrivateCompilers,
1657 mut targets: Vec<TargetSelection>,
1658 ) -> Self {
1659 targets.sort();
1661 Self { compilers, targets }
1662 }
1663}
1664
1665impl Step for GccCodegenBackend {
1666 type Output = GccCodegenBackendOutput;
1667
1668 const IS_HOST: bool = true;
1669
1670 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1671 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1672 }
1673
1674 fn make_run(run: RunConfig<'_>) {
1675 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target);
1678 run.builder.ensure(GccCodegenBackend { compilers, targets: vec![run.target] });
1679 }
1680
1681 fn run(self, builder: &Builder<'_>) -> Self::Output {
1682 let host = self.compilers.target();
1683 let build_compiler = self.compilers.build_compiler();
1684
1685 let stamp = build_stamp::codegen_backend_stamp(
1686 builder,
1687 build_compiler,
1688 host,
1689 &CodegenBackendKind::Gcc,
1690 );
1691
1692 let dylib_set = GccDylibSet {
1693 dylibs: self
1694 .targets
1695 .iter()
1696 .map(|&target| {
1697 let target_pair = GccTargetPair::for_target_pair(host, target);
1698 (target_pair, builder.ensure(Gcc { target_pair }))
1699 })
1700 .collect(),
1701 host_pair: GccTargetPair::for_native_build(host),
1702 };
1703
1704 if builder.config.keep_stage.contains(&build_compiler.stage) {
1705 trace!("`keep-stage` requested");
1706 builder.info(
1707 "WARNING: Using a potentially old codegen backend. \
1708 This may not behave well.",
1709 );
1710 return GccCodegenBackendOutput { stamp, dylib_set };
1713 }
1714
1715 let mut cargo = builder::Cargo::new(
1716 builder,
1717 build_compiler,
1718 Mode::Codegen,
1719 SourceType::InTree,
1720 host,
1721 Kind::Build,
1722 );
1723 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1724 rustc_cargo_env(builder, &mut cargo, host);
1725
1726 add_cg_gcc_cargo_flags(&mut cargo, dylib_set.host_dylib());
1727
1728 let _guard =
1729 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host);
1730 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1731
1732 GccCodegenBackendOutput {
1733 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1734 dylib_set,
1735 }
1736 }
1737
1738 fn metadata(&self) -> Option<StepMetadata> {
1739 Some(
1740 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1741 .built_by(self.compilers.build_compiler()),
1742 )
1743 }
1744}
1745
1746#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1747pub struct CraneliftCodegenBackend {
1748 pub compilers: RustcPrivateCompilers,
1749}
1750
1751impl Step for CraneliftCodegenBackend {
1752 type Output = BuildStamp;
1753 const IS_HOST: bool = true;
1754
1755 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1756 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1757 }
1758
1759 fn make_run(run: RunConfig<'_>) {
1760 run.builder.ensure(CraneliftCodegenBackend {
1761 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1762 });
1763 }
1764
1765 fn run(self, builder: &Builder<'_>) -> Self::Output {
1766 let target = self.compilers.target();
1767 let build_compiler = self.compilers.build_compiler();
1768
1769 let stamp = build_stamp::codegen_backend_stamp(
1770 builder,
1771 build_compiler,
1772 target,
1773 &CodegenBackendKind::Cranelift,
1774 );
1775
1776 if builder.config.keep_stage.contains(&build_compiler.stage) {
1777 trace!("`keep-stage` requested");
1778 builder.info(
1779 "WARNING: Using a potentially old codegen backend. \
1780 This may not behave well.",
1781 );
1782 return stamp;
1785 }
1786
1787 let mut cargo = builder::Cargo::new(
1788 builder,
1789 build_compiler,
1790 Mode::Codegen,
1791 SourceType::InTree,
1792 target,
1793 Kind::Build,
1794 );
1795 cargo
1796 .arg("--manifest-path")
1797 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1798 rustc_cargo_env(builder, &mut cargo, target);
1799
1800 let _guard = builder.msg(
1801 Kind::Build,
1802 "codegen backend cranelift",
1803 Mode::Codegen,
1804 build_compiler,
1805 target,
1806 );
1807 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1808 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1809 }
1810
1811 fn metadata(&self) -> Option<StepMetadata> {
1812 Some(
1813 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1814 .built_by(self.compilers.build_compiler()),
1815 )
1816 }
1817}
1818
1819fn write_codegen_backend_stamp(
1821 mut stamp: BuildStamp,
1822 files: Vec<PathBuf>,
1823 dry_run: bool,
1824) -> BuildStamp {
1825 if dry_run {
1826 return stamp;
1827 }
1828
1829 let mut files = files.into_iter().filter(|f| {
1830 let filename = f.file_name().unwrap().to_str().unwrap();
1831 is_dylib(f) && filename.contains("rustc_codegen_")
1832 });
1833 let codegen_backend = match files.next() {
1834 Some(f) => f,
1835 None => panic!("no dylibs built for codegen backend?"),
1836 };
1837 if let Some(f) = files.next() {
1838 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1839 }
1840
1841 let codegen_backend = codegen_backend.to_str().unwrap();
1842 stamp = stamp.add_stamp(codegen_backend);
1843 t!(stamp.write());
1844 stamp
1845}
1846
1847fn copy_codegen_backends_to_sysroot(
1854 builder: &Builder<'_>,
1855 stamp: BuildStamp,
1856 target_compiler: Compiler,
1857) {
1858 let dst = builder.sysroot_codegen_backends(target_compiler);
1867 t!(fs::create_dir_all(&dst), dst);
1868
1869 if builder.config.dry_run() {
1870 return;
1871 }
1872
1873 if stamp.path().exists() {
1874 let file = get_codegen_backend_file(&stamp);
1875 builder.copy_link(
1876 &file,
1877 &dst.join(normalize_codegen_backend_name(builder, &file)),
1878 FileType::NativeLibrary,
1879 );
1880 }
1881}
1882
1883pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1885 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1886}
1887
1888pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1890 let filename = path.file_name().unwrap().to_str().unwrap();
1891 let dash = filename.find('-').unwrap();
1894 let dot = filename.find('.').unwrap();
1895 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1896}
1897
1898pub fn compiler_file(
1899 builder: &Builder<'_>,
1900 compiler: &Path,
1901 target: TargetSelection,
1902 c: CLang,
1903 file: &str,
1904) -> PathBuf {
1905 if builder.config.dry_run() {
1906 return PathBuf::new();
1907 }
1908 let mut cmd = command(compiler);
1909 cmd.args(builder.cc_handled_clags(target, c));
1910 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1911 cmd.arg(format!("-print-file-name={file}"));
1912 let out = cmd.run_capture_stdout(builder).stdout();
1913 PathBuf::from(out.trim())
1914}
1915
1916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1917pub struct Sysroot {
1918 pub compiler: Compiler,
1919 force_recompile: bool,
1921}
1922
1923impl Sysroot {
1924 pub(crate) fn new(compiler: Compiler) -> Self {
1925 Sysroot { compiler, force_recompile: false }
1926 }
1927}
1928
1929impl Step for Sysroot {
1930 type Output = PathBuf;
1931
1932 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1933 run.never()
1934 }
1935
1936 fn run(self, builder: &Builder<'_>) -> PathBuf {
1940 let compiler = self.compiler;
1941 let host_dir = builder.out.join(compiler.host);
1942
1943 let sysroot_dir = |stage| {
1944 if stage == 0 {
1945 host_dir.join("stage0-sysroot")
1946 } else if self.force_recompile && stage == compiler.stage {
1947 host_dir.join(format!("stage{stage}-test-sysroot"))
1948 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1949 host_dir.join("ci-rustc-sysroot")
1950 } else {
1951 host_dir.join(format!("stage{stage}"))
1952 }
1953 };
1954 let sysroot = sysroot_dir(compiler.stage);
1955 trace!(stage = ?compiler.stage, ?sysroot);
1956
1957 builder.do_if_verbose(|| {
1958 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1959 });
1960 let _ = fs::remove_dir_all(&sysroot);
1961 t!(fs::create_dir_all(&sysroot));
1962
1963 if compiler.stage == 0 {
1970 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1971 }
1972
1973 if builder.download_rustc() && compiler.stage != 0 {
1975 assert_eq!(
1976 builder.config.host_target, compiler.host,
1977 "Cross-compiling is not yet supported with `download-rustc`",
1978 );
1979
1980 for stage in 0..=2 {
1982 if stage != compiler.stage {
1983 let dir = sysroot_dir(stage);
1984 if !dir.ends_with("ci-rustc-sysroot") {
1985 let _ = fs::remove_dir_all(dir);
1986 }
1987 }
1988 }
1989
1990 let mut filtered_files = Vec::new();
2000 let mut add_filtered_files = |suffix, contents| {
2001 for path in contents {
2002 let path = Path::new(&path);
2003 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
2004 filtered_files.push(path.file_name().unwrap().to_owned());
2005 }
2006 }
2007 };
2008 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
2009 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
2010 add_filtered_files("lib", builder.config.ci_rust_std_contents());
2013
2014 let filtered_extensions = [
2015 OsStr::new("rmeta"),
2016 OsStr::new("rlib"),
2017 OsStr::new(std::env::consts::DLL_EXTENSION),
2019 ];
2020 let ci_rustc_dir = builder.config.ci_rustc_dir();
2021 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
2022 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
2023 return true;
2024 }
2025 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
2026 return true;
2027 }
2028 filtered_files.iter().all(|f| f != path.file_name().unwrap())
2029 });
2030 }
2031
2032 if compiler.stage != 0 {
2038 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
2039 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
2040 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
2041 if let Err(e) =
2042 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
2043 {
2044 eprintln!(
2045 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2046 sysroot_lib_rustlib_src_rust.display(),
2047 builder.src.display(),
2048 e,
2049 );
2050 if builder.config.rust_remap_debuginfo {
2051 eprintln!(
2052 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
2053 sysroot_lib_rustlib_src_rust.display(),
2054 );
2055 }
2056 build_helper::exit!(1);
2057 }
2058 }
2059
2060 if !builder.download_rustc() {
2062 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
2063 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
2064 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
2065 if let Err(e) =
2066 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
2067 {
2068 eprintln!(
2069 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2070 sysroot_lib_rustlib_rustcsrc_rust.display(),
2071 builder.src.display(),
2072 e,
2073 );
2074 build_helper::exit!(1);
2075 }
2076 }
2077
2078 sysroot
2079 }
2080}
2081
2082#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2089pub struct Assemble {
2090 pub target_compiler: Compiler,
2095}
2096
2097impl Step for Assemble {
2098 type Output = Compiler;
2099 const IS_HOST: bool = true;
2100
2101 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2102 run.path("compiler/rustc").path("compiler")
2103 }
2104
2105 fn make_run(run: RunConfig<'_>) {
2106 run.builder.ensure(Assemble {
2107 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2108 });
2109 }
2110
2111 fn run(self, builder: &Builder<'_>) -> Compiler {
2112 let target_compiler = self.target_compiler;
2113
2114 if target_compiler.stage == 0 {
2115 trace!("stage 0 build compiler is always available, simply returning");
2116 assert_eq!(
2117 builder.config.host_target, target_compiler.host,
2118 "Cannot obtain compiler for non-native build triple at stage 0"
2119 );
2120 return target_compiler;
2122 }
2123
2124 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2127 let libdir_bin = libdir.parent().unwrap().join("bin");
2128 t!(fs::create_dir_all(&libdir_bin));
2129
2130 if builder.config.llvm_enabled(target_compiler.host) {
2131 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2132
2133 let target = target_compiler.host;
2134 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2135 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2136 trace!("LLVM tools enabled");
2137
2138 let host_llvm_bin_dir = command(&host_llvm_config)
2139 .arg("--bindir")
2140 .cached()
2141 .run_capture_stdout(builder)
2142 .stdout()
2143 .trim()
2144 .to_string();
2145
2146 let llvm_bin_dir = if target == builder.host_target {
2147 PathBuf::from(host_llvm_bin_dir)
2148 } else {
2149 let external_llvm_config = builder
2152 .config
2153 .target_config
2154 .get(&target)
2155 .and_then(|t| t.llvm_config.clone());
2156 if let Some(external_llvm_config) = external_llvm_config {
2157 external_llvm_config.parent().unwrap().to_path_buf()
2160 } else {
2161 let host_llvm_out = builder.llvm_out(builder.host_target);
2165 let target_llvm_out = builder.llvm_out(target);
2166 if let Ok(relative_path) =
2167 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2168 {
2169 target_llvm_out.join(relative_path)
2170 } else {
2171 PathBuf::from(
2174 host_llvm_bin_dir
2175 .replace(&*builder.host_target.triple, &target.triple),
2176 )
2177 }
2178 }
2179 };
2180
2181 #[cfg(feature = "tracing")]
2188 let _llvm_tools_span =
2189 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2190 .entered();
2191 for tool in LLVM_TOOLS {
2192 trace!("installing `{tool}`");
2193 let tool_exe = exe(tool, target_compiler.host);
2194 let src_path = llvm_bin_dir.join(&tool_exe);
2195
2196 if !src_path.exists() && builder.config.llvm_from_ci {
2198 eprintln!("{} does not exist; skipping copy", src_path.display());
2199 continue;
2200 }
2201
2202 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2209 }
2210 }
2211 }
2212
2213 let maybe_install_llvm_bitcode_linker = || {
2214 if builder.config.llvm_bitcode_linker_enabled {
2215 trace!("llvm-bitcode-linker enabled, installing");
2216 let llvm_bitcode_linker = builder.ensure(
2217 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2218 builder,
2219 target_compiler,
2220 ),
2221 );
2222
2223 let bindir_self_contained = builder
2225 .sysroot(target_compiler)
2226 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2227 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2228
2229 t!(fs::create_dir_all(&bindir_self_contained));
2230 builder.copy_link(
2231 &llvm_bitcode_linker.tool_path,
2232 &bindir_self_contained.join(tool_exe),
2233 FileType::Executable,
2234 );
2235 }
2236 };
2237
2238 if builder.download_rustc() {
2240 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2241
2242 builder.std(target_compiler, target_compiler.host);
2243 let sysroot =
2244 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2245 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2248 if target_compiler.stage == builder.top_stage {
2250 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2251 }
2252
2253 maybe_install_llvm_bitcode_linker();
2256
2257 return target_compiler;
2258 }
2259
2260 debug!(
2274 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2275 target_compiler.stage - 1,
2276 builder.config.host_target,
2277 );
2278 let build_compiler =
2279 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2280
2281 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2283 debug!("`llvm_enzyme` requested");
2284 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2285 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2286 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2287 let lib_ext = std::env::consts::DLL_EXTENSION;
2288 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2289 let src_lib =
2290 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2291 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2292 let target_libdir =
2293 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2294 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2295 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2296 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2297 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2298 }
2299 }
2300
2301 if builder.config.llvm_offload && !builder.config.dry_run() {
2302 debug!("`llvm_offload` requested");
2303 let offload_install = builder.ensure(llvm::OmpOffload { target: build_compiler.host });
2304 if let Some(_llvm_config) = builder.llvm_config(builder.config.host_target) {
2305 let target_libdir =
2306 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2307 for p in offload_install.offload_paths() {
2308 let libname = p.file_name().unwrap();
2309 let dst_lib = target_libdir.join(libname);
2310 builder.resolve_symlink_and_copy(&p, &dst_lib);
2311 }
2312 }
2317 }
2318
2319 debug!(
2322 ?build_compiler,
2323 "target_compiler.host" = ?target_compiler.host,
2324 "building compiler libraries to link to"
2325 );
2326
2327 let BuiltRustc { build_compiler } =
2329 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2330
2331 let stage = target_compiler.stage;
2332 let host = target_compiler.host;
2333 let (host_info, dir_name) = if build_compiler.host == host {
2334 ("".into(), "host".into())
2335 } else {
2336 (format!(" ({host})"), host.to_string())
2337 };
2338 let msg = format!(
2343 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2344 );
2345 builder.info(&msg);
2346
2347 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2349 let proc_macros = builder
2350 .read_stamp_file(&stamp)
2351 .into_iter()
2352 .filter_map(|(path, dependency_type)| {
2353 if dependency_type == DependencyType::Host {
2354 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2355 } else {
2356 None
2357 }
2358 })
2359 .collect::<HashSet<_>>();
2360
2361 let sysroot = builder.sysroot(target_compiler);
2362 let rustc_libdir = builder.rustc_libdir(target_compiler);
2363 t!(fs::create_dir_all(&rustc_libdir));
2364 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2365 for f in builder.read_dir(&src_libdir) {
2366 let filename = f.file_name().into_string().unwrap();
2367
2368 let is_proc_macro = proc_macros.contains(&filename);
2369 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2370
2371 let can_be_rustc_dynamic_dep = if builder
2375 .link_std_into_rustc_driver(target_compiler.host)
2376 && !target_compiler.host.is_windows()
2377 {
2378 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2379 !is_std
2380 } else {
2381 true
2382 };
2383
2384 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2385 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2386 }
2387 }
2388
2389 {
2390 #[cfg(feature = "tracing")]
2391 let _codegen_backend_span =
2392 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2393
2394 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2395 if builder.kind == Kind::Check && builder.top_stage == 1 {
2412 continue;
2413 }
2414
2415 let prepare_compilers = || {
2416 RustcPrivateCompilers::from_build_and_target_compiler(
2417 build_compiler,
2418 target_compiler,
2419 )
2420 };
2421
2422 match backend {
2423 CodegenBackendKind::Cranelift => {
2424 let stamp = builder
2425 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2426 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2427 }
2428 CodegenBackendKind::Gcc => {
2429 let compilers = prepare_compilers();
2461
2462 let mut targets = HashSet::new();
2467 for target in &builder.hosts {
2470 targets.insert(*target);
2471 }
2472 for target in &builder.targets {
2474 targets.insert(*target);
2475 }
2476 targets.insert(compilers.target_compiler().host);
2479
2480 let output = builder.ensure(GccCodegenBackend::for_targets(
2481 compilers,
2482 targets.into_iter().collect(),
2483 ));
2484 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2485 output.dylib_set.install_to(builder, target_compiler);
2488 }
2489 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2490 }
2491 }
2492 }
2493
2494 if builder.config.lld_enabled {
2495 let lld_wrapper =
2496 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2497 builder,
2498 target_compiler,
2499 ));
2500 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2501 }
2502
2503 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2504 debug!(
2505 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2506 workaround faulty homebrew `strip`s"
2507 );
2508
2509 let src_exe = exe("llvm-objcopy", target_compiler.host);
2516 let dst_exe = exe("rust-objcopy", target_compiler.host);
2517 builder.copy_link(
2518 &libdir_bin.join(src_exe),
2519 &libdir_bin.join(dst_exe),
2520 FileType::Executable,
2521 );
2522 }
2523
2524 if builder.tool_enabled("wasm-component-ld") {
2527 let wasm_component = builder.ensure(
2528 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2529 builder,
2530 target_compiler,
2531 ),
2532 );
2533 builder.copy_link(
2534 &wasm_component.tool_path,
2535 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2536 FileType::Executable,
2537 );
2538 }
2539
2540 maybe_install_llvm_bitcode_linker();
2541
2542 debug!(
2545 "target_compiler.host" = ?target_compiler.host,
2546 ?sysroot,
2547 "ensuring availability of `libLLVM.so` in compiler directory"
2548 );
2549 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2550 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2551
2552 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2554 let rustc = out_dir.join(exe("rustc-main", host));
2555 let bindir = sysroot.join("bin");
2556 t!(fs::create_dir_all(bindir));
2557 let compiler = builder.rustc(target_compiler);
2558 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2559 builder.copy_link(&rustc, &compiler, FileType::Executable);
2560
2561 target_compiler
2562 }
2563}
2564
2565#[track_caller]
2570pub fn add_to_sysroot(
2571 builder: &Builder<'_>,
2572 sysroot_dst: &Path,
2573 sysroot_host_dst: &Path,
2574 stamp: &BuildStamp,
2575) {
2576 let self_contained_dst = &sysroot_dst.join("self-contained");
2577 t!(fs::create_dir_all(sysroot_dst));
2578 t!(fs::create_dir_all(sysroot_host_dst));
2579 t!(fs::create_dir_all(self_contained_dst));
2580
2581 let mut crates = HashMap::new();
2582 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2583 let filename = path.file_name().unwrap().to_str().unwrap();
2584 let dst = match dependency_type {
2585 DependencyType::Host => {
2586 if sysroot_dst == sysroot_host_dst {
2587 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2590 }
2591
2592 sysroot_host_dst
2593 }
2594 DependencyType::Target => {
2595 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2598
2599 sysroot_dst
2600 }
2601 DependencyType::TargetSelfContained => self_contained_dst,
2602 };
2603 builder.copy_link(&path, &dst.join(filename), FileType::Regular);
2604 }
2605
2606 let mut seen_crates = HashMap::new();
2612 for (filestem, path) in crates {
2613 if !filestem.contains("rustc_") || filestem.contains("rustc_hash") {
2614 continue;
2615 }
2616 if let Some(other_path) =
2617 seen_crates.insert(filestem.split_once('-').unwrap().0.to_owned(), path.clone())
2618 {
2619 panic!(
2620 "duplicate rustc crate {}\n- first copy at {}\n- second copy at {}",
2621 filestem.split_once('-').unwrap().0.to_owned(),
2622 other_path.display(),
2623 path.display(),
2624 );
2625 }
2626 }
2627}
2628
2629pub fn run_cargo(
2630 builder: &Builder<'_>,
2631 cargo: Cargo,
2632 tail_args: Vec<String>,
2633 stamp: &BuildStamp,
2634 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2635 is_check: bool,
2636 rlib_only_metadata: bool,
2637) -> Vec<PathBuf> {
2638 let target_root_dir = stamp.path().parent().unwrap();
2640 let target_deps_dir = target_root_dir.join("deps");
2642 let host_root_dir = target_root_dir
2644 .parent()
2645 .unwrap() .parent()
2647 .unwrap() .join(target_root_dir.file_name().unwrap());
2649
2650 let mut deps = Vec::new();
2654 let mut toplevel = Vec::new();
2655 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2656 let (filenames_vec, crate_types) = match msg {
2657 CargoMessage::CompilerArtifact {
2658 filenames,
2659 target: CargoTarget { crate_types },
2660 ..
2661 } => {
2662 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2663 f.sort(); (f, crate_types)
2665 }
2666 _ => return,
2667 };
2668 for filename in filenames_vec {
2669 let mut keep = false;
2671 if filename.ends_with(".lib")
2672 || filename.ends_with(".a")
2673 || is_debug_info(&filename)
2674 || is_dylib(Path::new(&*filename))
2675 {
2676 keep = true;
2678 }
2679 if is_check && filename.ends_with(".rmeta") {
2680 keep = true;
2682 } else if rlib_only_metadata {
2683 if filename.contains("jemalloc_sys")
2684 || filename.contains("rustc_public_bridge")
2685 || filename.contains("rustc_public")
2686 {
2687 keep |= filename.ends_with(".rlib");
2690 } else {
2691 keep |= filename.ends_with(".rmeta");
2695 }
2696 } else {
2697 keep |= filename.ends_with(".rlib");
2699 }
2700
2701 if !keep {
2702 continue;
2703 }
2704
2705 let filename = Path::new(&*filename);
2706
2707 if filename.starts_with(&host_root_dir) {
2710 if crate_types.iter().any(|t| t == "proc-macro") {
2712 if filename.file_name().unwrap().to_str().unwrap().contains("-") {
2717 deps.push((filename.to_path_buf(), DependencyType::Host));
2718 }
2719 }
2720 continue;
2721 }
2722
2723 if filename.starts_with(&target_deps_dir) {
2726 deps.push((filename.to_path_buf(), DependencyType::Target));
2727 continue;
2728 }
2729
2730 let expected_len = t!(filename.metadata()).len();
2741 let filename = filename.file_name().unwrap().to_str().unwrap();
2742 let mut parts = filename.splitn(2, '.');
2743 let file_stem = parts.next().unwrap().to_owned();
2744 let extension = parts.next().unwrap().to_owned();
2745
2746 toplevel.push((file_stem, extension, expected_len));
2747 }
2748 });
2749
2750 if !ok {
2751 crate::exit!(1);
2752 }
2753
2754 if builder.config.dry_run() {
2755 return Vec::new();
2756 }
2757
2758 let contents = target_deps_dir
2762 .read_dir()
2763 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2764 .map(|e| t!(e))
2765 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2766 .collect::<Vec<_>>();
2767 for (prefix, extension, expected_len) in toplevel {
2768 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2769 meta.len() == expected_len
2770 && filename
2771 .strip_prefix(&prefix[..])
2772 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2773 .unwrap_or(false)
2774 });
2775 let max = candidates.max_by_key(|&(_, _, metadata)| {
2776 metadata.modified().expect("mtime should be available on all relevant OSes")
2777 });
2778 let path_to_add = match max {
2779 Some(triple) => triple.0.to_str().unwrap(),
2780 None => panic!("no output generated for {prefix:?} {extension:?}"),
2781 };
2782 if is_dylib(Path::new(path_to_add)) {
2783 let candidate = format!("{path_to_add}.lib");
2784 let candidate = PathBuf::from(candidate);
2785 if candidate.exists() {
2786 deps.push((candidate, DependencyType::Target));
2787 }
2788 }
2789 deps.push((path_to_add.into(), DependencyType::Target));
2790 }
2791
2792 deps.extend(additional_target_deps);
2793 deps.sort();
2794 let mut new_contents = Vec::new();
2795 for (dep, dependency_type) in deps.iter() {
2796 new_contents.extend(match *dependency_type {
2797 DependencyType::Host => b"h",
2798 DependencyType::Target => b"t",
2799 DependencyType::TargetSelfContained => b"s",
2800 });
2801 new_contents.extend(dep.to_str().unwrap().as_bytes());
2802 new_contents.extend(b"\0");
2803 }
2804 t!(fs::write(stamp.path(), &new_contents));
2805 deps.into_iter().map(|(d, _)| d).collect()
2806}
2807
2808pub fn stream_cargo(
2809 builder: &Builder<'_>,
2810 cargo: Cargo,
2811 tail_args: Vec<String>,
2812 cb: &mut dyn FnMut(CargoMessage<'_>),
2813) -> bool {
2814 let mut cmd = cargo.into_cmd();
2815
2816 let mut message_format = if builder.config.json_output {
2819 String::from("json")
2820 } else {
2821 String::from("json-render-diagnostics")
2822 };
2823 if let Some(s) = &builder.config.rustc_error_format {
2824 message_format.push_str(",json-diagnostic-");
2825 message_format.push_str(s);
2826 }
2827 cmd.arg("--message-format").arg(message_format);
2828
2829 for arg in tail_args {
2830 cmd.arg(arg);
2831 }
2832
2833 builder.do_if_verbose(|| println!("running: {cmd:?}"));
2834
2835 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2836
2837 let Some(mut streaming_command) = streaming_command else {
2838 return true;
2839 };
2840
2841 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2845 for line in stdout.lines() {
2846 let line = t!(line);
2847 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2848 Ok(msg) => {
2849 if builder.config.json_output {
2850 println!("{line}");
2852 }
2853 cb(msg)
2854 }
2855 Err(_) => println!("{line}"),
2857 }
2858 }
2859
2860 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2862 if builder.is_verbose() && !status.success() {
2863 eprintln!(
2864 "command did not execute successfully: {cmd:?}\n\
2865 expected success, got: {status}"
2866 );
2867 }
2868
2869 status.success()
2870}
2871
2872#[derive(Deserialize)]
2873pub struct CargoTarget<'a> {
2874 crate_types: Vec<Cow<'a, str>>,
2875}
2876
2877#[derive(Deserialize)]
2878#[serde(tag = "reason", rename_all = "kebab-case")]
2879pub enum CargoMessage<'a> {
2880 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2881 BuildScriptExecuted,
2882 BuildFinished,
2883}
2884
2885pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2886 if target != "x86_64-unknown-linux-gnu"
2890 || !builder.config.is_host_target(target)
2891 || !path.exists()
2892 {
2893 return;
2894 }
2895
2896 let previous_mtime = t!(t!(path.metadata()).modified());
2897 let stamp = BuildStamp::new(path.parent().unwrap())
2898 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2899 .with_prefix("strip")
2900 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2901
2902 if !stamp.is_up_to_date() {
2905 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2906 }
2907 t!(stamp.write());
2908
2909 let file = t!(fs::File::open(path));
2910
2911 t!(file.set_modified(previous_mtime));
2924}
2925
2926pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2928 build_compiler.stage != 0
2929}