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::backend::CodegenBackendKind;
23use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair};
24use crate::core::build_steps::llvm::{LlvmFromCi, prebuilt_llvm_output};
25use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
26use crate::core::build_steps::{dist, llvm};
27use crate::core::builder::{
28 self, Builder, Cargo, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata,
29 apply_pgo, crate_description,
30};
31use crate::core::compiler::Compiler;
32use crate::core::config::toml::target::DefaultLinuxLinkerOverride;
33use crate::core::config::{
34 Allocator, CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
35};
36use crate::core::session::{CLang, DependencyType, FileType, GitRepo, Mode};
37use crate::utils::build_stamp;
38use crate::utils::build_stamp::BuildStamp;
39use crate::utils::exec::command;
40use crate::utils::helpers::{
41 self, exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
42};
43use crate::{debug, trace};
44
45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
47pub struct Std {
48 pub target: TargetSelection,
49 pub build_compiler: Compiler,
51 crates: Vec<String>,
55 force_recompile: bool,
58 extra_rust_args: &'static [&'static str],
59 is_for_mir_opt_tests: bool,
60}
61
62impl Std {
63 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
64 Self {
65 target,
66 build_compiler,
67 crates: Default::default(),
68 force_recompile: false,
69 extra_rust_args: &[],
70 is_for_mir_opt_tests: false,
71 }
72 }
73
74 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
75 self.force_recompile = force_recompile;
76 self
77 }
78
79 #[expect(clippy::wrong_self_convention)]
80 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
81 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
82 self
83 }
84
85 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
86 self.extra_rust_args = extra_rust_args;
87 self
88 }
89
90 fn copy_extra_objects(
91 &self,
92 builder: &Builder<'_>,
93 compiler: &Compiler,
94 target: TargetSelection,
95 ) -> Vec<(PathBuf, DependencyType)> {
96 let mut deps = Vec::new();
97 if !self.is_for_mir_opt_tests {
98 deps.extend(copy_third_party_objects(builder, compiler, target));
99 deps.extend(copy_self_contained_objects(builder, compiler, target));
100 }
101 deps
102 }
103
104 pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool {
109 stage > 1 && !builder.config.full_bootstrap
110 }
111}
112
113impl CommandLineStep for Std {
114 type Output = Option<BuildStamp>;
116
117 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
118 run.crate_or_deps("sysroot").path("library")
119 }
120
121 fn is_default_step(_builder: &Builder<'_>) -> bool {
122 true
123 }
124
125 fn make_run(run: RunConfig<'_>) {
126 let crates = std_crates_for_make_run(&run);
127 let builder = run.builder;
128
129 let force_recompile = builder.rust_info().is_managed_git_subrepository()
133 && builder.download_rustc()
134 && builder.config.has_changes_from_upstream(&["library"]);
135
136 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
137 trace!("download_rustc: {}", builder.download_rustc());
138 trace!(force_recompile);
139
140 run.builder.ensure(Std {
141 build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target),
144 target: run.target,
145 crates,
146 force_recompile,
147 extra_rust_args: &[],
148 is_for_mir_opt_tests: false,
149 });
150 }
151
152 fn run(self, builder: &Builder<'_>) -> Self::Output {
158 let target = self.target;
159
160 if self.build_compiler.stage == 0
165 && !(builder.local_rebuild && target != builder.host_target)
166 {
167 let compiler = self.build_compiler;
168 builder.ensure(StdLink::from_std(self, compiler));
169
170 return None;
171 }
172
173 let build_compiler = if builder.download_rustc() && self.force_recompile {
174 builder
177 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
178 } else {
179 self.build_compiler
180 };
181
182 if builder.download_rustc()
185 && builder.config.is_host_target(target)
186 && !self.force_recompile
187 {
188 let sysroot =
189 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
190 cp_rustc_component_to_ci_sysroot(
191 builder,
192 &sysroot,
193 builder.config.ci_rust_std_contents(),
194 );
195 return None;
196 }
197
198 if builder.config.keep_stage.contains(&build_compiler.stage)
199 || builder.config.keep_stage_std.contains(&build_compiler.stage)
200 {
201 trace!(keep_stage = ?builder.config.keep_stage);
202 trace!(keep_stage_std = ?builder.config.keep_stage_std);
203
204 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
205
206 builder.ensure(StartupObjects { compiler: build_compiler, target });
207
208 self.copy_extra_objects(builder, &build_compiler, target);
209
210 builder.ensure(StdLink::from_std(self, build_compiler));
211 return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
212 }
213
214 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
215
216 let stage = build_compiler.stage;
218
219 if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
220 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
221 let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
222
223 let msg = if build_compiler_for_std_to_uplift.host == target {
224 format!(
225 "Uplifting library (stage{} -> stage{stage})",
226 build_compiler_for_std_to_uplift.stage
227 )
228 } else {
229 format!(
230 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
231 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
232 )
233 };
234
235 builder.info(&msg);
236
237 self.copy_extra_objects(builder, &build_compiler, target);
240
241 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
242 return stage_1_stamp;
243 }
244
245 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
246
247 let mut cargo = if self.is_for_mir_opt_tests {
251 trace!("building special sysroot for mir-opt tests");
252 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
253 builder,
254 build_compiler,
255 Mode::Std,
256 SourceType::InTree,
257 target,
258 Kind::Check,
259 );
260 cargo.rustflag("-Zalways-encode-mir");
261 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
262 cargo
263 } else {
264 trace!("building regular sysroot");
265 let mut cargo = builder::Cargo::new(
266 builder,
267 build_compiler,
268 Mode::Std,
269 SourceType::InTree,
270 target,
271 Kind::Build,
272 );
273 std_cargo(builder, target, &mut cargo, &self.crates);
274 cargo
275 };
276
277 if target.is_synthetic() {
279 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
280 }
281 for rustflag in self.extra_rust_args.iter() {
282 cargo.rustflag(rustflag);
283 }
284
285 let _guard = builder.msg(
286 Kind::Build,
287 format_args!("library artifacts{}", crate_description(&self.crates)),
288 Mode::Std,
289 build_compiler,
290 target,
291 );
292
293 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
294 run_cargo(
295 builder,
296 cargo,
297 vec![],
298 &stamp,
299 target_deps,
300 if self.is_for_mir_opt_tests {
301 ArtifactKeepMode::OnlyRmeta
302 } else {
303 ArtifactKeepMode::BothRlibAndRmeta
305 },
306 );
307
308 builder.ensure(StdLink::from_std(
309 self,
310 builder.compiler(build_compiler.stage, builder.config.host_target),
311 ));
312 Some(stamp)
313 }
314
315 fn metadata(&self) -> Option<StepMetadata> {
316 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
317 }
318}
319
320fn copy_and_stamp(
321 builder: &Builder<'_>,
322 libdir: &Path,
323 sourcedir: &Path,
324 name: &str,
325 target_deps: &mut Vec<(PathBuf, DependencyType)>,
326 dependency_type: DependencyType,
327) {
328 let target = libdir.join(name);
329 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
330
331 target_deps.push((target, dependency_type));
332}
333
334fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
335 let libunwind_path = builder.ensure(llvm::Libunwind { target });
336 let libunwind_source = libunwind_path.join("libunwind.a");
337 let libunwind_target = libdir.join("libunwind.a");
338 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
339 libunwind_target
340}
341
342fn copy_third_party_objects(
344 builder: &Builder<'_>,
345 compiler: &Compiler,
346 target: TargetSelection,
347) -> Vec<(PathBuf, DependencyType)> {
348 let mut target_deps = vec![];
349
350 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
351 target_deps.extend(
354 copy_sanitizers(builder, compiler, target)
355 .into_iter()
356 .map(|d| (d, DependencyType::Target)),
357 );
358 }
359
360 if target == "x86_64-fortanix-unknown-sgx"
361 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
362 && (target.contains("linux")
363 || target.contains("fuchsia")
364 || target.contains("aix")
365 || target.contains("hexagon"))
366 {
367 let libunwind_path =
368 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
369 target_deps.push((libunwind_path, DependencyType::Target));
370 }
371
372 target_deps
373}
374
375fn copy_self_contained_objects(
377 builder: &Builder<'_>,
378 compiler: &Compiler,
379 target: TargetSelection,
380) -> Vec<(PathBuf, DependencyType)> {
381 let libdir_self_contained =
382 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
383 t!(fs::create_dir_all(&libdir_self_contained));
384 let mut target_deps = vec![];
385
386 if target.needs_crt_begin_end() {
394 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
395 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
396 });
397 if !target.starts_with("wasm32") {
398 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
399 copy_and_stamp(
400 builder,
401 &libdir_self_contained,
402 &srcdir,
403 obj,
404 &mut target_deps,
405 DependencyType::TargetSelfContained,
406 );
407 }
408 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
409 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
410 let src = crt_path.join(obj);
411 let target = libdir_self_contained.join(obj);
412 builder.copy_link(&src, &target, FileType::NativeLibrary);
413 target_deps.push((target, DependencyType::TargetSelfContained));
414 }
415 } else {
416 for &obj in &["libc.a", "crt1-command.o"] {
419 copy_and_stamp(
420 builder,
421 &libdir_self_contained,
422 &srcdir,
423 obj,
424 &mut target_deps,
425 DependencyType::TargetSelfContained,
426 );
427 }
428 }
429 if !target.starts_with("s390x") {
430 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
431 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
432 }
433 } else if target.contains("-wasi") {
434 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
435 panic!(
436 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
437 or `$WASI_SDK_PATH` set",
438 target.triple
439 )
440 });
441
442 let srcdir = if target == "wasm32-wasip3" {
446 assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now");
447 builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap()
448 } else {
449 srcdir
450 };
451 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
452 copy_and_stamp(
453 builder,
454 &libdir_self_contained,
455 &srcdir,
456 obj,
457 &mut target_deps,
458 DependencyType::TargetSelfContained,
459 );
460 }
461 if srcdir.join("eh").exists() {
462 copy_and_stamp(
463 builder,
464 &libdir_self_contained,
465 &srcdir.join("eh"),
466 "libunwind.a",
467 &mut target_deps,
468 DependencyType::TargetSelfContained,
469 );
470 }
471 } else if target.is_windows_gnu() || target.is_windows_gnullvm() {
472 for obj in ["crt2.o", "dllcrt2.o"].iter() {
473 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
474 let dst = libdir_self_contained.join(obj);
475 builder.copy_link(&src, &dst, FileType::NativeLibrary);
476 target_deps.push((dst, DependencyType::TargetSelfContained));
477 }
478 }
479
480 target_deps
481}
482
483pub fn std_crates_for_make_run(run: &RunConfig<'_>) -> Vec<String> {
486 let mut crates = run.make_run_crates(builder::Alias::Library);
487
488 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
497 if target_is_no_std {
498 crates.retain(|c| c == "core" || c == "alloc");
499 }
500 crates
501}
502
503fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
509 if let Some(downloaded_llvm) = builder.ensure(LlvmFromCi { target: builder.host_target }) {
511 let ci_llvm_compiler_rt = downloaded_llvm.output.root_dir().join("compiler-rt");
512 if !builder.config.dry_run() {
513 assert!(
514 ci_llvm_compiler_rt.exists(),
515 "compiler-rt sources not found in LLVM downloaded from CI at {ci_llvm_compiler_rt:?}"
516 );
517 }
518 return ci_llvm_compiler_rt;
519 }
520
521 builder.require_submodule("src/llvm-project", {
523 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
524 });
525 builder.src.join("src/llvm-project/compiler-rt")
526}
527
528pub fn std_cargo(
531 builder: &Builder<'_>,
532 target: TargetSelection,
533 cargo: &mut Cargo,
534 crates: &[String],
535) {
536 if target.contains("apple") && !builder.config.dry_run() {
554 let mut cmd = builder.rustc_cmd(cargo.compiler());
558 cmd.arg("--target").arg(target.rustc_target_arg());
559 cmd.arg("-Zunstable-options").env("RUSTC_BOOTSTRAP", "1");
562 cmd.arg("--print=deployment-target");
563 let output = cmd.run_capture_stdout(builder).stdout();
564
565 let (env_var, value) = output.split_once('=').unwrap();
566 cargo.env(env_var.trim(), value.trim());
569
570 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
580 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
581 }
582 }
583
584 if let Some(path) = builder.config.profiler_path(target) {
586 cargo.env("LLVM_PROFILER_RT_LIB", path);
587 } else if builder.config.profiler_enabled(target) {
588 let compiler_rt = compiler_rt_for_profiler(builder);
589 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
593 }
594
595 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
609 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
610 cargo.env("LLVM_COMPILER_RT_LIB", path);
611 " compiler-builtins-c"
612 }
613 CompilerBuiltins::BuildLLVMFuncs => {
614 builder.require_submodule(
624 "src/llvm-project",
625 Some(
626 "The `build.optimized-compiler-builtins` config option \
627 requires `compiler-rt` sources from LLVM.",
628 ),
629 );
630 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
631 if !builder.config.dry_run() {
632 assert!(compiler_builtins_root.exists());
635 }
636
637 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
640 " compiler-builtins-c"
641 }
642 CompilerBuiltins::BuildRustOnly => "",
643 };
644
645 for krate in crates {
646 cargo.args(["-p", krate]);
647 }
648
649 let mut features = String::new();
650
651 if builder.no_std(target) == Some(true) {
652 features += " compiler-builtins-mem";
653 if !target.starts_with("bpf") {
654 features.push_str(compiler_builtins_c_feature);
655 }
656
657 if crates.is_empty() {
659 cargo.args(["-p", "alloc"]);
660 }
661 cargo
662 .arg("--manifest-path")
663 .arg(builder.src.join("library/alloc/Cargo.toml"))
664 .arg("--features")
665 .arg(features);
666 } else {
667 features += &builder.std_features(target);
668 features.push_str(compiler_builtins_c_feature);
669
670 cargo
671 .arg("--features")
672 .arg(features)
673 .arg("--manifest-path")
674 .arg(builder.src.join("library/sysroot/Cargo.toml"));
675
676 if target.contains("musl")
679 && let Some(p) = builder.musl_libdir(target)
680 {
681 let root = format!("native={}", p.to_str().unwrap());
682 cargo.rustflag("-L").rustflag(&root);
683 }
684
685 if target.contains("-wasi")
686 && let Some(dir) = builder.wasi_libdir(target)
687 {
688 let root = format!("native={}", dir.to_str().unwrap());
689 cargo.rustflag("-L").rustflag(&root);
690 }
691 }
692
693 if builder.config.rust_lto == RustcLto::Off {
694 cargo.rustflag("-Clto=off");
695 }
696
697 if target.contains("riscv") {
704 cargo.rustflag("-Cforce-unwind-tables=yes");
705 }
706
707 let html_root =
708 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
709 cargo.rustflag(&html_root);
710 cargo.rustdocflag(&html_root);
711
712 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
713}
714
715#[derive(Debug, Clone, PartialEq, Eq, Hash)]
724pub struct StdLink {
725 pub compiler: Compiler,
726 pub target_compiler: Compiler,
727 pub target: TargetSelection,
728 crates: Vec<String>,
730 force_recompile: bool,
732}
733
734impl StdLink {
735 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
736 Self {
737 compiler: host_compiler,
738 target_compiler: std.build_compiler,
739 target: std.target,
740 crates: std.crates,
741 force_recompile: std.force_recompile,
742 }
743 }
744}
745
746impl Step for StdLink {
747 type Output = ();
748
749 fn run(self, builder: &Builder<'_>) {
758 let compiler = self.compiler;
759 let target_compiler = self.target_compiler;
760 let target = self.target;
761
762 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
764 let lib = builder.sysroot_libdir_relative(self.compiler);
766 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
767 compiler: self.compiler,
768 force_recompile: self.force_recompile,
769 });
770 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
771 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
772 (libdir, hostdir)
773 } else {
774 let libdir = builder.sysroot_target_libdir(target_compiler, target);
775 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
776 (libdir, hostdir)
777 };
778
779 let is_downloaded_beta_stage0 = builder
780 .sess
781 .initial_rustc
782 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
783
784 if compiler.stage == 0 && is_downloaded_beta_stage0 {
788 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
790
791 let host = compiler.host;
792 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
793 let sysroot_bin_dir = sysroot.join("bin");
794 t!(fs::create_dir_all(&sysroot_bin_dir));
795 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
796
797 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
798 t!(fs::create_dir_all(sysroot.join("lib")));
799 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
800
801 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
803 t!(fs::create_dir_all(&sysroot_codegen_backends));
804 let stage0_codegen_backends = builder
805 .out
806 .join(host)
807 .join("stage0/lib/rustlib")
808 .join(host)
809 .join("codegen-backends");
810 if stage0_codegen_backends.exists() {
811 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
812 }
813 } else if compiler.stage == 0 {
814 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
815
816 if builder.local_rebuild {
817 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
821 }
822
823 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
824 } else {
825 if builder.download_rustc() {
826 let _ = fs::remove_dir_all(&libdir);
828 let _ = fs::remove_dir_all(&hostdir);
829 }
830
831 add_to_sysroot(
832 builder,
833 &libdir,
834 &hostdir,
835 &build_stamp::libstd_stamp(builder, compiler, target),
836 );
837 }
838 }
839}
840
841fn copy_sanitizers(
843 builder: &Builder<'_>,
844 compiler: &Compiler,
845 target: TargetSelection,
846) -> Vec<PathBuf> {
847 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
848
849 if builder.config.dry_run() {
850 return Vec::new();
851 }
852
853 let mut target_deps = Vec::new();
854 let libdir = builder.sysroot_target_libdir(*compiler, target);
855
856 for runtime in &runtimes {
857 let dst = libdir.join(&runtime.name);
858 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
859
860 if target == "x86_64-apple-darwin"
864 || target == "aarch64-apple-darwin"
865 || target == "aarch64-apple-ios"
866 || target == "aarch64-apple-ios-sim"
867 || target == "x86_64-apple-ios"
868 {
869 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
871 apple_darwin_sign_file(builder, &dst);
874 }
875
876 target_deps.push(dst);
877 }
878
879 target_deps
880}
881
882fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
883 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
884}
885
886fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
887 command("codesign")
888 .arg("-f") .arg("-s")
890 .arg("-")
891 .arg(file_path)
892 .run(builder);
893}
894
895#[derive(Debug, Clone, PartialEq, Eq, Hash)]
896pub struct StartupObjects {
897 pub compiler: Compiler,
898 pub target: TargetSelection,
899}
900
901impl CommandLineStep for StartupObjects {
902 type Output = Vec<(PathBuf, DependencyType)>;
903
904 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
905 run.path("library/rtstartup")
906 }
907
908 fn make_run(run: RunConfig<'_>) {
909 run.builder.ensure(StartupObjects {
910 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
911 target: run.target,
912 });
913 }
914
915 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
922 let for_compiler = self.compiler;
923 let target = self.target;
924 if !target.is_windows_gnu() {
927 return vec![];
928 }
929
930 let mut target_deps = vec![];
931
932 let src_dir = &builder.src.join("library").join("rtstartup");
933 let dst_dir = &builder.native_dir(target).join("rtstartup");
934 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
935 t!(fs::create_dir_all(dst_dir));
936
937 for file in &["rsbegin", "rsend"] {
938 let src_file = &src_dir.join(file.to_string() + ".rs");
939 let dst_file = &dst_dir.join(file.to_string() + ".o");
940 if !up_to_date(src_file, dst_file) {
941 let mut cmd = command(&builder.initial_rustc);
942 cmd.env("RUSTC_BOOTSTRAP", "1");
943 if !builder.local_rebuild {
944 cmd.arg("--cfg").arg("bootstrap");
946 }
947 cmd.arg("--target")
948 .arg(target.rustc_target_arg())
949 .arg("--emit=obj")
950 .arg("-o")
951 .arg(dst_file)
952 .arg(src_file)
953 .run(builder);
954 }
955
956 let obj = sysroot_dir.join((*file).to_string() + ".o");
957 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
958 target_deps.push((obj, DependencyType::Target));
959 }
960
961 target_deps
962 }
963}
964
965fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
966 let ci_rustc_dir = builder.config.ci_rustc_dir();
967
968 for file in contents {
969 let src = ci_rustc_dir.join(&file);
970 let dst = sysroot.join(file);
971 if src.is_dir() {
972 t!(fs::create_dir_all(dst));
973 } else {
974 builder.copy_link(&src, &dst, FileType::Regular);
975 }
976 }
977}
978
979#[derive(Clone, Debug)]
981pub struct BuiltRustc {
982 pub build_compiler: Compiler,
986}
987
988#[derive(Debug, Clone, PartialEq, Eq, Hash)]
995pub struct Rustc {
996 pub target: TargetSelection,
998 pub build_compiler: Compiler,
1000 crates: Vec<String>,
1006}
1007
1008impl Rustc {
1009 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
1010 Self { target, build_compiler, crates: Default::default() }
1011 }
1012}
1013
1014impl CommandLineStep for Rustc {
1015 type Output = BuiltRustc;
1016 const IS_HOST: bool = true;
1017
1018 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1019 run.crate_or_deps_filtered("rustc-main", |krate| {
1020 krate.name != "rustc-main"
1023 })
1024 }
1025
1026 fn is_default_step(_builder: &Builder<'_>) -> bool {
1027 false
1028 }
1029
1030 fn make_run(run: RunConfig<'_>) {
1031 if run.builder.paths == vec![PathBuf::from("compiler")] {
1034 return;
1035 }
1036
1037 let crates = run.cargo_crates_in_set();
1038 run.builder.ensure(Rustc {
1039 build_compiler: run
1040 .builder
1041 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1042 target: run.target,
1043 crates,
1044 });
1045 }
1046
1047 fn run(self, builder: &Builder<'_>) -> Self::Output {
1053 let build_compiler = self.build_compiler;
1054 let target = self.target;
1055
1056 if builder.download_rustc() && build_compiler.stage != 0 {
1059 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1060
1061 let sysroot =
1062 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1063 cp_rustc_component_to_ci_sysroot(
1064 builder,
1065 &sysroot,
1066 builder.config.ci_rustc_dev_contents(),
1067 );
1068 return BuiltRustc { build_compiler };
1069 }
1070
1071 builder.std(build_compiler, target);
1074
1075 if builder.config.keep_stage.contains(&build_compiler.stage) {
1076 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1077
1078 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1079 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1080 builder.ensure(RustcLink::from_rustc(self));
1081
1082 return BuiltRustc { build_compiler };
1083 }
1084
1085 let stage = build_compiler.stage + 1;
1087
1088 if build_compiler.stage >= 2
1093 && !builder.config.full_bootstrap
1094 && target == builder.host_target
1095 {
1096 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1100
1101 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1102 builder.info(&msg);
1103
1104 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1108 uplift_build_compiler,
1110 build_compiler,
1112 target,
1113 self.crates,
1114 ));
1115
1116 return BuiltRustc { build_compiler: uplift_build_compiler };
1119 }
1120
1121 builder.std(
1127 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1128 builder.config.host_target,
1129 );
1130
1131 let mut cargo = builder::Cargo::new(
1132 builder,
1133 build_compiler,
1134 Mode::Rustc,
1135 SourceType::InTree,
1136 target,
1137 Kind::Build,
1138 );
1139
1140 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1141
1142 for krate in &*self.crates {
1146 cargo.arg("-p").arg(krate);
1147 }
1148
1149 if builder.sess.config.enable_bolt_settings && build_compiler.stage == 1 {
1150 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1152 }
1153
1154 let _guard = builder.msg(
1155 Kind::Build,
1156 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1157 Mode::Rustc,
1158 build_compiler,
1159 target,
1160 );
1161 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1162
1163 run_cargo(
1164 builder,
1165 cargo,
1166 vec![],
1167 &stamp,
1168 vec![],
1169 ArtifactKeepMode::Custom(Box::new(|filename| {
1170 if filename.contains("jemalloc_sys")
1171 || filename.contains("rustc_public_bridge")
1172 || filename.contains("rustc_public")
1173 {
1174 if filename.ends_with(".rlib") {
1177 return true;
1178 }
1179 }
1180
1181 filename.ends_with(".rmeta")
1185 })),
1186 );
1187
1188 let target_root_dir = stamp.path().parent().unwrap();
1189 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1195 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1196 {
1197 let rustc_driver = target_root_dir.join("librustc_driver.so");
1198 strip_debug(builder, target, &rustc_driver);
1199 }
1200
1201 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1202 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1205 }
1206
1207 builder.ensure(RustcLink::from_rustc(self));
1208 BuiltRustc { build_compiler }
1209 }
1210
1211 fn metadata(&self) -> Option<StepMetadata> {
1212 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1213 }
1214}
1215
1216pub fn rustc_cargo(
1217 builder: &Builder<'_>,
1218 cargo: &mut Cargo,
1219 target: TargetSelection,
1220 build_compiler: &Compiler,
1221 crates: &[String],
1222) {
1223 let kind = cargo.kind();
1224 cargo
1225 .arg("--features")
1226 .arg(builder.rustc_features(kind, target, crates))
1227 .arg("--manifest-path")
1228 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1229
1230 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1231
1232 cargo.rustflag("-Zon-broken-pipe=kill");
1246
1247 if target.is_msvc() {
1252 cargo.rustflag("-Clink-arg=/Brepro");
1253 }
1254
1255 if builder.sess.config.bootstrap_override_lld.is_used() {
1260 cargo.rustflag("-Zdefault-visibility=protected");
1261 }
1262
1263 if is_lto_stage(build_compiler) {
1264 match builder.config.rust_lto {
1265 RustcLto::Thin | RustcLto::Fat => {
1266 cargo.rustflag("-Zdylib-lto");
1269 let lto_type = match builder.config.rust_lto {
1273 RustcLto::Thin => "thin",
1274 RustcLto::Fat => "fat",
1275 _ => unreachable!(),
1276 };
1277 cargo.rustflag(&format!("-Clto={lto_type}"));
1278 cargo.rustflag("-Cembed-bitcode=yes");
1279 }
1280 RustcLto::ThinLocal => { }
1281 RustcLto::Off => {
1282 cargo.rustflag("-Clto=off");
1283 }
1284 }
1285 } else if builder.config.rust_lto == RustcLto::Off {
1286 cargo.rustflag("-Clto=off");
1287 }
1288
1289 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1297 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1298 }
1299
1300 apply_pgo(builder, cargo, *build_compiler, &builder.config.rust_pgo);
1301
1302 if let Some(ref ccache) = builder.config.ccache
1310 && build_compiler.stage == 0
1311 && !cfg!(windows)
1312 && !builder.config.incremental
1313 {
1314 cargo.env("RUSTC_WRAPPER", ccache);
1315 }
1316
1317 rustc_cargo_env(builder, cargo, target);
1318}
1319
1320fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1321 cargo
1324 .env("CFG_RELEASE", builder.rust_release())
1325 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1326 .env("CFG_VERSION", builder.rust_version());
1327
1328 if builder.config.omit_git_hash {
1332 cargo.env("CFG_OMIT_GIT_HASH", "1");
1333 }
1334
1335 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1336
1337 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1338 let target_config = builder.config.target_config.get(&target);
1339
1340 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1341
1342 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1343 cargo.env("CFG_VER_DATE", ver_date);
1344 }
1345 if let Some(ref ver_hash) = builder.rust_info().sha() {
1346 cargo.env("CFG_VER_HASH", ver_hash);
1347 }
1348 if !builder.unstable_features() {
1349 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1350 }
1351
1352 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1355 cargo.env("CFG_DEFAULT_LINKER", s);
1356 } else if let Some(ref s) = builder.config.rustc_default_linker {
1357 cargo.env("CFG_DEFAULT_LINKER", s);
1358 }
1359
1360 if let Some(linker) = target_config.map(|c| c.default_linker_linux_override) {
1362 match linker {
1363 DefaultLinuxLinkerOverride::Off => {}
1364 DefaultLinuxLinkerOverride::SelfContainedLldCc => {
1365 cargo.env("CFG_DEFAULT_LINKER_SELF_CONTAINED_LLD_CC", "1");
1366 }
1367 }
1368 }
1369
1370 cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple);
1372
1373 if builder.config.rust_verify_llvm_ir {
1374 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1375 }
1376
1377 let nightly = builder.config.channel == "nightly" || builder.config.channel == "dev";
1378 if nightly {
1379 cargo.env("CFG_DEFAULT_POLONIUS_NEXT", "1");
1381 cargo.env("CFG_DEFAULT_NEXT_SOLVER_GLOBALLY", "1");
1382 }
1383
1384 if builder.config.llvm_enabled(target) {
1405 let building_llvm_is_expensive = prebuilt_llvm_output(builder, target).is_none();
1406
1407 let skip_llvm = cargo.kind().is_check_like() && building_llvm_is_expensive;
1408 if skip_llvm {
1409 cargo.env("RUST_CHECK", "1");
1410 } else {
1411 rustc_llvm_env(builder, cargo, target);
1412 }
1413 }
1414
1415 if builder.config.allocator(target) == Allocator::Jemalloc
1417 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1418 {
1419 if target.starts_with("aarch64") {
1422 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1423 }
1424 else if target.starts_with("loongarch") {
1426 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1427 }
1428 }
1429}
1430
1431fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1437 let llvm_output = builder.ensure(llvm::Llvm { target });
1438 if builder.config.is_rust_llvm(&llvm_output, target) {
1439 cargo.env("LLVM_RUSTLLVM", "1");
1440 }
1441 if builder.config.llvm_enzyme {
1442 cargo.env("LLVM_ENZYME", "1");
1443 }
1444 if builder.config.llvm_offload {
1445 builder.ensure(llvm::OmpOffload { target });
1446 cargo.env("LLVM_OFFLOAD", "1");
1447 }
1448
1449 cargo.env("LLVM_CONFIG", builder.host_llvm_config());
1451
1452 let mut llvm_linker_flags = String::new();
1462 if builder.config.llvm_pgo.generate_profile.is_some()
1463 && target.is_msvc()
1464 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1465 {
1466 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1468 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1469 }
1470
1471 if let Some(ref s) = builder.config.llvm_ldflags {
1473 if !llvm_linker_flags.is_empty() {
1474 llvm_linker_flags.push(' ');
1475 }
1476 llvm_linker_flags.push_str(s);
1477 }
1478
1479 if !llvm_linker_flags.is_empty() {
1481 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1482 }
1483
1484 if builder.config.llvm_static_stdcpp
1487 && !target.contains("freebsd")
1488 && !target.is_msvc()
1489 && !target.contains("apple")
1490 && !target.contains("solaris")
1491 {
1492 let libstdcxx_name =
1493 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1494 let file = compiler_file(
1495 builder,
1496 &builder.cxx(target).unwrap(),
1497 target,
1498 CLang::Cxx,
1499 libstdcxx_name,
1500 );
1501 cargo.env("LLVM_STATIC_STDCPP", file);
1502 }
1503 if llvm_output.link_shared() {
1504 cargo.env("LLVM_LINK_SHARED", "1");
1505 }
1506 if builder.config.llvm_use_libcxx {
1507 cargo.env("LLVM_USE_LIBCXX", "1");
1508 }
1509 if builder.config.llvm_assertions {
1510 cargo.env("LLVM_ASSERTIONS", "1");
1511 }
1512 if builder.cxx_tool(target).is_like_gnu() || builder.cc_tool(target).is_like_gnu() {
1513 cargo.env("LLVM_COMPILER_IS_GNU_LIKE", "1");
1514 }
1515}
1516
1517#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1530struct RustcLink {
1531 build_compiler: Compiler,
1533 sysroot_compiler: Compiler,
1536 target: TargetSelection,
1537 crates: Vec<String>,
1539}
1540
1541impl RustcLink {
1542 fn from_rustc(rustc: Rustc) -> Self {
1545 Self {
1546 build_compiler: rustc.build_compiler,
1547 sysroot_compiler: rustc.build_compiler,
1548 target: rustc.target,
1549 crates: rustc.crates,
1550 }
1551 }
1552
1553 fn from_build_compiler_and_sysroot(
1555 build_compiler: Compiler,
1556 sysroot_compiler: Compiler,
1557 target: TargetSelection,
1558 crates: Vec<String>,
1559 ) -> Self {
1560 Self { build_compiler, sysroot_compiler, target, crates }
1561 }
1562}
1563
1564impl Step for RustcLink {
1565 type Output = ();
1566
1567 fn run(self, builder: &Builder<'_>) {
1569 let build_compiler = self.build_compiler;
1570 let sysroot_compiler = self.sysroot_compiler;
1571 let target = self.target;
1572 add_to_sysroot(
1573 builder,
1574 &builder.sysroot_target_libdir(sysroot_compiler, target),
1575 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1576 &build_stamp::librustc_stamp(builder, build_compiler, target),
1577 );
1578 }
1579}
1580
1581#[derive(Clone)]
1587pub struct GccDylibSet {
1588 dylibs: BTreeMap<GccTargetPair, GccOutput>,
1589}
1590
1591impl GccDylibSet {
1592 pub fn build(
1595 builder: &Builder<'_>,
1596 host: TargetSelection,
1597 targets: Vec<TargetSelection>,
1598 ) -> Self {
1599 let dylibs = targets
1600 .iter()
1601 .map(|t| GccTargetPair::for_target_pair(host, *t))
1602 .map(|target_pair| (target_pair, builder.ensure(Gcc { target_pair })))
1603 .collect();
1604 Self { dylibs }
1605 }
1606
1607 pub fn install_to(&self, builder: &Builder<'_>, compiler: Compiler) {
1611 if builder.config.dry_run() {
1612 return;
1613 }
1614
1615 let cg_sysroot = builder.sysroot_codegen_backends(compiler);
1617
1618 for (target_pair, libgccjit) in &self.dylibs {
1619 assert_eq!(
1620 target_pair.host(),
1621 compiler.host,
1622 "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",
1623 compiler.host
1624 );
1625 let libgccjit_path = libgccjit.libgccjit();
1626
1627 let libgccjit_path = t!(
1631 libgccjit_path.canonicalize(),
1632 format!("Cannot find libgccjit at {}", libgccjit_path.display())
1633 );
1634
1635 let dst = cg_sysroot.join(libgccjit_path_relative_to_cg_dir(target_pair, libgccjit));
1636 t!(std::fs::create_dir_all(dst.parent().unwrap()));
1637 builder.copy_link(&libgccjit_path, &dst, FileType::NativeLibrary);
1638 }
1639 }
1640}
1641
1642pub fn libgccjit_path_relative_to_cg_dir(
1645 target_pair: &GccTargetPair,
1646 libgccjit: &GccOutput,
1647) -> PathBuf {
1648 let target_filename = libgccjit.libgccjit().file_name().unwrap().to_str().unwrap();
1649
1650 Path::new("lib").join(target_pair.target()).join(target_filename)
1652}
1653
1654#[derive(Clone)]
1658pub struct GccCodegenBackendOutput {
1659 stamp: BuildStamp,
1660}
1661
1662impl GccCodegenBackendOutput {
1663 pub fn stamp(&self) -> &BuildStamp {
1664 &self.stamp
1665 }
1666}
1667
1668#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1675pub struct GccCodegenBackend {
1676 compilers: RustcPrivateCompilers,
1677 target: TargetSelection,
1678}
1679
1680impl GccCodegenBackend {
1681 pub fn for_target(compilers: RustcPrivateCompilers, target: TargetSelection) -> Self {
1683 Self { compilers, target }
1684 }
1685}
1686
1687impl CommandLineStep for GccCodegenBackend {
1688 type Output = GccCodegenBackendOutput;
1689
1690 const IS_HOST: bool = true;
1691
1692 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1693 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1694 }
1695
1696 fn make_run(run: RunConfig<'_>) {
1697 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target);
1698 run.builder.ensure(GccCodegenBackend::for_target(compilers, run.target));
1699 }
1700
1701 fn run(self, builder: &Builder<'_>) -> Self::Output {
1702 let host = self.compilers.target();
1703 let build_compiler = self.compilers.build_compiler();
1704
1705 let stamp = build_stamp::codegen_backend_stamp(
1706 builder,
1707 build_compiler,
1708 host,
1709 &CodegenBackendKind::Gcc,
1710 );
1711
1712 if builder.config.keep_stage.contains(&build_compiler.stage) && stamp.path().exists() {
1713 trace!("`keep-stage` requested");
1714 builder.info(
1715 "WARNING: Using a potentially old codegen backend. \
1716 This may not behave well.",
1717 );
1718 return GccCodegenBackendOutput { stamp };
1721 }
1722
1723 let mut cargo = builder::Cargo::new(
1724 builder,
1725 build_compiler,
1726 Mode::Codegen,
1727 SourceType::InTree,
1728 host,
1729 Kind::Build,
1730 );
1731 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
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::OnlyDylib);
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 CommandLineStep 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
1803 let _guard = builder.msg(
1804 Kind::Build,
1805 "codegen backend cranelift",
1806 Mode::Codegen,
1807 build_compiler,
1808 target,
1809 );
1810 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyDylib);
1811 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1812 }
1813
1814 fn metadata(&self) -> Option<StepMetadata> {
1815 Some(
1816 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1817 .built_by(self.compilers.build_compiler()),
1818 )
1819 }
1820}
1821
1822fn write_codegen_backend_stamp(
1824 mut stamp: BuildStamp,
1825 files: Vec<PathBuf>,
1826 dry_run: bool,
1827) -> BuildStamp {
1828 if dry_run {
1829 return stamp;
1830 }
1831
1832 let mut files = files.into_iter().filter(|f| looks_like_codegen_backend(Path::new(f)));
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
1847pub fn looks_like_codegen_backend(path: &Path) -> bool {
1848 is_dylib(path)
1849 && path.file_name().and_then(|p| p.to_str()).is_some_and(|n| n.contains("rustc_codegen_"))
1850}
1851
1852fn copy_codegen_backends_to_sysroot(
1859 builder: &Builder<'_>,
1860 stamp: BuildStamp,
1861 target_compiler: Compiler,
1862) {
1863 let dst = builder.sysroot_codegen_backends(target_compiler);
1872 t!(fs::create_dir_all(&dst), dst);
1873
1874 if builder.config.dry_run() {
1875 return;
1876 }
1877
1878 if stamp.path().exists() {
1879 let file = get_codegen_backend_file(&stamp);
1880 builder.copy_link(
1881 &file,
1882 &dst.join(normalize_codegen_backend_name(builder, &file)),
1883 FileType::NativeLibrary,
1884 );
1885 }
1886}
1887
1888pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1890 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1891}
1892
1893pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1895 let filename = path.file_name().unwrap().to_str().unwrap();
1896 let dash = filename.find('-').unwrap();
1899 let dot = filename.find('.').unwrap();
1900 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1901}
1902
1903pub fn compiler_file(
1904 builder: &Builder<'_>,
1905 compiler: &Path,
1906 target: TargetSelection,
1907 c: CLang,
1908 file: &str,
1909) -> PathBuf {
1910 if builder.config.dry_run() {
1911 return PathBuf::new();
1912 }
1913 let mut cmd = command(compiler);
1914 cmd.args(builder.cc_handled_cflags(target, c));
1915 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1916 cmd.arg(format!("-print-file-name={file}"));
1917 let out = cmd.run_capture_stdout(builder).stdout();
1918 PathBuf::from(out.trim())
1919}
1920
1921#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1922pub struct Sysroot {
1923 pub compiler: Compiler,
1924 force_recompile: bool,
1926}
1927
1928impl Sysroot {
1929 pub(crate) fn new(compiler: Compiler) -> Self {
1930 Sysroot { compiler, force_recompile: false }
1931 }
1932}
1933
1934impl Step for Sysroot {
1935 type Output = PathBuf;
1936
1937 fn run(self, builder: &Builder<'_>) -> PathBuf {
1941 let compiler = self.compiler;
1942 let host_dir = builder.out.join(compiler.host);
1943
1944 let sysroot_dir = |stage| {
1945 if stage == 0 {
1946 host_dir.join("stage0-sysroot")
1947 } else if self.force_recompile && stage == compiler.stage {
1948 host_dir.join(format!("stage{stage}-test-sysroot"))
1949 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1950 host_dir.join("ci-rustc-sysroot")
1951 } else {
1952 host_dir.join(format!("stage{stage}"))
1953 }
1954 };
1955 let sysroot = sysroot_dir(compiler.stage);
1956 trace!(stage = ?compiler.stage, ?sysroot);
1957
1958 builder.do_if_verbose(|| {
1959 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1960 });
1961 let _ = fs::remove_dir_all(&sysroot);
1962 t!(fs::create_dir_all(&sysroot));
1963
1964 if compiler.stage == 0 {
1971 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1972 }
1973
1974 if builder.download_rustc() && compiler.stage != 0 {
1976 assert_eq!(
1977 builder.config.host_target, compiler.host,
1978 "Cross-compiling is not yet supported with `download-rustc`",
1979 );
1980
1981 for stage in 0..=2 {
1983 if stage != compiler.stage {
1984 let dir = sysroot_dir(stage);
1985 if !dir.ends_with("ci-rustc-sysroot") {
1986 let _ = fs::remove_dir_all(dir);
1987 }
1988 }
1989 }
1990
1991 let mut filtered_files = Vec::new();
2005 let mut add_filtered_files = |suffix, contents| {
2006 for path in contents {
2007 let path = Path::new(&path);
2008 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
2009 filtered_files.push(path.file_name().unwrap().to_owned());
2010 }
2011 }
2012 };
2013 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
2014 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
2015 add_filtered_files("lib", builder.config.ci_rust_std_contents());
2018
2019 let filtered_extensions = [
2020 OsStr::new("rmeta"),
2021 OsStr::new("rlib"),
2022 OsStr::new(std::env::consts::DLL_EXTENSION),
2024 ];
2025 let ci_rustc_dir = builder.config.ci_rustc_dir();
2026 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
2027 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
2028 return true;
2029 }
2030 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
2031 return true;
2032 }
2033 filtered_files.iter().all(|f| f != path.file_name().unwrap())
2034 });
2035 }
2036
2037 if compiler.stage != 0 {
2043 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
2044 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
2045 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
2046 if let Err(e) =
2047 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
2048 {
2049 eprintln!(
2050 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2051 sysroot_lib_rustlib_src_rust.display(),
2052 builder.src.display(),
2053 e,
2054 );
2055 if builder.config.rust_remap_debuginfo {
2056 eprintln!(
2057 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
2058 sysroot_lib_rustlib_src_rust.display(),
2059 );
2060 }
2061 helpers::exit_process(1);
2062 }
2063 }
2064
2065 if !builder.download_rustc() {
2067 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
2068 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
2069 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
2070 if let Err(e) =
2071 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
2072 {
2073 eprintln!(
2074 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2075 sysroot_lib_rustlib_rustcsrc_rust.display(),
2076 builder.src.display(),
2077 e,
2078 );
2079 helpers::exit_process(1);
2080 }
2081 }
2082
2083 sysroot
2084 }
2085}
2086
2087#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2094pub struct Assemble {
2095 pub target_compiler: Compiler,
2100}
2101
2102impl CommandLineStep for Assemble {
2103 type Output = Compiler;
2104 const IS_HOST: bool = true;
2105
2106 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2107 run.path("compiler/rustc").path("compiler")
2108 }
2109
2110 fn make_run(run: RunConfig<'_>) {
2111 run.builder.ensure(Assemble {
2112 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2113 });
2114 }
2115
2116 fn run(self, builder: &Builder<'_>) -> Compiler {
2117 let target_compiler = self.target_compiler;
2118
2119 if target_compiler.stage == 0 {
2120 trace!("stage 0 build compiler is always available, simply returning");
2121 assert_eq!(
2122 builder.config.host_target, target_compiler.host,
2123 "Cannot obtain compiler for non-native build triple at stage 0"
2124 );
2125 return target_compiler;
2127 }
2128
2129 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2132 let libdir_bin = libdir.parent().unwrap().join("bin");
2133 t!(fs::create_dir_all(&libdir_bin));
2134
2135 if builder.config.llvm_enabled(target_compiler.host) {
2136 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2137
2138 let target = target_compiler.host;
2139 let llvm_output = builder.ensure(llvm::Llvm { target });
2140 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2141 trace!("LLVM tools enabled");
2142
2143 let host_llvm = builder.ensure(llvm::Llvm { target: builder.host_target });
2144 let host_llvm_bin_dir = command(host_llvm.llvm_config())
2145 .arg("--bindir")
2146 .cached()
2147 .run_capture_stdout(builder)
2148 .stdout()
2149 .trim()
2150 .to_string();
2151
2152 let llvm_bin_dir = if target == builder.host_target {
2153 PathBuf::from(host_llvm_bin_dir)
2154 } else {
2155 let external_llvm_config = builder
2158 .config
2159 .target_config
2160 .get(&target)
2161 .and_then(|t| t.llvm_config.clone());
2162 if let Some(external_llvm_config) = external_llvm_config {
2163 external_llvm_config.parent().unwrap().to_path_buf()
2166 } else {
2167 let host_llvm_out = host_llvm.root_dir();
2171 let target_llvm_out = llvm_output.root_dir();
2172 if let Ok(relative_path) =
2173 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2174 {
2175 target_llvm_out.join(relative_path)
2176 } else {
2177 PathBuf::from(
2180 host_llvm_bin_dir
2181 .replace(&*builder.host_target.triple, &target.triple),
2182 )
2183 }
2184 }
2185 };
2186
2187 #[cfg(feature = "tracing")]
2194 let _llvm_tools_span =
2195 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2196 .entered();
2197 for tool in dist::LLVM_TOOLS {
2198 trace!("installing `{tool}`");
2199 let tool_exe = exe(tool, target_compiler.host);
2200 let src_path = llvm_bin_dir.join(&tool_exe);
2201
2202 if !src_path.exists() {
2203 if builder.config.llvm_ci_mode.download_from_ci() {
2205 eprintln!("{} does not exist; skipping copy", src_path.display());
2206 continue;
2207 }
2208 if *tool == "llubi" {
2211 continue;
2212 }
2213 }
2214
2215 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2222 }
2223 }
2224 }
2225
2226 let maybe_install_llvm_bitcode_linker = || {
2227 if builder.config.llvm_bitcode_linker_enabled {
2228 trace!("llvm-bitcode-linker enabled, installing");
2229 let llvm_bitcode_linker = builder.ensure(
2230 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2231 builder,
2232 target_compiler,
2233 ),
2234 );
2235
2236 let bindir_self_contained = builder
2238 .sysroot(target_compiler)
2239 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2240 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2241
2242 t!(fs::create_dir_all(&bindir_self_contained));
2243 builder.copy_link(
2244 &llvm_bitcode_linker.tool_path,
2245 &bindir_self_contained.join(tool_exe),
2246 FileType::Executable,
2247 );
2248 }
2249 };
2250
2251 if builder.download_rustc() {
2253 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2254
2255 builder.std(target_compiler, target_compiler.host);
2256 let sysroot =
2257 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2258 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2261 if target_compiler.stage == builder.top_stage {
2263 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2264 }
2265
2266 maybe_install_llvm_bitcode_linker();
2269
2270 return target_compiler;
2271 }
2272
2273 debug!(
2287 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2288 target_compiler.stage - 1,
2289 builder.config.host_target,
2290 );
2291 let build_compiler =
2292 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2293
2294 if builder.config.llvm_enzyme {
2296 debug!("`llvm_enzyme` requested");
2297 let enzyme = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2298 let target_libdir =
2299 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2300 let target_dst_lib = target_libdir.join(enzyme.enzyme_filename());
2301 builder.copy_link(&enzyme.enzyme_path(), &target_dst_lib, FileType::NativeLibrary);
2302 }
2303
2304 if builder.config.llvm_offload && !builder.config.dry_run() {
2305 debug!("`llvm_offload` requested");
2306 if builder.is_llvm_enabled_for(builder.config.host_target) {
2307 let rust_offload =
2308 builder.ensure(llvm::RustOffload { target: build_compiler.host });
2309 let target_libdir =
2310 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2311 let rust_offload_dst_lib = target_libdir.join(rust_offload.rust_offload_filename());
2312 builder.copy_link(
2313 &rust_offload.rust_offload_path(),
2314 &rust_offload_dst_lib,
2315 FileType::NativeLibrary,
2316 );
2317
2318 let omp_offload = builder.ensure(llvm::OmpOffload { target: build_compiler.host });
2319 for p in omp_offload.artifact_paths_with_symlink_targets() {
2320 let libname = p.file_name().unwrap();
2321 let dst_lib = target_libdir.join(libname);
2322 builder.resolve_symlink_and_copy(&p, &dst_lib);
2323 }
2324 }
2325 }
2326
2327 debug!(
2330 ?build_compiler,
2331 "target_compiler.host" = ?target_compiler.host,
2332 "building compiler libraries to link to"
2333 );
2334
2335 let BuiltRustc { build_compiler } =
2337 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2338
2339 let stage = target_compiler.stage;
2340 let host = target_compiler.host;
2341 let (host_info, dir_name) = if build_compiler.host == host {
2342 ("".into(), "host".into())
2343 } else {
2344 (format!(" ({host})"), host.to_string())
2345 };
2346 let msg = format!(
2351 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2352 );
2353 builder.info(&msg);
2354
2355 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2357 let proc_macros = builder
2358 .read_stamp_file(&stamp)
2359 .into_iter()
2360 .filter_map(|(path, dependency_type)| {
2361 if dependency_type == DependencyType::Host {
2362 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2363 } else {
2364 None
2365 }
2366 })
2367 .collect::<HashSet<_>>();
2368
2369 let sysroot = builder.sysroot(target_compiler);
2370 let rustc_libdir = builder.rustc_libdir(target_compiler);
2371 t!(fs::create_dir_all(&rustc_libdir));
2372 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2373 for f in builder.read_dir(&src_libdir) {
2374 let filename = f.file_name().into_string().unwrap();
2375
2376 let is_proc_macro = proc_macros.contains(&filename);
2377 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2378
2379 let can_be_rustc_dynamic_dep =
2381 !(filename.starts_with("std-") || filename.starts_with("libstd-"));
2382
2383 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2384 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2385 }
2386 }
2387
2388 {
2389 #[cfg(feature = "tracing")]
2390 let _codegen_backend_span =
2391 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2392
2393 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2394 if builder.kind == Kind::Check && builder.top_stage == 1 {
2411 continue;
2412 }
2413
2414 let prepare_compilers = || {
2415 RustcPrivateCompilers::from_build_and_target_compiler(
2416 build_compiler,
2417 target_compiler,
2418 )
2419 };
2420
2421 match backend {
2422 CodegenBackendKind::Cranelift => {
2423 let stamp = builder
2424 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2425 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2426 }
2427 CodegenBackendKind::Gcc => {
2428 let compilers = prepare_compilers();
2461 let cg_gcc = builder
2462 .ensure(GccCodegenBackend::for_target(compilers, target_compiler.host));
2463 copy_codegen_backends_to_sysroot(builder, cg_gcc.stamp, target_compiler);
2464
2465 let mut targets = HashSet::new();
2472 for target in &builder.hosts {
2475 targets.insert(*target);
2476 }
2477 for target in &builder.targets {
2479 targets.insert(*target);
2480 }
2481 targets.insert(compilers.target_compiler().host);
2484
2485 let dylib_set = GccDylibSet::build(
2487 builder,
2488 compilers.target_compiler().host,
2489 targets.into_iter().collect(),
2490 );
2491
2492 dylib_set.install_to(builder, target_compiler);
2495 }
2496 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2497 }
2498 }
2499 }
2500
2501 if builder.config.lld_enabled {
2502 let lld_wrapper =
2503 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2504 builder,
2505 target_compiler,
2506 ));
2507 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2508 }
2509
2510 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2511 debug!(
2512 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2513 workaround faulty homebrew `strip`s"
2514 );
2515
2516 let src_exe = exe("llvm-objcopy", target_compiler.host);
2523 let dst_exe = exe("rust-objcopy", target_compiler.host);
2524 builder.copy_link(
2525 &libdir_bin.join(src_exe),
2526 &libdir_bin.join(dst_exe),
2527 FileType::Executable,
2528 );
2529 }
2530
2531 if builder.tool_enabled("wasm-component-ld") {
2534 let wasm_component = builder.ensure(
2535 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2536 builder,
2537 target_compiler,
2538 ),
2539 );
2540 builder.copy_link(
2541 &wasm_component.tool_path,
2542 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2543 FileType::Executable,
2544 );
2545 }
2546
2547 maybe_install_llvm_bitcode_linker();
2548
2549 debug!(
2552 "target_compiler.host" = ?target_compiler.host,
2553 ?sysroot,
2554 "ensuring availability of `libLLVM.so` in compiler directory"
2555 );
2556 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2557 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2558
2559 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2561 let rustc = out_dir.join(exe("rustc-main", host));
2562 let bindir = sysroot.join("bin");
2563 t!(fs::create_dir_all(bindir));
2564 let compiler = builder.rustc(target_compiler);
2565 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2566 builder.copy_link(&rustc, &compiler, FileType::Executable);
2567
2568 target_compiler
2569 }
2570}
2571
2572#[track_caller]
2577pub fn add_to_sysroot(
2578 builder: &Builder<'_>,
2579 sysroot_dst: &Path,
2580 sysroot_host_dst: &Path,
2581 stamp: &BuildStamp,
2582) {
2583 let self_contained_dst = &sysroot_dst.join("self-contained");
2584 t!(fs::create_dir_all(sysroot_dst));
2585 t!(fs::create_dir_all(sysroot_host_dst));
2586 t!(fs::create_dir_all(self_contained_dst));
2587
2588 let mut crates = HashMap::new();
2589 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2590 let filename = path.file_name().unwrap().to_str().unwrap();
2591 let dst = match dependency_type {
2592 DependencyType::Host => {
2593 if sysroot_dst == sysroot_host_dst {
2594 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2597 }
2598
2599 sysroot_host_dst
2600 }
2601 DependencyType::Target => {
2602 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2605
2606 sysroot_dst
2607 }
2608 DependencyType::TargetSelfContained => self_contained_dst,
2609 };
2610 builder.copy_link(&path, &dst.join(filename), FileType::Regular);
2611 }
2612
2613 let mut seen_crates = HashMap::new();
2619 for (filestem, path) in crates {
2620 if !filestem.contains("rustc_") || filestem.contains("rustc_hash") {
2621 continue;
2622 }
2623 if let Some(other_path) =
2624 seen_crates.insert(filestem.split_once('-').unwrap().0.to_owned(), path.clone())
2625 {
2626 panic!(
2627 "duplicate rustc crate {}\n- first copy at {}\n- second copy at {}",
2628 filestem.split_once('-').unwrap().0.to_owned(),
2629 other_path.display(),
2630 path.display(),
2631 );
2632 }
2633 }
2634}
2635
2636pub enum ArtifactKeepMode {
2640 OnlyDylib,
2642 OnlyRmeta,
2644 BothRlibAndRmeta,
2646 Custom(Box<dyn Fn(&str) -> bool>),
2649}
2650
2651pub fn run_cargo(
2652 builder: &Builder<'_>,
2653 cargo: Cargo,
2654 tail_args: Vec<String>,
2655 stamp: &BuildStamp,
2656 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2657 artifact_keep_mode: ArtifactKeepMode,
2658) -> Vec<PathBuf> {
2659 let target_root_dir = stamp.path().parent().unwrap();
2661 let target_build_dir = target_root_dir.join("build");
2663 let host_root_dir = target_root_dir
2665 .parent()
2666 .unwrap() .parent()
2668 .unwrap() .join(target_root_dir.file_name().unwrap());
2670
2671 let mut deps = Vec::new();
2675 let mut toplevel = Vec::new();
2676 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2677 let (filenames_vec, crate_types) = match msg {
2678 CargoMessage::CompilerArtifact {
2679 filenames,
2680 target: CargoTarget { crate_types },
2681 ..
2682 } => {
2683 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2684 f.sort(); (f, crate_types)
2686 }
2687 _ => return,
2688 };
2689 for filename in filenames_vec {
2690 let keep = if filename.ends_with(".lib")
2692 || filename.ends_with(".a")
2693 || is_debug_info(&filename)
2694 || is_dylib(Path::new(&*filename))
2695 {
2696 true
2698 } else {
2699 match &artifact_keep_mode {
2700 ArtifactKeepMode::OnlyDylib => false,
2701 ArtifactKeepMode::OnlyRmeta => filename.ends_with(".rmeta"),
2702 ArtifactKeepMode::BothRlibAndRmeta => {
2703 filename.ends_with(".rmeta") || filename.ends_with(".rlib")
2704 }
2705 ArtifactKeepMode::Custom(func) => func(&filename),
2706 }
2707 };
2708
2709 if !keep {
2710 continue;
2711 }
2712
2713 let filename = Path::new(&*filename);
2714
2715 if filename.starts_with(&host_root_dir) {
2718 if crate_types.iter().any(|t| t == "proc-macro") {
2720 if filename.file_name().unwrap().to_str().unwrap().contains("-") {
2725 deps.push((filename.to_path_buf(), DependencyType::Host));
2726 }
2727 }
2728 continue;
2729 }
2730
2731 if filename.starts_with(&target_build_dir) {
2734 deps.push((filename.to_path_buf(), DependencyType::Target));
2735 continue;
2736 }
2737
2738 let expected_len = t!(filename.metadata()).len();
2749 let filename = filename.file_name().unwrap().to_str().unwrap();
2750 let mut parts = filename.splitn(2, '.');
2751 let file_stem = parts.next().unwrap().to_owned();
2752 let extension = parts.next().unwrap().to_owned();
2753
2754 toplevel.push((file_stem, extension, expected_len));
2755 }
2756 });
2757
2758 if !ok {
2759 helpers::exit_process(1);
2760 }
2761
2762 if builder.config.dry_run() {
2763 return Vec::new();
2764 }
2765
2766 let read_dir = |path: &Path| path.read_dir().ok().into_iter().flatten().filter_map(Result::ok);
2773 let contents = target_build_dir
2774 .read_dir()
2775 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_build_dir.display(), e))
2776 .map(|e| e.unwrap())
2777 .flat_map(|e| read_dir(&e.path()))
2778 .flat_map(|e| read_dir(&e.path()))
2779 .flat_map(|e| read_dir(&e.path()))
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}