1use std::borrow::Cow;
10use std::collections::{BTreeMap, HashMap, HashSet};
11use std::ffi::OsStr;
12use std::io::BufReader;
13use std::io::prelude::*;
14use std::path::{Path, PathBuf};
15use std::time::SystemTime;
16use std::{env, fs, str};
17
18use serde_derive::Deserialize;
19#[cfg(feature = "tracing")]
20use tracing::span;
21
22use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair};
23use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
24use crate::core::build_steps::{dist, llvm};
25use crate::core::builder;
26use crate::core::builder::{
27 Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
28};
29use crate::core::config::toml::target::DefaultLinuxLinkerOverride;
30use crate::core::config::{
31 CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
32};
33use crate::utils::build_stamp;
34use crate::utils::build_stamp::BuildStamp;
35use crate::utils::exec::command;
36use crate::utils::helpers::{
37 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
38};
39use crate::{
40 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
41 debug, exit, trace,
42};
43
44#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub struct Std {
47 pub target: TargetSelection,
48 pub build_compiler: Compiler,
50 crates: Vec<String>,
54 force_recompile: bool,
57 extra_rust_args: &'static [&'static str],
58 is_for_mir_opt_tests: bool,
59}
60
61impl Std {
62 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
63 Self {
64 target,
65 build_compiler,
66 crates: Default::default(),
67 force_recompile: false,
68 extra_rust_args: &[],
69 is_for_mir_opt_tests: false,
70 }
71 }
72
73 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
74 self.force_recompile = force_recompile;
75 self
76 }
77
78 #[expect(clippy::wrong_self_convention)]
79 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
80 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
81 self
82 }
83
84 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
85 self.extra_rust_args = extra_rust_args;
86 self
87 }
88
89 fn copy_extra_objects(
90 &self,
91 builder: &Builder<'_>,
92 compiler: &Compiler,
93 target: TargetSelection,
94 ) -> Vec<(PathBuf, DependencyType)> {
95 let mut deps = Vec::new();
96 if !self.is_for_mir_opt_tests {
97 deps.extend(copy_third_party_objects(builder, compiler, target));
98 deps.extend(copy_self_contained_objects(builder, compiler, target));
99 }
100 deps
101 }
102
103 pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool {
108 stage > 1 && !builder.config.full_bootstrap
109 }
110}
111
112impl Step for Std {
113 type Output = Option<BuildStamp>;
115
116 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
117 run.crate_or_deps("sysroot").path("library")
118 }
119
120 fn is_default_step(_builder: &Builder<'_>) -> bool {
121 true
122 }
123
124 fn make_run(run: RunConfig<'_>) {
125 let crates = std_crates_for_run_make(&run);
126 let builder = run.builder;
127
128 let force_recompile = builder.rust_info().is_managed_git_subrepository()
132 && builder.download_rustc()
133 && builder.config.has_changes_from_upstream(&["library"]);
134
135 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
136 trace!("download_rustc: {}", builder.download_rustc());
137 trace!(force_recompile);
138
139 run.builder.ensure(Std {
140 build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target),
143 target: run.target,
144 crates,
145 force_recompile,
146 extra_rust_args: &[],
147 is_for_mir_opt_tests: false,
148 });
149 }
150
151 fn run(self, builder: &Builder<'_>) -> Self::Output {
157 let target = self.target;
158
159 if self.build_compiler.stage == 0
164 && !(builder.local_rebuild && target != builder.host_target)
165 {
166 let compiler = self.build_compiler;
167 builder.ensure(StdLink::from_std(self, compiler));
168
169 return None;
170 }
171
172 let build_compiler = if builder.download_rustc() && self.force_recompile {
173 builder
176 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
177 } else {
178 self.build_compiler
179 };
180
181 if builder.download_rustc()
184 && builder.config.is_host_target(target)
185 && !self.force_recompile
186 {
187 let sysroot =
188 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
189 cp_rustc_component_to_ci_sysroot(
190 builder,
191 &sysroot,
192 builder.config.ci_rust_std_contents(),
193 );
194 return None;
195 }
196
197 if builder.config.keep_stage.contains(&build_compiler.stage)
198 || builder.config.keep_stage_std.contains(&build_compiler.stage)
199 {
200 trace!(keep_stage = ?builder.config.keep_stage);
201 trace!(keep_stage_std = ?builder.config.keep_stage_std);
202
203 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
204
205 builder.ensure(StartupObjects { compiler: build_compiler, target });
206
207 self.copy_extra_objects(builder, &build_compiler, target);
208
209 builder.ensure(StdLink::from_std(self, build_compiler));
210 return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
211 }
212
213 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
214
215 let stage = build_compiler.stage;
217
218 if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
219 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
220 let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
221
222 let msg = if build_compiler_for_std_to_uplift.host == target {
223 format!(
224 "Uplifting library (stage{} -> stage{stage})",
225 build_compiler_for_std_to_uplift.stage
226 )
227 } else {
228 format!(
229 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
230 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
231 )
232 };
233
234 builder.info(&msg);
235
236 self.copy_extra_objects(builder, &build_compiler, target);
239
240 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
241 return stage_1_stamp;
242 }
243
244 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
245
246 let mut cargo = if self.is_for_mir_opt_tests {
250 trace!("building special sysroot for mir-opt tests");
251 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
252 builder,
253 build_compiler,
254 Mode::Std,
255 SourceType::InTree,
256 target,
257 Kind::Check,
258 );
259 cargo.rustflag("-Zalways-encode-mir");
260 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
261 cargo
262 } else {
263 trace!("building regular sysroot");
264 let mut cargo = builder::Cargo::new(
265 builder,
266 build_compiler,
267 Mode::Std,
268 SourceType::InTree,
269 target,
270 Kind::Build,
271 );
272 std_cargo(builder, target, &mut cargo, &self.crates);
273 cargo
274 };
275
276 if target.is_synthetic() {
278 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
279 }
280 for rustflag in self.extra_rust_args.iter() {
281 cargo.rustflag(rustflag);
282 }
283
284 let _guard = builder.msg(
285 Kind::Build,
286 format_args!("library artifacts{}", crate_description(&self.crates)),
287 Mode::Std,
288 build_compiler,
289 target,
290 );
291
292 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
293 run_cargo(
294 builder,
295 cargo,
296 vec![],
297 &stamp,
298 target_deps,
299 if self.is_for_mir_opt_tests {
300 ArtifactKeepMode::OnlyRmeta
301 } else {
302 ArtifactKeepMode::BothRlibAndRmeta
304 },
305 );
306
307 builder.ensure(StdLink::from_std(
308 self,
309 builder.compiler(build_compiler.stage, builder.config.host_target),
310 ));
311 Some(stamp)
312 }
313
314 fn metadata(&self) -> Option<StepMetadata> {
315 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
316 }
317}
318
319fn copy_and_stamp(
320 builder: &Builder<'_>,
321 libdir: &Path,
322 sourcedir: &Path,
323 name: &str,
324 target_deps: &mut Vec<(PathBuf, DependencyType)>,
325 dependency_type: DependencyType,
326) {
327 let target = libdir.join(name);
328 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
329
330 target_deps.push((target, dependency_type));
331}
332
333fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
334 let libunwind_path = builder.ensure(llvm::Libunwind { target });
335 let libunwind_source = libunwind_path.join("libunwind.a");
336 let libunwind_target = libdir.join("libunwind.a");
337 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
338 libunwind_target
339}
340
341fn copy_third_party_objects(
343 builder: &Builder<'_>,
344 compiler: &Compiler,
345 target: TargetSelection,
346) -> Vec<(PathBuf, DependencyType)> {
347 let mut target_deps = vec![];
348
349 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
350 target_deps.extend(
353 copy_sanitizers(builder, compiler, target)
354 .into_iter()
355 .map(|d| (d, DependencyType::Target)),
356 );
357 }
358
359 if target == "x86_64-fortanix-unknown-sgx"
360 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
361 && (target.contains("linux")
362 || target.contains("fuchsia")
363 || target.contains("aix")
364 || target.contains("hexagon"))
365 {
366 let libunwind_path =
367 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
368 target_deps.push((libunwind_path, DependencyType::Target));
369 }
370
371 target_deps
372}
373
374fn copy_self_contained_objects(
376 builder: &Builder<'_>,
377 compiler: &Compiler,
378 target: TargetSelection,
379) -> Vec<(PathBuf, DependencyType)> {
380 let libdir_self_contained =
381 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
382 t!(fs::create_dir_all(&libdir_self_contained));
383 let mut target_deps = vec![];
384
385 if target.needs_crt_begin_end() {
393 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
394 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
395 });
396 if !target.starts_with("wasm32") {
397 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
398 copy_and_stamp(
399 builder,
400 &libdir_self_contained,
401 &srcdir,
402 obj,
403 &mut target_deps,
404 DependencyType::TargetSelfContained,
405 );
406 }
407 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
408 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
409 let src = crt_path.join(obj);
410 let target = libdir_self_contained.join(obj);
411 builder.copy_link(&src, &target, FileType::NativeLibrary);
412 target_deps.push((target, DependencyType::TargetSelfContained));
413 }
414 } else {
415 for &obj in &["libc.a", "crt1-command.o"] {
418 copy_and_stamp(
419 builder,
420 &libdir_self_contained,
421 &srcdir,
422 obj,
423 &mut target_deps,
424 DependencyType::TargetSelfContained,
425 );
426 }
427 }
428 if !target.starts_with("s390x") {
429 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
430 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
431 }
432 } else if target.contains("-wasi") {
433 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
434 panic!(
435 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
436 or `$WASI_SDK_PATH` set",
437 target.triple
438 )
439 });
440
441 let srcdir = if target == "wasm32-wasip3" {
445 assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now");
446 builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap()
447 } else {
448 srcdir
449 };
450 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
451 copy_and_stamp(
452 builder,
453 &libdir_self_contained,
454 &srcdir,
455 obj,
456 &mut target_deps,
457 DependencyType::TargetSelfContained,
458 );
459 }
460 if srcdir.join("eh").exists() {
461 copy_and_stamp(
462 builder,
463 &libdir_self_contained,
464 &srcdir.join("eh"),
465 "libunwind.a",
466 &mut target_deps,
467 DependencyType::TargetSelfContained,
468 );
469 }
470 } else if target.is_windows_gnu() || target.is_windows_gnullvm() {
471 for obj in ["crt2.o", "dllcrt2.o"].iter() {
472 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
473 let dst = libdir_self_contained.join(obj);
474 builder.copy_link(&src, &dst, FileType::NativeLibrary);
475 target_deps.push((dst, DependencyType::TargetSelfContained));
476 }
477 }
478
479 target_deps
480}
481
482pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
485 let mut crates = run.make_run_crates(builder::Alias::Library);
486
487 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
496 if target_is_no_std {
497 crates.retain(|c| c == "core" || c == "alloc");
498 }
499 crates
500}
501
502fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
508 if builder.config.llvm_from_ci {
510 builder.config.maybe_download_ci_llvm();
512 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
513 if ci_llvm_compiler_rt.exists() {
514 return ci_llvm_compiler_rt;
515 }
516 }
517
518 builder.require_submodule("src/llvm-project", {
520 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
521 });
522 builder.src.join("src/llvm-project/compiler-rt")
523}
524
525pub fn std_cargo(
528 builder: &Builder<'_>,
529 target: TargetSelection,
530 cargo: &mut Cargo,
531 crates: &[String],
532) {
533 if target.contains("apple") && !builder.config.dry_run() {
551 let mut cmd = builder.rustc_cmd(cargo.compiler());
555 cmd.arg("--target").arg(target.rustc_target_arg());
556 cmd.arg("-Zunstable-options").env("RUSTC_BOOTSTRAP", "1");
559 cmd.arg("--print=deployment-target");
560 let output = cmd.run_capture_stdout(builder).stdout();
561
562 let (env_var, value) = output.split_once('=').unwrap();
563 cargo.env(env_var.trim(), value.trim());
566
567 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
577 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
578 }
579 }
580
581 if let Some(path) = builder.config.profiler_path(target) {
583 cargo.env("LLVM_PROFILER_RT_LIB", path);
584 } else if builder.config.profiler_enabled(target) {
585 let compiler_rt = compiler_rt_for_profiler(builder);
586 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
590 }
591
592 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
606 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
607 cargo.env("LLVM_COMPILER_RT_LIB", path);
608 " compiler-builtins-c"
609 }
610 CompilerBuiltins::BuildLLVMFuncs => {
611 builder.require_submodule(
621 "src/llvm-project",
622 Some(
623 "The `build.optimized-compiler-builtins` config option \
624 requires `compiler-rt` sources from LLVM.",
625 ),
626 );
627 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
628 if !builder.config.dry_run() {
629 assert!(compiler_builtins_root.exists());
632 }
633
634 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
637 " compiler-builtins-c"
638 }
639 CompilerBuiltins::BuildRustOnly => "",
640 };
641
642 for krate in crates {
643 cargo.args(["-p", krate]);
644 }
645
646 let mut features = String::new();
647
648 if builder.no_std(target) == Some(true) {
649 features += " compiler-builtins-mem";
650 if !target.starts_with("bpf") {
651 features.push_str(compiler_builtins_c_feature);
652 }
653
654 if crates.is_empty() {
656 cargo.args(["-p", "alloc"]);
657 }
658 cargo
659 .arg("--manifest-path")
660 .arg(builder.src.join("library/alloc/Cargo.toml"))
661 .arg("--features")
662 .arg(features);
663 } else {
664 features += &builder.std_features(target);
665 features.push_str(compiler_builtins_c_feature);
666
667 cargo
668 .arg("--features")
669 .arg(features)
670 .arg("--manifest-path")
671 .arg(builder.src.join("library/sysroot/Cargo.toml"));
672
673 if target.contains("musl")
676 && let Some(p) = builder.musl_libdir(target)
677 {
678 let root = format!("native={}", p.to_str().unwrap());
679 cargo.rustflag("-L").rustflag(&root);
680 }
681
682 if target.contains("-wasi")
683 && let Some(dir) = builder.wasi_libdir(target)
684 {
685 let root = format!("native={}", dir.to_str().unwrap());
686 cargo.rustflag("-L").rustflag(&root);
687 }
688 }
689
690 if builder.config.rust_lto == RustcLto::Off {
691 cargo.rustflag("-Clto=off");
692 }
693
694 if target.contains("riscv") {
701 cargo.rustflag("-Cforce-unwind-tables=yes");
702 }
703
704 let html_root =
705 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
706 cargo.rustflag(&html_root);
707 cargo.rustdocflag(&html_root);
708
709 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
710}
711
712#[derive(Debug, Clone, PartialEq, Eq, Hash)]
721pub struct StdLink {
722 pub compiler: Compiler,
723 pub target_compiler: Compiler,
724 pub target: TargetSelection,
725 crates: Vec<String>,
727 force_recompile: bool,
729}
730
731impl StdLink {
732 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
733 Self {
734 compiler: host_compiler,
735 target_compiler: std.build_compiler,
736 target: std.target,
737 crates: std.crates,
738 force_recompile: std.force_recompile,
739 }
740 }
741}
742
743impl Step for StdLink {
744 type Output = ();
745
746 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
747 run.never()
748 }
749
750 fn run(self, builder: &Builder<'_>) {
759 let compiler = self.compiler;
760 let target_compiler = self.target_compiler;
761 let target = self.target;
762
763 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
765 let lib = builder.sysroot_libdir_relative(self.compiler);
767 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
768 compiler: self.compiler,
769 force_recompile: self.force_recompile,
770 });
771 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
772 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
773 (libdir, hostdir)
774 } else {
775 let libdir = builder.sysroot_target_libdir(target_compiler, target);
776 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
777 (libdir, hostdir)
778 };
779
780 let is_downloaded_beta_stage0 = builder
781 .build
782 .config
783 .initial_rustc
784 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
785
786 if compiler.stage == 0 && is_downloaded_beta_stage0 {
790 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
792
793 let host = compiler.host;
794 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
795 let sysroot_bin_dir = sysroot.join("bin");
796 t!(fs::create_dir_all(&sysroot_bin_dir));
797 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
798
799 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
800 t!(fs::create_dir_all(sysroot.join("lib")));
801 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
802
803 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
805 t!(fs::create_dir_all(&sysroot_codegen_backends));
806 let stage0_codegen_backends = builder
807 .out
808 .join(host)
809 .join("stage0/lib/rustlib")
810 .join(host)
811 .join("codegen-backends");
812 if stage0_codegen_backends.exists() {
813 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
814 }
815 } else if compiler.stage == 0 {
816 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
817
818 if builder.local_rebuild {
819 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
823 }
824
825 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
826 } else {
827 if builder.download_rustc() {
828 let _ = fs::remove_dir_all(&libdir);
830 let _ = fs::remove_dir_all(&hostdir);
831 }
832
833 add_to_sysroot(
834 builder,
835 &libdir,
836 &hostdir,
837 &build_stamp::libstd_stamp(builder, compiler, target),
838 );
839 }
840 }
841}
842
843fn copy_sanitizers(
845 builder: &Builder<'_>,
846 compiler: &Compiler,
847 target: TargetSelection,
848) -> Vec<PathBuf> {
849 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
850
851 if builder.config.dry_run() {
852 return Vec::new();
853 }
854
855 let mut target_deps = Vec::new();
856 let libdir = builder.sysroot_target_libdir(*compiler, target);
857
858 for runtime in &runtimes {
859 let dst = libdir.join(&runtime.name);
860 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
861
862 if target == "x86_64-apple-darwin"
866 || target == "aarch64-apple-darwin"
867 || target == "aarch64-apple-ios"
868 || target == "aarch64-apple-ios-sim"
869 || target == "x86_64-apple-ios"
870 {
871 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
873 apple_darwin_sign_file(builder, &dst);
876 }
877
878 target_deps.push(dst);
879 }
880
881 target_deps
882}
883
884fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
885 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
886}
887
888fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
889 command("codesign")
890 .arg("-f") .arg("-s")
892 .arg("-")
893 .arg(file_path)
894 .run(builder);
895}
896
897#[derive(Debug, Clone, PartialEq, Eq, Hash)]
898pub struct StartupObjects {
899 pub compiler: Compiler,
900 pub target: TargetSelection,
901}
902
903impl Step for StartupObjects {
904 type Output = Vec<(PathBuf, DependencyType)>;
905
906 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
907 run.path("library/rtstartup")
908 }
909
910 fn make_run(run: RunConfig<'_>) {
911 run.builder.ensure(StartupObjects {
912 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
913 target: run.target,
914 });
915 }
916
917 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
924 let for_compiler = self.compiler;
925 let target = self.target;
926 if !target.is_windows_gnu() {
929 return vec![];
930 }
931
932 let mut target_deps = vec![];
933
934 let src_dir = &builder.src.join("library").join("rtstartup");
935 let dst_dir = &builder.native_dir(target).join("rtstartup");
936 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
937 t!(fs::create_dir_all(dst_dir));
938
939 for file in &["rsbegin", "rsend"] {
940 let src_file = &src_dir.join(file.to_string() + ".rs");
941 let dst_file = &dst_dir.join(file.to_string() + ".o");
942 if !up_to_date(src_file, dst_file) {
943 let mut cmd = command(&builder.initial_rustc);
944 cmd.env("RUSTC_BOOTSTRAP", "1");
945 if !builder.local_rebuild {
946 cmd.arg("--cfg").arg("bootstrap");
948 }
949 cmd.arg("--target")
950 .arg(target.rustc_target_arg())
951 .arg("--emit=obj")
952 .arg("-o")
953 .arg(dst_file)
954 .arg(src_file)
955 .run(builder);
956 }
957
958 let obj = sysroot_dir.join((*file).to_string() + ".o");
959 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
960 target_deps.push((obj, DependencyType::Target));
961 }
962
963 target_deps
964 }
965}
966
967fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
968 let ci_rustc_dir = builder.config.ci_rustc_dir();
969
970 for file in contents {
971 let src = ci_rustc_dir.join(&file);
972 let dst = sysroot.join(file);
973 if src.is_dir() {
974 t!(fs::create_dir_all(dst));
975 } else {
976 builder.copy_link(&src, &dst, FileType::Regular);
977 }
978 }
979}
980
981#[derive(Clone, Debug)]
983pub struct BuiltRustc {
984 pub build_compiler: Compiler,
988}
989
990#[derive(Debug, Clone, PartialEq, Eq, Hash)]
997pub struct Rustc {
998 pub target: TargetSelection,
1000 pub build_compiler: Compiler,
1002 crates: Vec<String>,
1008}
1009
1010impl Rustc {
1011 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
1012 Self { target, build_compiler, crates: Default::default() }
1013 }
1014}
1015
1016impl Step for Rustc {
1017 type Output = BuiltRustc;
1018 const IS_HOST: bool = true;
1019
1020 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1021 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1022 for (i, krate) in crates.iter().enumerate() {
1023 if krate.name == "rustc-main" {
1026 crates.swap_remove(i);
1027 break;
1028 }
1029 }
1030 run.crates(crates)
1031 }
1032
1033 fn is_default_step(_builder: &Builder<'_>) -> bool {
1034 false
1035 }
1036
1037 fn make_run(run: RunConfig<'_>) {
1038 if run.builder.paths == vec![PathBuf::from("compiler")] {
1041 return;
1042 }
1043
1044 let crates = run.cargo_crates_in_set();
1045 run.builder.ensure(Rustc {
1046 build_compiler: run
1047 .builder
1048 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1049 target: run.target,
1050 crates,
1051 });
1052 }
1053
1054 fn run(self, builder: &Builder<'_>) -> Self::Output {
1060 let build_compiler = self.build_compiler;
1061 let target = self.target;
1062
1063 if builder.download_rustc() && build_compiler.stage != 0 {
1066 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1067
1068 let sysroot =
1069 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1070 cp_rustc_component_to_ci_sysroot(
1071 builder,
1072 &sysroot,
1073 builder.config.ci_rustc_dev_contents(),
1074 );
1075 return BuiltRustc { build_compiler };
1076 }
1077
1078 builder.std(build_compiler, target);
1081
1082 if builder.config.keep_stage.contains(&build_compiler.stage) {
1083 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1084
1085 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1086 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1087 builder.ensure(RustcLink::from_rustc(self));
1088
1089 return BuiltRustc { build_compiler };
1090 }
1091
1092 let stage = build_compiler.stage + 1;
1094
1095 if build_compiler.stage >= 2
1100 && !builder.config.full_bootstrap
1101 && target == builder.host_target
1102 {
1103 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1107
1108 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1109 builder.info(&msg);
1110
1111 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1115 uplift_build_compiler,
1117 build_compiler,
1119 target,
1120 self.crates,
1121 ));
1122
1123 return BuiltRustc { build_compiler: uplift_build_compiler };
1126 }
1127
1128 builder.std(
1134 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1135 builder.config.host_target,
1136 );
1137
1138 let mut cargo = builder::Cargo::new(
1139 builder,
1140 build_compiler,
1141 Mode::Rustc,
1142 SourceType::InTree,
1143 target,
1144 Kind::Build,
1145 );
1146
1147 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1148
1149 for krate in &*self.crates {
1153 cargo.arg("-p").arg(krate);
1154 }
1155
1156 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1157 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1159 }
1160
1161 let _guard = builder.msg(
1162 Kind::Build,
1163 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1164 Mode::Rustc,
1165 build_compiler,
1166 target,
1167 );
1168 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1169
1170 run_cargo(
1171 builder,
1172 cargo,
1173 vec![],
1174 &stamp,
1175 vec![],
1176 ArtifactKeepMode::Custom(Box::new(|filename| {
1177 if filename.contains("jemalloc_sys")
1178 || filename.contains("rustc_public_bridge")
1179 || filename.contains("rustc_public")
1180 {
1181 filename.ends_with(".rlib")
1184 } else {
1185 filename.ends_with(".rmeta")
1189 }
1190 })),
1191 );
1192
1193 let target_root_dir = stamp.path().parent().unwrap();
1194 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1200 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1201 {
1202 let rustc_driver = target_root_dir.join("librustc_driver.so");
1203 strip_debug(builder, target, &rustc_driver);
1204 }
1205
1206 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1207 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1210 }
1211
1212 builder.ensure(RustcLink::from_rustc(self));
1213 BuiltRustc { build_compiler }
1214 }
1215
1216 fn metadata(&self) -> Option<StepMetadata> {
1217 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1218 }
1219}
1220
1221pub fn rustc_cargo(
1222 builder: &Builder<'_>,
1223 cargo: &mut Cargo,
1224 target: TargetSelection,
1225 build_compiler: &Compiler,
1226 crates: &[String],
1227) {
1228 cargo
1229 .arg("--features")
1230 .arg(builder.rustc_features(builder.kind, target, crates))
1231 .arg("--manifest-path")
1232 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1233
1234 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1235
1236 cargo.rustflag("-Zon-broken-pipe=kill");
1250
1251 if builder.build.config.bootstrap_override_lld.is_used() {
1256 cargo.rustflag("-Zdefault-visibility=protected");
1257 }
1258
1259 if is_lto_stage(build_compiler) {
1260 match builder.config.rust_lto {
1261 RustcLto::Thin | RustcLto::Fat => {
1262 cargo.rustflag("-Zdylib-lto");
1265 let lto_type = match builder.config.rust_lto {
1269 RustcLto::Thin => "thin",
1270 RustcLto::Fat => "fat",
1271 _ => unreachable!(),
1272 };
1273 cargo.rustflag(&format!("-Clto={lto_type}"));
1274 cargo.rustflag("-Cembed-bitcode=yes");
1275 }
1276 RustcLto::ThinLocal => { }
1277 RustcLto::Off => {
1278 cargo.rustflag("-Clto=off");
1279 }
1280 }
1281 } else if builder.config.rust_lto == RustcLto::Off {
1282 cargo.rustflag("-Clto=off");
1283 }
1284
1285 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1293 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1294 }
1295
1296 let is_collecting = if let Some(path) = &builder.config.rust_pgo.generate_profile {
1297 if build_compiler.stage == 1 {
1298 cargo
1299 .rustflag(&format!("-Cprofile-generate={}", path.to_str().expect("non-UTF8 path")));
1300 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1303 true
1304 } else {
1305 false
1306 }
1307 } else if let Some(path) = &builder.config.rust_pgo.use_profile {
1308 if build_compiler.stage == 1 {
1309 cargo.rustflag(&format!("-Cprofile-use={}", path.to_str().expect("non-UTF8 path")));
1310 if builder.is_verbose() {
1311 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1312 }
1313 true
1314 } else {
1315 false
1316 }
1317 } else {
1318 false
1319 };
1320 if is_collecting {
1321 cargo.rustflag(&format!(
1323 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1324 builder.config.src.components().count()
1325 ));
1326 }
1327
1328 if let Some(ref ccache) = builder.config.ccache
1333 && build_compiler.stage == 0
1334 && !builder.config.incremental
1335 {
1336 cargo.env("RUSTC_WRAPPER", ccache);
1337 }
1338
1339 rustc_cargo_env(builder, cargo, target);
1340}
1341
1342pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1343 cargo
1346 .env("CFG_RELEASE", builder.rust_release())
1347 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1348 .env("CFG_VERSION", builder.rust_version());
1349
1350 if builder.config.omit_git_hash {
1354 cargo.env("CFG_OMIT_GIT_HASH", "1");
1355 }
1356
1357 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1358
1359 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1360 let target_config = builder.config.target_config.get(&target);
1361
1362 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1363
1364 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1365 cargo.env("CFG_VER_DATE", ver_date);
1366 }
1367 if let Some(ref ver_hash) = builder.rust_info().sha() {
1368 cargo.env("CFG_VER_HASH", ver_hash);
1369 }
1370 if !builder.unstable_features() {
1371 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1372 }
1373
1374 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1377 cargo.env("CFG_DEFAULT_LINKER", s);
1378 } else if let Some(ref s) = builder.config.rustc_default_linker {
1379 cargo.env("CFG_DEFAULT_LINKER", s);
1380 }
1381
1382 if let Some(linker) = target_config.map(|c| c.default_linker_linux_override) {
1384 match linker {
1385 DefaultLinuxLinkerOverride::Off => {}
1386 DefaultLinuxLinkerOverride::SelfContainedLldCc => {
1387 cargo.env("CFG_DEFAULT_LINKER_SELF_CONTAINED_LLD_CC", "1");
1388 }
1389 }
1390 }
1391
1392 cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple);
1394
1395 if builder.config.rust_verify_llvm_ir {
1396 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1397 }
1398
1399 if builder.config.llvm_enabled(target) {
1411 let building_llvm_is_expensive =
1412 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1413 .should_build();
1414
1415 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1416 if !skip_llvm {
1417 rustc_llvm_env(builder, cargo, target)
1418 }
1419 }
1420
1421 if builder.config.jemalloc(target) && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
1423 if target.starts_with("aarch64") {
1426 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1427 }
1428 else if target.starts_with("loongarch") {
1430 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1431 }
1432 }
1433}
1434
1435fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1441 if builder.config.is_rust_llvm(target) {
1442 cargo.env("LLVM_RUSTLLVM", "1");
1443 }
1444 if builder.config.llvm_enzyme {
1445 cargo.env("LLVM_ENZYME", "1");
1446 }
1447 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1448 if builder.config.llvm_offload {
1449 builder.ensure(llvm::OmpOffload { target });
1450 cargo.env("LLVM_OFFLOAD", "1");
1451 }
1452
1453 cargo.env("LLVM_CONFIG", &host_llvm_config);
1454
1455 let mut llvm_linker_flags = String::new();
1465 if builder.config.llvm_pgo.generate_profile.is_some()
1466 && target.is_msvc()
1467 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1468 {
1469 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1471 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1472 }
1473
1474 if let Some(ref s) = builder.config.llvm_ldflags {
1476 if !llvm_linker_flags.is_empty() {
1477 llvm_linker_flags.push(' ');
1478 }
1479 llvm_linker_flags.push_str(s);
1480 }
1481
1482 if !llvm_linker_flags.is_empty() {
1484 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1485 }
1486
1487 if builder.config.llvm_static_stdcpp
1490 && !target.contains("freebsd")
1491 && !target.is_msvc()
1492 && !target.contains("apple")
1493 && !target.contains("solaris")
1494 {
1495 let libstdcxx_name =
1496 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1497 let file = compiler_file(
1498 builder,
1499 &builder.cxx(target).unwrap(),
1500 target,
1501 CLang::Cxx,
1502 libstdcxx_name,
1503 );
1504 cargo.env("LLVM_STATIC_STDCPP", file);
1505 }
1506 if builder.llvm_link_shared() {
1507 cargo.env("LLVM_LINK_SHARED", "1");
1508 }
1509 if builder.config.llvm_use_libcxx {
1510 cargo.env("LLVM_USE_LIBCXX", "1");
1511 }
1512 if builder.config.llvm_assertions {
1513 cargo.env("LLVM_ASSERTIONS", "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 should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1568 run.never()
1569 }
1570
1571 fn run(self, builder: &Builder<'_>) {
1573 let build_compiler = self.build_compiler;
1574 let sysroot_compiler = self.sysroot_compiler;
1575 let target = self.target;
1576 add_to_sysroot(
1577 builder,
1578 &builder.sysroot_target_libdir(sysroot_compiler, target),
1579 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1580 &build_stamp::librustc_stamp(builder, build_compiler, target),
1581 );
1582 }
1583}
1584
1585#[derive(Clone)]
1591pub struct GccDylibSet {
1592 dylibs: BTreeMap<GccTargetPair, GccOutput>,
1593}
1594
1595impl GccDylibSet {
1596 pub fn build(
1599 builder: &Builder<'_>,
1600 host: TargetSelection,
1601 targets: Vec<TargetSelection>,
1602 ) -> Self {
1603 let dylibs = targets
1604 .iter()
1605 .map(|t| GccTargetPair::for_target_pair(host, *t))
1606 .map(|target_pair| (target_pair, builder.ensure(Gcc { target_pair })))
1607 .collect();
1608 Self { dylibs }
1609 }
1610
1611 pub fn install_to(&self, builder: &Builder<'_>, compiler: Compiler) {
1615 if builder.config.dry_run() {
1616 return;
1617 }
1618
1619 let cg_sysroot = builder.sysroot_codegen_backends(compiler);
1621
1622 for (target_pair, libgccjit) in &self.dylibs {
1623 assert_eq!(
1624 target_pair.host(),
1625 compiler.host,
1626 "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})",
1627 compiler.host
1628 );
1629 let libgccjit_path = libgccjit.libgccjit();
1630
1631 let libgccjit_path = t!(
1635 libgccjit_path.canonicalize(),
1636 format!("Cannot find libgccjit at {}", libgccjit_path.display())
1637 );
1638
1639 let dst = cg_sysroot.join(libgccjit_path_relative_to_cg_dir(target_pair, libgccjit));
1640 t!(std::fs::create_dir_all(dst.parent().unwrap()));
1641 builder.copy_link(&libgccjit_path, &dst, FileType::NativeLibrary);
1642 }
1643 }
1644}
1645
1646pub fn libgccjit_path_relative_to_cg_dir(
1649 target_pair: &GccTargetPair,
1650 libgccjit: &GccOutput,
1651) -> PathBuf {
1652 let target_filename = libgccjit.libgccjit().file_name().unwrap().to_str().unwrap();
1653
1654 Path::new("lib").join(target_pair.target()).join(target_filename)
1656}
1657
1658#[derive(Clone)]
1662pub struct GccCodegenBackendOutput {
1663 stamp: BuildStamp,
1664}
1665
1666impl GccCodegenBackendOutput {
1667 pub fn stamp(&self) -> &BuildStamp {
1668 &self.stamp
1669 }
1670}
1671
1672#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1679pub struct GccCodegenBackend {
1680 compilers: RustcPrivateCompilers,
1681 target: TargetSelection,
1682}
1683
1684impl GccCodegenBackend {
1685 pub fn for_target(compilers: RustcPrivateCompilers, target: TargetSelection) -> Self {
1687 Self { compilers, target }
1688 }
1689}
1690
1691impl Step for GccCodegenBackend {
1692 type Output = GccCodegenBackendOutput;
1693
1694 const IS_HOST: bool = true;
1695
1696 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1697 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1698 }
1699
1700 fn make_run(run: RunConfig<'_>) {
1701 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target);
1702 run.builder.ensure(GccCodegenBackend::for_target(compilers, run.target));
1703 }
1704
1705 fn run(self, builder: &Builder<'_>) -> Self::Output {
1706 let host = self.compilers.target();
1707 let build_compiler = self.compilers.build_compiler();
1708
1709 let stamp = build_stamp::codegen_backend_stamp(
1710 builder,
1711 build_compiler,
1712 host,
1713 &CodegenBackendKind::Gcc,
1714 );
1715
1716 if builder.config.keep_stage.contains(&build_compiler.stage) && stamp.path().exists() {
1717 trace!("`keep-stage` requested");
1718 builder.info(
1719 "WARNING: Using a potentially old codegen backend. \
1720 This may not behave well.",
1721 );
1722 return GccCodegenBackendOutput { stamp };
1725 }
1726
1727 let mut cargo = builder::Cargo::new(
1728 builder,
1729 build_compiler,
1730 Mode::Codegen,
1731 SourceType::InTree,
1732 host,
1733 Kind::Build,
1734 );
1735 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1736 rustc_cargo_env(builder, &mut cargo, host);
1737
1738 let _guard =
1739 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host);
1740 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
1741
1742 GccCodegenBackendOutput {
1743 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1744 }
1745 }
1746
1747 fn metadata(&self) -> Option<StepMetadata> {
1748 Some(
1749 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1750 .built_by(self.compilers.build_compiler()),
1751 )
1752 }
1753}
1754
1755#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1756pub struct CraneliftCodegenBackend {
1757 pub compilers: RustcPrivateCompilers,
1758}
1759
1760impl Step for CraneliftCodegenBackend {
1761 type Output = BuildStamp;
1762 const IS_HOST: bool = true;
1763
1764 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1765 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1766 }
1767
1768 fn make_run(run: RunConfig<'_>) {
1769 run.builder.ensure(CraneliftCodegenBackend {
1770 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1771 });
1772 }
1773
1774 fn run(self, builder: &Builder<'_>) -> Self::Output {
1775 let target = self.compilers.target();
1776 let build_compiler = self.compilers.build_compiler();
1777
1778 let stamp = build_stamp::codegen_backend_stamp(
1779 builder,
1780 build_compiler,
1781 target,
1782 &CodegenBackendKind::Cranelift,
1783 );
1784
1785 if builder.config.keep_stage.contains(&build_compiler.stage) {
1786 trace!("`keep-stage` requested");
1787 builder.info(
1788 "WARNING: Using a potentially old codegen backend. \
1789 This may not behave well.",
1790 );
1791 return stamp;
1794 }
1795
1796 let mut cargo = builder::Cargo::new(
1797 builder,
1798 build_compiler,
1799 Mode::Codegen,
1800 SourceType::InTree,
1801 target,
1802 Kind::Build,
1803 );
1804 cargo
1805 .arg("--manifest-path")
1806 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1807 rustc_cargo_env(builder, &mut cargo, target);
1808
1809 let _guard = builder.msg(
1810 Kind::Build,
1811 "codegen backend cranelift",
1812 Mode::Codegen,
1813 build_compiler,
1814 target,
1815 );
1816 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
1817 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1818 }
1819
1820 fn metadata(&self) -> Option<StepMetadata> {
1821 Some(
1822 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1823 .built_by(self.compilers.build_compiler()),
1824 )
1825 }
1826}
1827
1828fn write_codegen_backend_stamp(
1830 mut stamp: BuildStamp,
1831 files: Vec<PathBuf>,
1832 dry_run: bool,
1833) -> BuildStamp {
1834 if dry_run {
1835 return stamp;
1836 }
1837
1838 let mut files = files.into_iter().filter(|f| {
1839 let filename = f.file_name().unwrap().to_str().unwrap();
1840 is_dylib(f) && filename.contains("rustc_codegen_")
1841 });
1842 let codegen_backend = match files.next() {
1843 Some(f) => f,
1844 None => panic!("no dylibs built for codegen backend?"),
1845 };
1846 if let Some(f) = files.next() {
1847 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1848 }
1849
1850 let codegen_backend = codegen_backend.to_str().unwrap();
1851 stamp = stamp.add_stamp(codegen_backend);
1852 t!(stamp.write());
1853 stamp
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, GitRepo::Rustc, 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 should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1942 run.never()
1943 }
1944
1945 fn run(self, builder: &Builder<'_>) -> PathBuf {
1949 let compiler = self.compiler;
1950 let host_dir = builder.out.join(compiler.host);
1951
1952 let sysroot_dir = |stage| {
1953 if stage == 0 {
1954 host_dir.join("stage0-sysroot")
1955 } else if self.force_recompile && stage == compiler.stage {
1956 host_dir.join(format!("stage{stage}-test-sysroot"))
1957 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1958 host_dir.join("ci-rustc-sysroot")
1959 } else {
1960 host_dir.join(format!("stage{stage}"))
1961 }
1962 };
1963 let sysroot = sysroot_dir(compiler.stage);
1964 trace!(stage = ?compiler.stage, ?sysroot);
1965
1966 builder.do_if_verbose(|| {
1967 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1968 });
1969 let _ = fs::remove_dir_all(&sysroot);
1970 t!(fs::create_dir_all(&sysroot));
1971
1972 if compiler.stage == 0 {
1979 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1980 }
1981
1982 if builder.download_rustc() && compiler.stage != 0 {
1984 assert_eq!(
1985 builder.config.host_target, compiler.host,
1986 "Cross-compiling is not yet supported with `download-rustc`",
1987 );
1988
1989 for stage in 0..=2 {
1991 if stage != compiler.stage {
1992 let dir = sysroot_dir(stage);
1993 if !dir.ends_with("ci-rustc-sysroot") {
1994 let _ = fs::remove_dir_all(dir);
1995 }
1996 }
1997 }
1998
1999 let mut filtered_files = Vec::new();
2013 let mut add_filtered_files = |suffix, contents| {
2014 for path in contents {
2015 let path = Path::new(&path);
2016 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
2017 filtered_files.push(path.file_name().unwrap().to_owned());
2018 }
2019 }
2020 };
2021 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
2022 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
2023 add_filtered_files("lib", builder.config.ci_rust_std_contents());
2026
2027 let filtered_extensions = [
2028 OsStr::new("rmeta"),
2029 OsStr::new("rlib"),
2030 OsStr::new(std::env::consts::DLL_EXTENSION),
2032 ];
2033 let ci_rustc_dir = builder.config.ci_rustc_dir();
2034 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
2035 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
2036 return true;
2037 }
2038 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
2039 return true;
2040 }
2041 filtered_files.iter().all(|f| f != path.file_name().unwrap())
2042 });
2043 }
2044
2045 if compiler.stage != 0 {
2051 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
2052 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
2053 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
2054 if let Err(e) =
2055 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
2056 {
2057 eprintln!(
2058 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2059 sysroot_lib_rustlib_src_rust.display(),
2060 builder.src.display(),
2061 e,
2062 );
2063 if builder.config.rust_remap_debuginfo {
2064 eprintln!(
2065 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
2066 sysroot_lib_rustlib_src_rust.display(),
2067 );
2068 }
2069 exit!(1);
2070 }
2071 }
2072
2073 if !builder.download_rustc() {
2075 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
2076 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
2077 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
2078 if let Err(e) =
2079 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
2080 {
2081 eprintln!(
2082 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
2083 sysroot_lib_rustlib_rustcsrc_rust.display(),
2084 builder.src.display(),
2085 e,
2086 );
2087 exit!(1);
2088 }
2089 }
2090
2091 sysroot
2092 }
2093}
2094
2095#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2102pub struct Assemble {
2103 pub target_compiler: Compiler,
2108}
2109
2110impl Step for Assemble {
2111 type Output = Compiler;
2112 const IS_HOST: bool = true;
2113
2114 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2115 run.path("compiler/rustc").path("compiler")
2116 }
2117
2118 fn make_run(run: RunConfig<'_>) {
2119 run.builder.ensure(Assemble {
2120 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2121 });
2122 }
2123
2124 fn run(self, builder: &Builder<'_>) -> Compiler {
2125 let target_compiler = self.target_compiler;
2126
2127 if target_compiler.stage == 0 {
2128 trace!("stage 0 build compiler is always available, simply returning");
2129 assert_eq!(
2130 builder.config.host_target, target_compiler.host,
2131 "Cannot obtain compiler for non-native build triple at stage 0"
2132 );
2133 return target_compiler;
2135 }
2136
2137 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2140 let libdir_bin = libdir.parent().unwrap().join("bin");
2141 t!(fs::create_dir_all(&libdir_bin));
2142
2143 if builder.config.llvm_enabled(target_compiler.host) {
2144 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2145
2146 let target = target_compiler.host;
2147 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2148 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2149 trace!("LLVM tools enabled");
2150
2151 let host_llvm_bin_dir = command(&host_llvm_config)
2152 .arg("--bindir")
2153 .cached()
2154 .run_capture_stdout(builder)
2155 .stdout()
2156 .trim()
2157 .to_string();
2158
2159 let llvm_bin_dir = if target == builder.host_target {
2160 PathBuf::from(host_llvm_bin_dir)
2161 } else {
2162 let external_llvm_config = builder
2165 .config
2166 .target_config
2167 .get(&target)
2168 .and_then(|t| t.llvm_config.clone());
2169 if let Some(external_llvm_config) = external_llvm_config {
2170 external_llvm_config.parent().unwrap().to_path_buf()
2173 } else {
2174 let host_llvm_out = builder.llvm_out(builder.host_target);
2178 let target_llvm_out = builder.llvm_out(target);
2179 if let Ok(relative_path) =
2180 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2181 {
2182 target_llvm_out.join(relative_path)
2183 } else {
2184 PathBuf::from(
2187 host_llvm_bin_dir
2188 .replace(&*builder.host_target.triple, &target.triple),
2189 )
2190 }
2191 }
2192 };
2193
2194 #[cfg(feature = "tracing")]
2201 let _llvm_tools_span =
2202 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2203 .entered();
2204 for tool in LLVM_TOOLS {
2205 trace!("installing `{tool}`");
2206 let tool_exe = exe(tool, target_compiler.host);
2207 let src_path = llvm_bin_dir.join(&tool_exe);
2208
2209 if !src_path.exists() && builder.config.llvm_from_ci {
2211 eprintln!("{} does not exist; skipping copy", src_path.display());
2212 continue;
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 let offload_install = builder.ensure(llvm::OmpOffload { target: build_compiler.host });
2307 if let Some(_llvm_config) = builder.llvm_config(builder.config.host_target) {
2308 let target_libdir =
2309 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2310 for p in offload_install.offload_paths() {
2311 let libname = p.file_name().unwrap();
2312 let dst_lib = target_libdir.join(libname);
2313 builder.resolve_symlink_and_copy(&p, &dst_lib);
2314 }
2315 }
2320 }
2321
2322 debug!(
2325 ?build_compiler,
2326 "target_compiler.host" = ?target_compiler.host,
2327 "building compiler libraries to link to"
2328 );
2329
2330 let BuiltRustc { build_compiler } =
2332 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2333
2334 let stage = target_compiler.stage;
2335 let host = target_compiler.host;
2336 let (host_info, dir_name) = if build_compiler.host == host {
2337 ("".into(), "host".into())
2338 } else {
2339 (format!(" ({host})"), host.to_string())
2340 };
2341 let msg = format!(
2346 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2347 );
2348 builder.info(&msg);
2349
2350 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2352 let proc_macros = builder
2353 .read_stamp_file(&stamp)
2354 .into_iter()
2355 .filter_map(|(path, dependency_type)| {
2356 if dependency_type == DependencyType::Host {
2357 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2358 } else {
2359 None
2360 }
2361 })
2362 .collect::<HashSet<_>>();
2363
2364 let sysroot = builder.sysroot(target_compiler);
2365 let rustc_libdir = builder.rustc_libdir(target_compiler);
2366 t!(fs::create_dir_all(&rustc_libdir));
2367 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2368 for f in builder.read_dir(&src_libdir) {
2369 let filename = f.file_name().into_string().unwrap();
2370
2371 let is_proc_macro = proc_macros.contains(&filename);
2372 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2373
2374 let can_be_rustc_dynamic_dep = if builder
2378 .link_std_into_rustc_driver(target_compiler.host)
2379 && !target_compiler.host.is_windows()
2380 {
2381 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2382 !is_std
2383 } else {
2384 true
2385 };
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") {
2538 let wasm_component = builder.ensure(
2539 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2540 builder,
2541 target_compiler,
2542 ),
2543 );
2544 builder.copy_link(
2545 &wasm_component.tool_path,
2546 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2547 FileType::Executable,
2548 );
2549 }
2550
2551 maybe_install_llvm_bitcode_linker();
2552
2553 debug!(
2556 "target_compiler.host" = ?target_compiler.host,
2557 ?sysroot,
2558 "ensuring availability of `libLLVM.so` in compiler directory"
2559 );
2560 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2561 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2562
2563 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2565 let rustc = out_dir.join(exe("rustc-main", host));
2566 let bindir = sysroot.join("bin");
2567 t!(fs::create_dir_all(bindir));
2568 let compiler = builder.rustc(target_compiler);
2569 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2570 builder.copy_link(&rustc, &compiler, FileType::Executable);
2571
2572 target_compiler
2573 }
2574}
2575
2576#[track_caller]
2581pub fn add_to_sysroot(
2582 builder: &Builder<'_>,
2583 sysroot_dst: &Path,
2584 sysroot_host_dst: &Path,
2585 stamp: &BuildStamp,
2586) {
2587 let self_contained_dst = &sysroot_dst.join("self-contained");
2588 t!(fs::create_dir_all(sysroot_dst));
2589 t!(fs::create_dir_all(sysroot_host_dst));
2590 t!(fs::create_dir_all(self_contained_dst));
2591
2592 let mut crates = HashMap::new();
2593 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2594 let filename = path.file_name().unwrap().to_str().unwrap();
2595 let dst = match dependency_type {
2596 DependencyType::Host => {
2597 if sysroot_dst == sysroot_host_dst {
2598 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2601 }
2602
2603 sysroot_host_dst
2604 }
2605 DependencyType::Target => {
2606 crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
2609
2610 sysroot_dst
2611 }
2612 DependencyType::TargetSelfContained => self_contained_dst,
2613 };
2614 builder.copy_link(&path, &dst.join(filename), FileType::Regular);
2615 }
2616
2617 let mut seen_crates = HashMap::new();
2623 for (filestem, path) in crates {
2624 if !filestem.contains("rustc_") || filestem.contains("rustc_hash") {
2625 continue;
2626 }
2627 if let Some(other_path) =
2628 seen_crates.insert(filestem.split_once('-').unwrap().0.to_owned(), path.clone())
2629 {
2630 panic!(
2631 "duplicate rustc crate {}\n- first copy at {}\n- second copy at {}",
2632 filestem.split_once('-').unwrap().0.to_owned(),
2633 other_path.display(),
2634 path.display(),
2635 );
2636 }
2637 }
2638}
2639
2640pub enum ArtifactKeepMode {
2644 OnlyRlib,
2646 OnlyRmeta,
2648 BothRlibAndRmeta,
2652 Custom(Box<dyn Fn(&str) -> bool>),
2655}
2656
2657pub fn run_cargo(
2658 builder: &Builder<'_>,
2659 cargo: Cargo,
2660 tail_args: Vec<String>,
2661 stamp: &BuildStamp,
2662 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2663 artifact_keep_mode: ArtifactKeepMode,
2664) -> Vec<PathBuf> {
2665 let target_root_dir = stamp.path().parent().unwrap();
2667 let target_build_dir = target_root_dir.join("build");
2669 let host_root_dir = target_root_dir
2671 .parent()
2672 .unwrap() .parent()
2674 .unwrap() .join(target_root_dir.file_name().unwrap());
2676
2677 let mut deps = Vec::new();
2681 let mut toplevel = Vec::new();
2682 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2683 let (filenames_vec, crate_types) = match msg {
2684 CargoMessage::CompilerArtifact {
2685 filenames,
2686 target: CargoTarget { crate_types },
2687 ..
2688 } => {
2689 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2690 f.sort(); (f, crate_types)
2692 }
2693 _ => return,
2694 };
2695 for filename in filenames_vec {
2696 let keep = if filename.ends_with(".lib")
2698 || filename.ends_with(".a")
2699 || is_debug_info(&filename)
2700 || is_dylib(Path::new(&*filename))
2701 {
2702 true
2704 } else {
2705 match &artifact_keep_mode {
2706 ArtifactKeepMode::OnlyRlib => filename.ends_with(".rlib"),
2707 ArtifactKeepMode::OnlyRmeta => filename.ends_with(".rmeta"),
2708 ArtifactKeepMode::BothRlibAndRmeta => {
2709 filename.ends_with(".rmeta") || filename.ends_with(".rlib")
2710 }
2711 ArtifactKeepMode::Custom(func) => func(&filename),
2712 }
2713 };
2714
2715 if !keep {
2716 continue;
2717 }
2718
2719 let filename = Path::new(&*filename);
2720
2721 if filename.starts_with(&host_root_dir) {
2724 if crate_types.iter().any(|t| t == "proc-macro") {
2726 if filename.file_name().unwrap().to_str().unwrap().contains("-") {
2731 deps.push((filename.to_path_buf(), DependencyType::Host));
2732 }
2733 }
2734 continue;
2735 }
2736
2737 if filename.starts_with(&target_build_dir) {
2740 deps.push((filename.to_path_buf(), DependencyType::Target));
2741 continue;
2742 }
2743
2744 let expected_len = t!(filename.metadata()).len();
2755 let filename = filename.file_name().unwrap().to_str().unwrap();
2756 let mut parts = filename.splitn(2, '.');
2757 let file_stem = parts.next().unwrap().to_owned();
2758 let extension = parts.next().unwrap().to_owned();
2759
2760 toplevel.push((file_stem, extension, expected_len));
2761 }
2762 });
2763
2764 if !ok {
2765 crate::exit!(1);
2766 }
2767
2768 if builder.config.dry_run() {
2769 return Vec::new();
2770 }
2771
2772 let read_dir = |path: &Path| path.read_dir().ok().into_iter().flatten().filter_map(Result::ok);
2779 let contents = target_build_dir
2780 .read_dir()
2781 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_build_dir.display(), e))
2782 .map(|e| e.unwrap())
2783 .flat_map(|e| read_dir(&e.path()))
2784 .flat_map(|e| read_dir(&e.path()))
2785 .flat_map(|e| read_dir(&e.path()))
2786 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2787 .collect::<Vec<_>>();
2788 for (prefix, extension, expected_len) in toplevel {
2789 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2790 meta.len() == expected_len
2791 && filename
2792 .strip_prefix(&prefix[..])
2793 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2794 .unwrap_or(false)
2795 });
2796 let max = candidates.max_by_key(|&(_, _, metadata)| {
2797 metadata.modified().expect("mtime should be available on all relevant OSes")
2798 });
2799 let path_to_add = match max {
2800 Some(triple) => triple.0.to_str().unwrap(),
2801 None => panic!("no output generated for {prefix:?} {extension:?}"),
2802 };
2803 if is_dylib(Path::new(path_to_add)) {
2804 let candidate = format!("{path_to_add}.lib");
2805 let candidate = PathBuf::from(candidate);
2806 if candidate.exists() {
2807 deps.push((candidate, DependencyType::Target));
2808 }
2809 }
2810 deps.push((path_to_add.into(), DependencyType::Target));
2811 }
2812
2813 deps.extend(additional_target_deps);
2814 deps.sort();
2815 let mut new_contents = Vec::new();
2816 for (dep, dependency_type) in deps.iter() {
2817 new_contents.extend(match *dependency_type {
2818 DependencyType::Host => b"h",
2819 DependencyType::Target => b"t",
2820 DependencyType::TargetSelfContained => b"s",
2821 });
2822 new_contents.extend(dep.to_str().unwrap().as_bytes());
2823 new_contents.extend(b"\0");
2824 }
2825 t!(fs::write(stamp.path(), &new_contents));
2826 deps.into_iter().map(|(d, _)| d).collect()
2827}
2828
2829pub fn stream_cargo(
2830 builder: &Builder<'_>,
2831 cargo: Cargo,
2832 tail_args: Vec<String>,
2833 cb: &mut dyn FnMut(CargoMessage<'_>),
2834) -> bool {
2835 let mut cmd = cargo.into_cmd();
2836
2837 let mut message_format = if builder.config.json_output {
2840 String::from("json")
2841 } else {
2842 String::from("json-render-diagnostics")
2843 };
2844 if let Some(s) = &builder.config.rustc_error_format {
2845 message_format.push_str(",json-diagnostic-");
2846 message_format.push_str(s);
2847 }
2848 cmd.arg("--message-format").arg(message_format);
2849
2850 for arg in tail_args {
2851 cmd.arg(arg);
2852 }
2853
2854 builder.do_if_verbose(|| println!("running: {cmd:?}"));
2855
2856 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2857
2858 let Some(mut streaming_command) = streaming_command else {
2859 return true;
2860 };
2861
2862 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2866 for line in stdout.lines() {
2867 let line = t!(line);
2868 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2869 Ok(msg) => {
2870 if builder.config.json_output {
2871 println!("{line}");
2873 }
2874 cb(msg)
2875 }
2876 Err(_) => println!("{line}"),
2878 }
2879 }
2880
2881 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2883 if builder.is_verbose() && !status.success() {
2884 eprintln!(
2885 "command did not execute successfully: {cmd:?}\n\
2886 expected success, got: {status}"
2887 );
2888 }
2889
2890 status.success()
2891}
2892
2893#[derive(Deserialize)]
2894pub struct CargoTarget<'a> {
2895 crate_types: Vec<Cow<'a, str>>,
2896}
2897
2898#[derive(Deserialize)]
2899#[serde(tag = "reason", rename_all = "kebab-case")]
2900pub enum CargoMessage<'a> {
2901 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2902 BuildScriptExecuted,
2903 BuildFinished,
2904}
2905
2906pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2907 if target != "x86_64-unknown-linux-gnu"
2911 || !builder.config.is_host_target(target)
2912 || !path.exists()
2913 {
2914 return;
2915 }
2916
2917 let previous_mtime = t!(t!(path.metadata()).modified());
2918 let stamp = BuildStamp::new(path.parent().unwrap())
2919 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2920 .with_prefix("strip")
2921 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2922
2923 if !stamp.is_up_to_date() {
2926 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2927 }
2928 t!(stamp.write());
2929
2930 let file = t!(fs::File::open(path));
2931
2932 t!(file.set_modified(previous_mtime));
2945}
2946
2947pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2949 build_compiler.stage != 0
2950}