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, LlvmKind, 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, 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 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
443 copy_and_stamp(
444 builder,
445 &libdir_self_contained,
446 &srcdir,
447 obj,
448 &mut target_deps,
449 DependencyType::TargetSelfContained,
450 );
451 }
452 if srcdir.join("eh").exists() {
453 copy_and_stamp(
454 builder,
455 &libdir_self_contained,
456 &srcdir.join("eh"),
457 "libunwind.a",
458 &mut target_deps,
459 DependencyType::TargetSelfContained,
460 );
461 }
462 } else if target.is_windows_gnu() || target.is_windows_gnullvm() {
463 for obj in ["crt2.o", "dllcrt2.o"].iter() {
464 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
465 let dst = libdir_self_contained.join(obj);
466 builder.copy_link(&src, &dst, FileType::NativeLibrary);
467 target_deps.push((dst, DependencyType::TargetSelfContained));
468 }
469 }
470
471 target_deps
472}
473
474pub fn std_crates_for_make_run(run: &RunConfig<'_>) -> Vec<String> {
477 let mut crates = run.make_run_crates(builder::Alias::Library);
478
479 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
488 if target_is_no_std {
489 crates.retain(|c| c == "core" || c == "alloc");
490 }
491 crates
492}
493
494fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
500 if let Some(downloaded_llvm) = builder.ensure(LlvmFromCi { target: builder.host_target }) {
502 let ci_llvm_compiler_rt = downloaded_llvm.output.root_dir().join("compiler-rt");
503 if !builder.config.dry_run() {
504 assert!(
505 ci_llvm_compiler_rt.exists(),
506 "compiler-rt sources not found in LLVM downloaded from CI at {ci_llvm_compiler_rt:?}"
507 );
508 }
509 return ci_llvm_compiler_rt;
510 }
511
512 builder.require_submodule("src/llvm-project", {
514 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
515 });
516 builder.src.join("src/llvm-project/compiler-rt")
517}
518
519pub fn std_cargo(
522 builder: &Builder<'_>,
523 target: TargetSelection,
524 cargo: &mut Cargo,
525 crates: &[String],
526) {
527 if target.contains("apple") && !builder.config.dry_run() {
545 let mut cmd = builder.rustc_cmd(cargo.compiler());
549 cmd.arg("--target").arg(target.rustc_target_arg());
550 cmd.arg("-Zunstable-options").env("RUSTC_BOOTSTRAP", "1");
553 cmd.arg("--print=deployment-target");
554 let output = cmd.run_capture_stdout(builder).stdout();
555
556 let (env_var, value) = output.split_once('=').unwrap();
557 cargo.env(env_var.trim(), value.trim());
560
561 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
571 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
572 }
573 }
574
575 if let Some(path) = builder.config.profiler_path(target) {
577 cargo.env("LLVM_PROFILER_RT_LIB", path);
578 } else if builder.config.profiler_enabled(target) {
579 let compiler_rt = compiler_rt_for_profiler(builder);
580 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
584 }
585
586 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
600 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
601 cargo.env("LLVM_COMPILER_RT_LIB", path);
602 " compiler-builtins-c"
603 }
604 CompilerBuiltins::BuildLLVMFuncs => {
605 builder.require_submodule(
615 "src/llvm-project",
616 Some(
617 "The `build.optimized-compiler-builtins` config option \
618 requires `compiler-rt` sources from LLVM.",
619 ),
620 );
621 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
622 if !builder.config.dry_run() {
623 assert!(compiler_builtins_root.exists());
626 }
627
628 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
631 " compiler-builtins-c"
632 }
633 CompilerBuiltins::BuildRustOnly => "",
634 };
635
636 for krate in crates {
637 cargo.args(["-p", krate]);
638 }
639
640 let mut features = String::new();
641
642 if builder.no_std(target) == Some(true) {
643 features += " compiler-builtins-mem";
644 if !target.starts_with("bpf") {
645 features.push_str(compiler_builtins_c_feature);
646 }
647
648 if crates.is_empty() {
650 cargo.args(["-p", "alloc"]);
651 }
652 cargo
653 .arg("--manifest-path")
654 .arg(builder.src.join("library/alloc/Cargo.toml"))
655 .arg("--features")
656 .arg(features);
657 } else {
658 features += &builder.std_features(target);
659 features.push_str(compiler_builtins_c_feature);
660
661 cargo
662 .arg("--features")
663 .arg(features)
664 .arg("--manifest-path")
665 .arg(builder.src.join("library/sysroot/Cargo.toml"));
666
667 if target.contains("musl")
670 && let Some(p) = builder.musl_libdir(target)
671 {
672 let root = format!("native={}", p.to_str().unwrap());
673 cargo.rustflag("-L").rustflag(&root);
674 }
675
676 if target.contains("-wasi")
677 && let Some(dir) = builder.wasi_libdir(target)
678 {
679 let root = format!("native={}", dir.to_str().unwrap());
680 cargo.rustflag("-L").rustflag(&root);
681 }
682 }
683
684 if builder.config.rust_lto == RustcLto::Off {
685 cargo.rustflag("-Clto=off");
686 }
687
688 if target.contains("riscv") {
695 cargo.rustflag("-Cforce-unwind-tables=yes");
696 }
697
698 let html_root =
699 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
700 cargo.rustflag(&html_root);
701 cargo.rustdocflag(&html_root);
702
703 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
704}
705
706#[derive(Debug, Clone, PartialEq, Eq, Hash)]
715pub struct StdLink {
716 pub compiler: Compiler,
717 pub target_compiler: Compiler,
718 pub target: TargetSelection,
719 crates: Vec<String>,
721 force_recompile: bool,
723}
724
725impl StdLink {
726 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
727 Self {
728 compiler: host_compiler,
729 target_compiler: std.build_compiler,
730 target: std.target,
731 crates: std.crates,
732 force_recompile: std.force_recompile,
733 }
734 }
735}
736
737impl Step for StdLink {
738 type Output = ();
739
740 fn run(self, builder: &Builder<'_>) {
749 let compiler = self.compiler;
750 let target_compiler = self.target_compiler;
751 let target = self.target;
752
753 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
755 let lib = builder.sysroot_libdir_relative(self.compiler);
757 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
758 compiler: self.compiler,
759 force_recompile: self.force_recompile,
760 });
761 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
762 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
763 (libdir, hostdir)
764 } else {
765 let libdir = builder.sysroot_target_libdir(target_compiler, target);
766 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
767 (libdir, hostdir)
768 };
769
770 let is_downloaded_beta_stage0 = builder
771 .sess
772 .initial_rustc
773 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
774
775 if compiler.stage == 0 && is_downloaded_beta_stage0 {
779 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
781
782 let host = compiler.host;
783 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
784 let sysroot_bin_dir = sysroot.join("bin");
785 t!(fs::create_dir_all(&sysroot_bin_dir));
786 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
787
788 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
789 t!(fs::create_dir_all(sysroot.join("lib")));
790 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
791
792 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
794 t!(fs::create_dir_all(&sysroot_codegen_backends));
795 let stage0_codegen_backends = builder
796 .out
797 .join(host)
798 .join("stage0/lib/rustlib")
799 .join(host)
800 .join("codegen-backends");
801 if stage0_codegen_backends.exists() {
802 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
803 }
804 } else if compiler.stage == 0 {
805 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
806
807 if builder.local_rebuild {
808 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
812 }
813
814 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
815 } else {
816 if builder.download_rustc() {
817 let _ = fs::remove_dir_all(&libdir);
819 let _ = fs::remove_dir_all(&hostdir);
820 }
821
822 add_to_sysroot(
823 builder,
824 &libdir,
825 &hostdir,
826 &build_stamp::libstd_stamp(builder, compiler, target),
827 );
828 }
829 }
830}
831
832fn copy_sanitizers(
834 builder: &Builder<'_>,
835 compiler: &Compiler,
836 target: TargetSelection,
837) -> Vec<PathBuf> {
838 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
839
840 if builder.config.dry_run() {
841 return Vec::new();
842 }
843
844 let mut target_deps = Vec::new();
845 let libdir = builder.sysroot_target_libdir(*compiler, target);
846
847 for runtime in &runtimes {
848 let dst = libdir.join(&runtime.name);
849 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
850
851 if target == "x86_64-apple-darwin"
855 || target == "aarch64-apple-darwin"
856 || target == "aarch64-apple-ios"
857 || target == "aarch64-apple-ios-sim"
858 || target == "x86_64-apple-ios"
859 {
860 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
862 apple_darwin_sign_file(builder, &dst);
865 }
866
867 target_deps.push(dst);
868 }
869
870 target_deps
871}
872
873fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
874 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
875}
876
877fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
878 command("codesign")
879 .arg("-f") .arg("-s")
881 .arg("-")
882 .arg(file_path)
883 .run(builder);
884}
885
886#[derive(Debug, Clone, PartialEq, Eq, Hash)]
887pub struct StartupObjects {
888 pub compiler: Compiler,
889 pub target: TargetSelection,
890}
891
892impl CommandLineStep for StartupObjects {
893 type Output = Vec<(PathBuf, DependencyType)>;
894
895 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
896 run.path("library/rtstartup")
897 }
898
899 fn make_run(run: RunConfig<'_>) {
900 run.builder.ensure(StartupObjects {
901 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
902 target: run.target,
903 });
904 }
905
906 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
913 let for_compiler = self.compiler;
914 let target = self.target;
915 if !target.is_windows_gnu() {
918 return vec![];
919 }
920
921 let mut target_deps = vec![];
922
923 let src_dir = &builder.src.join("library").join("rtstartup");
924 let dst_dir = &builder.native_dir(target).join("rtstartup");
925 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
926 t!(fs::create_dir_all(dst_dir));
927
928 for file in &["rsbegin", "rsend"] {
929 let src_file = &src_dir.join(file.to_string() + ".rs");
930 let dst_file = &dst_dir.join(file.to_string() + ".o");
931 if !up_to_date(src_file, dst_file) {
932 let mut cmd = command(&builder.initial_rustc);
933 cmd.env("RUSTC_BOOTSTRAP", "1");
934 if !builder.local_rebuild {
935 cmd.arg("--cfg").arg("bootstrap");
937 }
938 cmd.arg("--target")
939 .arg(target.rustc_target_arg())
940 .arg("--emit=obj")
941 .arg("-o")
942 .arg(dst_file)
943 .arg(src_file)
944 .run(builder);
945 }
946
947 let obj = sysroot_dir.join((*file).to_string() + ".o");
948 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
949 target_deps.push((obj, DependencyType::Target));
950 }
951
952 target_deps
953 }
954}
955
956fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
957 let ci_rustc_dir = builder.config.ci_rustc_dir();
958
959 for file in contents {
960 let src = ci_rustc_dir.join(&file);
961 let dst = sysroot.join(file);
962 if src.is_dir() {
963 t!(fs::create_dir_all(dst));
964 } else {
965 builder.copy_link(&src, &dst, FileType::Regular);
966 }
967 }
968}
969
970#[derive(Clone, Debug)]
972pub struct BuiltRustc {
973 pub build_compiler: Compiler,
977}
978
979#[derive(Debug, Clone, PartialEq, Eq, Hash)]
986pub struct Rustc {
987 pub target: TargetSelection,
989 pub build_compiler: Compiler,
991 crates: Vec<String>,
997}
998
999impl Rustc {
1000 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
1001 Self { target, build_compiler, crates: Default::default() }
1002 }
1003}
1004
1005impl CommandLineStep for Rustc {
1006 type Output = BuiltRustc;
1007 const IS_HOST: bool = true;
1008
1009 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1010 run.crate_or_deps_filtered("rustc-main", |krate| {
1011 krate.name != "rustc-main"
1014 })
1015 }
1016
1017 fn is_default_step(_builder: &Builder<'_>) -> bool {
1018 false
1019 }
1020
1021 fn make_run(run: RunConfig<'_>) {
1022 if run.builder.paths == vec![PathBuf::from("compiler")] {
1025 return;
1026 }
1027
1028 let crates = run.cargo_crates_in_set();
1029 run.builder.ensure(Rustc {
1030 build_compiler: run
1031 .builder
1032 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1033 target: run.target,
1034 crates,
1035 });
1036 }
1037
1038 fn run(self, builder: &Builder<'_>) -> Self::Output {
1044 let build_compiler = self.build_compiler;
1045 let target = self.target;
1046
1047 if builder.download_rustc() && build_compiler.stage != 0 {
1050 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1051
1052 let sysroot =
1053 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1054 cp_rustc_component_to_ci_sysroot(
1055 builder,
1056 &sysroot,
1057 builder.config.ci_rustc_dev_contents(),
1058 );
1059 return BuiltRustc { build_compiler };
1060 }
1061
1062 builder.std(build_compiler, target);
1065
1066 if builder.config.keep_stage.contains(&build_compiler.stage) {
1067 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1068
1069 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1070 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1071 builder.ensure(RustcLink::from_rustc(self));
1072
1073 return BuiltRustc { build_compiler };
1074 }
1075
1076 let stage = build_compiler.stage + 1;
1078
1079 if build_compiler.stage >= 2
1084 && !builder.config.full_bootstrap
1085 && target == builder.host_target
1086 {
1087 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1091
1092 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1093 builder.info(&msg);
1094
1095 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1099 uplift_build_compiler,
1101 build_compiler,
1103 target,
1104 self.crates,
1105 ));
1106
1107 return BuiltRustc { build_compiler: uplift_build_compiler };
1110 }
1111
1112 builder.std(
1118 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1119 builder.config.host_target,
1120 );
1121
1122 let mut cargo = builder::Cargo::new(
1123 builder,
1124 build_compiler,
1125 Mode::Rustc,
1126 SourceType::InTree,
1127 target,
1128 Kind::Build,
1129 );
1130
1131 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1132
1133 for krate in &*self.crates {
1137 cargo.arg("-p").arg(krate);
1138 }
1139
1140 if builder.sess.config.enable_bolt_settings && build_compiler.stage == 1 {
1141 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1143 }
1144
1145 let _guard = builder.msg(
1146 Kind::Build,
1147 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1148 Mode::Rustc,
1149 build_compiler,
1150 target,
1151 );
1152 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1153
1154 run_cargo(
1155 builder,
1156 cargo,
1157 vec![],
1158 &stamp,
1159 vec![],
1160 ArtifactKeepMode::Custom(Box::new(|filename| {
1161 if filename.contains("jemalloc_sys")
1162 || filename.contains("rustc_public_bridge")
1163 || filename.contains("rustc_public")
1164 {
1165 if filename.ends_with(".rlib") {
1168 return true;
1169 }
1170 }
1171
1172 filename.ends_with(".rmeta")
1176 })),
1177 );
1178
1179 let target_root_dir = stamp.path().parent().unwrap();
1180 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1186 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1187 {
1188 let rustc_driver = target_root_dir.join("librustc_driver.so");
1189 strip_debug(builder, target, &rustc_driver);
1190 }
1191
1192 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1193 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1196 }
1197
1198 builder.ensure(RustcLink::from_rustc(self));
1199 BuiltRustc { build_compiler }
1200 }
1201
1202 fn metadata(&self) -> Option<StepMetadata> {
1203 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1204 }
1205}
1206
1207pub fn rustc_cargo(
1208 builder: &Builder<'_>,
1209 cargo: &mut Cargo,
1210 target: TargetSelection,
1211 build_compiler: &Compiler,
1212 crates: &[String],
1213) {
1214 let kind = cargo.kind();
1215 cargo
1216 .arg("--features")
1217 .arg(builder.rustc_features(kind, target, crates))
1218 .arg("--manifest-path")
1219 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1220
1221 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1222
1223 cargo.rustflag("-Zon-broken-pipe=kill");
1237
1238 if target.is_msvc() {
1243 cargo.rustflag("-Clink-arg=/Brepro");
1244 }
1245
1246 if builder.sess.config.bootstrap_override_lld.is_used() {
1251 cargo.rustflag("-Zdefault-visibility=protected");
1252 }
1253
1254 apply_dylib_lto(builder, build_compiler, cargo);
1255
1256 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1264 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1265 }
1266
1267 apply_pgo(builder, cargo, *build_compiler, &builder.config.rust_pgo);
1268
1269 if let Some(ref ccache) = builder.config.ccache
1277 && build_compiler.stage == 0
1278 && !cfg!(windows)
1279 && !builder.config.incremental
1280 {
1281 cargo.env("RUSTC_WRAPPER", ccache);
1282 }
1283
1284 rustc_cargo_env(builder, cargo, target);
1285}
1286
1287fn apply_dylib_lto(builder: &Builder<'_>, build_compiler: &Compiler, cargo: &mut Cargo) {
1288 if is_lto_stage(build_compiler) {
1289 match builder.config.rust_lto {
1290 RustcLto::Thin | RustcLto::Fat => {
1291 cargo.rustflag("-Zdylib-lto");
1294 let lto_type = match builder.config.rust_lto {
1298 RustcLto::Thin => "thin",
1299 RustcLto::Fat => "fat",
1300 _ => unreachable!(),
1301 };
1302 cargo.rustflag(&format!("-Clto={lto_type}"));
1303 cargo.rustflag("-Cembed-bitcode=yes");
1304 }
1305 RustcLto::ThinLocal => { }
1306 RustcLto::Off => {
1307 cargo.rustflag("-Clto=off");
1308 }
1309 }
1310 } else if builder.config.rust_lto == RustcLto::Off {
1311 cargo.rustflag("-Clto=off");
1312 }
1313}
1314
1315fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1316 cargo
1319 .env("CFG_RELEASE", builder.rust_release())
1320 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1321 .env("CFG_VERSION", builder.rust_version());
1322
1323 if builder.config.omit_git_hash {
1327 cargo.env("CFG_OMIT_GIT_HASH", "1");
1328 }
1329
1330 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1331
1332 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1333 let target_config = builder.config.target_config.get(&target);
1334
1335 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1336
1337 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1338 cargo.env("CFG_VER_DATE", ver_date);
1339 }
1340 if let Some(ref ver_hash) = builder.rust_info().sha() {
1341 cargo.env("CFG_VER_HASH", ver_hash);
1342 }
1343 if !builder.unstable_features() {
1344 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1345 }
1346
1347 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1350 cargo.env("CFG_DEFAULT_LINKER", s);
1351 } else if let Some(ref s) = builder.config.rustc_default_linker {
1352 cargo.env("CFG_DEFAULT_LINKER", s);
1353 }
1354
1355 if let Some(linker) = target_config.map(|c| c.default_linker_linux_override) {
1357 match linker {
1358 DefaultLinuxLinkerOverride::Off => {}
1359 DefaultLinuxLinkerOverride::SelfContainedLldCc => {
1360 cargo.env("CFG_DEFAULT_LINKER_SELF_CONTAINED_LLD_CC", "1");
1361 }
1362 }
1363 }
1364
1365 cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple);
1367
1368 if builder.config.rust_verify_llvm_ir {
1369 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1370 }
1371
1372 let nightly = builder.config.channel == "nightly" || builder.config.channel == "dev";
1373 if nightly {
1374 cargo.env("CFG_DEFAULT_POLONIUS_NEXT", "1");
1376 cargo.env("CFG_DEFAULT_NEXT_SOLVER_GLOBALLY", "1");
1377 }
1378
1379 if builder.config.llvm_enabled(target) {
1400 let building_llvm_is_expensive = prebuilt_llvm_output(builder, target).is_none();
1401
1402 let skip_llvm = cargo.kind().is_check_like() && building_llvm_is_expensive;
1403 if skip_llvm {
1404 cargo.env("RUST_CHECK", "1");
1405 } else {
1406 rustc_llvm_env(builder, cargo, target);
1407 }
1408 }
1409
1410 if builder.config.allocator(target) == Allocator::Jemalloc
1412 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1413 {
1414 if target.starts_with("aarch64") {
1417 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1418 }
1419 else if target.starts_with("loongarch") {
1421 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1422 }
1423 }
1424
1425 if builder.config.wasm_panic_unwind_default {
1428 cargo.env("CFG_WASM_PANIC_UNWIND_DEFAULT", "1");
1429 }
1430}
1431
1432fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1438 let llvm_output = builder.ensure(llvm::Llvm { target });
1439 if builder.config.is_rust_llvm(&llvm_output, target) {
1440 cargo.env("LLVM_RUSTLLVM", "1");
1441 }
1442 if builder.config.llvm_enzyme {
1443 cargo.env("LLVM_ENZYME", "1");
1444 }
1445 if builder.config.llvm_offload {
1446 builder.ensure(llvm::OmpOffload { target });
1447 cargo.env("LLVM_OFFLOAD", "1");
1448 }
1449
1450 cargo.env("LLVM_CONFIG", builder.host_llvm_config());
1452
1453 let mut llvm_linker_flags = String::new();
1463 if builder.config.llvm_pgo.generate_profile.is_some()
1464 && target.is_msvc()
1465 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1466 {
1467 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1469 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1470 }
1471
1472 if let Some(ref s) = builder.config.llvm_ldflags {
1474 if !llvm_linker_flags.is_empty() {
1475 llvm_linker_flags.push(' ');
1476 }
1477 llvm_linker_flags.push_str(s);
1478 }
1479
1480 if !llvm_linker_flags.is_empty() {
1482 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1483 }
1484
1485 if builder.config.llvm_static_stdcpp
1488 && !target.contains("freebsd")
1489 && !target.is_msvc()
1490 && !target.contains("apple")
1491 && !target.contains("solaris")
1492 {
1493 let libstdcxx_name =
1494 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1495 let file = compiler_file(
1496 builder,
1497 &builder.cxx(target).unwrap(),
1498 target,
1499 CLang::Cxx,
1500 libstdcxx_name,
1501 );
1502 cargo.env("LLVM_STATIC_STDCPP", file);
1503 }
1504 if llvm_output.link_shared() {
1505 cargo.env("LLVM_LINK_SHARED", "1");
1506 }
1507 if builder.config.llvm_use_libcxx {
1508 cargo.env("LLVM_USE_LIBCXX", "1");
1509 }
1510 if builder.config.llvm_assertions {
1511 cargo.env("LLVM_ASSERTIONS", "1");
1512 }
1513 if builder.cxx_tool(target).is_like_gnu() || builder.cc_tool(target).is_like_gnu() {
1514 cargo.env("LLVM_COMPILER_IS_GNU_LIKE", "1");
1515 }
1516}
1517
1518#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1531struct RustcLink {
1532 build_compiler: Compiler,
1534 sysroot_compiler: Compiler,
1537 target: TargetSelection,
1538 crates: Vec<String>,
1540}
1541
1542impl RustcLink {
1543 fn from_rustc(rustc: Rustc) -> Self {
1546 Self {
1547 build_compiler: rustc.build_compiler,
1548 sysroot_compiler: rustc.build_compiler,
1549 target: rustc.target,
1550 crates: rustc.crates,
1551 }
1552 }
1553
1554 fn from_build_compiler_and_sysroot(
1556 build_compiler: Compiler,
1557 sysroot_compiler: Compiler,
1558 target: TargetSelection,
1559 crates: Vec<String>,
1560 ) -> Self {
1561 Self { build_compiler, sysroot_compiler, target, crates }
1562 }
1563}
1564
1565impl Step for RustcLink {
1566 type Output = ();
1567
1568 fn run(self, builder: &Builder<'_>) {
1570 let build_compiler = self.build_compiler;
1571 let sysroot_compiler = self.sysroot_compiler;
1572 let target = self.target;
1573 add_to_sysroot(
1574 builder,
1575 &builder.sysroot_target_libdir(sysroot_compiler, target),
1576 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1577 &build_stamp::librustc_stamp(builder, build_compiler, target),
1578 );
1579 }
1580}
1581
1582#[derive(Clone)]
1588pub struct GccDylibSet {
1589 dylibs: BTreeMap<GccTargetPair, GccOutput>,
1590}
1591
1592impl GccDylibSet {
1593 pub fn build(
1596 builder: &Builder<'_>,
1597 host: TargetSelection,
1598 targets: Vec<TargetSelection>,
1599 ) -> Self {
1600 let dylibs = targets
1601 .iter()
1602 .map(|t| GccTargetPair::for_target_pair(host, *t))
1603 .map(|target_pair| (target_pair, builder.ensure(Gcc { target_pair })))
1604 .collect();
1605 Self { dylibs }
1606 }
1607
1608 pub fn install_to(&self, builder: &Builder<'_>, compiler: Compiler) {
1612 if builder.config.dry_run() {
1613 return;
1614 }
1615
1616 let cg_sysroot = builder.sysroot_codegen_backends(compiler);
1618
1619 for (target_pair, libgccjit) in &self.dylibs {
1620 assert_eq!(
1621 target_pair.host(),
1622 compiler.host,
1623 "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",
1624 compiler.host
1625 );
1626 let libgccjit_path = libgccjit.libgccjit();
1627
1628 let libgccjit_path = t!(
1632 libgccjit_path.canonicalize(),
1633 format!("Cannot find libgccjit at {}", libgccjit_path.display())
1634 );
1635
1636 let dst = cg_sysroot.join(libgccjit_path_relative_to_cg_dir(target_pair, libgccjit));
1637 t!(std::fs::create_dir_all(dst.parent().unwrap()));
1638 builder.copy_link(&libgccjit_path, &dst, FileType::NativeLibrary);
1639 }
1640 }
1641}
1642
1643pub fn libgccjit_path_relative_to_cg_dir(
1646 target_pair: &GccTargetPair,
1647 libgccjit: &GccOutput,
1648) -> PathBuf {
1649 let target_filename = libgccjit.libgccjit().file_name().unwrap().to_str().unwrap();
1650
1651 Path::new("lib").join(target_pair.target()).join(target_filename)
1653}
1654
1655#[derive(Clone)]
1659pub struct GccCodegenBackendOutput {
1660 stamp: BuildStamp,
1661}
1662
1663impl GccCodegenBackendOutput {
1664 pub fn stamp(&self) -> &BuildStamp {
1665 &self.stamp
1666 }
1667}
1668
1669#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1676pub struct GccCodegenBackend {
1677 compilers: RustcPrivateCompilers,
1678 target: TargetSelection,
1679}
1680
1681impl GccCodegenBackend {
1682 pub fn for_target(compilers: RustcPrivateCompilers, target: TargetSelection) -> Self {
1684 Self { compilers, target }
1685 }
1686}
1687
1688impl CommandLineStep for GccCodegenBackend {
1689 type Output = GccCodegenBackendOutput;
1690
1691 const IS_HOST: bool = true;
1692
1693 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1694 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1695 }
1696
1697 fn make_run(run: RunConfig<'_>) {
1698 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target);
1699 run.builder.ensure(GccCodegenBackend::for_target(compilers, run.target));
1700 }
1701
1702 fn run(self, builder: &Builder<'_>) -> Self::Output {
1703 let host = self.compilers.target();
1704 let build_compiler = self.compilers.build_compiler();
1705
1706 let stamp = build_stamp::codegen_backend_stamp(
1707 builder,
1708 build_compiler,
1709 host,
1710 &CodegenBackendKind::Gcc,
1711 );
1712
1713 if builder.config.keep_stage.contains(&build_compiler.stage) && stamp.path().exists() {
1714 trace!("`keep-stage` requested");
1715 builder.info(
1716 "WARNING: Using a potentially old codegen backend. \
1717 This may not behave well.",
1718 );
1719 return GccCodegenBackendOutput { stamp };
1722 }
1723
1724 let mut cargo = builder::Cargo::new(
1725 builder,
1726 build_compiler,
1727 Mode::Codegen,
1728 SourceType::InTree,
1729 host,
1730 Kind::Build,
1731 );
1732 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1733 apply_dylib_lto(builder, &build_compiler, &mut cargo);
1734
1735 let _guard =
1736 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host);
1737 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyDylib);
1738
1739 GccCodegenBackendOutput {
1740 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1741 }
1742 }
1743
1744 fn metadata(&self) -> Option<StepMetadata> {
1745 Some(
1746 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1747 .built_by(self.compilers.build_compiler()),
1748 )
1749 }
1750}
1751
1752#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1753pub struct CraneliftCodegenBackend {
1754 pub compilers: RustcPrivateCompilers,
1755}
1756
1757impl CommandLineStep for CraneliftCodegenBackend {
1758 type Output = BuildStamp;
1759 const IS_HOST: bool = true;
1760
1761 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1762 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1763 }
1764
1765 fn make_run(run: RunConfig<'_>) {
1766 run.builder.ensure(CraneliftCodegenBackend {
1767 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1768 });
1769 }
1770
1771 fn run(self, builder: &Builder<'_>) -> Self::Output {
1772 let target = self.compilers.target();
1773 let build_compiler = self.compilers.build_compiler();
1774
1775 let stamp = build_stamp::codegen_backend_stamp(
1776 builder,
1777 build_compiler,
1778 target,
1779 &CodegenBackendKind::Cranelift,
1780 );
1781
1782 if builder.config.keep_stage.contains(&build_compiler.stage) {
1783 trace!("`keep-stage` requested");
1784 builder.info(
1785 "WARNING: Using a potentially old codegen backend. \
1786 This may not behave well.",
1787 );
1788 return stamp;
1791 }
1792
1793 let mut cargo = builder::Cargo::new(
1794 builder,
1795 build_compiler,
1796 Mode::Codegen,
1797 SourceType::InTree,
1798 target,
1799 Kind::Build,
1800 );
1801 cargo
1802 .arg("--manifest-path")
1803 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1804 apply_dylib_lto(builder, &build_compiler, &mut cargo);
1805 apply_pgo(builder, &mut cargo, build_compiler, &builder.config.cranelift_pgo);
1806
1807 let _guard = builder.msg(
1808 Kind::Build,
1809 "codegen backend cranelift",
1810 Mode::Codegen,
1811 build_compiler,
1812 target,
1813 );
1814 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyDylib);
1815 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1816 }
1817
1818 fn metadata(&self) -> Option<StepMetadata> {
1819 Some(
1820 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1821 .built_by(self.compilers.build_compiler()),
1822 )
1823 }
1824}
1825
1826fn write_codegen_backend_stamp(
1828 mut stamp: BuildStamp,
1829 files: Vec<PathBuf>,
1830 dry_run: bool,
1831) -> BuildStamp {
1832 if dry_run {
1833 return stamp;
1834 }
1835
1836 let mut files = files.into_iter().filter(|f| looks_like_codegen_backend(Path::new(f)));
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
1851pub fn looks_like_codegen_backend(path: &Path) -> bool {
1852 is_dylib(path)
1853 && path.file_name().and_then(|p| p.to_str()).is_some_and(|n| n.contains("rustc_codegen_"))
1854}
1855
1856fn copy_codegen_backends_to_sysroot(
1863 builder: &Builder<'_>,
1864 stamp: BuildStamp,
1865 target_compiler: Compiler,
1866) {
1867 let dst = builder.sysroot_codegen_backends(target_compiler);
1876 t!(fs::create_dir_all(&dst), dst);
1877
1878 if builder.config.dry_run() {
1879 return;
1880 }
1881
1882 if stamp.path().exists() {
1883 let file = get_codegen_backend_file(&stamp);
1884 builder.copy_link(
1885 &file,
1886 &dst.join(normalize_codegen_backend_name(builder, &file)),
1887 FileType::NativeLibrary,
1888 );
1889 }
1890}
1891
1892pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1894 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1895}
1896
1897pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1899 let filename = path.file_name().unwrap().to_str().unwrap();
1900 let dash = filename.find('-').unwrap();
1903 let dot = filename.find('.').unwrap();
1904 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1905}
1906
1907pub fn compiler_file(
1908 builder: &Builder<'_>,
1909 compiler: &Path,
1910 target: TargetSelection,
1911 c: CLang,
1912 file: &str,
1913) -> PathBuf {
1914 if builder.config.dry_run() {
1915 return PathBuf::new();
1916 }
1917 let mut cmd = command(compiler);
1918 cmd.args(builder.cc_handled_cflags(target, c));
1919 cmd.args(builder.cc_unhandled_cflags(target, c));
1920 cmd.arg(format!("-print-file-name={file}"));
1921 let out = cmd.run_capture_stdout(builder).stdout();
1922 PathBuf::from(out.trim())
1923}
1924
1925#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1926pub struct Sysroot {
1927 pub compiler: Compiler,
1928 force_recompile: bool,
1930}
1931
1932impl Sysroot {
1933 pub(crate) fn new(compiler: Compiler) -> Self {
1934 Sysroot { compiler, force_recompile: false }
1935 }
1936}
1937
1938impl Step for Sysroot {
1939 type Output = PathBuf;
1940
1941 fn run(self, builder: &Builder<'_>) -> PathBuf {
1945 let compiler = self.compiler;
1946 let host_dir = builder.out.join(compiler.host);
1947
1948 let sysroot_dir = |stage| {
1949 if stage == 0 {
1950 host_dir.join("stage0-sysroot")
1951 } else if self.force_recompile && stage == compiler.stage {
1952 host_dir.join(format!("stage{stage}-test-sysroot"))
1953 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1954 host_dir.join("ci-rustc-sysroot")
1955 } else {
1956 host_dir.join(format!("stage{stage}"))
1957 }
1958 };
1959 let sysroot = sysroot_dir(compiler.stage);
1960 trace!(stage = ?compiler.stage, ?sysroot);
1961
1962 builder.do_if_verbose(|| {
1963 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1964 });
1965 let _ = fs::remove_dir_all(&sysroot);
1966 t!(fs::create_dir_all(&sysroot));
1967
1968 if compiler.stage == 0 {
1975 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1976 }
1977
1978 if builder.download_rustc() && compiler.stage != 0 {
1980 assert_eq!(
1981 builder.config.host_target, compiler.host,
1982 "Cross-compiling is not yet supported with `download-rustc`",
1983 );
1984
1985 for stage in 0..=2 {
1987 if stage != compiler.stage {
1988 let dir = sysroot_dir(stage);
1989 if !dir.ends_with("ci-rustc-sysroot") {
1990 let _ = fs::remove_dir_all(dir);
1991 }
1992 }
1993 }
1994
1995 let mut filtered_files = Vec::new();
2009 let mut add_filtered_files = |suffix, contents| {
2010 for path in contents {
2011 let path = Path::new(&path);
2012 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
2013 filtered_files.push(path.file_name().unwrap().to_owned());
2014 }
2015 }
2016 };
2017 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
2018 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
2019 add_filtered_files("lib", builder.config.ci_rust_std_contents());
2022
2023 let filtered_extensions = [
2024 OsStr::new("rmeta"),
2025 OsStr::new("rlib"),
2026 OsStr::new(std::env::consts::DLL_EXTENSION),
2028 ];
2029 let ci_rustc_dir = builder.config.ci_rustc_dir();
2030 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
2031 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
2032 return true;
2033 }
2034 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
2035 return true;
2036 }
2037 filtered_files.iter().all(|f| f != path.file_name().unwrap())
2038 });
2039 }
2040
2041 if compiler.stage != 0 {
2047 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
2048 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
2049 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
2050 if let Err(e) =
2051 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
2052 {
2053 eprintln!(
2054 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2055 sysroot_lib_rustlib_src_rust.display(),
2056 builder.src.display(),
2057 e,
2058 );
2059 if builder.config.rust_remap_debuginfo {
2060 eprintln!(
2061 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
2062 sysroot_lib_rustlib_src_rust.display(),
2063 );
2064 }
2065 helpers::exit_process(1);
2066 }
2067 }
2068
2069 if !builder.download_rustc() {
2071 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
2072 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
2073 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
2074 if let Err(e) =
2075 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
2076 {
2077 eprintln!(
2078 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2079 sysroot_lib_rustlib_rustcsrc_rust.display(),
2080 builder.src.display(),
2081 e,
2082 );
2083 helpers::exit_process(1);
2084 }
2085 }
2086
2087 sysroot
2088 }
2089}
2090
2091#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2098pub struct Assemble {
2099 pub target_compiler: Compiler,
2104}
2105
2106impl CommandLineStep for Assemble {
2107 type Output = Compiler;
2108 const IS_HOST: bool = true;
2109
2110 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2111 run.path("compiler/rustc").path("compiler")
2112 }
2113
2114 fn make_run(run: RunConfig<'_>) {
2115 run.builder.ensure(Assemble {
2116 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2117 });
2118 }
2119
2120 fn run(self, builder: &Builder<'_>) -> Compiler {
2121 let target_compiler = self.target_compiler;
2122
2123 if target_compiler.stage == 0 {
2124 trace!("stage 0 build compiler is always available, simply returning");
2125 assert_eq!(
2126 builder.config.host_target, target_compiler.host,
2127 "Cannot obtain compiler for non-native build triple at stage 0"
2128 );
2129 return target_compiler;
2131 }
2132
2133 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2136 let libdir_bin = libdir.parent().unwrap().join("bin");
2137 t!(fs::create_dir_all(&libdir_bin));
2138
2139 if builder.config.llvm_enabled(target_compiler.host) {
2140 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2141
2142 let target = target_compiler.host;
2143 let llvm_output = builder.ensure(llvm::Llvm { target });
2144 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2145 trace!("LLVM tools enabled");
2146
2147 let host_llvm = builder.ensure(llvm::Llvm { target: builder.host_target });
2148 let host_llvm_bin_dir = command(host_llvm.llvm_config())
2149 .arg("--bindir")
2150 .cached()
2151 .run_capture_stdout(builder)
2152 .stdout()
2153 .trim()
2154 .to_string();
2155
2156 let llvm_bin_dir = if target == builder.host_target {
2157 PathBuf::from(host_llvm_bin_dir)
2158 } else {
2159 let external_llvm_config = builder
2162 .config
2163 .target_config
2164 .get(&target)
2165 .and_then(|t| t.llvm_config.clone());
2166 if let Some(external_llvm_config) = external_llvm_config {
2167 external_llvm_config.parent().unwrap().to_path_buf()
2170 } else {
2171 let host_llvm_out = host_llvm.root_dir();
2175 let target_llvm_out = llvm_output.root_dir();
2176 if let Ok(relative_path) =
2177 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2178 {
2179 target_llvm_out.join(relative_path)
2180 } else {
2181 PathBuf::from(
2184 host_llvm_bin_dir
2185 .replace(&*builder.host_target.triple, &target.triple),
2186 )
2187 }
2188 }
2189 };
2190
2191 #[cfg(feature = "tracing")]
2198 let _llvm_tools_span =
2199 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2200 .entered();
2201 for tool in dist::LLVM_TOOLS {
2202 trace!("installing `{tool}`");
2203 let tool_exe = exe(tool, target_compiler.host);
2204 let src_path = llvm_bin_dir.join(&tool_exe);
2205
2206 if !src_path.exists() {
2207 if llvm_output.kind() == LlvmKind::DownloadedFromCi {
2209 eprintln!("{} does not exist; skipping copy", src_path.display());
2210 continue;
2211 }
2212 if *tool == "llubi" {
2215 continue;
2216 }
2217 }
2218
2219 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2226 }
2227 }
2228 }
2229
2230 let maybe_install_llvm_bitcode_linker = || {
2231 if builder.config.llvm_bitcode_linker_enabled {
2232 trace!("llvm-bitcode-linker enabled, installing");
2233 let llvm_bitcode_linker = builder.ensure(
2234 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2235 builder,
2236 target_compiler,
2237 ),
2238 );
2239
2240 let bindir_self_contained = builder
2242 .sysroot(target_compiler)
2243 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2244 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2245
2246 t!(fs::create_dir_all(&bindir_self_contained));
2247 builder.copy_link(
2248 &llvm_bitcode_linker.tool_path,
2249 &bindir_self_contained.join(tool_exe),
2250 FileType::Executable,
2251 );
2252 }
2253 };
2254
2255 if builder.download_rustc() {
2257 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2258
2259 builder.std(target_compiler, target_compiler.host);
2260 let sysroot =
2261 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2262 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2265 if target_compiler.stage == builder.top_stage {
2267 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2268 }
2269
2270 maybe_install_llvm_bitcode_linker();
2273
2274 return target_compiler;
2275 }
2276
2277 debug!(
2291 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2292 target_compiler.stage - 1,
2293 builder.config.host_target,
2294 );
2295 let build_compiler =
2296 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2297
2298 if builder.config.llvm_enzyme {
2300 debug!("`llvm_enzyme` requested");
2301 let enzyme = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2302 let target_libdir =
2303 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2304 let target_dst_lib = target_libdir.join(enzyme.enzyme_filename());
2305 builder.copy_link(&enzyme.enzyme_path(), &target_dst_lib, FileType::NativeLibrary);
2306 }
2307
2308 if builder.config.llvm_offload && !builder.config.dry_run() {
2309 debug!("`llvm_offload` requested");
2310 if builder.is_llvm_enabled_for(builder.config.host_target) {
2311 let rust_offload =
2312 builder.ensure(llvm::RustOffload { target: build_compiler.host });
2313 let target_libdir =
2314 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2315 let rust_offload_dst_lib = target_libdir.join(rust_offload.rust_offload_filename());
2316 builder.copy_link(
2317 &rust_offload.rust_offload_path(),
2318 &rust_offload_dst_lib,
2319 FileType::NativeLibrary,
2320 );
2321
2322 let omp_offload = builder.ensure(llvm::OmpOffload { target: build_compiler.host });
2323 for p in omp_offload.artifact_paths_with_symlink_targets() {
2324 let libname = p.file_name().unwrap();
2325 let dst_lib = target_libdir.join(libname);
2326 builder.resolve_symlink_and_copy(&p, &dst_lib);
2327 }
2328 }
2329 }
2330
2331 debug!(
2334 ?build_compiler,
2335 "target_compiler.host" = ?target_compiler.host,
2336 "building compiler libraries to link to"
2337 );
2338
2339 let BuiltRustc { build_compiler } =
2341 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2342
2343 let stage = target_compiler.stage;
2344 let host = target_compiler.host;
2345 let (host_info, dir_name) = if build_compiler.host == host {
2346 ("".into(), "host".into())
2347 } else {
2348 (format!(" ({host})"), host.to_string())
2349 };
2350 let msg = format!(
2355 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2356 );
2357 builder.info(&msg);
2358
2359 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2361 let proc_macros = builder
2362 .read_stamp_file(&stamp)
2363 .into_iter()
2364 .filter_map(|(path, dependency_type)| {
2365 if dependency_type == DependencyType::Host {
2366 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2367 } else {
2368 None
2369 }
2370 })
2371 .collect::<HashSet<_>>();
2372
2373 let sysroot = builder.sysroot(target_compiler);
2374 let rustc_libdir = builder.rustc_libdir(target_compiler);
2375 t!(fs::create_dir_all(&rustc_libdir));
2376 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2377 for f in builder.read_dir(&src_libdir) {
2378 let filename = f.file_name().into_string().unwrap();
2379
2380 let is_proc_macro = proc_macros.contains(&filename);
2381 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2382
2383 let can_be_rustc_dynamic_dep =
2385 !(filename.starts_with("std-") || filename.starts_with("libstd-"));
2386
2387 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2388 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2389 }
2390 }
2391
2392 {
2393 #[cfg(feature = "tracing")]
2394 let _codegen_backend_span =
2395 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2396
2397 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2398 if builder.kind == Kind::Check && builder.top_stage == 1 {
2415 continue;
2416 }
2417
2418 let prepare_compilers = || {
2419 RustcPrivateCompilers::from_build_and_target_compiler(
2420 build_compiler,
2421 target_compiler,
2422 )
2423 };
2424
2425 match backend {
2426 CodegenBackendKind::Cranelift => {
2427 let stamp = builder
2428 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2429 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2430 }
2431 CodegenBackendKind::Gcc => {
2432 let compilers = prepare_compilers();
2465 let cg_gcc = builder
2466 .ensure(GccCodegenBackend::for_target(compilers, target_compiler.host));
2467 copy_codegen_backends_to_sysroot(builder, cg_gcc.stamp, target_compiler);
2468
2469 let mut targets = HashSet::new();
2476 for target in &builder.hosts {
2479 targets.insert(*target);
2480 }
2481 for target in &builder.targets {
2483 targets.insert(*target);
2484 }
2485 targets.insert(compilers.target_compiler().host);
2488
2489 let dylib_set = GccDylibSet::build(
2491 builder,
2492 compilers.target_compiler().host,
2493 targets.into_iter().collect(),
2494 );
2495
2496 dylib_set.install_to(builder, target_compiler);
2499 }
2500 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2501 }
2502 }
2503 }
2504
2505 if builder.config.lld_enabled {
2506 let lld_wrapper =
2507 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2508 builder,
2509 target_compiler,
2510 ));
2511 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2512 }
2513
2514 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2515 debug!(
2516 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2517 workaround faulty homebrew `strip`s"
2518 );
2519
2520 let src_exe = exe("llvm-objcopy", target_compiler.host);
2527 let dst_exe = exe("rust-objcopy", target_compiler.host);
2528 builder.copy_link(
2529 &libdir_bin.join(src_exe),
2530 &libdir_bin.join(dst_exe),
2531 FileType::Executable,
2532 );
2533 }
2534
2535 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 if builder.config.llvm_tpde {
2555 debug!("`llvm_tpde` requested");
2556 if !host.contains("linux") {
2558 builder.info(&format!("host target `{host}` not supported by tpde. skipping"));
2559 } else {
2560 let tpde_output = builder.ensure(llvm::Tpde { target: host });
2562 let target_libdir =
2563 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2564 let target_dst_lib =
2565 target_libdir.join(tpde_output.plugin_path().file_name().unwrap());
2566 builder.copy_link(
2567 tpde_output.plugin_path(),
2568 &target_dst_lib,
2569 FileType::NativeLibrary,
2570 );
2571 }
2572 }
2573
2574 debug!(
2577 "target_compiler.host" = ?target_compiler.host,
2578 ?sysroot,
2579 "ensuring availability of `libLLVM.so` in compiler directory"
2580 );
2581 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2582 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2583
2584 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2586 let rustc = out_dir.join(exe("rustc-main", host));
2587 let bindir = sysroot.join("bin");
2588 t!(fs::create_dir_all(bindir));
2589 let compiler = builder.rustc(target_compiler);
2590 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2591 builder.copy_link(&rustc, &compiler, FileType::Executable);
2592
2593 target_compiler
2594 }
2595}
2596
2597#[track_caller]
2602pub fn add_to_sysroot(
2603 builder: &Builder<'_>,
2604 sysroot_dst: &Path,
2605 sysroot_host_dst: &Path,
2606 stamp: &BuildStamp,
2607) {
2608 let self_contained_dst = &sysroot_dst.join("self-contained");
2609 t!(fs::create_dir_all(sysroot_dst));
2610 t!(fs::create_dir_all(sysroot_host_dst));
2611 t!(fs::create_dir_all(self_contained_dst));
2612
2613 let mut crates = HashMap::new();
2614 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2615 let filename = path.file_name().unwrap().to_str().unwrap();
2616 let dst = match dependency_type {
2617 DependencyType::Host => {
2618 if sysroot_dst == sysroot_host_dst {
2619 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2622 }
2623
2624 sysroot_host_dst
2625 }
2626 DependencyType::Target => {
2627 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2630
2631 sysroot_dst
2632 }
2633 DependencyType::TargetSelfContained => self_contained_dst,
2634 };
2635 builder.copy_link(&path, &dst.join(filename), FileType::Regular);
2636 }
2637
2638 let mut seen_crates = HashMap::new();
2644 for (filestem, path) in crates {
2645 if !filestem.contains("rustc_") || filestem.contains("rustc_hash") {
2646 continue;
2647 }
2648 if let Some(other_path) =
2649 seen_crates.insert(filestem.split_once('-').unwrap().0.to_owned(), path.clone())
2650 {
2651 panic!(
2652 "duplicate rustc crate {}\n- first copy at {}\n- second copy at {}",
2653 filestem.split_once('-').unwrap().0.to_owned(),
2654 other_path.display(),
2655 path.display(),
2656 );
2657 }
2658 }
2659}
2660
2661pub enum ArtifactKeepMode {
2665 OnlyDylib,
2667 OnlyRmeta,
2669 BothRlibAndRmeta,
2671 Custom(Box<dyn Fn(&str) -> bool>),
2674}
2675
2676pub fn run_cargo(
2677 builder: &Builder<'_>,
2678 cargo: Cargo,
2679 tail_args: Vec<String>,
2680 stamp: &BuildStamp,
2681 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2682 artifact_keep_mode: ArtifactKeepMode,
2683) -> Vec<PathBuf> {
2684 let target_root_dir = stamp.path().parent().unwrap();
2686 let target_build_dir = target_root_dir.join("build");
2688 let host_root_dir = target_root_dir
2690 .parent()
2691 .unwrap() .parent()
2693 .unwrap() .join(target_root_dir.file_name().unwrap());
2695
2696 let mut deps = Vec::new();
2700 let mut toplevel = Vec::new();
2701 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2702 let (filenames_vec, crate_types) = match msg {
2703 CargoMessage::CompilerArtifact {
2704 filenames,
2705 target: CargoTarget { crate_types, .. },
2706 ..
2707 } => {
2708 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2709 f.sort(); (f, crate_types)
2711 }
2712 _ => return,
2713 };
2714 for filename in filenames_vec {
2715 let keep = if filename.ends_with(".lib")
2717 || filename.ends_with(".a")
2718 || is_debug_info(&filename)
2719 || is_dylib(Path::new(&*filename))
2720 {
2721 true
2723 } else {
2724 match &artifact_keep_mode {
2725 ArtifactKeepMode::OnlyDylib => false,
2726 ArtifactKeepMode::OnlyRmeta => filename.ends_with(".rmeta"),
2727 ArtifactKeepMode::BothRlibAndRmeta => {
2728 filename.ends_with(".rmeta") || filename.ends_with(".rlib")
2729 }
2730 ArtifactKeepMode::Custom(func) => func(&filename),
2731 }
2732 };
2733
2734 if !keep {
2735 continue;
2736 }
2737
2738 let filename = Path::new(&*filename);
2739
2740 if filename.starts_with(&host_root_dir) {
2743 if crate_types.iter().any(|t| t == "proc-macro") {
2745 if filename.file_name().unwrap().to_str().unwrap().contains("-") {
2750 deps.push((filename.to_path_buf(), DependencyType::Host));
2751 }
2752 }
2753 continue;
2754 }
2755
2756 if filename.starts_with(&target_build_dir) {
2759 deps.push((filename.to_path_buf(), DependencyType::Target));
2760 continue;
2761 }
2762
2763 let expected_len = t!(filename.metadata()).len();
2774 let filename = filename.file_name().unwrap().to_str().unwrap();
2775 let mut parts = filename.splitn(2, '.');
2776 let file_stem = parts.next().unwrap().to_owned();
2777 let extension = parts.next().unwrap().to_owned();
2778
2779 toplevel.push((file_stem, extension, expected_len));
2780 }
2781 });
2782
2783 if !ok {
2784 helpers::exit_process(1);
2785 }
2786
2787 if builder.config.dry_run() {
2788 return Vec::new();
2789 }
2790
2791 let read_dir = |path: &Path| path.read_dir().ok().into_iter().flatten().filter_map(Result::ok);
2798 let contents = target_build_dir
2799 .read_dir()
2800 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_build_dir.display(), e))
2801 .map(|e| e.unwrap())
2802 .flat_map(|e| read_dir(&e.path()))
2803 .flat_map(|e| read_dir(&e.path()))
2804 .flat_map(|e| read_dir(&e.path()))
2805 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2806 .collect::<Vec<_>>();
2807 for (prefix, extension, expected_len) in toplevel {
2808 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2809 meta.len() == expected_len
2810 && filename
2811 .strip_prefix(&prefix[..])
2812 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2813 .unwrap_or(false)
2814 });
2815 let max = candidates.max_by_key(|&(_, _, metadata)| {
2816 metadata.modified().expect("mtime should be available on all relevant OSes")
2817 });
2818 let path_to_add = match max {
2819 Some(triple) => triple.0.to_str().unwrap(),
2820 None => panic!("no output generated for {prefix:?} {extension:?}"),
2821 };
2822 if is_dylib(Path::new(path_to_add)) {
2823 let candidate = format!("{path_to_add}.lib");
2824 let candidate = PathBuf::from(candidate);
2825 if candidate.exists() {
2826 deps.push((candidate, DependencyType::Target));
2827 }
2828 }
2829 deps.push((path_to_add.into(), DependencyType::Target));
2830 }
2831
2832 deps.extend(additional_target_deps);
2833 deps.sort();
2834 let mut new_contents = Vec::new();
2835 for (dep, dependency_type) in deps.iter() {
2836 new_contents.extend(match *dependency_type {
2837 DependencyType::Host => b"h",
2838 DependencyType::Target => b"t",
2839 DependencyType::TargetSelfContained => b"s",
2840 });
2841 new_contents.extend(dep.to_str().unwrap().as_bytes());
2842 new_contents.extend(b"\0");
2843 }
2844 t!(fs::write(stamp.path(), &new_contents));
2845 deps.into_iter().map(|(d, _)| d).collect()
2846}
2847
2848pub fn stream_cargo(
2849 builder: &Builder<'_>,
2850 cargo: Cargo,
2851 tail_args: Vec<String>,
2852 cb: &mut dyn FnMut(CargoMessage<'_>),
2853) -> bool {
2854 let mut cmd = cargo.into_cmd();
2855
2856 let mut message_format = if builder.config.json_output {
2859 String::from("json")
2860 } else {
2861 String::from("json-render-diagnostics")
2862 };
2863 if let Some(s) = &builder.config.rustc_error_format {
2864 message_format.push_str(",json-diagnostic-");
2865 message_format.push_str(s);
2866 }
2867 cmd.arg("--message-format").arg(message_format);
2868
2869 for arg in tail_args {
2870 cmd.arg(arg);
2871 }
2872
2873 builder.do_if_verbose(|| println!("running: {cmd:?}"));
2874
2875 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2876
2877 let Some(mut streaming_command) = streaming_command else {
2878 return true;
2879 };
2880
2881 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2885 for line in stdout.lines() {
2886 let line = t!(line);
2887 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2888 Ok(msg) => {
2889 if builder.config.json_output {
2890 println!("{line}");
2892 }
2893 cb(msg)
2894 }
2895 Err(_) => println!("{line}"),
2897 }
2898 }
2899
2900 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2902 if builder.is_verbose() && !status.success() {
2903 eprintln!(
2904 "command did not execute successfully: {cmd:?}\n\
2905 expected success, got: {status}"
2906 );
2907 }
2908
2909 status.success()
2910}
2911
2912#[derive(Deserialize, Debug)]
2913pub struct CargoTarget<'a> {
2914 pub crate_types: Vec<Cow<'a, str>>,
2915 #[serde(default)]
2916 pub doc: bool,
2917}
2918
2919#[derive(Deserialize, Debug)]
2920#[serde(tag = "reason", rename_all = "kebab-case")]
2921pub enum CargoMessage<'a> {
2922 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2923 BuildScriptExecuted,
2924 BuildFinished,
2925}
2926
2927pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2928 if target != "x86_64-unknown-linux-gnu"
2932 || !builder.config.is_host_target(target)
2933 || !path.exists()
2934 {
2935 return;
2936 }
2937
2938 let previous_mtime = t!(t!(path.metadata()).modified());
2939 let stamp = BuildStamp::new(path.parent().unwrap())
2940 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2941 .with_prefix("strip")
2942 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2943
2944 if !stamp.is_up_to_date() {
2947 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2948 }
2949 t!(stamp.write());
2950
2951 let file = t!(fs::File::open(path));
2952
2953 t!(file.set_modified(previous_mtime));
2966}
2967
2968pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2970 build_compiler.stage != 0
2971}