1use std::borrow::Cow;
10use std::collections::HashSet;
11use std::ffi::OsStr;
12use std::io::BufReader;
13use std::io::prelude::*;
14use std::path::{Path, PathBuf};
15use std::{env, fs, str};
16
17use serde_derive::Deserialize;
18#[cfg(feature = "tracing")]
19use tracing::{instrument, span};
20
21use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags};
22use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
23use crate::core::build_steps::{dist, llvm};
24use crate::core::builder;
25use crate::core::builder::{
26 Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
27};
28use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
29use crate::utils::build_stamp;
30use crate::utils::build_stamp::BuildStamp;
31use crate::utils::exec::command;
32use crate::utils::helpers::{
33 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
34};
35use crate::{
36 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
37 debug, trace,
38};
39
40#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct Std {
43 pub target: TargetSelection,
44 pub compiler: Compiler,
45 crates: Vec<String>,
49 force_recompile: bool,
52 extra_rust_args: &'static [&'static str],
53 is_for_mir_opt_tests: bool,
54}
55
56impl Std {
57 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
58 Self {
59 target,
60 compiler,
61 crates: Default::default(),
62 force_recompile: false,
63 extra_rust_args: &[],
64 is_for_mir_opt_tests: false,
65 }
66 }
67
68 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
69 self.force_recompile = force_recompile;
70 self
71 }
72
73 #[expect(clippy::wrong_self_convention)]
74 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
75 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
76 self
77 }
78
79 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
80 self.extra_rust_args = extra_rust_args;
81 self
82 }
83
84 fn copy_extra_objects(
85 &self,
86 builder: &Builder<'_>,
87 compiler: &Compiler,
88 target: TargetSelection,
89 ) -> Vec<(PathBuf, DependencyType)> {
90 let mut deps = Vec::new();
91 if !self.is_for_mir_opt_tests {
92 deps.extend(copy_third_party_objects(builder, compiler, target));
93 deps.extend(copy_self_contained_objects(builder, compiler, target));
94 }
95 deps
96 }
97}
98
99impl Step for Std {
100 type Output = ();
101 const DEFAULT: bool = true;
102
103 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
104 run.crate_or_deps("sysroot").path("library")
105 }
106
107 #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
108 fn make_run(run: RunConfig<'_>) {
109 let crates = std_crates_for_run_make(&run);
110 let builder = run.builder;
111
112 let force_recompile = builder.rust_info().is_managed_git_subrepository()
116 && builder.download_rustc()
117 && builder.config.has_changes_from_upstream(&["library"]);
118
119 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
120 trace!("download_rustc: {}", builder.download_rustc());
121 trace!(force_recompile);
122
123 run.builder.ensure(Std {
124 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
125 target: run.target,
126 crates,
127 force_recompile,
128 extra_rust_args: &[],
129 is_for_mir_opt_tests: false,
130 });
131 }
132
133 #[cfg_attr(
139 feature = "tracing",
140 instrument(
141 level = "debug",
142 name = "Std::run",
143 skip_all,
144 fields(
145 target = ?self.target,
146 compiler = ?self.compiler,
147 force_recompile = self.force_recompile
148 ),
149 ),
150 )]
151 fn run(self, builder: &Builder<'_>) {
152 let target = self.target;
153
154 if self.compiler.stage == 0 {
156 let compiler = self.compiler;
157 builder.ensure(StdLink::from_std(self, compiler));
158
159 return;
160 }
161
162 let build_compiler = if builder.download_rustc() && self.force_recompile {
163 builder.compiler(self.compiler.stage.saturating_sub(1), builder.config.host_target)
166 } else {
167 self.compiler
168 };
169
170 if builder.download_rustc()
173 && builder.config.is_host_target(target)
174 && !self.force_recompile
175 {
176 let sysroot =
177 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
178 cp_rustc_component_to_ci_sysroot(
179 builder,
180 &sysroot,
181 builder.config.ci_rust_std_contents(),
182 );
183 return;
184 }
185
186 if builder.config.keep_stage.contains(&build_compiler.stage)
187 || builder.config.keep_stage_std.contains(&build_compiler.stage)
188 {
189 trace!(keep_stage = ?builder.config.keep_stage);
190 trace!(keep_stage_std = ?builder.config.keep_stage_std);
191
192 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
193
194 builder.ensure(StartupObjects { compiler: build_compiler, target });
195
196 self.copy_extra_objects(builder, &build_compiler, target);
197
198 builder.ensure(StdLink::from_std(self, build_compiler));
199 return;
200 }
201
202 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
203
204 let compiler_to_use =
205 builder.compiler_for(build_compiler.stage, build_compiler.host, target);
206 trace!(?compiler_to_use);
207
208 if compiler_to_use != build_compiler
209 && build_compiler.stage > 1
214 {
215 trace!(
216 ?compiler_to_use,
217 ?build_compiler,
218 "build_compiler != compiler_to_use, uplifting library"
219 );
220
221 builder.std(compiler_to_use, target);
222 let msg = if compiler_to_use.host == target {
223 format!(
224 "Uplifting library (stage{} -> stage{})",
225 compiler_to_use.stage, build_compiler.stage
226 )
227 } else {
228 format!(
229 "Uplifting library (stage{}:{} -> stage{}:{})",
230 compiler_to_use.stage, compiler_to_use.host, build_compiler.stage, target
231 )
232 };
233 builder.info(&msg);
234
235 self.copy_extra_objects(builder, &build_compiler, target);
238
239 builder.ensure(StdLink::from_std(self, compiler_to_use));
240 return;
241 }
242
243 trace!(
244 ?compiler_to_use,
245 ?build_compiler,
246 "compiler == compiler_to_use, handling not-cross-compile scenario"
247 );
248
249 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
250
251 let mut cargo = if self.is_for_mir_opt_tests {
255 trace!("building special sysroot for mir-opt tests");
256 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
257 builder,
258 build_compiler,
259 Mode::Std,
260 SourceType::InTree,
261 target,
262 Kind::Check,
263 );
264 cargo.rustflag("-Zalways-encode-mir");
265 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
266 cargo
267 } else {
268 trace!("building regular sysroot");
269 let mut cargo = builder::Cargo::new(
270 builder,
271 build_compiler,
272 Mode::Std,
273 SourceType::InTree,
274 target,
275 Kind::Build,
276 );
277 std_cargo(builder, target, &mut cargo);
278 for krate in &*self.crates {
279 cargo.arg("-p").arg(krate);
280 }
281 cargo
282 };
283
284 if target.is_synthetic() {
286 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
287 }
288 for rustflag in self.extra_rust_args.iter() {
289 cargo.rustflag(rustflag);
290 }
291
292 let _guard = builder.msg(
293 Kind::Build,
294 format_args!("library artifacts{}", crate_description(&self.crates)),
295 Mode::Std,
296 build_compiler,
297 target,
298 );
299 run_cargo(
300 builder,
301 cargo,
302 vec![],
303 &build_stamp::libstd_stamp(builder, build_compiler, target),
304 target_deps,
305 self.is_for_mir_opt_tests, false,
307 );
308
309 builder.ensure(StdLink::from_std(
310 self,
311 builder.compiler(build_compiler.stage, builder.config.host_target),
312 ));
313 }
314
315 fn metadata(&self) -> Option<StepMetadata> {
316 Some(StepMetadata::build("std", self.target).built_by(self.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") || target.contains("fuchsia") || target.contains("aix"))
363 {
364 let libunwind_path =
365 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
366 target_deps.push((libunwind_path, DependencyType::Target));
367 }
368
369 target_deps
370}
371
372fn copy_self_contained_objects(
374 builder: &Builder<'_>,
375 compiler: &Compiler,
376 target: TargetSelection,
377) -> Vec<(PathBuf, DependencyType)> {
378 let libdir_self_contained =
379 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
380 t!(fs::create_dir_all(&libdir_self_contained));
381 let mut target_deps = vec![];
382
383 if target.needs_crt_begin_end() {
391 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
392 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
393 });
394 if !target.starts_with("wasm32") {
395 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
396 copy_and_stamp(
397 builder,
398 &libdir_self_contained,
399 &srcdir,
400 obj,
401 &mut target_deps,
402 DependencyType::TargetSelfContained,
403 );
404 }
405 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
406 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
407 let src = crt_path.join(obj);
408 let target = libdir_self_contained.join(obj);
409 builder.copy_link(&src, &target, FileType::NativeLibrary);
410 target_deps.push((target, DependencyType::TargetSelfContained));
411 }
412 } else {
413 for &obj in &["libc.a", "crt1-command.o"] {
416 copy_and_stamp(
417 builder,
418 &libdir_self_contained,
419 &srcdir,
420 obj,
421 &mut target_deps,
422 DependencyType::TargetSelfContained,
423 );
424 }
425 }
426 if !target.starts_with("s390x") {
427 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
428 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
429 }
430 } else if target.contains("-wasi") {
431 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
432 panic!(
433 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
434 or `$WASI_SDK_PATH` set",
435 target.triple
436 )
437 });
438 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
439 copy_and_stamp(
440 builder,
441 &libdir_self_contained,
442 &srcdir,
443 obj,
444 &mut target_deps,
445 DependencyType::TargetSelfContained,
446 );
447 }
448 } else if target.is_windows_gnu() {
449 for obj in ["crt2.o", "dllcrt2.o"].iter() {
450 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
451 let dst = libdir_self_contained.join(obj);
452 builder.copy_link(&src, &dst, FileType::NativeLibrary);
453 target_deps.push((dst, DependencyType::TargetSelfContained));
454 }
455 }
456
457 target_deps
458}
459
460pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
463 let mut crates = run.make_run_crates(builder::Alias::Library);
464
465 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
474 if target_is_no_std {
475 crates.retain(|c| c == "core" || c == "alloc");
476 }
477 crates
478}
479
480fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
486 if builder.config.llvm_from_ci {
488 builder.config.maybe_download_ci_llvm();
490 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
491 if ci_llvm_compiler_rt.exists() {
492 return ci_llvm_compiler_rt;
493 }
494 }
495
496 builder.require_submodule("src/llvm-project", {
498 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
499 });
500 builder.src.join("src/llvm-project/compiler-rt")
501}
502
503pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
506 if target.contains("apple") && !builder.config.dry_run() {
524 let mut cmd = command(builder.rustc(cargo.compiler()));
528 cmd.arg("--target").arg(target.rustc_target_arg());
529 cmd.arg("--print=deployment-target");
530 let output = cmd.run_capture_stdout(builder).stdout();
531
532 let (env_var, value) = output.split_once('=').unwrap();
533 cargo.env(env_var.trim(), value.trim());
536
537 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
547 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
548 }
549 }
550
551 if let Some(path) = builder.config.profiler_path(target) {
553 cargo.env("LLVM_PROFILER_RT_LIB", path);
554 } else if builder.config.profiler_enabled(target) {
555 let compiler_rt = compiler_rt_for_profiler(builder);
556 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
560 }
561
562 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
576 builder.require_submodule(
584 "src/llvm-project",
585 Some(
586 "The `build.optimized-compiler-builtins` config option \
587 requires `compiler-rt` sources from LLVM.",
588 ),
589 );
590 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
591 assert!(compiler_builtins_root.exists());
592 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
595 " compiler-builtins-c"
596 } else {
597 ""
598 };
599
600 if !builder.unstable_features() {
603 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
604 }
605
606 let mut features = String::new();
607
608 if builder.no_std(target) == Some(true) {
609 features += " compiler-builtins-mem";
610 if !target.starts_with("bpf") {
611 features.push_str(compiler_builtins_c_feature);
612 }
613
614 cargo
616 .args(["-p", "alloc"])
617 .arg("--manifest-path")
618 .arg(builder.src.join("library/alloc/Cargo.toml"))
619 .arg("--features")
620 .arg(features);
621 } else {
622 features += &builder.std_features(target);
623 features.push_str(compiler_builtins_c_feature);
624
625 cargo
626 .arg("--features")
627 .arg(features)
628 .arg("--manifest-path")
629 .arg(builder.src.join("library/sysroot/Cargo.toml"));
630
631 if target.contains("musl")
634 && let Some(p) = builder.musl_libdir(target)
635 {
636 let root = format!("native={}", p.to_str().unwrap());
637 cargo.rustflag("-L").rustflag(&root);
638 }
639
640 if target.contains("-wasi")
641 && let Some(dir) = builder.wasi_libdir(target)
642 {
643 let root = format!("native={}", dir.to_str().unwrap());
644 cargo.rustflag("-L").rustflag(&root);
645 }
646 }
647
648 cargo.rustflag("-Cembed-bitcode=yes");
654
655 if builder.config.rust_lto == RustcLto::Off {
656 cargo.rustflag("-Clto=off");
657 }
658
659 if target.contains("riscv") {
666 cargo.rustflag("-Cforce-unwind-tables=yes");
667 }
668
669 cargo.rustflag("-Zunstable-options");
672 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
673
674 let html_root =
675 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
676 cargo.rustflag(&html_root);
677 cargo.rustdocflag(&html_root);
678
679 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
680}
681
682#[derive(Debug, Clone, PartialEq, Eq, Hash)]
683pub struct StdLink {
684 pub compiler: Compiler,
685 pub target_compiler: Compiler,
686 pub target: TargetSelection,
687 crates: Vec<String>,
689 force_recompile: bool,
691}
692
693impl StdLink {
694 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
695 Self {
696 compiler: host_compiler,
697 target_compiler: std.compiler,
698 target: std.target,
699 crates: std.crates,
700 force_recompile: std.force_recompile,
701 }
702 }
703}
704
705impl Step for StdLink {
706 type Output = ();
707
708 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
709 run.never()
710 }
711
712 #[cfg_attr(
721 feature = "tracing",
722 instrument(
723 level = "trace",
724 name = "StdLink::run",
725 skip_all,
726 fields(
727 compiler = ?self.compiler,
728 target_compiler = ?self.target_compiler,
729 target = ?self.target
730 ),
731 ),
732 )]
733 fn run(self, builder: &Builder<'_>) {
734 let compiler = self.compiler;
735 let target_compiler = self.target_compiler;
736 let target = self.target;
737
738 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
740 let lib = builder.sysroot_libdir_relative(self.compiler);
742 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
743 compiler: self.compiler,
744 force_recompile: self.force_recompile,
745 });
746 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
747 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
748 (libdir, hostdir)
749 } else {
750 let libdir = builder.sysroot_target_libdir(target_compiler, target);
751 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
752 (libdir, hostdir)
753 };
754
755 let is_downloaded_beta_stage0 = builder
756 .build
757 .config
758 .initial_rustc
759 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
760
761 if compiler.stage == 0 && is_downloaded_beta_stage0 {
765 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
767
768 let host = compiler.host;
769 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
770 let sysroot_bin_dir = sysroot.join("bin");
771 t!(fs::create_dir_all(&sysroot_bin_dir));
772 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
773
774 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
775 t!(fs::create_dir_all(sysroot.join("lib")));
776 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
777
778 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
780 t!(fs::create_dir_all(&sysroot_codegen_backends));
781 let stage0_codegen_backends = builder
782 .out
783 .join(host)
784 .join("stage0/lib/rustlib")
785 .join(host)
786 .join("codegen-backends");
787 if stage0_codegen_backends.exists() {
788 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
789 }
790 } else if compiler.stage == 0 {
791 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
792
793 if builder.local_rebuild {
794 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
798 }
799
800 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
801 } else {
802 if builder.download_rustc() {
803 let _ = fs::remove_dir_all(&libdir);
805 let _ = fs::remove_dir_all(&hostdir);
806 }
807
808 add_to_sysroot(
809 builder,
810 &libdir,
811 &hostdir,
812 &build_stamp::libstd_stamp(builder, compiler, target),
813 );
814 }
815 }
816}
817
818fn copy_sanitizers(
820 builder: &Builder<'_>,
821 compiler: &Compiler,
822 target: TargetSelection,
823) -> Vec<PathBuf> {
824 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
825
826 if builder.config.dry_run() {
827 return Vec::new();
828 }
829
830 let mut target_deps = Vec::new();
831 let libdir = builder.sysroot_target_libdir(*compiler, target);
832
833 for runtime in &runtimes {
834 let dst = libdir.join(&runtime.name);
835 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
836
837 if target == "x86_64-apple-darwin"
841 || target == "aarch64-apple-darwin"
842 || target == "aarch64-apple-ios"
843 || target == "aarch64-apple-ios-sim"
844 || target == "x86_64-apple-ios"
845 {
846 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
848 apple_darwin_sign_file(builder, &dst);
851 }
852
853 target_deps.push(dst);
854 }
855
856 target_deps
857}
858
859fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
860 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
861}
862
863fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
864 command("codesign")
865 .arg("-f") .arg("-s")
867 .arg("-")
868 .arg(file_path)
869 .run(builder);
870}
871
872#[derive(Debug, Clone, PartialEq, Eq, Hash)]
873pub struct StartupObjects {
874 pub compiler: Compiler,
875 pub target: TargetSelection,
876}
877
878impl Step for StartupObjects {
879 type Output = Vec<(PathBuf, DependencyType)>;
880
881 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
882 run.path("library/rtstartup")
883 }
884
885 fn make_run(run: RunConfig<'_>) {
886 run.builder.ensure(StartupObjects {
887 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
888 target: run.target,
889 });
890 }
891
892 #[cfg_attr(
899 feature = "tracing",
900 instrument(
901 level = "trace",
902 name = "StartupObjects::run",
903 skip_all,
904 fields(compiler = ?self.compiler, target = ?self.target),
905 ),
906 )]
907 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
908 let for_compiler = self.compiler;
909 let target = self.target;
910 if !target.is_windows_gnu() {
911 return vec![];
912 }
913
914 let mut target_deps = vec![];
915
916 let src_dir = &builder.src.join("library").join("rtstartup");
917 let dst_dir = &builder.native_dir(target).join("rtstartup");
918 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
919 t!(fs::create_dir_all(dst_dir));
920
921 for file in &["rsbegin", "rsend"] {
922 let src_file = &src_dir.join(file.to_string() + ".rs");
923 let dst_file = &dst_dir.join(file.to_string() + ".o");
924 if !up_to_date(src_file, dst_file) {
925 let mut cmd = command(&builder.initial_rustc);
926 cmd.env("RUSTC_BOOTSTRAP", "1");
927 if !builder.local_rebuild {
928 cmd.arg("--cfg").arg("bootstrap");
930 }
931 cmd.arg("--target")
932 .arg(target.rustc_target_arg())
933 .arg("--emit=obj")
934 .arg("-o")
935 .arg(dst_file)
936 .arg(src_file)
937 .run(builder);
938 }
939
940 let obj = sysroot_dir.join((*file).to_string() + ".o");
941 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
942 target_deps.push((obj, DependencyType::Target));
943 }
944
945 target_deps
946 }
947}
948
949fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
950 let ci_rustc_dir = builder.config.ci_rustc_dir();
951
952 for file in contents {
953 let src = ci_rustc_dir.join(&file);
954 let dst = sysroot.join(file);
955 if src.is_dir() {
956 t!(fs::create_dir_all(dst));
957 } else {
958 builder.copy_link(&src, &dst, FileType::Regular);
959 }
960 }
961}
962
963#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
970pub struct Rustc {
971 pub target: TargetSelection,
973 pub build_compiler: Compiler,
975 crates: Vec<String>,
981}
982
983impl Rustc {
984 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
985 Self { target, build_compiler, crates: Default::default() }
986 }
987}
988
989impl Step for Rustc {
990 type Output = u32;
998 const ONLY_HOSTS: bool = true;
999 const DEFAULT: bool = false;
1000
1001 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1002 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1003 for (i, krate) in crates.iter().enumerate() {
1004 if krate.name == "rustc-main" {
1007 crates.swap_remove(i);
1008 break;
1009 }
1010 }
1011 run.crates(crates)
1012 }
1013
1014 fn make_run(run: RunConfig<'_>) {
1015 if run.builder.paths == vec![PathBuf::from("compiler")] {
1018 return;
1019 }
1020
1021 let crates = run.cargo_crates_in_set();
1022 run.builder.ensure(Rustc {
1023 build_compiler: run
1024 .builder
1025 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1026 target: run.target,
1027 crates,
1028 });
1029 }
1030
1031 #[cfg_attr(
1037 feature = "tracing",
1038 instrument(
1039 level = "debug",
1040 name = "Rustc::run",
1041 skip_all,
1042 fields(previous_compiler = ?self.build_compiler, target = ?self.target),
1043 ),
1044 )]
1045 fn run(self, builder: &Builder<'_>) -> u32 {
1046 let build_compiler = self.build_compiler;
1047 let target = self.target;
1048
1049 if builder.download_rustc() && build_compiler.stage != 0 {
1052 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1053
1054 let sysroot =
1055 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1056 cp_rustc_component_to_ci_sysroot(
1057 builder,
1058 &sysroot,
1059 builder.config.ci_rustc_dev_contents(),
1060 );
1061 return build_compiler.stage;
1062 }
1063
1064 builder.std(build_compiler, target);
1067
1068 if builder.config.keep_stage.contains(&build_compiler.stage) {
1069 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1070
1071 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1072 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1073 builder.ensure(RustcLink::from_rustc(self, build_compiler));
1074
1075 return build_compiler.stage;
1076 }
1077
1078 let compiler_to_use =
1079 builder.compiler_for(build_compiler.stage, build_compiler.host, target);
1080 if compiler_to_use != build_compiler {
1081 builder.ensure(Rustc::new(compiler_to_use, target));
1082 let msg = if compiler_to_use.host == target {
1083 format!(
1084 "Uplifting rustc (stage{} -> stage{})",
1085 compiler_to_use.stage,
1086 build_compiler.stage + 1
1087 )
1088 } else {
1089 format!(
1090 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1091 compiler_to_use.stage,
1092 compiler_to_use.host,
1093 build_compiler.stage + 1,
1094 target
1095 )
1096 };
1097 builder.info(&msg);
1098 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1099 return compiler_to_use.stage;
1100 }
1101
1102 builder.std(
1108 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1109 builder.config.host_target,
1110 );
1111
1112 let mut cargo = builder::Cargo::new(
1113 builder,
1114 build_compiler,
1115 Mode::Rustc,
1116 SourceType::InTree,
1117 target,
1118 Kind::Build,
1119 );
1120
1121 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1122
1123 for krate in &*self.crates {
1127 cargo.arg("-p").arg(krate);
1128 }
1129
1130 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1131 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1133 }
1134
1135 let _guard = builder.msg(
1136 Kind::Build,
1137 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1138 Mode::Rustc,
1139 build_compiler,
1140 target,
1141 );
1142 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1143 run_cargo(
1144 builder,
1145 cargo,
1146 vec![],
1147 &stamp,
1148 vec![],
1149 false,
1150 true, );
1152
1153 let target_root_dir = stamp.path().parent().unwrap();
1154 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1160 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1161 {
1162 let rustc_driver = target_root_dir.join("librustc_driver.so");
1163 strip_debug(builder, target, &rustc_driver);
1164 }
1165
1166 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1167 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1170 }
1171
1172 builder.ensure(RustcLink::from_rustc(
1173 self,
1174 builder.compiler(build_compiler.stage, builder.config.host_target),
1175 ));
1176
1177 build_compiler.stage
1178 }
1179
1180 fn metadata(&self) -> Option<StepMetadata> {
1181 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1182 }
1183}
1184
1185pub fn rustc_cargo(
1186 builder: &Builder<'_>,
1187 cargo: &mut Cargo,
1188 target: TargetSelection,
1189 build_compiler: &Compiler,
1190 crates: &[String],
1191) {
1192 cargo
1193 .arg("--features")
1194 .arg(builder.rustc_features(builder.kind, target, crates))
1195 .arg("--manifest-path")
1196 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1197
1198 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1199
1200 cargo.rustflag("-Zon-broken-pipe=kill");
1214
1215 if builder.config.llvm_enzyme {
1218 let arch = builder.build.host_target;
1219 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1220 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1221
1222 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1223 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1224 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1225 }
1226 }
1227
1228 if builder.build.config.lld_mode.is_used() {
1233 cargo.rustflag("-Zdefault-visibility=protected");
1234 }
1235
1236 if is_lto_stage(build_compiler) {
1237 match builder.config.rust_lto {
1238 RustcLto::Thin | RustcLto::Fat => {
1239 cargo.rustflag("-Zdylib-lto");
1242 let lto_type = match builder.config.rust_lto {
1246 RustcLto::Thin => "thin",
1247 RustcLto::Fat => "fat",
1248 _ => unreachable!(),
1249 };
1250 cargo.rustflag(&format!("-Clto={lto_type}"));
1251 cargo.rustflag("-Cembed-bitcode=yes");
1252 }
1253 RustcLto::ThinLocal => { }
1254 RustcLto::Off => {
1255 cargo.rustflag("-Clto=off");
1256 }
1257 }
1258 } else if builder.config.rust_lto == RustcLto::Off {
1259 cargo.rustflag("-Clto=off");
1260 }
1261
1262 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1270 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1271 }
1272
1273 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1274 panic!("Cannot use and generate PGO profiles at the same time");
1275 }
1276 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1277 if build_compiler.stage == 1 {
1278 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1279 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1282 true
1283 } else {
1284 false
1285 }
1286 } else if let Some(path) = &builder.config.rust_profile_use {
1287 if build_compiler.stage == 1 {
1288 cargo.rustflag(&format!("-Cprofile-use={path}"));
1289 if builder.is_verbose() {
1290 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1291 }
1292 true
1293 } else {
1294 false
1295 }
1296 } else {
1297 false
1298 };
1299 if is_collecting {
1300 cargo.rustflag(&format!(
1302 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1303 builder.config.src.components().count()
1304 ));
1305 }
1306
1307 if let Some(ref ccache) = builder.config.ccache
1312 && build_compiler.stage == 0
1313 && !builder.config.incremental
1314 {
1315 cargo.env("RUSTC_WRAPPER", ccache);
1316 }
1317
1318 rustc_cargo_env(builder, cargo, target);
1319}
1320
1321pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1322 cargo
1325 .env("CFG_RELEASE", builder.rust_release())
1326 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1327 .env("CFG_VERSION", builder.rust_version());
1328
1329 if builder.config.omit_git_hash {
1333 cargo.env("CFG_OMIT_GIT_HASH", "1");
1334 }
1335
1336 if let Some(backend) = builder.config.default_codegen_backend(target) {
1337 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
1338 }
1339
1340 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1341 let target_config = builder.config.target_config.get(&target);
1342
1343 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1344
1345 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1346 cargo.env("CFG_VER_DATE", ver_date);
1347 }
1348 if let Some(ref ver_hash) = builder.rust_info().sha() {
1349 cargo.env("CFG_VER_HASH", ver_hash);
1350 }
1351 if !builder.unstable_features() {
1352 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1353 }
1354
1355 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1358 cargo.env("CFG_DEFAULT_LINKER", s);
1359 } else if let Some(ref s) = builder.config.rustc_default_linker {
1360 cargo.env("CFG_DEFAULT_LINKER", s);
1361 }
1362
1363 if builder.config.lld_enabled {
1365 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1366 }
1367
1368 if builder.config.rust_verify_llvm_ir {
1369 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1370 }
1371
1372 if builder.config.llvm_enzyme {
1373 cargo.rustflag("--cfg=llvm_enzyme");
1374 }
1375
1376 if builder.config.llvm_enabled(target) {
1388 let building_llvm_is_expensive =
1389 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1390 .should_build();
1391
1392 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1393 if !skip_llvm {
1394 rustc_llvm_env(builder, cargo, target)
1395 }
1396 }
1397
1398 if builder.config.jemalloc(target)
1401 && target.starts_with("aarch64")
1402 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1403 {
1404 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1405 }
1406}
1407
1408fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1414 if builder.config.is_rust_llvm(target) {
1415 cargo.env("LLVM_RUSTLLVM", "1");
1416 }
1417 if builder.config.llvm_enzyme {
1418 cargo.env("LLVM_ENZYME", "1");
1419 }
1420 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1421 cargo.env("LLVM_CONFIG", &llvm_config);
1422
1423 let mut llvm_linker_flags = String::new();
1433 if builder.config.llvm_profile_generate
1434 && target.is_msvc()
1435 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1436 {
1437 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1439 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1440 }
1441
1442 if let Some(ref s) = builder.config.llvm_ldflags {
1444 if !llvm_linker_flags.is_empty() {
1445 llvm_linker_flags.push(' ');
1446 }
1447 llvm_linker_flags.push_str(s);
1448 }
1449
1450 if !llvm_linker_flags.is_empty() {
1452 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1453 }
1454
1455 if builder.config.llvm_static_stdcpp
1458 && !target.contains("freebsd")
1459 && !target.is_msvc()
1460 && !target.contains("apple")
1461 && !target.contains("solaris")
1462 {
1463 let libstdcxx_name =
1464 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1465 let file = compiler_file(
1466 builder,
1467 &builder.cxx(target).unwrap(),
1468 target,
1469 CLang::Cxx,
1470 libstdcxx_name,
1471 );
1472 cargo.env("LLVM_STATIC_STDCPP", file);
1473 }
1474 if builder.llvm_link_shared() {
1475 cargo.env("LLVM_LINK_SHARED", "1");
1476 }
1477 if builder.config.llvm_use_libcxx {
1478 cargo.env("LLVM_USE_LIBCXX", "1");
1479 }
1480 if builder.config.llvm_assertions {
1481 cargo.env("LLVM_ASSERTIONS", "1");
1482 }
1483}
1484
1485#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1491struct RustcLink {
1492 pub compiler: Compiler,
1494 pub previous_stage_compiler: Compiler,
1496 pub target: TargetSelection,
1497 crates: Vec<String>,
1499}
1500
1501impl RustcLink {
1502 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1503 Self {
1504 compiler: host_compiler,
1505 previous_stage_compiler: rustc.build_compiler,
1506 target: rustc.target,
1507 crates: rustc.crates,
1508 }
1509 }
1510}
1511
1512impl Step for RustcLink {
1513 type Output = ();
1514
1515 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1516 run.never()
1517 }
1518
1519 #[cfg_attr(
1521 feature = "tracing",
1522 instrument(
1523 level = "trace",
1524 name = "RustcLink::run",
1525 skip_all,
1526 fields(
1527 compiler = ?self.compiler,
1528 previous_stage_compiler = ?self.previous_stage_compiler,
1529 target = ?self.target,
1530 ),
1531 ),
1532 )]
1533 fn run(self, builder: &Builder<'_>) {
1534 let compiler = self.compiler;
1535 let previous_stage_compiler = self.previous_stage_compiler;
1536 let target = self.target;
1537 add_to_sysroot(
1538 builder,
1539 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1540 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1541 &build_stamp::librustc_stamp(builder, compiler, target),
1542 );
1543 }
1544}
1545
1546#[derive(Clone)]
1549pub struct GccCodegenBackendOutput {
1550 stamp: BuildStamp,
1551 gcc: GccOutput,
1552}
1553
1554#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1555pub struct GccCodegenBackend {
1556 compilers: RustcPrivateCompilers,
1557}
1558
1559impl Step for GccCodegenBackend {
1560 type Output = GccCodegenBackendOutput;
1561
1562 const ONLY_HOSTS: bool = true;
1563
1564 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1565 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1566 }
1567
1568 fn make_run(run: RunConfig<'_>) {
1569 run.builder.ensure(GccCodegenBackend {
1570 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1571 });
1572 }
1573
1574 #[cfg_attr(
1575 feature = "tracing",
1576 instrument(
1577 level = "debug",
1578 name = "GccCodegenBackend::run",
1579 skip_all,
1580 fields(
1581 compilers = ?self.compilers,
1582 ),
1583 ),
1584 )]
1585 fn run(self, builder: &Builder<'_>) -> Self::Output {
1586 let target = self.compilers.target();
1587 let build_compiler = self.compilers.build_compiler();
1588
1589 let stamp = build_stamp::codegen_backend_stamp(
1590 builder,
1591 build_compiler,
1592 target,
1593 &CodegenBackendKind::Gcc,
1594 );
1595
1596 let gcc = builder.ensure(Gcc { target });
1597
1598 if builder.config.keep_stage.contains(&build_compiler.stage) {
1599 trace!("`keep-stage` requested");
1600 builder.info(
1601 "WARNING: Using a potentially old codegen backend. \
1602 This may not behave well.",
1603 );
1604 return GccCodegenBackendOutput { stamp, gcc };
1607 }
1608
1609 let mut cargo = builder::Cargo::new(
1610 builder,
1611 build_compiler,
1612 Mode::Codegen,
1613 SourceType::InTree,
1614 target,
1615 Kind::Build,
1616 );
1617 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1618 rustc_cargo_env(builder, &mut cargo, target);
1619
1620 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1621
1622 let _guard =
1623 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1624 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1625
1626 GccCodegenBackendOutput {
1627 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1628 gcc,
1629 }
1630 }
1631
1632 fn metadata(&self) -> Option<StepMetadata> {
1633 Some(
1634 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1635 .built_by(self.compilers.build_compiler()),
1636 )
1637 }
1638}
1639
1640#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1641pub struct CraneliftCodegenBackend {
1642 pub compilers: RustcPrivateCompilers,
1643}
1644
1645impl Step for CraneliftCodegenBackend {
1646 type Output = BuildStamp;
1647 const ONLY_HOSTS: bool = true;
1648
1649 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1650 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1651 }
1652
1653 fn make_run(run: RunConfig<'_>) {
1654 run.builder.ensure(CraneliftCodegenBackend {
1655 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1656 });
1657 }
1658
1659 #[cfg_attr(
1660 feature = "tracing",
1661 instrument(
1662 level = "debug",
1663 name = "CraneliftCodegenBackend::run",
1664 skip_all,
1665 fields(
1666 compilers = ?self.compilers,
1667 ),
1668 ),
1669 )]
1670 fn run(self, builder: &Builder<'_>) -> Self::Output {
1671 let target = self.compilers.target();
1672 let build_compiler = self.compilers.build_compiler();
1673
1674 let stamp = build_stamp::codegen_backend_stamp(
1675 builder,
1676 build_compiler,
1677 target,
1678 &CodegenBackendKind::Cranelift,
1679 );
1680
1681 if builder.config.keep_stage.contains(&build_compiler.stage) {
1682 trace!("`keep-stage` requested");
1683 builder.info(
1684 "WARNING: Using a potentially old codegen backend. \
1685 This may not behave well.",
1686 );
1687 return stamp;
1690 }
1691
1692 let mut cargo = builder::Cargo::new(
1693 builder,
1694 build_compiler,
1695 Mode::Codegen,
1696 SourceType::InTree,
1697 target,
1698 Kind::Build,
1699 );
1700 cargo
1701 .arg("--manifest-path")
1702 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1703 rustc_cargo_env(builder, &mut cargo, target);
1704
1705 let _guard = builder.msg(
1706 Kind::Build,
1707 "codegen backend cranelift",
1708 Mode::Codegen,
1709 build_compiler,
1710 target,
1711 );
1712 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1713 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1714 }
1715
1716 fn metadata(&self) -> Option<StepMetadata> {
1717 Some(
1718 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1719 .built_by(self.compilers.build_compiler()),
1720 )
1721 }
1722}
1723
1724fn write_codegen_backend_stamp(
1726 mut stamp: BuildStamp,
1727 files: Vec<PathBuf>,
1728 dry_run: bool,
1729) -> BuildStamp {
1730 if dry_run {
1731 return stamp;
1732 }
1733
1734 let mut files = files.into_iter().filter(|f| {
1735 let filename = f.file_name().unwrap().to_str().unwrap();
1736 is_dylib(f) && filename.contains("rustc_codegen_")
1737 });
1738 let codegen_backend = match files.next() {
1739 Some(f) => f,
1740 None => panic!("no dylibs built for codegen backend?"),
1741 };
1742 if let Some(f) = files.next() {
1743 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1744 }
1745
1746 let codegen_backend = codegen_backend.to_str().unwrap();
1747 stamp = stamp.add_stamp(codegen_backend);
1748 t!(stamp.write());
1749 stamp
1750}
1751
1752fn copy_codegen_backends_to_sysroot(
1759 builder: &Builder<'_>,
1760 stamp: BuildStamp,
1761 target_compiler: Compiler,
1762) {
1763 let dst = builder.sysroot_codegen_backends(target_compiler);
1772 t!(fs::create_dir_all(&dst), dst);
1773
1774 if builder.config.dry_run() {
1775 return;
1776 }
1777
1778 if stamp.path().exists() {
1779 let file = get_codegen_backend_file(&stamp);
1780 builder.copy_link(
1781 &file,
1782 &dst.join(normalize_codegen_backend_name(builder, &file)),
1783 FileType::NativeLibrary,
1784 );
1785 }
1786}
1787
1788pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1790 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1791}
1792
1793pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1795 let filename = path.file_name().unwrap().to_str().unwrap();
1796 let dash = filename.find('-').unwrap();
1799 let dot = filename.find('.').unwrap();
1800 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1801}
1802
1803pub fn compiler_file(
1804 builder: &Builder<'_>,
1805 compiler: &Path,
1806 target: TargetSelection,
1807 c: CLang,
1808 file: &str,
1809) -> PathBuf {
1810 if builder.config.dry_run() {
1811 return PathBuf::new();
1812 }
1813 let mut cmd = command(compiler);
1814 cmd.args(builder.cc_handled_clags(target, c));
1815 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1816 cmd.arg(format!("-print-file-name={file}"));
1817 let out = cmd.run_capture_stdout(builder).stdout();
1818 PathBuf::from(out.trim())
1819}
1820
1821#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1822pub struct Sysroot {
1823 pub compiler: Compiler,
1824 force_recompile: bool,
1826}
1827
1828impl Sysroot {
1829 pub(crate) fn new(compiler: Compiler) -> Self {
1830 Sysroot { compiler, force_recompile: false }
1831 }
1832}
1833
1834impl Step for Sysroot {
1835 type Output = PathBuf;
1836
1837 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1838 run.never()
1839 }
1840
1841 #[cfg_attr(
1845 feature = "tracing",
1846 instrument(
1847 level = "debug",
1848 name = "Sysroot::run",
1849 skip_all,
1850 fields(compiler = ?self.compiler),
1851 ),
1852 )]
1853 fn run(self, builder: &Builder<'_>) -> PathBuf {
1854 let compiler = self.compiler;
1855 let host_dir = builder.out.join(compiler.host);
1856
1857 let sysroot_dir = |stage| {
1858 if stage == 0 {
1859 host_dir.join("stage0-sysroot")
1860 } else if self.force_recompile && stage == compiler.stage {
1861 host_dir.join(format!("stage{stage}-test-sysroot"))
1862 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1863 host_dir.join("ci-rustc-sysroot")
1864 } else {
1865 host_dir.join(format!("stage{stage}"))
1866 }
1867 };
1868 let sysroot = sysroot_dir(compiler.stage);
1869 trace!(stage = ?compiler.stage, ?sysroot);
1870
1871 builder
1872 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1873 let _ = fs::remove_dir_all(&sysroot);
1874 t!(fs::create_dir_all(&sysroot));
1875
1876 if compiler.stage == 0 {
1883 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1884 }
1885
1886 if builder.download_rustc() && compiler.stage != 0 {
1888 assert_eq!(
1889 builder.config.host_target, compiler.host,
1890 "Cross-compiling is not yet supported with `download-rustc`",
1891 );
1892
1893 for stage in 0..=2 {
1895 if stage != compiler.stage {
1896 let dir = sysroot_dir(stage);
1897 if !dir.ends_with("ci-rustc-sysroot") {
1898 let _ = fs::remove_dir_all(dir);
1899 }
1900 }
1901 }
1902
1903 let mut filtered_files = Vec::new();
1913 let mut add_filtered_files = |suffix, contents| {
1914 for path in contents {
1915 let path = Path::new(&path);
1916 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1917 filtered_files.push(path.file_name().unwrap().to_owned());
1918 }
1919 }
1920 };
1921 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1922 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1923 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1926
1927 let filtered_extensions = [
1928 OsStr::new("rmeta"),
1929 OsStr::new("rlib"),
1930 OsStr::new(std::env::consts::DLL_EXTENSION),
1932 ];
1933 let ci_rustc_dir = builder.config.ci_rustc_dir();
1934 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1935 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1936 return true;
1937 }
1938 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1939 return true;
1940 }
1941 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1942 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1943 false
1944 } else {
1945 true
1946 }
1947 });
1948 }
1949
1950 if compiler.stage != 0 {
1956 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1957 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1958 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1959 if let Err(e) =
1960 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1961 {
1962 eprintln!(
1963 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1964 sysroot_lib_rustlib_src_rust.display(),
1965 builder.src.display(),
1966 e,
1967 );
1968 if builder.config.rust_remap_debuginfo {
1969 eprintln!(
1970 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1971 sysroot_lib_rustlib_src_rust.display(),
1972 );
1973 }
1974 build_helper::exit!(1);
1975 }
1976 }
1977
1978 if !builder.download_rustc() {
1980 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1981 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1982 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1983 if let Err(e) =
1984 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1985 {
1986 eprintln!(
1987 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1988 sysroot_lib_rustlib_rustcsrc_rust.display(),
1989 builder.src.display(),
1990 e,
1991 );
1992 build_helper::exit!(1);
1993 }
1994 }
1995
1996 sysroot
1997 }
1998}
1999
2000#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
2001pub struct Assemble {
2002 pub target_compiler: Compiler,
2007}
2008
2009impl Step for Assemble {
2010 type Output = Compiler;
2011 const ONLY_HOSTS: bool = true;
2012
2013 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2014 run.path("compiler/rustc").path("compiler")
2015 }
2016
2017 fn make_run(run: RunConfig<'_>) {
2018 run.builder.ensure(Assemble {
2019 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2020 });
2021 }
2022
2023 #[cfg_attr(
2029 feature = "tracing",
2030 instrument(
2031 level = "debug",
2032 name = "Assemble::run",
2033 skip_all,
2034 fields(target_compiler = ?self.target_compiler),
2035 ),
2036 )]
2037 fn run(self, builder: &Builder<'_>) -> Compiler {
2038 let target_compiler = self.target_compiler;
2039
2040 if target_compiler.stage == 0 {
2041 trace!("stage 0 build compiler is always available, simply returning");
2042 assert_eq!(
2043 builder.config.host_target, target_compiler.host,
2044 "Cannot obtain compiler for non-native build triple at stage 0"
2045 );
2046 return target_compiler;
2048 }
2049
2050 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2053 let libdir_bin = libdir.parent().unwrap().join("bin");
2054 t!(fs::create_dir_all(&libdir_bin));
2055
2056 if builder.config.llvm_enabled(target_compiler.host) {
2057 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2058
2059 let llvm::LlvmResult { llvm_config, .. } =
2060 builder.ensure(llvm::Llvm { target: target_compiler.host });
2061 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2062 trace!("LLVM tools enabled");
2063
2064 let llvm_bin_dir =
2065 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
2066 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
2067
2068 #[cfg(feature = "tracing")]
2075 let _llvm_tools_span =
2076 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2077 .entered();
2078 for tool in LLVM_TOOLS {
2079 trace!("installing `{tool}`");
2080 let tool_exe = exe(tool, target_compiler.host);
2081 let src_path = llvm_bin_dir.join(&tool_exe);
2082
2083 if !src_path.exists() && builder.config.llvm_from_ci {
2085 eprintln!("{} does not exist; skipping copy", src_path.display());
2086 continue;
2087 }
2088
2089 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2096 }
2097 }
2098 }
2099
2100 let maybe_install_llvm_bitcode_linker = || {
2101 if builder.config.llvm_bitcode_linker_enabled {
2102 trace!("llvm-bitcode-linker enabled, installing");
2103 let llvm_bitcode_linker = builder.ensure(
2104 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2105 builder,
2106 target_compiler,
2107 ),
2108 );
2109
2110 let bindir_self_contained = builder
2112 .sysroot(target_compiler)
2113 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2114 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2115
2116 t!(fs::create_dir_all(&bindir_self_contained));
2117 builder.copy_link(
2118 &llvm_bitcode_linker.tool_path,
2119 &bindir_self_contained.join(tool_exe),
2120 FileType::Executable,
2121 );
2122 }
2123 };
2124
2125 if builder.download_rustc() {
2127 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2128
2129 builder.std(target_compiler, target_compiler.host);
2130 let sysroot =
2131 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2132 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2135 if target_compiler.stage == builder.top_stage {
2137 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2138 }
2139
2140 maybe_install_llvm_bitcode_linker();
2143
2144 return target_compiler;
2145 }
2146
2147 debug!(
2161 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2162 target_compiler.stage - 1,
2163 builder.config.host_target,
2164 );
2165 let mut build_compiler =
2166 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2167
2168 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2170 debug!("`llvm_enzyme` requested");
2171 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2172 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2173 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2174 let lib_ext = std::env::consts::DLL_EXTENSION;
2175 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2176 let src_lib =
2177 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2178 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2179 let target_libdir =
2180 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2181 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2182 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2183 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2184 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2185 }
2186 }
2187
2188 debug!(
2194 ?build_compiler,
2195 "target_compiler.host" = ?target_compiler.host,
2196 "building compiler libraries to link to"
2197 );
2198 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2199 debug!(
2202 "(old) build_compiler.stage" = build_compiler.stage,
2203 "(adjusted) build_compiler.stage" = actual_stage,
2204 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2205 );
2206 build_compiler.stage = actual_stage;
2207
2208 let stage = target_compiler.stage;
2209 let host = target_compiler.host;
2210 let (host_info, dir_name) = if build_compiler.host == host {
2211 ("".into(), "host".into())
2212 } else {
2213 (format!(" ({host})"), host.to_string())
2214 };
2215 let msg = format!(
2220 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2221 );
2222 builder.info(&msg);
2223
2224 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2226 let proc_macros = builder
2227 .read_stamp_file(&stamp)
2228 .into_iter()
2229 .filter_map(|(path, dependency_type)| {
2230 if dependency_type == DependencyType::Host {
2231 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2232 } else {
2233 None
2234 }
2235 })
2236 .collect::<HashSet<_>>();
2237
2238 let sysroot = builder.sysroot(target_compiler);
2239 let rustc_libdir = builder.rustc_libdir(target_compiler);
2240 t!(fs::create_dir_all(&rustc_libdir));
2241 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2242 for f in builder.read_dir(&src_libdir) {
2243 let filename = f.file_name().into_string().unwrap();
2244
2245 let is_proc_macro = proc_macros.contains(&filename);
2246 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2247
2248 let can_be_rustc_dynamic_dep = if builder
2252 .link_std_into_rustc_driver(target_compiler.host)
2253 && !target_compiler.host.is_windows()
2254 {
2255 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2256 !is_std
2257 } else {
2258 true
2259 };
2260
2261 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2262 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2263 }
2264 }
2265
2266 {
2267 #[cfg(feature = "tracing")]
2268 let _codegen_backend_span =
2269 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2270
2271 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2272 if builder.kind == Kind::Check && builder.top_stage == 1 {
2289 continue;
2290 }
2291
2292 let prepare_compilers = || {
2293 RustcPrivateCompilers::from_build_and_target_compiler(
2294 build_compiler,
2295 target_compiler,
2296 )
2297 };
2298
2299 match backend {
2300 CodegenBackendKind::Cranelift => {
2301 let stamp = builder
2302 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2303 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2304 }
2305 CodegenBackendKind::Gcc => {
2306 let output =
2307 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2308 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2309 output.gcc.install_to(builder, &rustc_libdir);
2312 }
2313 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2314 }
2315 }
2316 }
2317
2318 if builder.config.lld_enabled {
2319 let lld_wrapper =
2320 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2321 builder,
2322 target_compiler,
2323 ));
2324 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2325 }
2326
2327 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2328 debug!(
2329 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2330 workaround faulty homebrew `strip`s"
2331 );
2332
2333 let src_exe = exe("llvm-objcopy", target_compiler.host);
2340 let dst_exe = exe("rust-objcopy", target_compiler.host);
2341 builder.copy_link(
2342 &libdir_bin.join(src_exe),
2343 &libdir_bin.join(dst_exe),
2344 FileType::Executable,
2345 );
2346 }
2347
2348 if builder.tool_enabled("wasm-component-ld") {
2351 let wasm_component = builder.ensure(
2352 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2353 builder,
2354 target_compiler,
2355 ),
2356 );
2357 builder.copy_link(
2358 &wasm_component.tool_path,
2359 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2360 FileType::Executable,
2361 );
2362 }
2363
2364 maybe_install_llvm_bitcode_linker();
2365
2366 debug!(
2369 "target_compiler.host" = ?target_compiler.host,
2370 ?sysroot,
2371 "ensuring availability of `libLLVM.so` in compiler directory"
2372 );
2373 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2374 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2375
2376 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2378 let rustc = out_dir.join(exe("rustc-main", host));
2379 let bindir = sysroot.join("bin");
2380 t!(fs::create_dir_all(bindir));
2381 let compiler = builder.rustc(target_compiler);
2382 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2383 builder.copy_link(&rustc, &compiler, FileType::Executable);
2384
2385 target_compiler
2386 }
2387}
2388
2389pub fn add_to_sysroot(
2394 builder: &Builder<'_>,
2395 sysroot_dst: &Path,
2396 sysroot_host_dst: &Path,
2397 stamp: &BuildStamp,
2398) {
2399 let self_contained_dst = &sysroot_dst.join("self-contained");
2400 t!(fs::create_dir_all(sysroot_dst));
2401 t!(fs::create_dir_all(sysroot_host_dst));
2402 t!(fs::create_dir_all(self_contained_dst));
2403 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2404 let dst = match dependency_type {
2405 DependencyType::Host => sysroot_host_dst,
2406 DependencyType::Target => sysroot_dst,
2407 DependencyType::TargetSelfContained => self_contained_dst,
2408 };
2409 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2410 }
2411}
2412
2413pub fn run_cargo(
2414 builder: &Builder<'_>,
2415 cargo: Cargo,
2416 tail_args: Vec<String>,
2417 stamp: &BuildStamp,
2418 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2419 is_check: bool,
2420 rlib_only_metadata: bool,
2421) -> Vec<PathBuf> {
2422 let target_root_dir = stamp.path().parent().unwrap();
2424 let target_deps_dir = target_root_dir.join("deps");
2426 let host_root_dir = target_root_dir
2428 .parent()
2429 .unwrap() .parent()
2431 .unwrap() .join(target_root_dir.file_name().unwrap());
2433
2434 let mut deps = Vec::new();
2438 let mut toplevel = Vec::new();
2439 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2440 let (filenames_vec, crate_types) = match msg {
2441 CargoMessage::CompilerArtifact {
2442 filenames,
2443 target: CargoTarget { crate_types },
2444 ..
2445 } => {
2446 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2447 f.sort(); (f, crate_types)
2449 }
2450 _ => return,
2451 };
2452 for filename in filenames_vec {
2453 let mut keep = false;
2455 if filename.ends_with(".lib")
2456 || filename.ends_with(".a")
2457 || is_debug_info(&filename)
2458 || is_dylib(Path::new(&*filename))
2459 {
2460 keep = true;
2462 }
2463 if is_check && filename.ends_with(".rmeta") {
2464 keep = true;
2466 } else if rlib_only_metadata {
2467 if filename.contains("jemalloc_sys")
2468 || filename.contains("rustc_public_bridge")
2469 || filename.contains("rustc_public")
2470 {
2471 keep |= filename.ends_with(".rlib");
2474 } else {
2475 keep |= filename.ends_with(".rmeta");
2479 }
2480 } else {
2481 keep |= filename.ends_with(".rlib");
2483 }
2484
2485 if !keep {
2486 continue;
2487 }
2488
2489 let filename = Path::new(&*filename);
2490
2491 if filename.starts_with(&host_root_dir) {
2494 if crate_types.iter().any(|t| t == "proc-macro") {
2496 deps.push((filename.to_path_buf(), DependencyType::Host));
2497 }
2498 continue;
2499 }
2500
2501 if filename.starts_with(&target_deps_dir) {
2504 deps.push((filename.to_path_buf(), DependencyType::Target));
2505 continue;
2506 }
2507
2508 let expected_len = t!(filename.metadata()).len();
2519 let filename = filename.file_name().unwrap().to_str().unwrap();
2520 let mut parts = filename.splitn(2, '.');
2521 let file_stem = parts.next().unwrap().to_owned();
2522 let extension = parts.next().unwrap().to_owned();
2523
2524 toplevel.push((file_stem, extension, expected_len));
2525 }
2526 });
2527
2528 if !ok {
2529 crate::exit!(1);
2530 }
2531
2532 if builder.config.dry_run() {
2533 return Vec::new();
2534 }
2535
2536 let contents = target_deps_dir
2540 .read_dir()
2541 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2542 .map(|e| t!(e))
2543 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2544 .collect::<Vec<_>>();
2545 for (prefix, extension, expected_len) in toplevel {
2546 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2547 meta.len() == expected_len
2548 && filename
2549 .strip_prefix(&prefix[..])
2550 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2551 .unwrap_or(false)
2552 });
2553 let max = candidates.max_by_key(|&(_, _, metadata)| {
2554 metadata.modified().expect("mtime should be available on all relevant OSes")
2555 });
2556 let path_to_add = match max {
2557 Some(triple) => triple.0.to_str().unwrap(),
2558 None => panic!("no output generated for {prefix:?} {extension:?}"),
2559 };
2560 if is_dylib(Path::new(path_to_add)) {
2561 let candidate = format!("{path_to_add}.lib");
2562 let candidate = PathBuf::from(candidate);
2563 if candidate.exists() {
2564 deps.push((candidate, DependencyType::Target));
2565 }
2566 }
2567 deps.push((path_to_add.into(), DependencyType::Target));
2568 }
2569
2570 deps.extend(additional_target_deps);
2571 deps.sort();
2572 let mut new_contents = Vec::new();
2573 for (dep, dependency_type) in deps.iter() {
2574 new_contents.extend(match *dependency_type {
2575 DependencyType::Host => b"h",
2576 DependencyType::Target => b"t",
2577 DependencyType::TargetSelfContained => b"s",
2578 });
2579 new_contents.extend(dep.to_str().unwrap().as_bytes());
2580 new_contents.extend(b"\0");
2581 }
2582 t!(fs::write(stamp.path(), &new_contents));
2583 deps.into_iter().map(|(d, _)| d).collect()
2584}
2585
2586pub fn stream_cargo(
2587 builder: &Builder<'_>,
2588 cargo: Cargo,
2589 tail_args: Vec<String>,
2590 cb: &mut dyn FnMut(CargoMessage<'_>),
2591) -> bool {
2592 let mut cmd = cargo.into_cmd();
2593
2594 #[cfg(feature = "tracing")]
2595 let _run_span = crate::trace_cmd!(cmd);
2596
2597 let mut message_format = if builder.config.json_output {
2600 String::from("json")
2601 } else {
2602 String::from("json-render-diagnostics")
2603 };
2604 if let Some(s) = &builder.config.rustc_error_format {
2605 message_format.push_str(",json-diagnostic-");
2606 message_format.push_str(s);
2607 }
2608 cmd.arg("--message-format").arg(message_format);
2609
2610 for arg in tail_args {
2611 cmd.arg(arg);
2612 }
2613
2614 builder.verbose(|| println!("running: {cmd:?}"));
2615
2616 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2617
2618 let Some(mut streaming_command) = streaming_command else {
2619 return true;
2620 };
2621
2622 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2626 for line in stdout.lines() {
2627 let line = t!(line);
2628 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2629 Ok(msg) => {
2630 if builder.config.json_output {
2631 println!("{line}");
2633 }
2634 cb(msg)
2635 }
2636 Err(_) => println!("{line}"),
2638 }
2639 }
2640
2641 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2643 if builder.is_verbose() && !status.success() {
2644 eprintln!(
2645 "command did not execute successfully: {cmd:?}\n\
2646 expected success, got: {status}"
2647 );
2648 }
2649
2650 status.success()
2651}
2652
2653#[derive(Deserialize)]
2654pub struct CargoTarget<'a> {
2655 crate_types: Vec<Cow<'a, str>>,
2656}
2657
2658#[derive(Deserialize)]
2659#[serde(tag = "reason", rename_all = "kebab-case")]
2660pub enum CargoMessage<'a> {
2661 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2662 BuildScriptExecuted,
2663 BuildFinished,
2664}
2665
2666pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2667 if target != "x86_64-unknown-linux-gnu"
2671 || !builder.config.is_host_target(target)
2672 || !path.exists()
2673 {
2674 return;
2675 }
2676
2677 let previous_mtime = t!(t!(path.metadata()).modified());
2678 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2679
2680 let file = t!(fs::File::open(path));
2681
2682 t!(file.set_modified(previous_mtime));
2695}
2696
2697pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2699 build_compiler.stage != 0
2700}