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};
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 if self.is_for_mir_opt_tests {
300 ArtifactKeepMode::OnlyRmeta
301 } else {
302 ArtifactKeepMode::BothRlibAndRmeta
304 },
305 );
306
307 builder.ensure(StdLink::from_std(
308 self,
309 builder.compiler(build_compiler.stage, builder.config.host_target),
310 ));
311 Some(stamp)
312 }
313
314 fn metadata(&self) -> Option<StepMetadata> {
315 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
316 }
317}
318
319fn copy_and_stamp(
320 builder: &Builder<'_>,
321 libdir: &Path,
322 sourcedir: &Path,
323 name: &str,
324 target_deps: &mut Vec<(PathBuf, DependencyType)>,
325 dependency_type: DependencyType,
326) {
327 let target = libdir.join(name);
328 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
329
330 target_deps.push((target, dependency_type));
331}
332
333fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
334 let libunwind_path = builder.ensure(llvm::Libunwind { target });
335 let libunwind_source = libunwind_path.join("libunwind.a");
336 let libunwind_target = libdir.join("libunwind.a");
337 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
338 libunwind_target
339}
340
341fn copy_third_party_objects(
343 builder: &Builder<'_>,
344 compiler: &Compiler,
345 target: TargetSelection,
346) -> Vec<(PathBuf, DependencyType)> {
347 let mut target_deps = vec![];
348
349 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
350 target_deps.extend(
353 copy_sanitizers(builder, compiler, target)
354 .into_iter()
355 .map(|d| (d, DependencyType::Target)),
356 );
357 }
358
359 if target == "x86_64-fortanix-unknown-sgx"
360 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
361 && (target.contains("linux")
362 || target.contains("fuchsia")
363 || target.contains("aix")
364 || target.contains("hexagon"))
365 {
366 let libunwind_path =
367 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
368 target_deps.push((libunwind_path, DependencyType::Target));
369 }
370
371 target_deps
372}
373
374fn copy_self_contained_objects(
376 builder: &Builder<'_>,
377 compiler: &Compiler,
378 target: TargetSelection,
379) -> Vec<(PathBuf, DependencyType)> {
380 let libdir_self_contained =
381 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
382 t!(fs::create_dir_all(&libdir_self_contained));
383 let mut target_deps = vec![];
384
385 if target.needs_crt_begin_end() {
393 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
394 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
395 });
396 if !target.starts_with("wasm32") {
397 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
398 copy_and_stamp(
399 builder,
400 &libdir_self_contained,
401 &srcdir,
402 obj,
403 &mut target_deps,
404 DependencyType::TargetSelfContained,
405 );
406 }
407 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
408 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
409 let src = crt_path.join(obj);
410 let target = libdir_self_contained.join(obj);
411 builder.copy_link(&src, &target, FileType::NativeLibrary);
412 target_deps.push((target, DependencyType::TargetSelfContained));
413 }
414 } else {
415 for &obj in &["libc.a", "crt1-command.o"] {
418 copy_and_stamp(
419 builder,
420 &libdir_self_contained,
421 &srcdir,
422 obj,
423 &mut target_deps,
424 DependencyType::TargetSelfContained,
425 );
426 }
427 }
428 if !target.starts_with("s390x") {
429 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
430 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
431 }
432 } else if target.contains("-wasi") {
433 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
434 panic!(
435 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
436 or `$WASI_SDK_PATH` set",
437 target.triple
438 )
439 });
440
441 let srcdir = if target == "wasm32-wasip3" {
445 assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now");
446 builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap()
447 } else {
448 srcdir
449 };
450 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
451 copy_and_stamp(
452 builder,
453 &libdir_self_contained,
454 &srcdir,
455 obj,
456 &mut target_deps,
457 DependencyType::TargetSelfContained,
458 );
459 }
460 } else if target.is_windows_gnu() || target.is_windows_gnullvm() {
461 for obj in ["crt2.o", "dllcrt2.o"].iter() {
462 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
463 let dst = libdir_self_contained.join(obj);
464 builder.copy_link(&src, &dst, FileType::NativeLibrary);
465 target_deps.push((dst, DependencyType::TargetSelfContained));
466 }
467 }
468
469 target_deps
470}
471
472pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
475 let mut crates = run.make_run_crates(builder::Alias::Library);
476
477 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
486 if target_is_no_std {
487 crates.retain(|c| c == "core" || c == "alloc");
488 }
489 crates
490}
491
492fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
498 if builder.config.llvm_from_ci {
500 builder.config.maybe_download_ci_llvm();
502 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
503 if ci_llvm_compiler_rt.exists() {
504 return ci_llvm_compiler_rt;
505 }
506 }
507
508 builder.require_submodule("src/llvm-project", {
510 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
511 });
512 builder.src.join("src/llvm-project/compiler-rt")
513}
514
515pub fn std_cargo(
518 builder: &Builder<'_>,
519 target: TargetSelection,
520 cargo: &mut Cargo,
521 crates: &[String],
522) {
523 if target.contains("apple") && !builder.config.dry_run() {
541 let mut cmd = builder.rustc_cmd(cargo.compiler());
545 cmd.arg("--target").arg(target.rustc_target_arg());
546 cmd.arg("--print=deployment-target");
547 let output = cmd.run_capture_stdout(builder).stdout();
548
549 let (env_var, value) = output.split_once('=').unwrap();
550 cargo.env(env_var.trim(), value.trim());
553
554 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
564 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
565 }
566 }
567
568 if let Some(path) = builder.config.profiler_path(target) {
570 cargo.env("LLVM_PROFILER_RT_LIB", path);
571 } else if builder.config.profiler_enabled(target) {
572 let compiler_rt = compiler_rt_for_profiler(builder);
573 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
577 }
578
579 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
593 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
594 cargo.env("LLVM_COMPILER_RT_LIB", path);
595 " compiler-builtins-c"
596 }
597 CompilerBuiltins::BuildLLVMFuncs => {
598 builder.require_submodule(
608 "src/llvm-project",
609 Some(
610 "The `build.optimized-compiler-builtins` config option \
611 requires `compiler-rt` sources from LLVM.",
612 ),
613 );
614 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
615 if !builder.config.dry_run() {
616 assert!(compiler_builtins_root.exists());
619 }
620
621 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
624 " compiler-builtins-c"
625 }
626 CompilerBuiltins::BuildRustOnly => "",
627 };
628
629 if !builder.unstable_features() {
632 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
633 }
634
635 for krate in crates {
636 cargo.args(["-p", krate]);
637 }
638
639 let mut features = String::new();
640
641 if builder.no_std(target) == Some(true) {
642 features += " compiler-builtins-mem";
643 if !target.starts_with("bpf") {
644 features.push_str(compiler_builtins_c_feature);
645 }
646
647 if crates.is_empty() {
649 cargo.args(["-p", "alloc"]);
650 }
651 cargo
652 .arg("--manifest-path")
653 .arg(builder.src.join("library/alloc/Cargo.toml"))
654 .arg("--features")
655 .arg(features);
656 } else {
657 features += &builder.std_features(target);
658 features.push_str(compiler_builtins_c_feature);
659
660 cargo
661 .arg("--features")
662 .arg(features)
663 .arg("--manifest-path")
664 .arg(builder.src.join("library/sysroot/Cargo.toml"));
665
666 if target.contains("musl")
669 && let Some(p) = builder.musl_libdir(target)
670 {
671 let root = format!("native={}", p.to_str().unwrap());
672 cargo.rustflag("-L").rustflag(&root);
673 }
674
675 if target.contains("-wasi")
676 && let Some(dir) = builder.wasi_libdir(target)
677 {
678 let root = format!("native={}", dir.to_str().unwrap());
679 cargo.rustflag("-L").rustflag(&root);
680 }
681 }
682
683 cargo.rustflag("-Cembed-bitcode=yes");
689
690 if builder.config.rust_lto == RustcLto::Off {
691 cargo.rustflag("-Clto=off");
692 }
693
694 if target.contains("riscv") {
701 cargo.rustflag("-Cforce-unwind-tables=yes");
702 }
703
704 cargo.rustflag("-Zunstable-options");
707 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
708
709 let html_root =
710 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
711 cargo.rustflag(&html_root);
712 cargo.rustdocflag(&html_root);
713
714 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
715}
716
717#[derive(Debug, Clone, PartialEq, Eq, Hash)]
726pub struct StdLink {
727 pub compiler: Compiler,
728 pub target_compiler: Compiler,
729 pub target: TargetSelection,
730 crates: Vec<String>,
732 force_recompile: bool,
734}
735
736impl StdLink {
737 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
738 Self {
739 compiler: host_compiler,
740 target_compiler: std.build_compiler,
741 target: std.target,
742 crates: std.crates,
743 force_recompile: std.force_recompile,
744 }
745 }
746}
747
748impl Step for StdLink {
749 type Output = ();
750
751 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
752 run.never()
753 }
754
755 fn run(self, builder: &Builder<'_>) {
764 let compiler = self.compiler;
765 let target_compiler = self.target_compiler;
766 let target = self.target;
767
768 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
770 let lib = builder.sysroot_libdir_relative(self.compiler);
772 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
773 compiler: self.compiler,
774 force_recompile: self.force_recompile,
775 });
776 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
777 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
778 (libdir, hostdir)
779 } else {
780 let libdir = builder.sysroot_target_libdir(target_compiler, target);
781 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
782 (libdir, hostdir)
783 };
784
785 let is_downloaded_beta_stage0 = builder
786 .build
787 .config
788 .initial_rustc
789 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
790
791 if compiler.stage == 0 && is_downloaded_beta_stage0 {
795 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
797
798 let host = compiler.host;
799 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
800 let sysroot_bin_dir = sysroot.join("bin");
801 t!(fs::create_dir_all(&sysroot_bin_dir));
802 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
803
804 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
805 t!(fs::create_dir_all(sysroot.join("lib")));
806 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
807
808 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
810 t!(fs::create_dir_all(&sysroot_codegen_backends));
811 let stage0_codegen_backends = builder
812 .out
813 .join(host)
814 .join("stage0/lib/rustlib")
815 .join(host)
816 .join("codegen-backends");
817 if stage0_codegen_backends.exists() {
818 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
819 }
820 } else if compiler.stage == 0 {
821 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
822
823 if builder.local_rebuild {
824 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
828 }
829
830 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
831 } else {
832 if builder.download_rustc() {
833 let _ = fs::remove_dir_all(&libdir);
835 let _ = fs::remove_dir_all(&hostdir);
836 }
837
838 add_to_sysroot(
839 builder,
840 &libdir,
841 &hostdir,
842 &build_stamp::libstd_stamp(builder, compiler, target),
843 );
844 }
845 }
846}
847
848fn copy_sanitizers(
850 builder: &Builder<'_>,
851 compiler: &Compiler,
852 target: TargetSelection,
853) -> Vec<PathBuf> {
854 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
855
856 if builder.config.dry_run() {
857 return Vec::new();
858 }
859
860 let mut target_deps = Vec::new();
861 let libdir = builder.sysroot_target_libdir(*compiler, target);
862
863 for runtime in &runtimes {
864 let dst = libdir.join(&runtime.name);
865 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
866
867 if target == "x86_64-apple-darwin"
871 || target == "aarch64-apple-darwin"
872 || target == "aarch64-apple-ios"
873 || target == "aarch64-apple-ios-sim"
874 || target == "x86_64-apple-ios"
875 {
876 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
878 apple_darwin_sign_file(builder, &dst);
881 }
882
883 target_deps.push(dst);
884 }
885
886 target_deps
887}
888
889fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
890 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
891}
892
893fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
894 command("codesign")
895 .arg("-f") .arg("-s")
897 .arg("-")
898 .arg(file_path)
899 .run(builder);
900}
901
902#[derive(Debug, Clone, PartialEq, Eq, Hash)]
903pub struct StartupObjects {
904 pub compiler: Compiler,
905 pub target: TargetSelection,
906}
907
908impl Step for StartupObjects {
909 type Output = Vec<(PathBuf, DependencyType)>;
910
911 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
912 run.path("library/rtstartup")
913 }
914
915 fn make_run(run: RunConfig<'_>) {
916 run.builder.ensure(StartupObjects {
917 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
918 target: run.target,
919 });
920 }
921
922 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
929 let for_compiler = self.compiler;
930 let target = self.target;
931 if !target.is_windows_gnu() {
934 return vec![];
935 }
936
937 let mut target_deps = vec![];
938
939 let src_dir = &builder.src.join("library").join("rtstartup");
940 let dst_dir = &builder.native_dir(target).join("rtstartup");
941 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
942 t!(fs::create_dir_all(dst_dir));
943
944 for file in &["rsbegin", "rsend"] {
945 let src_file = &src_dir.join(file.to_string() + ".rs");
946 let dst_file = &dst_dir.join(file.to_string() + ".o");
947 if !up_to_date(src_file, dst_file) {
948 let mut cmd = command(&builder.initial_rustc);
949 cmd.env("RUSTC_BOOTSTRAP", "1");
950 if !builder.local_rebuild {
951 cmd.arg("--cfg").arg("bootstrap");
953 }
954 cmd.arg("--target")
955 .arg(target.rustc_target_arg())
956 .arg("--emit=obj")
957 .arg("-o")
958 .arg(dst_file)
959 .arg(src_file)
960 .run(builder);
961 }
962
963 let obj = sysroot_dir.join((*file).to_string() + ".o");
964 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
965 target_deps.push((obj, DependencyType::Target));
966 }
967
968 target_deps
969 }
970}
971
972fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
973 let ci_rustc_dir = builder.config.ci_rustc_dir();
974
975 for file in contents {
976 let src = ci_rustc_dir.join(&file);
977 let dst = sysroot.join(file);
978 if src.is_dir() {
979 t!(fs::create_dir_all(dst));
980 } else {
981 builder.copy_link(&src, &dst, FileType::Regular);
982 }
983 }
984}
985
986#[derive(Clone, Debug)]
988pub struct BuiltRustc {
989 pub build_compiler: Compiler,
993}
994
995#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1002pub struct Rustc {
1003 pub target: TargetSelection,
1005 pub build_compiler: Compiler,
1007 crates: Vec<String>,
1013}
1014
1015impl Rustc {
1016 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
1017 Self { target, build_compiler, crates: Default::default() }
1018 }
1019}
1020
1021impl Step for Rustc {
1022 type Output = BuiltRustc;
1023 const IS_HOST: bool = true;
1024
1025 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1026 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1027 for (i, krate) in crates.iter().enumerate() {
1028 if krate.name == "rustc-main" {
1031 crates.swap_remove(i);
1032 break;
1033 }
1034 }
1035 run.crates(crates)
1036 }
1037
1038 fn is_default_step(_builder: &Builder<'_>) -> bool {
1039 false
1040 }
1041
1042 fn make_run(run: RunConfig<'_>) {
1043 if run.builder.paths == vec![PathBuf::from("compiler")] {
1046 return;
1047 }
1048
1049 let crates = run.cargo_crates_in_set();
1050 run.builder.ensure(Rustc {
1051 build_compiler: run
1052 .builder
1053 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1054 target: run.target,
1055 crates,
1056 });
1057 }
1058
1059 fn run(self, builder: &Builder<'_>) -> Self::Output {
1065 let build_compiler = self.build_compiler;
1066 let target = self.target;
1067
1068 if builder.download_rustc() && build_compiler.stage != 0 {
1071 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1072
1073 let sysroot =
1074 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1075 cp_rustc_component_to_ci_sysroot(
1076 builder,
1077 &sysroot,
1078 builder.config.ci_rustc_dev_contents(),
1079 );
1080 return BuiltRustc { build_compiler };
1081 }
1082
1083 builder.std(build_compiler, target);
1086
1087 if builder.config.keep_stage.contains(&build_compiler.stage) {
1088 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1089
1090 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1091 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1092 builder.ensure(RustcLink::from_rustc(self));
1093
1094 return BuiltRustc { build_compiler };
1095 }
1096
1097 let stage = build_compiler.stage + 1;
1099
1100 if build_compiler.stage >= 2
1105 && !builder.config.full_bootstrap
1106 && target == builder.host_target
1107 {
1108 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1112
1113 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1114 builder.info(&msg);
1115
1116 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1120 uplift_build_compiler,
1122 build_compiler,
1124 target,
1125 self.crates,
1126 ));
1127
1128 return BuiltRustc { build_compiler: uplift_build_compiler };
1131 }
1132
1133 builder.std(
1139 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1140 builder.config.host_target,
1141 );
1142
1143 let mut cargo = builder::Cargo::new(
1144 builder,
1145 build_compiler,
1146 Mode::Rustc,
1147 SourceType::InTree,
1148 target,
1149 Kind::Build,
1150 );
1151
1152 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1153
1154 for krate in &*self.crates {
1158 cargo.arg("-p").arg(krate);
1159 }
1160
1161 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1162 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1164 }
1165
1166 let _guard = builder.msg(
1167 Kind::Build,
1168 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1169 Mode::Rustc,
1170 build_compiler,
1171 target,
1172 );
1173 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1174
1175 run_cargo(
1176 builder,
1177 cargo,
1178 vec![],
1179 &stamp,
1180 vec![],
1181 ArtifactKeepMode::Custom(Box::new(|filename| {
1182 if filename.contains("jemalloc_sys")
1183 || filename.contains("rustc_public_bridge")
1184 || filename.contains("rustc_public")
1185 {
1186 filename.ends_with(".rlib")
1189 } else {
1190 filename.ends_with(".rmeta")
1194 }
1195 })),
1196 );
1197
1198 let target_root_dir = stamp.path().parent().unwrap();
1199 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1205 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1206 {
1207 let rustc_driver = target_root_dir.join("librustc_driver.so");
1208 strip_debug(builder, target, &rustc_driver);
1209 }
1210
1211 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1212 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1215 }
1216
1217 builder.ensure(RustcLink::from_rustc(self));
1218 BuiltRustc { build_compiler }
1219 }
1220
1221 fn metadata(&self) -> Option<StepMetadata> {
1222 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1223 }
1224}
1225
1226pub fn rustc_cargo(
1227 builder: &Builder<'_>,
1228 cargo: &mut Cargo,
1229 target: TargetSelection,
1230 build_compiler: &Compiler,
1231 crates: &[String],
1232) {
1233 cargo
1234 .arg("--features")
1235 .arg(builder.rustc_features(builder.kind, target, crates))
1236 .arg("--manifest-path")
1237 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1238
1239 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1240
1241 cargo.rustflag("-Zon-broken-pipe=kill");
1255
1256 if builder.build.config.bootstrap_override_lld.is_used() {
1261 cargo.rustflag("-Zdefault-visibility=protected");
1262 }
1263
1264 if is_lto_stage(build_compiler) {
1265 match builder.config.rust_lto {
1266 RustcLto::Thin | RustcLto::Fat => {
1267 cargo.rustflag("-Zdylib-lto");
1270 let lto_type = match builder.config.rust_lto {
1274 RustcLto::Thin => "thin",
1275 RustcLto::Fat => "fat",
1276 _ => unreachable!(),
1277 };
1278 cargo.rustflag(&format!("-Clto={lto_type}"));
1279 cargo.rustflag("-Cembed-bitcode=yes");
1280 }
1281 RustcLto::ThinLocal => { }
1282 RustcLto::Off => {
1283 cargo.rustflag("-Clto=off");
1284 }
1285 }
1286 } else if builder.config.rust_lto == RustcLto::Off {
1287 cargo.rustflag("-Clto=off");
1288 }
1289
1290 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1298 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1299 }
1300
1301 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1302 panic!("Cannot use and generate PGO profiles at the same time");
1303 }
1304 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1305 if build_compiler.stage == 1 {
1306 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1307 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1310 true
1311 } else {
1312 false
1313 }
1314 } else if let Some(path) = &builder.config.rust_profile_use {
1315 if build_compiler.stage == 1 {
1316 cargo.rustflag(&format!("-Cprofile-use={path}"));
1317 if builder.is_verbose() {
1318 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1319 }
1320 true
1321 } else {
1322 false
1323 }
1324 } else {
1325 false
1326 };
1327 if is_collecting {
1328 cargo.rustflag(&format!(
1330 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1331 builder.config.src.components().count()
1332 ));
1333 }
1334
1335 if let Some(ref ccache) = builder.config.ccache
1340 && build_compiler.stage == 0
1341 && !builder.config.incremental
1342 {
1343 cargo.env("RUSTC_WRAPPER", ccache);
1344 }
1345
1346 rustc_cargo_env(builder, cargo, target);
1347}
1348
1349pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1350 cargo
1353 .env("CFG_RELEASE", builder.rust_release())
1354 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1355 .env("CFG_VERSION", builder.rust_version());
1356
1357 if builder.config.omit_git_hash {
1361 cargo.env("CFG_OMIT_GIT_HASH", "1");
1362 }
1363
1364 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1365
1366 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1367 let target_config = builder.config.target_config.get(&target);
1368
1369 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1370
1371 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1372 cargo.env("CFG_VER_DATE", ver_date);
1373 }
1374 if let Some(ref ver_hash) = builder.rust_info().sha() {
1375 cargo.env("CFG_VER_HASH", ver_hash);
1376 }
1377 if !builder.unstable_features() {
1378 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1379 }
1380
1381 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1384 cargo.env("CFG_DEFAULT_LINKER", s);
1385 } else if let Some(ref s) = builder.config.rustc_default_linker {
1386 cargo.env("CFG_DEFAULT_LINKER", s);
1387 }
1388
1389 if let Some(linker) = target_config.map(|c| c.default_linker_linux_override) {
1391 match linker {
1392 DefaultLinuxLinkerOverride::Off => {}
1393 DefaultLinuxLinkerOverride::SelfContainedLldCc => {
1394 cargo.env("CFG_DEFAULT_LINKER_SELF_CONTAINED_LLD_CC", "1");
1395 }
1396 }
1397 }
1398
1399 if builder.config.rust_verify_llvm_ir {
1400 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1401 }
1402
1403 if builder.config.llvm_enabled(target) {
1415 let building_llvm_is_expensive =
1416 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1417 .should_build();
1418
1419 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1420 if !skip_llvm {
1421 rustc_llvm_env(builder, cargo, target)
1422 }
1423 }
1424
1425 if builder.config.jemalloc(target) && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
1427 if target.starts_with("aarch64") {
1430 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1431 }
1432 else if target.starts_with("loongarch") {
1434 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1435 }
1436 }
1437}
1438
1439fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1445 if builder.config.is_rust_llvm(target) {
1446 cargo.env("LLVM_RUSTLLVM", "1");
1447 }
1448 if builder.config.llvm_enzyme {
1449 cargo.env("LLVM_ENZYME", "1");
1450 }
1451 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1452 if builder.config.llvm_offload {
1453 builder.ensure(llvm::OmpOffload { target });
1454 cargo.env("LLVM_OFFLOAD", "1");
1455 }
1456
1457 cargo.env("LLVM_CONFIG", &host_llvm_config);
1458
1459 let mut llvm_linker_flags = String::new();
1469 if builder.config.llvm_profile_generate
1470 && target.is_msvc()
1471 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1472 {
1473 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1475 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1476 }
1477
1478 if let Some(ref s) = builder.config.llvm_ldflags {
1480 if !llvm_linker_flags.is_empty() {
1481 llvm_linker_flags.push(' ');
1482 }
1483 llvm_linker_flags.push_str(s);
1484 }
1485
1486 if !llvm_linker_flags.is_empty() {
1488 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1489 }
1490
1491 if builder.config.llvm_static_stdcpp
1494 && !target.contains("freebsd")
1495 && !target.is_msvc()
1496 && !target.contains("apple")
1497 && !target.contains("solaris")
1498 {
1499 let libstdcxx_name =
1500 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1501 let file = compiler_file(
1502 builder,
1503 &builder.cxx(target).unwrap(),
1504 target,
1505 CLang::Cxx,
1506 libstdcxx_name,
1507 );
1508 cargo.env("LLVM_STATIC_STDCPP", file);
1509 }
1510 if builder.llvm_link_shared() {
1511 cargo.env("LLVM_LINK_SHARED", "1");
1512 }
1513 if builder.config.llvm_use_libcxx {
1514 cargo.env("LLVM_USE_LIBCXX", "1");
1515 }
1516 if builder.config.llvm_assertions {
1517 cargo.env("LLVM_ASSERTIONS", "1");
1518 }
1519}
1520
1521#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1534struct RustcLink {
1535 build_compiler: Compiler,
1537 sysroot_compiler: Compiler,
1540 target: TargetSelection,
1541 crates: Vec<String>,
1543}
1544
1545impl RustcLink {
1546 fn from_rustc(rustc: Rustc) -> Self {
1549 Self {
1550 build_compiler: rustc.build_compiler,
1551 sysroot_compiler: rustc.build_compiler,
1552 target: rustc.target,
1553 crates: rustc.crates,
1554 }
1555 }
1556
1557 fn from_build_compiler_and_sysroot(
1559 build_compiler: Compiler,
1560 sysroot_compiler: Compiler,
1561 target: TargetSelection,
1562 crates: Vec<String>,
1563 ) -> Self {
1564 Self { build_compiler, sysroot_compiler, target, crates }
1565 }
1566}
1567
1568impl Step for RustcLink {
1569 type Output = ();
1570
1571 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1572 run.never()
1573 }
1574
1575 fn run(self, builder: &Builder<'_>) {
1577 let build_compiler = self.build_compiler;
1578 let sysroot_compiler = self.sysroot_compiler;
1579 let target = self.target;
1580 add_to_sysroot(
1581 builder,
1582 &builder.sysroot_target_libdir(sysroot_compiler, target),
1583 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1584 &build_stamp::librustc_stamp(builder, build_compiler, target),
1585 );
1586 }
1587}
1588
1589#[derive(Clone)]
1595pub struct GccDylibSet {
1596 dylibs: BTreeMap<GccTargetPair, GccOutput>,
1597}
1598
1599impl GccDylibSet {
1600 pub fn build(
1603 builder: &Builder<'_>,
1604 host: TargetSelection,
1605 targets: Vec<TargetSelection>,
1606 ) -> Self {
1607 let dylibs = targets
1608 .iter()
1609 .map(|t| GccTargetPair::for_target_pair(host, *t))
1610 .map(|target_pair| (target_pair, builder.ensure(Gcc { target_pair })))
1611 .collect();
1612 Self { dylibs }
1613 }
1614
1615 pub fn install_to(&self, builder: &Builder<'_>, compiler: Compiler) {
1619 if builder.config.dry_run() {
1620 return;
1621 }
1622
1623 let cg_sysroot = builder.sysroot_codegen_backends(compiler);
1625
1626 for (target_pair, libgccjit) in &self.dylibs {
1627 assert_eq!(
1628 target_pair.host(),
1629 compiler.host,
1630 "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",
1631 compiler.host
1632 );
1633 let libgccjit = libgccjit.libgccjit();
1634 let target_filename = libgccjit.file_name().unwrap().to_str().unwrap();
1635
1636 let actual_libgccjit_path = t!(
1640 libgccjit.canonicalize(),
1641 format!("Cannot find libgccjit at {}", libgccjit.display())
1642 );
1643
1644 let dest_dir = cg_sysroot.join("lib").join(target_pair.target());
1646 t!(fs::create_dir_all(&dest_dir));
1647 let dst = dest_dir.join(target_filename);
1648 builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
1649 }
1650 }
1651}
1652
1653#[derive(Clone)]
1657pub struct GccCodegenBackendOutput {
1658 stamp: BuildStamp,
1659}
1660
1661impl GccCodegenBackendOutput {
1662 pub fn stamp(&self) -> &BuildStamp {
1663 &self.stamp
1664 }
1665}
1666
1667#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1674pub struct GccCodegenBackend {
1675 compilers: RustcPrivateCompilers,
1676 target: TargetSelection,
1677}
1678
1679impl GccCodegenBackend {
1680 pub fn for_target(compilers: RustcPrivateCompilers, target: TargetSelection) -> Self {
1682 Self { compilers, target }
1683 }
1684}
1685
1686impl Step for GccCodegenBackend {
1687 type Output = GccCodegenBackendOutput;
1688
1689 const IS_HOST: bool = true;
1690
1691 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1692 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1693 }
1694
1695 fn make_run(run: RunConfig<'_>) {
1696 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target);
1697 run.builder.ensure(GccCodegenBackend::for_target(compilers, run.target));
1698 }
1699
1700 fn run(self, builder: &Builder<'_>) -> Self::Output {
1701 let host = self.compilers.target();
1702 let build_compiler = self.compilers.build_compiler();
1703
1704 let stamp = build_stamp::codegen_backend_stamp(
1705 builder,
1706 build_compiler,
1707 host,
1708 &CodegenBackendKind::Gcc,
1709 );
1710
1711 if builder.config.keep_stage.contains(&build_compiler.stage) && stamp.path().exists() {
1712 trace!("`keep-stage` requested");
1713 builder.info(
1714 "WARNING: Using a potentially old codegen backend. \
1715 This may not behave well.",
1716 );
1717 return GccCodegenBackendOutput { stamp };
1720 }
1721
1722 let mut cargo = builder::Cargo::new(
1723 builder,
1724 build_compiler,
1725 Mode::Codegen,
1726 SourceType::InTree,
1727 host,
1728 Kind::Build,
1729 );
1730 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1731 rustc_cargo_env(builder, &mut cargo, host);
1732
1733 let _guard =
1734 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host);
1735 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
1736
1737 GccCodegenBackendOutput {
1738 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1739 }
1740 }
1741
1742 fn metadata(&self) -> Option<StepMetadata> {
1743 Some(
1744 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1745 .built_by(self.compilers.build_compiler()),
1746 )
1747 }
1748}
1749
1750#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1751pub struct CraneliftCodegenBackend {
1752 pub compilers: RustcPrivateCompilers,
1753}
1754
1755impl Step for CraneliftCodegenBackend {
1756 type Output = BuildStamp;
1757 const IS_HOST: bool = true;
1758
1759 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1760 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1761 }
1762
1763 fn make_run(run: RunConfig<'_>) {
1764 run.builder.ensure(CraneliftCodegenBackend {
1765 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1766 });
1767 }
1768
1769 fn run(self, builder: &Builder<'_>) -> Self::Output {
1770 let target = self.compilers.target();
1771 let build_compiler = self.compilers.build_compiler();
1772
1773 let stamp = build_stamp::codegen_backend_stamp(
1774 builder,
1775 build_compiler,
1776 target,
1777 &CodegenBackendKind::Cranelift,
1778 );
1779
1780 if builder.config.keep_stage.contains(&build_compiler.stage) {
1781 trace!("`keep-stage` requested");
1782 builder.info(
1783 "WARNING: Using a potentially old codegen backend. \
1784 This may not behave well.",
1785 );
1786 return stamp;
1789 }
1790
1791 let mut cargo = builder::Cargo::new(
1792 builder,
1793 build_compiler,
1794 Mode::Codegen,
1795 SourceType::InTree,
1796 target,
1797 Kind::Build,
1798 );
1799 cargo
1800 .arg("--manifest-path")
1801 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1802 rustc_cargo_env(builder, &mut cargo, target);
1803
1804 let _guard = builder.msg(
1805 Kind::Build,
1806 "codegen backend cranelift",
1807 Mode::Codegen,
1808 build_compiler,
1809 target,
1810 );
1811 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
1812 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1813 }
1814
1815 fn metadata(&self) -> Option<StepMetadata> {
1816 Some(
1817 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1818 .built_by(self.compilers.build_compiler()),
1819 )
1820 }
1821}
1822
1823fn write_codegen_backend_stamp(
1825 mut stamp: BuildStamp,
1826 files: Vec<PathBuf>,
1827 dry_run: bool,
1828) -> BuildStamp {
1829 if dry_run {
1830 return stamp;
1831 }
1832
1833 let mut files = files.into_iter().filter(|f| {
1834 let filename = f.file_name().unwrap().to_str().unwrap();
1835 is_dylib(f) && filename.contains("rustc_codegen_")
1836 });
1837 let codegen_backend = match files.next() {
1838 Some(f) => f,
1839 None => panic!("no dylibs built for codegen backend?"),
1840 };
1841 if let Some(f) = files.next() {
1842 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1843 }
1844
1845 let codegen_backend = codegen_backend.to_str().unwrap();
1846 stamp = stamp.add_stamp(codegen_backend);
1847 t!(stamp.write());
1848 stamp
1849}
1850
1851fn copy_codegen_backends_to_sysroot(
1858 builder: &Builder<'_>,
1859 stamp: BuildStamp,
1860 target_compiler: Compiler,
1861) {
1862 let dst = builder.sysroot_codegen_backends(target_compiler);
1871 t!(fs::create_dir_all(&dst), dst);
1872
1873 if builder.config.dry_run() {
1874 return;
1875 }
1876
1877 if stamp.path().exists() {
1878 let file = get_codegen_backend_file(&stamp);
1879 builder.copy_link(
1880 &file,
1881 &dst.join(normalize_codegen_backend_name(builder, &file)),
1882 FileType::NativeLibrary,
1883 );
1884 }
1885}
1886
1887pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1889 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1890}
1891
1892pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1894 let filename = path.file_name().unwrap().to_str().unwrap();
1895 let dash = filename.find('-').unwrap();
1898 let dot = filename.find('.').unwrap();
1899 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1900}
1901
1902pub fn compiler_file(
1903 builder: &Builder<'_>,
1904 compiler: &Path,
1905 target: TargetSelection,
1906 c: CLang,
1907 file: &str,
1908) -> PathBuf {
1909 if builder.config.dry_run() {
1910 return PathBuf::new();
1911 }
1912 let mut cmd = command(compiler);
1913 cmd.args(builder.cc_handled_clags(target, c));
1914 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1915 cmd.arg(format!("-print-file-name={file}"));
1916 let out = cmd.run_capture_stdout(builder).stdout();
1917 PathBuf::from(out.trim())
1918}
1919
1920#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1921pub struct Sysroot {
1922 pub compiler: Compiler,
1923 force_recompile: bool,
1925}
1926
1927impl Sysroot {
1928 pub(crate) fn new(compiler: Compiler) -> Self {
1929 Sysroot { compiler, force_recompile: false }
1930 }
1931}
1932
1933impl Step for Sysroot {
1934 type Output = PathBuf;
1935
1936 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1937 run.never()
1938 }
1939
1940 fn run(self, builder: &Builder<'_>) -> PathBuf {
1944 let compiler = self.compiler;
1945 let host_dir = builder.out.join(compiler.host);
1946
1947 let sysroot_dir = |stage| {
1948 if stage == 0 {
1949 host_dir.join("stage0-sysroot")
1950 } else if self.force_recompile && stage == compiler.stage {
1951 host_dir.join(format!("stage{stage}-test-sysroot"))
1952 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1953 host_dir.join("ci-rustc-sysroot")
1954 } else {
1955 host_dir.join(format!("stage{stage}"))
1956 }
1957 };
1958 let sysroot = sysroot_dir(compiler.stage);
1959 trace!(stage = ?compiler.stage, ?sysroot);
1960
1961 builder.do_if_verbose(|| {
1962 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1963 });
1964 let _ = fs::remove_dir_all(&sysroot);
1965 t!(fs::create_dir_all(&sysroot));
1966
1967 if compiler.stage == 0 {
1974 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1975 }
1976
1977 if builder.download_rustc() && compiler.stage != 0 {
1979 assert_eq!(
1980 builder.config.host_target, compiler.host,
1981 "Cross-compiling is not yet supported with `download-rustc`",
1982 );
1983
1984 for stage in 0..=2 {
1986 if stage != compiler.stage {
1987 let dir = sysroot_dir(stage);
1988 if !dir.ends_with("ci-rustc-sysroot") {
1989 let _ = fs::remove_dir_all(dir);
1990 }
1991 }
1992 }
1993
1994 let mut filtered_files = Vec::new();
2004 let mut add_filtered_files = |suffix, contents| {
2005 for path in contents {
2006 let path = Path::new(&path);
2007 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
2008 filtered_files.push(path.file_name().unwrap().to_owned());
2009 }
2010 }
2011 };
2012 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
2013 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
2014 add_filtered_files("lib", builder.config.ci_rust_std_contents());
2017
2018 let filtered_extensions = [
2019 OsStr::new("rmeta"),
2020 OsStr::new("rlib"),
2021 OsStr::new(std::env::consts::DLL_EXTENSION),
2023 ];
2024 let ci_rustc_dir = builder.config.ci_rustc_dir();
2025 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
2026 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
2027 return true;
2028 }
2029 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
2030 return true;
2031 }
2032 filtered_files.iter().all(|f| f != path.file_name().unwrap())
2033 });
2034 }
2035
2036 if compiler.stage != 0 {
2042 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
2043 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
2044 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
2045 if let Err(e) =
2046 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
2047 {
2048 eprintln!(
2049 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2050 sysroot_lib_rustlib_src_rust.display(),
2051 builder.src.display(),
2052 e,
2053 );
2054 if builder.config.rust_remap_debuginfo {
2055 eprintln!(
2056 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
2057 sysroot_lib_rustlib_src_rust.display(),
2058 );
2059 }
2060 build_helper::exit!(1);
2061 }
2062 }
2063
2064 if !builder.download_rustc() {
2066 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
2067 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
2068 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
2069 if let Err(e) =
2070 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
2071 {
2072 eprintln!(
2073 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2074 sysroot_lib_rustlib_rustcsrc_rust.display(),
2075 builder.src.display(),
2076 e,
2077 );
2078 build_helper::exit!(1);
2079 }
2080 }
2081
2082 sysroot
2083 }
2084}
2085
2086#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2093pub struct Assemble {
2094 pub target_compiler: Compiler,
2099}
2100
2101impl Step for Assemble {
2102 type Output = Compiler;
2103 const IS_HOST: bool = true;
2104
2105 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2106 run.path("compiler/rustc").path("compiler")
2107 }
2108
2109 fn make_run(run: RunConfig<'_>) {
2110 run.builder.ensure(Assemble {
2111 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2112 });
2113 }
2114
2115 fn run(self, builder: &Builder<'_>) -> Compiler {
2116 let target_compiler = self.target_compiler;
2117
2118 if target_compiler.stage == 0 {
2119 trace!("stage 0 build compiler is always available, simply returning");
2120 assert_eq!(
2121 builder.config.host_target, target_compiler.host,
2122 "Cannot obtain compiler for non-native build triple at stage 0"
2123 );
2124 return target_compiler;
2126 }
2127
2128 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2131 let libdir_bin = libdir.parent().unwrap().join("bin");
2132 t!(fs::create_dir_all(&libdir_bin));
2133
2134 if builder.config.llvm_enabled(target_compiler.host) {
2135 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2136
2137 let target = target_compiler.host;
2138 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2139 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2140 trace!("LLVM tools enabled");
2141
2142 let host_llvm_bin_dir = command(&host_llvm_config)
2143 .arg("--bindir")
2144 .cached()
2145 .run_capture_stdout(builder)
2146 .stdout()
2147 .trim()
2148 .to_string();
2149
2150 let llvm_bin_dir = if target == builder.host_target {
2151 PathBuf::from(host_llvm_bin_dir)
2152 } else {
2153 let external_llvm_config = builder
2156 .config
2157 .target_config
2158 .get(&target)
2159 .and_then(|t| t.llvm_config.clone());
2160 if let Some(external_llvm_config) = external_llvm_config {
2161 external_llvm_config.parent().unwrap().to_path_buf()
2164 } else {
2165 let host_llvm_out = builder.llvm_out(builder.host_target);
2169 let target_llvm_out = builder.llvm_out(target);
2170 if let Ok(relative_path) =
2171 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2172 {
2173 target_llvm_out.join(relative_path)
2174 } else {
2175 PathBuf::from(
2178 host_llvm_bin_dir
2179 .replace(&*builder.host_target.triple, &target.triple),
2180 )
2181 }
2182 }
2183 };
2184
2185 #[cfg(feature = "tracing")]
2192 let _llvm_tools_span =
2193 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2194 .entered();
2195 for tool in LLVM_TOOLS {
2196 trace!("installing `{tool}`");
2197 let tool_exe = exe(tool, target_compiler.host);
2198 let src_path = llvm_bin_dir.join(&tool_exe);
2199
2200 if !src_path.exists() && builder.config.llvm_from_ci {
2202 eprintln!("{} does not exist; skipping copy", src_path.display());
2203 continue;
2204 }
2205
2206 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2213 }
2214 }
2215 }
2216
2217 let maybe_install_llvm_bitcode_linker = || {
2218 if builder.config.llvm_bitcode_linker_enabled {
2219 trace!("llvm-bitcode-linker enabled, installing");
2220 let llvm_bitcode_linker = builder.ensure(
2221 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2222 builder,
2223 target_compiler,
2224 ),
2225 );
2226
2227 let bindir_self_contained = builder
2229 .sysroot(target_compiler)
2230 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2231 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2232
2233 t!(fs::create_dir_all(&bindir_self_contained));
2234 builder.copy_link(
2235 &llvm_bitcode_linker.tool_path,
2236 &bindir_self_contained.join(tool_exe),
2237 FileType::Executable,
2238 );
2239 }
2240 };
2241
2242 if builder.download_rustc() {
2244 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2245
2246 builder.std(target_compiler, target_compiler.host);
2247 let sysroot =
2248 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2249 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2252 if target_compiler.stage == builder.top_stage {
2254 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2255 }
2256
2257 maybe_install_llvm_bitcode_linker();
2260
2261 return target_compiler;
2262 }
2263
2264 debug!(
2278 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2279 target_compiler.stage - 1,
2280 builder.config.host_target,
2281 );
2282 let build_compiler =
2283 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2284
2285 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2287 debug!("`llvm_enzyme` requested");
2288 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2289 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2290 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2291 let lib_ext = std::env::consts::DLL_EXTENSION;
2292 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2293 let src_lib =
2294 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2295 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2296 let target_libdir =
2297 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2298 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2299 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2300 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2301 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2302 }
2303 }
2304
2305 if builder.config.llvm_offload && !builder.config.dry_run() {
2306 debug!("`llvm_offload` requested");
2307 let offload_install = builder.ensure(llvm::OmpOffload { target: build_compiler.host });
2308 if let Some(_llvm_config) = builder.llvm_config(builder.config.host_target) {
2309 let target_libdir =
2310 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2311 for p in offload_install.offload_paths() {
2312 let libname = p.file_name().unwrap();
2313 let dst_lib = target_libdir.join(libname);
2314 builder.resolve_symlink_and_copy(&p, &dst_lib);
2315 }
2316 }
2321 }
2322
2323 debug!(
2326 ?build_compiler,
2327 "target_compiler.host" = ?target_compiler.host,
2328 "building compiler libraries to link to"
2329 );
2330
2331 let BuiltRustc { build_compiler } =
2333 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2334
2335 let stage = target_compiler.stage;
2336 let host = target_compiler.host;
2337 let (host_info, dir_name) = if build_compiler.host == host {
2338 ("".into(), "host".into())
2339 } else {
2340 (format!(" ({host})"), host.to_string())
2341 };
2342 let msg = format!(
2347 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2348 );
2349 builder.info(&msg);
2350
2351 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2353 let proc_macros = builder
2354 .read_stamp_file(&stamp)
2355 .into_iter()
2356 .filter_map(|(path, dependency_type)| {
2357 if dependency_type == DependencyType::Host {
2358 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2359 } else {
2360 None
2361 }
2362 })
2363 .collect::<HashSet<_>>();
2364
2365 let sysroot = builder.sysroot(target_compiler);
2366 let rustc_libdir = builder.rustc_libdir(target_compiler);
2367 t!(fs::create_dir_all(&rustc_libdir));
2368 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2369 for f in builder.read_dir(&src_libdir) {
2370 let filename = f.file_name().into_string().unwrap();
2371
2372 let is_proc_macro = proc_macros.contains(&filename);
2373 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2374
2375 let can_be_rustc_dynamic_dep = if builder
2379 .link_std_into_rustc_driver(target_compiler.host)
2380 && !target_compiler.host.is_windows()
2381 {
2382 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2383 !is_std
2384 } else {
2385 true
2386 };
2387
2388 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2389 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2390 }
2391 }
2392
2393 {
2394 #[cfg(feature = "tracing")]
2395 let _codegen_backend_span =
2396 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2397
2398 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2399 if builder.kind == Kind::Check && builder.top_stage == 1 {
2416 continue;
2417 }
2418
2419 let prepare_compilers = || {
2420 RustcPrivateCompilers::from_build_and_target_compiler(
2421 build_compiler,
2422 target_compiler,
2423 )
2424 };
2425
2426 match backend {
2427 CodegenBackendKind::Cranelift => {
2428 let stamp = builder
2429 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2430 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2431 }
2432 CodegenBackendKind::Gcc => {
2433 let compilers = prepare_compilers();
2466 let cg_gcc = builder
2467 .ensure(GccCodegenBackend::for_target(compilers, target_compiler.host));
2468 copy_codegen_backends_to_sysroot(builder, cg_gcc.stamp, target_compiler);
2469
2470 let mut targets = HashSet::new();
2477 for target in &builder.hosts {
2480 targets.insert(*target);
2481 }
2482 for target in &builder.targets {
2484 targets.insert(*target);
2485 }
2486 targets.insert(compilers.target_compiler().host);
2489
2490 let dylib_set = GccDylibSet::build(
2492 builder,
2493 compilers.target_compiler().host,
2494 targets.into_iter().collect(),
2495 );
2496
2497 dylib_set.install_to(builder, target_compiler);
2500 }
2501 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2502 }
2503 }
2504 }
2505
2506 if builder.config.lld_enabled {
2507 let lld_wrapper =
2508 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2509 builder,
2510 target_compiler,
2511 ));
2512 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2513 }
2514
2515 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2516 debug!(
2517 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2518 workaround faulty homebrew `strip`s"
2519 );
2520
2521 let src_exe = exe("llvm-objcopy", target_compiler.host);
2528 let dst_exe = exe("rust-objcopy", target_compiler.host);
2529 builder.copy_link(
2530 &libdir_bin.join(src_exe),
2531 &libdir_bin.join(dst_exe),
2532 FileType::Executable,
2533 );
2534 }
2535
2536 if builder.tool_enabled("wasm-component-ld") {
2539 let wasm_component = builder.ensure(
2540 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2541 builder,
2542 target_compiler,
2543 ),
2544 );
2545 builder.copy_link(
2546 &wasm_component.tool_path,
2547 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2548 FileType::Executable,
2549 );
2550 }
2551
2552 maybe_install_llvm_bitcode_linker();
2553
2554 debug!(
2557 "target_compiler.host" = ?target_compiler.host,
2558 ?sysroot,
2559 "ensuring availability of `libLLVM.so` in compiler directory"
2560 );
2561 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2562 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2563
2564 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2566 let rustc = out_dir.join(exe("rustc-main", host));
2567 let bindir = sysroot.join("bin");
2568 t!(fs::create_dir_all(bindir));
2569 let compiler = builder.rustc(target_compiler);
2570 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2571 builder.copy_link(&rustc, &compiler, FileType::Executable);
2572
2573 target_compiler
2574 }
2575}
2576
2577#[track_caller]
2582pub fn add_to_sysroot(
2583 builder: &Builder<'_>,
2584 sysroot_dst: &Path,
2585 sysroot_host_dst: &Path,
2586 stamp: &BuildStamp,
2587) {
2588 let self_contained_dst = &sysroot_dst.join("self-contained");
2589 t!(fs::create_dir_all(sysroot_dst));
2590 t!(fs::create_dir_all(sysroot_host_dst));
2591 t!(fs::create_dir_all(self_contained_dst));
2592
2593 let mut crates = HashMap::new();
2594 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2595 let filename = path.file_name().unwrap().to_str().unwrap();
2596 let dst = match dependency_type {
2597 DependencyType::Host => {
2598 if sysroot_dst == sysroot_host_dst {
2599 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2602 }
2603
2604 sysroot_host_dst
2605 }
2606 DependencyType::Target => {
2607 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2610
2611 sysroot_dst
2612 }
2613 DependencyType::TargetSelfContained => self_contained_dst,
2614 };
2615 builder.copy_link(&path, &dst.join(filename), FileType::Regular);
2616 }
2617
2618 let mut seen_crates = HashMap::new();
2624 for (filestem, path) in crates {
2625 if !filestem.contains("rustc_") || filestem.contains("rustc_hash") {
2626 continue;
2627 }
2628 if let Some(other_path) =
2629 seen_crates.insert(filestem.split_once('-').unwrap().0.to_owned(), path.clone())
2630 {
2631 panic!(
2632 "duplicate rustc crate {}\n- first copy at {}\n- second copy at {}",
2633 filestem.split_once('-').unwrap().0.to_owned(),
2634 other_path.display(),
2635 path.display(),
2636 );
2637 }
2638 }
2639}
2640
2641pub enum ArtifactKeepMode {
2645 OnlyRlib,
2647 OnlyRmeta,
2649 BothRlibAndRmeta,
2653 Custom(Box<dyn Fn(&str) -> bool>),
2656}
2657
2658pub fn run_cargo(
2659 builder: &Builder<'_>,
2660 cargo: Cargo,
2661 tail_args: Vec<String>,
2662 stamp: &BuildStamp,
2663 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2664 artifact_keep_mode: ArtifactKeepMode,
2665) -> Vec<PathBuf> {
2666 let target_root_dir = stamp.path().parent().unwrap();
2668 let target_deps_dir = target_root_dir.join("deps");
2670 let host_root_dir = target_root_dir
2672 .parent()
2673 .unwrap() .parent()
2675 .unwrap() .join(target_root_dir.file_name().unwrap());
2677
2678 let mut deps = Vec::new();
2682 let mut toplevel = Vec::new();
2683 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2684 let (filenames_vec, crate_types) = match msg {
2685 CargoMessage::CompilerArtifact {
2686 filenames,
2687 target: CargoTarget { crate_types },
2688 ..
2689 } => {
2690 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2691 f.sort(); (f, crate_types)
2693 }
2694 _ => return,
2695 };
2696 for filename in filenames_vec {
2697 let keep = if filename.ends_with(".lib")
2699 || filename.ends_with(".a")
2700 || is_debug_info(&filename)
2701 || is_dylib(Path::new(&*filename))
2702 {
2703 true
2705 } else {
2706 match &artifact_keep_mode {
2707 ArtifactKeepMode::OnlyRlib => filename.ends_with(".rlib"),
2708 ArtifactKeepMode::OnlyRmeta => filename.ends_with(".rmeta"),
2709 ArtifactKeepMode::BothRlibAndRmeta => {
2710 filename.ends_with(".rmeta") || filename.ends_with(".rlib")
2711 }
2712 ArtifactKeepMode::Custom(func) => func(&filename),
2713 }
2714 };
2715
2716 if !keep {
2717 continue;
2718 }
2719
2720 let filename = Path::new(&*filename);
2721
2722 if filename.starts_with(&host_root_dir) {
2725 if crate_types.iter().any(|t| t == "proc-macro") {
2727 if filename.file_name().unwrap().to_str().unwrap().contains("-") {
2732 deps.push((filename.to_path_buf(), DependencyType::Host));
2733 }
2734 }
2735 continue;
2736 }
2737
2738 if filename.starts_with(&target_deps_dir) {
2741 deps.push((filename.to_path_buf(), DependencyType::Target));
2742 continue;
2743 }
2744
2745 let expected_len = t!(filename.metadata()).len();
2756 let filename = filename.file_name().unwrap().to_str().unwrap();
2757 let mut parts = filename.splitn(2, '.');
2758 let file_stem = parts.next().unwrap().to_owned();
2759 let extension = parts.next().unwrap().to_owned();
2760
2761 toplevel.push((file_stem, extension, expected_len));
2762 }
2763 });
2764
2765 if !ok {
2766 crate::exit!(1);
2767 }
2768
2769 if builder.config.dry_run() {
2770 return Vec::new();
2771 }
2772
2773 let contents = target_deps_dir
2777 .read_dir()
2778 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2779 .map(|e| t!(e))
2780 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2781 .collect::<Vec<_>>();
2782 for (prefix, extension, expected_len) in toplevel {
2783 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2784 meta.len() == expected_len
2785 && filename
2786 .strip_prefix(&prefix[..])
2787 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2788 .unwrap_or(false)
2789 });
2790 let max = candidates.max_by_key(|&(_, _, metadata)| {
2791 metadata.modified().expect("mtime should be available on all relevant OSes")
2792 });
2793 let path_to_add = match max {
2794 Some(triple) => triple.0.to_str().unwrap(),
2795 None => panic!("no output generated for {prefix:?} {extension:?}"),
2796 };
2797 if is_dylib(Path::new(path_to_add)) {
2798 let candidate = format!("{path_to_add}.lib");
2799 let candidate = PathBuf::from(candidate);
2800 if candidate.exists() {
2801 deps.push((candidate, DependencyType::Target));
2802 }
2803 }
2804 deps.push((path_to_add.into(), DependencyType::Target));
2805 }
2806
2807 deps.extend(additional_target_deps);
2808 deps.sort();
2809 let mut new_contents = Vec::new();
2810 for (dep, dependency_type) in deps.iter() {
2811 new_contents.extend(match *dependency_type {
2812 DependencyType::Host => b"h",
2813 DependencyType::Target => b"t",
2814 DependencyType::TargetSelfContained => b"s",
2815 });
2816 new_contents.extend(dep.to_str().unwrap().as_bytes());
2817 new_contents.extend(b"\0");
2818 }
2819 t!(fs::write(stamp.path(), &new_contents));
2820 deps.into_iter().map(|(d, _)| d).collect()
2821}
2822
2823pub fn stream_cargo(
2824 builder: &Builder<'_>,
2825 cargo: Cargo,
2826 tail_args: Vec<String>,
2827 cb: &mut dyn FnMut(CargoMessage<'_>),
2828) -> bool {
2829 let mut cmd = cargo.into_cmd();
2830
2831 let mut message_format = if builder.config.json_output {
2834 String::from("json")
2835 } else {
2836 String::from("json-render-diagnostics")
2837 };
2838 if let Some(s) = &builder.config.rustc_error_format {
2839 message_format.push_str(",json-diagnostic-");
2840 message_format.push_str(s);
2841 }
2842 cmd.arg("--message-format").arg(message_format);
2843
2844 for arg in tail_args {
2845 cmd.arg(arg);
2846 }
2847
2848 builder.do_if_verbose(|| println!("running: {cmd:?}"));
2849
2850 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2851
2852 let Some(mut streaming_command) = streaming_command else {
2853 return true;
2854 };
2855
2856 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2860 for line in stdout.lines() {
2861 let line = t!(line);
2862 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2863 Ok(msg) => {
2864 if builder.config.json_output {
2865 println!("{line}");
2867 }
2868 cb(msg)
2869 }
2870 Err(_) => println!("{line}"),
2872 }
2873 }
2874
2875 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2877 if builder.is_verbose() && !status.success() {
2878 eprintln!(
2879 "command did not execute successfully: {cmd:?}\n\
2880 expected success, got: {status}"
2881 );
2882 }
2883
2884 status.success()
2885}
2886
2887#[derive(Deserialize)]
2888pub struct CargoTarget<'a> {
2889 crate_types: Vec<Cow<'a, str>>,
2890}
2891
2892#[derive(Deserialize)]
2893#[serde(tag = "reason", rename_all = "kebab-case")]
2894pub enum CargoMessage<'a> {
2895 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2896 BuildScriptExecuted,
2897 BuildFinished,
2898}
2899
2900pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2901 if target != "x86_64-unknown-linux-gnu"
2905 || !builder.config.is_host_target(target)
2906 || !path.exists()
2907 {
2908 return;
2909 }
2910
2911 let previous_mtime = t!(t!(path.metadata()).modified());
2912 let stamp = BuildStamp::new(path.parent().unwrap())
2913 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2914 .with_prefix("strip")
2915 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2916
2917 if !stamp.is_up_to_date() {
2920 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2921 }
2922 t!(stamp.write());
2923
2924 let file = t!(fs::File::open(path));
2925
2926 t!(file.set_modified(previous_mtime));
2939}
2940
2941pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2943 build_compiler.stage != 0
2944}