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, add_cg_gcc_cargo_flags};
22use crate::core::build_steps::tool::{SourceType, copy_lld_artifacts};
23use crate::core::build_steps::{dist, llvm};
24use crate::core::builder;
25use crate::core::builder::{
26 Builder, Cargo, Kind, PathSet, RunConfig, ShouldRun, Step, StepMetadata, TaskPath,
27 crate_description,
28};
29use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
30use crate::utils::build_stamp;
31use crate::utils::build_stamp::BuildStamp;
32use crate::utils::exec::command;
33use crate::utils::helpers::{
34 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
35};
36use crate::{CLang, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
37
38#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub struct Std {
41 pub target: TargetSelection,
42 pub compiler: Compiler,
43 crates: Vec<String>,
47 force_recompile: bool,
50 extra_rust_args: &'static [&'static str],
51 is_for_mir_opt_tests: bool,
52}
53
54impl Std {
55 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
56 Self {
57 target,
58 compiler,
59 crates: Default::default(),
60 force_recompile: false,
61 extra_rust_args: &[],
62 is_for_mir_opt_tests: false,
63 }
64 }
65
66 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
67 self.force_recompile = force_recompile;
68 self
69 }
70
71 #[expect(clippy::wrong_self_convention)]
72 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
73 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
74 self
75 }
76
77 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
78 self.extra_rust_args = extra_rust_args;
79 self
80 }
81
82 fn copy_extra_objects(
83 &self,
84 builder: &Builder<'_>,
85 compiler: &Compiler,
86 target: TargetSelection,
87 ) -> Vec<(PathBuf, DependencyType)> {
88 let mut deps = Vec::new();
89 if !self.is_for_mir_opt_tests {
90 deps.extend(copy_third_party_objects(builder, compiler, target));
91 deps.extend(copy_self_contained_objects(builder, compiler, target));
92 }
93 deps
94 }
95}
96
97impl Step for Std {
98 type Output = ();
99 const DEFAULT: bool = true;
100
101 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
102 run.crate_or_deps("sysroot").path("library")
103 }
104
105 #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
106 fn make_run(run: RunConfig<'_>) {
107 let crates = std_crates_for_run_make(&run);
108 let builder = run.builder;
109
110 let force_recompile = builder.rust_info().is_managed_git_subrepository()
114 && builder.download_rustc()
115 && builder.config.has_changes_from_upstream(&["library"]);
116
117 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
118 trace!("download_rustc: {}", builder.download_rustc());
119 trace!(force_recompile);
120
121 run.builder.ensure(Std {
122 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
123 target: run.target,
124 crates,
125 force_recompile,
126 extra_rust_args: &[],
127 is_for_mir_opt_tests: false,
128 });
129 }
130
131 #[cfg_attr(
137 feature = "tracing",
138 instrument(
139 level = "debug",
140 name = "Std::run",
141 skip_all,
142 fields(
143 target = ?self.target,
144 compiler = ?self.compiler,
145 force_recompile = self.force_recompile
146 ),
147 ),
148 )]
149 fn run(self, builder: &Builder<'_>) {
150 let target = self.target;
151
152 if self.compiler.stage == 0 {
154 let compiler = self.compiler;
155 builder.ensure(StdLink::from_std(self, compiler));
156
157 return;
158 }
159
160 let compiler = if builder.download_rustc() && self.force_recompile {
161 builder.compiler(self.compiler.stage.saturating_sub(1), builder.config.host_target)
164 } else {
165 self.compiler
166 };
167
168 if builder.download_rustc()
171 && builder.config.is_host_target(target)
172 && !self.force_recompile
173 {
174 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
175 cp_rustc_component_to_ci_sysroot(
176 builder,
177 &sysroot,
178 builder.config.ci_rust_std_contents(),
179 );
180 return;
181 }
182
183 if builder.config.keep_stage.contains(&compiler.stage)
184 || builder.config.keep_stage_std.contains(&compiler.stage)
185 {
186 trace!(keep_stage = ?builder.config.keep_stage);
187 trace!(keep_stage_std = ?builder.config.keep_stage_std);
188
189 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
190
191 builder.ensure(StartupObjects { compiler, target });
192
193 self.copy_extra_objects(builder, &compiler, target);
194
195 builder.ensure(StdLink::from_std(self, compiler));
196 return;
197 }
198
199 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
200
201 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
202 trace!(?compiler_to_use);
203
204 if compiler_to_use != compiler
205 && compiler.stage > 1
210 {
211 trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
212
213 builder.std(compiler_to_use, target);
214 let msg = if compiler_to_use.host == target {
215 format!(
216 "Uplifting library (stage{} -> stage{})",
217 compiler_to_use.stage, compiler.stage
218 )
219 } else {
220 format!(
221 "Uplifting library (stage{}:{} -> stage{}:{})",
222 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
223 )
224 };
225 builder.info(&msg);
226
227 self.copy_extra_objects(builder, &compiler, target);
230
231 builder.ensure(StdLink::from_std(self, compiler_to_use));
232 return;
233 }
234
235 trace!(
236 ?compiler_to_use,
237 ?compiler,
238 "compiler == compiler_to_use, handling not-cross-compile scenario"
239 );
240
241 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
242
243 let mut cargo = if self.is_for_mir_opt_tests {
247 trace!("building special sysroot for mir-opt tests");
248 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
249 builder,
250 compiler,
251 Mode::Std,
252 SourceType::InTree,
253 target,
254 Kind::Check,
255 );
256 cargo.rustflag("-Zalways-encode-mir");
257 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
258 cargo
259 } else {
260 trace!("building regular sysroot");
261 let mut cargo = builder::Cargo::new(
262 builder,
263 compiler,
264 Mode::Std,
265 SourceType::InTree,
266 target,
267 Kind::Build,
268 );
269 std_cargo(builder, target, compiler.stage, &mut cargo);
270 for krate in &*self.crates {
271 cargo.arg("-p").arg(krate);
272 }
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 compiler.stage,
287 format_args!("library artifacts{}", crate_description(&self.crates)),
288 compiler.host,
289 target,
290 );
291 run_cargo(
292 builder,
293 cargo,
294 vec![],
295 &build_stamp::libstd_stamp(builder, compiler, target),
296 target_deps,
297 self.is_for_mir_opt_tests, false,
299 );
300
301 builder.ensure(StdLink::from_std(
302 self,
303 builder.compiler(compiler.stage, builder.config.host_target),
304 ));
305 }
306
307 fn metadata(&self) -> Option<StepMetadata> {
308 Some(StepMetadata::build("std", self.target).built_by(self.compiler))
309 }
310}
311
312fn copy_and_stamp(
313 builder: &Builder<'_>,
314 libdir: &Path,
315 sourcedir: &Path,
316 name: &str,
317 target_deps: &mut Vec<(PathBuf, DependencyType)>,
318 dependency_type: DependencyType,
319) {
320 let target = libdir.join(name);
321 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
322
323 target_deps.push((target, dependency_type));
324}
325
326fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
327 let libunwind_path = builder.ensure(llvm::Libunwind { target });
328 let libunwind_source = libunwind_path.join("libunwind.a");
329 let libunwind_target = libdir.join("libunwind.a");
330 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
331 libunwind_target
332}
333
334fn copy_third_party_objects(
336 builder: &Builder<'_>,
337 compiler: &Compiler,
338 target: TargetSelection,
339) -> Vec<(PathBuf, DependencyType)> {
340 let mut target_deps = vec![];
341
342 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
343 target_deps.extend(
346 copy_sanitizers(builder, compiler, target)
347 .into_iter()
348 .map(|d| (d, DependencyType::Target)),
349 );
350 }
351
352 if target == "x86_64-fortanix-unknown-sgx"
353 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
354 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
355 {
356 let libunwind_path =
357 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
358 target_deps.push((libunwind_path, DependencyType::Target));
359 }
360
361 target_deps
362}
363
364fn copy_self_contained_objects(
366 builder: &Builder<'_>,
367 compiler: &Compiler,
368 target: TargetSelection,
369) -> Vec<(PathBuf, DependencyType)> {
370 let libdir_self_contained =
371 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
372 t!(fs::create_dir_all(&libdir_self_contained));
373 let mut target_deps = vec![];
374
375 if target.needs_crt_begin_end() {
383 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
384 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
385 });
386 if !target.starts_with("wasm32") {
387 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
388 copy_and_stamp(
389 builder,
390 &libdir_self_contained,
391 &srcdir,
392 obj,
393 &mut target_deps,
394 DependencyType::TargetSelfContained,
395 );
396 }
397 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
398 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
399 let src = crt_path.join(obj);
400 let target = libdir_self_contained.join(obj);
401 builder.copy_link(&src, &target, FileType::NativeLibrary);
402 target_deps.push((target, DependencyType::TargetSelfContained));
403 }
404 } else {
405 for &obj in &["libc.a", "crt1-command.o"] {
408 copy_and_stamp(
409 builder,
410 &libdir_self_contained,
411 &srcdir,
412 obj,
413 &mut target_deps,
414 DependencyType::TargetSelfContained,
415 );
416 }
417 }
418 if !target.starts_with("s390x") {
419 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
420 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
421 }
422 } else if target.contains("-wasi") {
423 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
424 panic!(
425 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
426 or `$WASI_SDK_PATH` set",
427 target.triple
428 )
429 });
430 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
431 copy_and_stamp(
432 builder,
433 &libdir_self_contained,
434 &srcdir,
435 obj,
436 &mut target_deps,
437 DependencyType::TargetSelfContained,
438 );
439 }
440 } else if target.is_windows_gnu() {
441 for obj in ["crt2.o", "dllcrt2.o"].iter() {
442 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
443 let dst = libdir_self_contained.join(obj);
444 builder.copy_link(&src, &dst, FileType::NativeLibrary);
445 target_deps.push((dst, DependencyType::TargetSelfContained));
446 }
447 }
448
449 target_deps
450}
451
452pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
455 let mut crates = run.make_run_crates(builder::Alias::Library);
456
457 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
466 if target_is_no_std {
467 crates.retain(|c| c == "core" || c == "alloc");
468 }
469 crates
470}
471
472fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
478 if builder.config.llvm_from_ci {
480 builder.config.maybe_download_ci_llvm();
482 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
483 if ci_llvm_compiler_rt.exists() {
484 return ci_llvm_compiler_rt;
485 }
486 }
487
488 builder.require_submodule("src/llvm-project", {
490 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
491 });
492 builder.src.join("src/llvm-project/compiler-rt")
493}
494
495pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
498 if target.contains("apple") && !builder.config.dry_run() {
516 let mut cmd = command(builder.rustc(cargo.compiler()));
520 cmd.arg("--target").arg(target.rustc_target_arg());
521 cmd.arg("--print=deployment-target");
522 let output = cmd.run_capture_stdout(builder).stdout();
523
524 let (env_var, value) = output.split_once('=').unwrap();
525 cargo.env(env_var.trim(), value.trim());
528
529 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
539 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
540 }
541 }
542
543 if let Some(path) = builder.config.profiler_path(target) {
545 cargo.env("LLVM_PROFILER_RT_LIB", path);
546 } else if builder.config.profiler_enabled(target) {
547 let compiler_rt = compiler_rt_for_profiler(builder);
548 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
552 }
553
554 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
568 builder.require_submodule(
576 "src/llvm-project",
577 Some(
578 "The `build.optimized-compiler-builtins` config option \
579 requires `compiler-rt` sources from LLVM.",
580 ),
581 );
582 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
583 assert!(compiler_builtins_root.exists());
584 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
587 " compiler-builtins-c"
588 } else {
589 ""
590 };
591
592 if !builder.unstable_features() {
595 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
596 }
597
598 let mut features = String::new();
599
600 if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
601 {
602 features += "compiler-builtins-no-f16-f128 ";
603 }
604
605 if builder.no_std(target) == Some(true) {
606 features += " compiler-builtins-mem";
607 if !target.starts_with("bpf") {
608 features.push_str(compiler_builtins_c_feature);
609 }
610
611 cargo
613 .args(["-p", "alloc"])
614 .arg("--manifest-path")
615 .arg(builder.src.join("library/alloc/Cargo.toml"))
616 .arg("--features")
617 .arg(features);
618 } else {
619 features += &builder.std_features(target);
620 features.push_str(compiler_builtins_c_feature);
621
622 cargo
623 .arg("--features")
624 .arg(features)
625 .arg("--manifest-path")
626 .arg(builder.src.join("library/sysroot/Cargo.toml"));
627
628 if target.contains("musl")
631 && let Some(p) = builder.musl_libdir(target)
632 {
633 let root = format!("native={}", p.to_str().unwrap());
634 cargo.rustflag("-L").rustflag(&root);
635 }
636
637 if target.contains("-wasi")
638 && let Some(dir) = builder.wasi_libdir(target)
639 {
640 let root = format!("native={}", dir.to_str().unwrap());
641 cargo.rustflag("-L").rustflag(&root);
642 }
643 }
644
645 if stage >= 1 {
654 cargo.rustflag("-Cembed-bitcode=yes");
655 }
656 if builder.config.rust_lto == RustcLto::Off {
657 cargo.rustflag("-Clto=off");
658 }
659
660 if target.contains("riscv") {
667 cargo.rustflag("-Cforce-unwind-tables=yes");
668 }
669
670 cargo.rustflag("-Zunstable-options");
673 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
674
675 let html_root =
676 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
677 cargo.rustflag(&html_root);
678 cargo.rustdocflag(&html_root);
679
680 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
681}
682
683#[derive(Debug, Clone, PartialEq, Eq, Hash)]
684pub struct StdLink {
685 pub compiler: Compiler,
686 pub target_compiler: Compiler,
687 pub target: TargetSelection,
688 crates: Vec<String>,
690 force_recompile: bool,
692}
693
694impl StdLink {
695 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
696 Self {
697 compiler: host_compiler,
698 target_compiler: std.compiler,
699 target: std.target,
700 crates: std.crates,
701 force_recompile: std.force_recompile,
702 }
703 }
704}
705
706impl Step for StdLink {
707 type Output = ();
708
709 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
710 run.never()
711 }
712
713 #[cfg_attr(
722 feature = "tracing",
723 instrument(
724 level = "trace",
725 name = "StdLink::run",
726 skip_all,
727 fields(
728 compiler = ?self.compiler,
729 target_compiler = ?self.target_compiler,
730 target = ?self.target
731 ),
732 ),
733 )]
734 fn run(self, builder: &Builder<'_>) {
735 let compiler = self.compiler;
736 let target_compiler = self.target_compiler;
737 let target = self.target;
738
739 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
741 let lib = builder.sysroot_libdir_relative(self.compiler);
743 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
744 compiler: self.compiler,
745 force_recompile: self.force_recompile,
746 });
747 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
748 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
749 (libdir, hostdir)
750 } else {
751 let libdir = builder.sysroot_target_libdir(target_compiler, target);
752 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
753 (libdir, hostdir)
754 };
755
756 let is_downloaded_beta_stage0 = builder
757 .build
758 .config
759 .initial_rustc
760 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
761
762 if compiler.stage == 0 && is_downloaded_beta_stage0 {
766 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
768
769 let host = compiler.host;
770 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
771 let sysroot_bin_dir = sysroot.join("bin");
772 t!(fs::create_dir_all(&sysroot_bin_dir));
773 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
774
775 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
776 t!(fs::create_dir_all(sysroot.join("lib")));
777 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
778
779 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
781 t!(fs::create_dir_all(&sysroot_codegen_backends));
782 let stage0_codegen_backends = builder
783 .out
784 .join(host)
785 .join("stage0/lib/rustlib")
786 .join(host)
787 .join("codegen-backends");
788 if stage0_codegen_backends.exists() {
789 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
790 }
791 } else if compiler.stage == 0 {
792 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
793
794 if builder.local_rebuild {
795 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
799 }
800
801 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
802 } else {
803 if builder.download_rustc() {
804 let _ = fs::remove_dir_all(&libdir);
806 let _ = fs::remove_dir_all(&hostdir);
807 }
808
809 add_to_sysroot(
810 builder,
811 &libdir,
812 &hostdir,
813 &build_stamp::libstd_stamp(builder, compiler, target),
814 );
815 }
816 }
817}
818
819fn copy_sanitizers(
821 builder: &Builder<'_>,
822 compiler: &Compiler,
823 target: TargetSelection,
824) -> Vec<PathBuf> {
825 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
826
827 if builder.config.dry_run() {
828 return Vec::new();
829 }
830
831 let mut target_deps = Vec::new();
832 let libdir = builder.sysroot_target_libdir(*compiler, target);
833
834 for runtime in &runtimes {
835 let dst = libdir.join(&runtime.name);
836 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
837
838 if target == "x86_64-apple-darwin"
842 || target == "aarch64-apple-darwin"
843 || target == "aarch64-apple-ios"
844 || target == "aarch64-apple-ios-sim"
845 || target == "x86_64-apple-ios"
846 {
847 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
849 apple_darwin_sign_file(builder, &dst);
852 }
853
854 target_deps.push(dst);
855 }
856
857 target_deps
858}
859
860fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
861 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
862}
863
864fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
865 command("codesign")
866 .arg("-f") .arg("-s")
868 .arg("-")
869 .arg(file_path)
870 .run(builder);
871}
872
873#[derive(Debug, Clone, PartialEq, Eq, Hash)]
874pub struct StartupObjects {
875 pub compiler: Compiler,
876 pub target: TargetSelection,
877}
878
879impl Step for StartupObjects {
880 type Output = Vec<(PathBuf, DependencyType)>;
881
882 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
883 run.path("library/rtstartup")
884 }
885
886 fn make_run(run: RunConfig<'_>) {
887 run.builder.ensure(StartupObjects {
888 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
889 target: run.target,
890 });
891 }
892
893 #[cfg_attr(
900 feature = "tracing",
901 instrument(
902 level = "trace",
903 name = "StartupObjects::run",
904 skip_all,
905 fields(compiler = ?self.compiler, target = ?self.target),
906 ),
907 )]
908 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
909 let for_compiler = self.compiler;
910 let target = self.target;
911 if !target.is_windows_gnu() {
912 return vec![];
913 }
914
915 let mut target_deps = vec![];
916
917 let src_dir = &builder.src.join("library").join("rtstartup");
918 let dst_dir = &builder.native_dir(target).join("rtstartup");
919 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
920 t!(fs::create_dir_all(dst_dir));
921
922 for file in &["rsbegin", "rsend"] {
923 let src_file = &src_dir.join(file.to_string() + ".rs");
924 let dst_file = &dst_dir.join(file.to_string() + ".o");
925 if !up_to_date(src_file, dst_file) {
926 let mut cmd = command(&builder.initial_rustc);
927 cmd.env("RUSTC_BOOTSTRAP", "1");
928 if !builder.local_rebuild {
929 cmd.arg("--cfg").arg("bootstrap");
931 }
932 cmd.arg("--target")
933 .arg(target.rustc_target_arg())
934 .arg("--emit=obj")
935 .arg("-o")
936 .arg(dst_file)
937 .arg(src_file)
938 .run(builder);
939 }
940
941 let obj = sysroot_dir.join((*file).to_string() + ".o");
942 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
943 target_deps.push((obj, DependencyType::Target));
944 }
945
946 target_deps
947 }
948}
949
950fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
951 let ci_rustc_dir = builder.config.ci_rustc_dir();
952
953 for file in contents {
954 let src = ci_rustc_dir.join(&file);
955 let dst = sysroot.join(file);
956 if src.is_dir() {
957 t!(fs::create_dir_all(dst));
958 } else {
959 builder.copy_link(&src, &dst, FileType::Regular);
960 }
961 }
962}
963
964#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
971pub struct Rustc {
972 pub target: TargetSelection,
974 pub build_compiler: Compiler,
976 crates: Vec<String>,
982}
983
984impl Rustc {
985 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
986 Self { target, build_compiler, crates: Default::default() }
987 }
988}
989
990impl Step for Rustc {
991 type Output = u32;
999 const ONLY_HOSTS: bool = true;
1000 const DEFAULT: bool = false;
1001
1002 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1003 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1004 for (i, krate) in crates.iter().enumerate() {
1005 if krate.name == "rustc-main" {
1008 crates.swap_remove(i);
1009 break;
1010 }
1011 }
1012 run.crates(crates)
1013 }
1014
1015 fn make_run(run: RunConfig<'_>) {
1016 if run.builder.paths == vec![PathBuf::from("compiler")] {
1019 return;
1020 }
1021
1022 let crates = run.cargo_crates_in_set();
1023 run.builder.ensure(Rustc {
1024 build_compiler: run
1025 .builder
1026 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1027 target: run.target,
1028 crates,
1029 });
1030 }
1031
1032 #[cfg_attr(
1038 feature = "tracing",
1039 instrument(
1040 level = "debug",
1041 name = "Rustc::run",
1042 skip_all,
1043 fields(previous_compiler = ?self.build_compiler, target = ?self.target),
1044 ),
1045 )]
1046 fn run(self, builder: &Builder<'_>) -> u32 {
1047 let build_compiler = self.build_compiler;
1048 let target = self.target;
1049
1050 if builder.download_rustc() && build_compiler.stage != 0 {
1053 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1054
1055 let sysroot =
1056 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1057 cp_rustc_component_to_ci_sysroot(
1058 builder,
1059 &sysroot,
1060 builder.config.ci_rustc_dev_contents(),
1061 );
1062 return build_compiler.stage;
1063 }
1064
1065 builder.std(build_compiler, target);
1068
1069 if builder.config.keep_stage.contains(&build_compiler.stage) {
1070 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1071
1072 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1073 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1074 builder.ensure(RustcLink::from_rustc(self, build_compiler));
1075
1076 return build_compiler.stage;
1077 }
1078
1079 let compiler_to_use =
1080 builder.compiler_for(build_compiler.stage, build_compiler.host, target);
1081 if compiler_to_use != build_compiler {
1082 builder.ensure(Rustc::new(compiler_to_use, target));
1083 let msg = if compiler_to_use.host == target {
1084 format!(
1085 "Uplifting rustc (stage{} -> stage{})",
1086 compiler_to_use.stage,
1087 build_compiler.stage + 1
1088 )
1089 } else {
1090 format!(
1091 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1092 compiler_to_use.stage,
1093 compiler_to_use.host,
1094 build_compiler.stage + 1,
1095 target
1096 )
1097 };
1098 builder.info(&msg);
1099 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1100 return compiler_to_use.stage;
1101 }
1102
1103 builder.std(
1109 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1110 builder.config.host_target,
1111 );
1112
1113 let mut cargo = builder::Cargo::new(
1114 builder,
1115 build_compiler,
1116 Mode::Rustc,
1117 SourceType::InTree,
1118 target,
1119 Kind::Build,
1120 );
1121
1122 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1123
1124 for krate in &*self.crates {
1128 cargo.arg("-p").arg(krate);
1129 }
1130
1131 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1132 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1134 }
1135
1136 let _guard = builder.msg_sysroot_tool(
1137 Kind::Build,
1138 build_compiler.stage,
1139 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1140 build_compiler.host,
1141 target,
1142 );
1143 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1144 run_cargo(
1145 builder,
1146 cargo,
1147 vec![],
1148 &stamp,
1149 vec![],
1150 false,
1151 true, );
1153
1154 let target_root_dir = stamp.path().parent().unwrap();
1155 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1161 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1162 {
1163 let rustc_driver = target_root_dir.join("librustc_driver.so");
1164 strip_debug(builder, target, &rustc_driver);
1165 }
1166
1167 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1168 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1171 }
1172
1173 builder.ensure(RustcLink::from_rustc(
1174 self,
1175 builder.compiler(build_compiler.stage, builder.config.host_target),
1176 ));
1177
1178 build_compiler.stage
1179 }
1180
1181 fn metadata(&self) -> Option<StepMetadata> {
1182 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1183 }
1184}
1185
1186pub fn rustc_cargo(
1187 builder: &Builder<'_>,
1188 cargo: &mut Cargo,
1189 target: TargetSelection,
1190 build_compiler: &Compiler,
1191 crates: &[String],
1192) {
1193 cargo
1194 .arg("--features")
1195 .arg(builder.rustc_features(builder.kind, target, crates))
1196 .arg("--manifest-path")
1197 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1198
1199 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1200
1201 cargo.rustflag("-Zon-broken-pipe=kill");
1215
1216 if builder.config.llvm_enzyme {
1219 let arch = builder.build.host_target;
1220 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1221 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1222
1223 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1224 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1225 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1226 }
1227 }
1228
1229 if builder.build.config.lld_mode.is_used() {
1234 cargo.rustflag("-Zdefault-visibility=protected");
1235 }
1236
1237 if is_lto_stage(build_compiler) {
1238 match builder.config.rust_lto {
1239 RustcLto::Thin | RustcLto::Fat => {
1240 cargo.rustflag("-Zdylib-lto");
1243 let lto_type = match builder.config.rust_lto {
1247 RustcLto::Thin => "thin",
1248 RustcLto::Fat => "fat",
1249 _ => unreachable!(),
1250 };
1251 cargo.rustflag(&format!("-Clto={lto_type}"));
1252 cargo.rustflag("-Cembed-bitcode=yes");
1253 }
1254 RustcLto::ThinLocal => { }
1255 RustcLto::Off => {
1256 cargo.rustflag("-Clto=off");
1257 }
1258 }
1259 } else if builder.config.rust_lto == RustcLto::Off {
1260 cargo.rustflag("-Clto=off");
1261 }
1262
1263 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1271 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1272 }
1273
1274 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1275 panic!("Cannot use and generate PGO profiles at the same time");
1276 }
1277 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1278 if build_compiler.stage == 1 {
1279 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1280 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1283 true
1284 } else {
1285 false
1286 }
1287 } else if let Some(path) = &builder.config.rust_profile_use {
1288 if build_compiler.stage == 1 {
1289 cargo.rustflag(&format!("-Cprofile-use={path}"));
1290 if builder.is_verbose() {
1291 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1292 }
1293 true
1294 } else {
1295 false
1296 }
1297 } else {
1298 false
1299 };
1300 if is_collecting {
1301 cargo.rustflag(&format!(
1303 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1304 builder.config.src.components().count()
1305 ));
1306 }
1307
1308 if let Some(ref ccache) = builder.config.ccache
1313 && build_compiler.stage == 0
1314 && !builder.config.incremental
1315 {
1316 cargo.env("RUSTC_WRAPPER", ccache);
1317 }
1318
1319 rustc_cargo_env(builder, cargo, target, build_compiler.stage);
1320}
1321
1322pub fn rustc_cargo_env(
1323 builder: &Builder<'_>,
1324 cargo: &mut Cargo,
1325 target: TargetSelection,
1326 build_stage: u32,
1327) {
1328 cargo
1331 .env("CFG_RELEASE", builder.rust_release())
1332 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1333 .env("CFG_VERSION", builder.rust_version());
1334
1335 if builder.config.omit_git_hash {
1339 cargo.env("CFG_OMIT_GIT_HASH", "1");
1340 }
1341
1342 if let Some(backend) = builder.config.default_codegen_backend(target) {
1343 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1344 }
1345
1346 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1347 let target_config = builder.config.target_config.get(&target);
1348
1349 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1350
1351 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1352 cargo.env("CFG_VER_DATE", ver_date);
1353 }
1354 if let Some(ref ver_hash) = builder.rust_info().sha() {
1355 cargo.env("CFG_VER_HASH", ver_hash);
1356 }
1357 if !builder.unstable_features() {
1358 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1359 }
1360
1361 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1364 cargo.env("CFG_DEFAULT_LINKER", s);
1365 } else if let Some(ref s) = builder.config.rustc_default_linker {
1366 cargo.env("CFG_DEFAULT_LINKER", s);
1367 }
1368
1369 if builder.config.lld_enabled {
1371 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1372 }
1373
1374 if builder.config.rust_verify_llvm_ir {
1375 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1376 }
1377
1378 if builder.config.llvm_enzyme {
1379 cargo.rustflag("--cfg=llvm_enzyme");
1380 }
1381
1382 if builder.config.llvm_enabled(target) {
1387 let building_is_expensive =
1388 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1389 .should_build();
1390 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == build_stage;
1392 let should_skip_build = building_is_expensive && can_skip_build;
1393 if !should_skip_build {
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) {
1411 if builder.config.is_rust_llvm(target) {
1412 cargo.env("LLVM_RUSTLLVM", "1");
1413 }
1414 if builder.config.llvm_enzyme {
1415 cargo.env("LLVM_ENZYME", "1");
1416 }
1417 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1418 cargo.env("LLVM_CONFIG", &llvm_config);
1419
1420 let mut llvm_linker_flags = String::new();
1430 if builder.config.llvm_profile_generate
1431 && target.is_msvc()
1432 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1433 {
1434 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1436 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1437 }
1438
1439 if let Some(ref s) = builder.config.llvm_ldflags {
1441 if !llvm_linker_flags.is_empty() {
1442 llvm_linker_flags.push(' ');
1443 }
1444 llvm_linker_flags.push_str(s);
1445 }
1446
1447 if !llvm_linker_flags.is_empty() {
1449 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1450 }
1451
1452 if builder.config.llvm_static_stdcpp
1455 && !target.contains("freebsd")
1456 && !target.is_msvc()
1457 && !target.contains("apple")
1458 && !target.contains("solaris")
1459 {
1460 let libstdcxx_name =
1461 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1462 let file = compiler_file(
1463 builder,
1464 &builder.cxx(target).unwrap(),
1465 target,
1466 CLang::Cxx,
1467 libstdcxx_name,
1468 );
1469 cargo.env("LLVM_STATIC_STDCPP", file);
1470 }
1471 if builder.llvm_link_shared() {
1472 cargo.env("LLVM_LINK_SHARED", "1");
1473 }
1474 if builder.config.llvm_use_libcxx {
1475 cargo.env("LLVM_USE_LIBCXX", "1");
1476 }
1477 if builder.config.llvm_assertions {
1478 cargo.env("LLVM_ASSERTIONS", "1");
1479 }
1480}
1481
1482#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1488struct RustcLink {
1489 pub compiler: Compiler,
1491 pub previous_stage_compiler: Compiler,
1493 pub target: TargetSelection,
1494 crates: Vec<String>,
1496}
1497
1498impl RustcLink {
1499 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1500 Self {
1501 compiler: host_compiler,
1502 previous_stage_compiler: rustc.build_compiler,
1503 target: rustc.target,
1504 crates: rustc.crates,
1505 }
1506 }
1507}
1508
1509impl Step for RustcLink {
1510 type Output = ();
1511
1512 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1513 run.never()
1514 }
1515
1516 #[cfg_attr(
1518 feature = "tracing",
1519 instrument(
1520 level = "trace",
1521 name = "RustcLink::run",
1522 skip_all,
1523 fields(
1524 compiler = ?self.compiler,
1525 previous_stage_compiler = ?self.previous_stage_compiler,
1526 target = ?self.target,
1527 ),
1528 ),
1529 )]
1530 fn run(self, builder: &Builder<'_>) {
1531 let compiler = self.compiler;
1532 let previous_stage_compiler = self.previous_stage_compiler;
1533 let target = self.target;
1534 add_to_sysroot(
1535 builder,
1536 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1537 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1538 &build_stamp::librustc_stamp(builder, compiler, target),
1539 );
1540 }
1541}
1542
1543#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1544pub struct CodegenBackend {
1545 pub target: TargetSelection,
1546 pub compiler: Compiler,
1547 pub backend: String,
1548}
1549
1550fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1551 let mut needs_codegen_cfg = false;
1552 for path_set in &run.paths {
1553 needs_codegen_cfg = match path_set {
1554 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1555 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1556 }
1557 }
1558 needs_codegen_cfg
1559}
1560
1561pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1562
1563fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1564 let path = path.path.to_str().unwrap();
1565
1566 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1567 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1568
1569 if path.contains(CODEGEN_BACKEND_PREFIX) {
1570 let mut needs_codegen_backend_config = true;
1571 for backend in run.builder.config.codegen_backends(run.target) {
1572 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1573 needs_codegen_backend_config = false;
1574 }
1575 }
1576 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1577 && needs_codegen_backend_config
1578 {
1579 run.builder.info(
1580 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1581 HELP: add backend to codegen-backends in bootstrap.toml.",
1582 );
1583 return true;
1584 }
1585 }
1586
1587 false
1588}
1589
1590impl Step for CodegenBackend {
1591 type Output = ();
1592 const ONLY_HOSTS: bool = true;
1593 const DEFAULT: bool = true;
1595
1596 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1597 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1598 }
1599
1600 fn make_run(run: RunConfig<'_>) {
1601 if needs_codegen_config(&run) {
1602 return;
1603 }
1604
1605 for backend in run.builder.config.codegen_backends(run.target) {
1606 if backend == "llvm" {
1607 continue; }
1609
1610 run.builder.ensure(CodegenBackend {
1611 target: run.target,
1612 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1613 backend: backend.clone(),
1614 });
1615 }
1616 }
1617
1618 #[cfg_attr(
1619 feature = "tracing",
1620 instrument(
1621 level = "debug",
1622 name = "CodegenBackend::run",
1623 skip_all,
1624 fields(
1625 compiler = ?self.compiler,
1626 target = ?self.target,
1627 backend = ?self.target,
1628 ),
1629 ),
1630 )]
1631 fn run(self, builder: &Builder<'_>) {
1632 let compiler = self.compiler;
1633 let target = self.target;
1634 let backend = self.backend;
1635
1636 builder.ensure(Rustc::new(compiler, target));
1637
1638 if builder.config.keep_stage.contains(&compiler.stage) {
1639 trace!("`keep-stage` requested");
1640 builder.info(
1641 "WARNING: Using a potentially old codegen backend. \
1642 This may not behave well.",
1643 );
1644 return;
1647 }
1648
1649 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1650 if compiler_to_use != compiler {
1651 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1652 return;
1653 }
1654
1655 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1656
1657 let mut cargo = builder::Cargo::new(
1658 builder,
1659 compiler,
1660 Mode::Codegen,
1661 SourceType::InTree,
1662 target,
1663 Kind::Build,
1664 );
1665 cargo
1666 .arg("--manifest-path")
1667 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1668 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1669
1670 if backend == "gcc" {
1674 let gcc = builder.ensure(Gcc { target });
1675 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1676 }
1677
1678 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1679
1680 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1681 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1682 if builder.config.dry_run() {
1683 return;
1684 }
1685 let mut files = files.into_iter().filter(|f| {
1686 let filename = f.file_name().unwrap().to_str().unwrap();
1687 is_dylib(f) && filename.contains("rustc_codegen_")
1688 });
1689 let codegen_backend = match files.next() {
1690 Some(f) => f,
1691 None => panic!("no dylibs built for codegen backend?"),
1692 };
1693 if let Some(f) = files.next() {
1694 panic!(
1695 "codegen backend built two dylibs:\n{}\n{}",
1696 codegen_backend.display(),
1697 f.display()
1698 );
1699 }
1700 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1701 let codegen_backend = codegen_backend.to_str().unwrap();
1702 t!(stamp.add_stamp(codegen_backend).write());
1703 }
1704}
1705
1706fn copy_codegen_backends_to_sysroot(
1713 builder: &Builder<'_>,
1714 compiler: Compiler,
1715 target_compiler: Compiler,
1716) {
1717 let target = target_compiler.host;
1718
1719 let dst = builder.sysroot_codegen_backends(target_compiler);
1728 t!(fs::create_dir_all(&dst), dst);
1729
1730 if builder.config.dry_run() {
1731 return;
1732 }
1733
1734 for backend in builder.config.codegen_backends(target) {
1735 if backend == "llvm" {
1736 continue; }
1738
1739 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1740 if stamp.path().exists() {
1741 let dylib = t!(fs::read_to_string(stamp.path()));
1742 let file = Path::new(&dylib);
1743 let filename = file.file_name().unwrap().to_str().unwrap();
1744 let target_filename = {
1747 let dash = filename.find('-').unwrap();
1748 let dot = filename.find('.').unwrap();
1749 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1750 };
1751 builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
1752 }
1753 }
1754}
1755
1756pub fn compiler_file(
1757 builder: &Builder<'_>,
1758 compiler: &Path,
1759 target: TargetSelection,
1760 c: CLang,
1761 file: &str,
1762) -> PathBuf {
1763 if builder.config.dry_run() {
1764 return PathBuf::new();
1765 }
1766 let mut cmd = command(compiler);
1767 cmd.args(builder.cc_handled_clags(target, c));
1768 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1769 cmd.arg(format!("-print-file-name={file}"));
1770 let out = cmd.run_capture_stdout(builder).stdout();
1771 PathBuf::from(out.trim())
1772}
1773
1774#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1775pub struct Sysroot {
1776 pub compiler: Compiler,
1777 force_recompile: bool,
1779}
1780
1781impl Sysroot {
1782 pub(crate) fn new(compiler: Compiler) -> Self {
1783 Sysroot { compiler, force_recompile: false }
1784 }
1785}
1786
1787impl Step for Sysroot {
1788 type Output = PathBuf;
1789
1790 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1791 run.never()
1792 }
1793
1794 #[cfg_attr(
1798 feature = "tracing",
1799 instrument(
1800 level = "debug",
1801 name = "Sysroot::run",
1802 skip_all,
1803 fields(compiler = ?self.compiler),
1804 ),
1805 )]
1806 fn run(self, builder: &Builder<'_>) -> PathBuf {
1807 let compiler = self.compiler;
1808 let host_dir = builder.out.join(compiler.host);
1809
1810 let sysroot_dir = |stage| {
1811 if stage == 0 {
1812 host_dir.join("stage0-sysroot")
1813 } else if self.force_recompile && stage == compiler.stage {
1814 host_dir.join(format!("stage{stage}-test-sysroot"))
1815 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1816 host_dir.join("ci-rustc-sysroot")
1817 } else {
1818 host_dir.join(format!("stage{stage}"))
1819 }
1820 };
1821 let sysroot = sysroot_dir(compiler.stage);
1822 trace!(stage = ?compiler.stage, ?sysroot);
1823
1824 builder
1825 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1826 let _ = fs::remove_dir_all(&sysroot);
1827 t!(fs::create_dir_all(&sysroot));
1828
1829 if compiler.stage == 0 {
1836 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1837 }
1838
1839 if builder.download_rustc() && compiler.stage != 0 {
1841 assert_eq!(
1842 builder.config.host_target, compiler.host,
1843 "Cross-compiling is not yet supported with `download-rustc`",
1844 );
1845
1846 for stage in 0..=2 {
1848 if stage != compiler.stage {
1849 let dir = sysroot_dir(stage);
1850 if !dir.ends_with("ci-rustc-sysroot") {
1851 let _ = fs::remove_dir_all(dir);
1852 }
1853 }
1854 }
1855
1856 let mut filtered_files = Vec::new();
1866 let mut add_filtered_files = |suffix, contents| {
1867 for path in contents {
1868 let path = Path::new(&path);
1869 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1870 filtered_files.push(path.file_name().unwrap().to_owned());
1871 }
1872 }
1873 };
1874 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1875 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1876 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1879
1880 let filtered_extensions = [
1881 OsStr::new("rmeta"),
1882 OsStr::new("rlib"),
1883 OsStr::new(std::env::consts::DLL_EXTENSION),
1885 ];
1886 let ci_rustc_dir = builder.config.ci_rustc_dir();
1887 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1888 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1889 return true;
1890 }
1891 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1892 return true;
1893 }
1894 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1895 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1896 false
1897 } else {
1898 true
1899 }
1900 });
1901 }
1902
1903 if compiler.stage != 0 {
1909 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1910 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1911 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1912 if let Err(e) =
1913 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1914 {
1915 eprintln!(
1916 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1917 sysroot_lib_rustlib_src_rust.display(),
1918 builder.src.display(),
1919 e,
1920 );
1921 if builder.config.rust_remap_debuginfo {
1922 eprintln!(
1923 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1924 sysroot_lib_rustlib_src_rust.display(),
1925 );
1926 }
1927 build_helper::exit!(1);
1928 }
1929 }
1930
1931 if !builder.download_rustc() {
1933 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1934 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1935 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1936 if let Err(e) =
1937 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1938 {
1939 eprintln!(
1940 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1941 sysroot_lib_rustlib_rustcsrc_rust.display(),
1942 builder.src.display(),
1943 e,
1944 );
1945 build_helper::exit!(1);
1946 }
1947 }
1948
1949 sysroot
1950 }
1951}
1952
1953#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1954pub struct Assemble {
1955 pub target_compiler: Compiler,
1960}
1961
1962impl Step for Assemble {
1963 type Output = Compiler;
1964 const ONLY_HOSTS: bool = true;
1965
1966 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1967 run.path("compiler/rustc").path("compiler")
1968 }
1969
1970 fn make_run(run: RunConfig<'_>) {
1971 run.builder.ensure(Assemble {
1972 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1973 });
1974 }
1975
1976 #[cfg_attr(
1982 feature = "tracing",
1983 instrument(
1984 level = "debug",
1985 name = "Assemble::run",
1986 skip_all,
1987 fields(target_compiler = ?self.target_compiler),
1988 ),
1989 )]
1990 fn run(self, builder: &Builder<'_>) -> Compiler {
1991 let target_compiler = self.target_compiler;
1992
1993 if target_compiler.stage == 0 {
1994 trace!("stage 0 build compiler is always available, simply returning");
1995 assert_eq!(
1996 builder.config.host_target, target_compiler.host,
1997 "Cannot obtain compiler for non-native build triple at stage 0"
1998 );
1999 return target_compiler;
2001 }
2002
2003 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2006 let libdir_bin = libdir.parent().unwrap().join("bin");
2007 t!(fs::create_dir_all(&libdir_bin));
2008
2009 if builder.config.llvm_enabled(target_compiler.host) {
2010 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2011
2012 let llvm::LlvmResult { llvm_config, .. } =
2013 builder.ensure(llvm::Llvm { target: target_compiler.host });
2014 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2015 trace!("LLVM tools enabled");
2016
2017 let llvm_bin_dir =
2018 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
2019 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
2020
2021 #[cfg(feature = "tracing")]
2028 let _llvm_tools_span =
2029 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2030 .entered();
2031 for tool in LLVM_TOOLS {
2032 trace!("installing `{tool}`");
2033 let tool_exe = exe(tool, target_compiler.host);
2034 let src_path = llvm_bin_dir.join(&tool_exe);
2035
2036 if !src_path.exists() && builder.config.llvm_from_ci {
2038 eprintln!("{} does not exist; skipping copy", src_path.display());
2039 continue;
2040 }
2041
2042 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2049 }
2050 }
2051 }
2052
2053 let maybe_install_llvm_bitcode_linker = || {
2054 if builder.config.llvm_bitcode_linker_enabled {
2055 trace!("llvm-bitcode-linker enabled, installing");
2056 let llvm_bitcode_linker = builder.ensure(
2057 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2058 builder,
2059 target_compiler,
2060 ),
2061 );
2062
2063 let bindir_self_contained = builder
2065 .sysroot(target_compiler)
2066 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2067 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2068
2069 t!(fs::create_dir_all(&bindir_self_contained));
2070 builder.copy_link(
2071 &llvm_bitcode_linker.tool_path,
2072 &bindir_self_contained.join(tool_exe),
2073 FileType::Executable,
2074 );
2075 }
2076 };
2077
2078 if builder.download_rustc() {
2080 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2081
2082 builder.std(target_compiler, target_compiler.host);
2083 let sysroot =
2084 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2085 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2088 if target_compiler.stage == builder.top_stage {
2090 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2091 }
2092
2093 maybe_install_llvm_bitcode_linker();
2096
2097 return target_compiler;
2098 }
2099
2100 debug!(
2114 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2115 target_compiler.stage - 1,
2116 builder.config.host_target,
2117 );
2118 let mut build_compiler =
2119 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2120
2121 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2123 debug!("`llvm_enzyme` requested");
2124 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2125 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2126 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2127 let lib_ext = std::env::consts::DLL_EXTENSION;
2128 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2129 let src_lib =
2130 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2131 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2132 let target_libdir =
2133 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2134 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2135 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2136 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2137 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2138 }
2139 }
2140
2141 debug!(
2147 ?build_compiler,
2148 "target_compiler.host" = ?target_compiler.host,
2149 "building compiler libraries to link to"
2150 );
2151 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2152 debug!(
2155 "(old) build_compiler.stage" = build_compiler.stage,
2156 "(adjusted) build_compiler.stage" = actual_stage,
2157 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2158 );
2159 build_compiler.stage = actual_stage;
2160
2161 #[cfg(feature = "tracing")]
2162 let _codegen_backend_span =
2163 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2164 for backend in builder.config.codegen_backends(target_compiler.host) {
2165 if backend == "llvm" {
2166 debug!("llvm codegen backend is already built as part of rustc");
2167 continue; }
2169
2170 if builder.kind == Kind::Check && builder.top_stage == 1 {
2187 continue;
2188 }
2189 builder.ensure(CodegenBackend {
2190 compiler: build_compiler,
2191 target: target_compiler.host,
2192 backend: backend.clone(),
2193 });
2194 }
2195 #[cfg(feature = "tracing")]
2196 drop(_codegen_backend_span);
2197
2198 let stage = target_compiler.stage;
2199 let host = target_compiler.host;
2200 let (host_info, dir_name) = if build_compiler.host == host {
2201 ("".into(), "host".into())
2202 } else {
2203 (format!(" ({host})"), host.to_string())
2204 };
2205 let msg = format!(
2210 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2211 );
2212 builder.info(&msg);
2213
2214 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2216 let proc_macros = builder
2217 .read_stamp_file(&stamp)
2218 .into_iter()
2219 .filter_map(|(path, dependency_type)| {
2220 if dependency_type == DependencyType::Host {
2221 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2222 } else {
2223 None
2224 }
2225 })
2226 .collect::<HashSet<_>>();
2227
2228 let sysroot = builder.sysroot(target_compiler);
2229 let rustc_libdir = builder.rustc_libdir(target_compiler);
2230 t!(fs::create_dir_all(&rustc_libdir));
2231 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2232 for f in builder.read_dir(&src_libdir) {
2233 let filename = f.file_name().into_string().unwrap();
2234
2235 let is_proc_macro = proc_macros.contains(&filename);
2236 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2237
2238 let can_be_rustc_dynamic_dep = if builder
2242 .link_std_into_rustc_driver(target_compiler.host)
2243 && !target_compiler.host.is_windows()
2244 {
2245 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2246 !is_std
2247 } else {
2248 true
2249 };
2250
2251 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2252 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2253 }
2254 }
2255
2256 debug!("copying codegen backends to sysroot");
2257 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2258
2259 if builder.config.lld_enabled {
2260 let lld_wrapper =
2261 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2262 builder,
2263 target_compiler,
2264 ));
2265 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2266 }
2267
2268 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2269 debug!(
2270 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2271 workaround faulty homebrew `strip`s"
2272 );
2273
2274 let src_exe = exe("llvm-objcopy", target_compiler.host);
2281 let dst_exe = exe("rust-objcopy", target_compiler.host);
2282 builder.copy_link(
2283 &libdir_bin.join(src_exe),
2284 &libdir_bin.join(dst_exe),
2285 FileType::Executable,
2286 );
2287 }
2288
2289 if builder.tool_enabled("wasm-component-ld") {
2292 let wasm_component = builder.ensure(
2293 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2294 builder,
2295 target_compiler,
2296 ),
2297 );
2298 builder.copy_link(
2299 &wasm_component.tool_path,
2300 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2301 FileType::Executable,
2302 );
2303 }
2304
2305 maybe_install_llvm_bitcode_linker();
2306
2307 debug!(
2310 "target_compiler.host" = ?target_compiler.host,
2311 ?sysroot,
2312 "ensuring availability of `libLLVM.so` in compiler directory"
2313 );
2314 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2315 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2316
2317 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2319 let rustc = out_dir.join(exe("rustc-main", host));
2320 let bindir = sysroot.join("bin");
2321 t!(fs::create_dir_all(bindir));
2322 let compiler = builder.rustc(target_compiler);
2323 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2324 builder.copy_link(&rustc, &compiler, FileType::Executable);
2325
2326 target_compiler
2327 }
2328}
2329
2330pub fn add_to_sysroot(
2335 builder: &Builder<'_>,
2336 sysroot_dst: &Path,
2337 sysroot_host_dst: &Path,
2338 stamp: &BuildStamp,
2339) {
2340 let self_contained_dst = &sysroot_dst.join("self-contained");
2341 t!(fs::create_dir_all(sysroot_dst));
2342 t!(fs::create_dir_all(sysroot_host_dst));
2343 t!(fs::create_dir_all(self_contained_dst));
2344 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2345 let dst = match dependency_type {
2346 DependencyType::Host => sysroot_host_dst,
2347 DependencyType::Target => sysroot_dst,
2348 DependencyType::TargetSelfContained => self_contained_dst,
2349 };
2350 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2351 }
2352}
2353
2354pub fn run_cargo(
2355 builder: &Builder<'_>,
2356 cargo: Cargo,
2357 tail_args: Vec<String>,
2358 stamp: &BuildStamp,
2359 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2360 is_check: bool,
2361 rlib_only_metadata: bool,
2362) -> Vec<PathBuf> {
2363 let target_root_dir = stamp.path().parent().unwrap();
2365 let target_deps_dir = target_root_dir.join("deps");
2367 let host_root_dir = target_root_dir
2369 .parent()
2370 .unwrap() .parent()
2372 .unwrap() .join(target_root_dir.file_name().unwrap());
2374
2375 let mut deps = Vec::new();
2379 let mut toplevel = Vec::new();
2380 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2381 let (filenames, crate_types) = match msg {
2382 CargoMessage::CompilerArtifact {
2383 filenames,
2384 target: CargoTarget { crate_types },
2385 ..
2386 } => (filenames, crate_types),
2387 _ => return,
2388 };
2389 for filename in filenames {
2390 let mut keep = false;
2392 if filename.ends_with(".lib")
2393 || filename.ends_with(".a")
2394 || is_debug_info(&filename)
2395 || is_dylib(Path::new(&*filename))
2396 {
2397 keep = true;
2399 }
2400 if is_check && filename.ends_with(".rmeta") {
2401 keep = true;
2403 } else if rlib_only_metadata {
2404 if filename.contains("jemalloc_sys")
2405 || filename.contains("rustc_public_bridge")
2406 || filename.contains("rustc_public")
2407 {
2408 keep |= filename.ends_with(".rlib");
2411 } else {
2412 keep |= filename.ends_with(".rmeta");
2416 }
2417 } else {
2418 keep |= filename.ends_with(".rlib");
2420 }
2421
2422 if !keep {
2423 continue;
2424 }
2425
2426 let filename = Path::new(&*filename);
2427
2428 if filename.starts_with(&host_root_dir) {
2431 if crate_types.iter().any(|t| t == "proc-macro") {
2433 deps.push((filename.to_path_buf(), DependencyType::Host));
2434 }
2435 continue;
2436 }
2437
2438 if filename.starts_with(&target_deps_dir) {
2441 deps.push((filename.to_path_buf(), DependencyType::Target));
2442 continue;
2443 }
2444
2445 let expected_len = t!(filename.metadata()).len();
2456 let filename = filename.file_name().unwrap().to_str().unwrap();
2457 let mut parts = filename.splitn(2, '.');
2458 let file_stem = parts.next().unwrap().to_owned();
2459 let extension = parts.next().unwrap().to_owned();
2460
2461 toplevel.push((file_stem, extension, expected_len));
2462 }
2463 });
2464
2465 if !ok {
2466 crate::exit!(1);
2467 }
2468
2469 if builder.config.dry_run() {
2470 return Vec::new();
2471 }
2472
2473 let contents = target_deps_dir
2477 .read_dir()
2478 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2479 .map(|e| t!(e))
2480 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2481 .collect::<Vec<_>>();
2482 for (prefix, extension, expected_len) in toplevel {
2483 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2484 meta.len() == expected_len
2485 && filename
2486 .strip_prefix(&prefix[..])
2487 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2488 .unwrap_or(false)
2489 });
2490 let max = candidates.max_by_key(|&(_, _, metadata)| {
2491 metadata.modified().expect("mtime should be available on all relevant OSes")
2492 });
2493 let path_to_add = match max {
2494 Some(triple) => triple.0.to_str().unwrap(),
2495 None => panic!("no output generated for {prefix:?} {extension:?}"),
2496 };
2497 if is_dylib(Path::new(path_to_add)) {
2498 let candidate = format!("{path_to_add}.lib");
2499 let candidate = PathBuf::from(candidate);
2500 if candidate.exists() {
2501 deps.push((candidate, DependencyType::Target));
2502 }
2503 }
2504 deps.push((path_to_add.into(), DependencyType::Target));
2505 }
2506
2507 deps.extend(additional_target_deps);
2508 deps.sort();
2509 let mut new_contents = Vec::new();
2510 for (dep, dependency_type) in deps.iter() {
2511 new_contents.extend(match *dependency_type {
2512 DependencyType::Host => b"h",
2513 DependencyType::Target => b"t",
2514 DependencyType::TargetSelfContained => b"s",
2515 });
2516 new_contents.extend(dep.to_str().unwrap().as_bytes());
2517 new_contents.extend(b"\0");
2518 }
2519 t!(fs::write(stamp.path(), &new_contents));
2520 deps.into_iter().map(|(d, _)| d).collect()
2521}
2522
2523pub fn stream_cargo(
2524 builder: &Builder<'_>,
2525 cargo: Cargo,
2526 tail_args: Vec<String>,
2527 cb: &mut dyn FnMut(CargoMessage<'_>),
2528) -> bool {
2529 let mut cmd = cargo.into_cmd();
2530
2531 #[cfg(feature = "tracing")]
2532 let _run_span = crate::trace_cmd!(cmd);
2533
2534 let mut message_format = if builder.config.json_output {
2537 String::from("json")
2538 } else {
2539 String::from("json-render-diagnostics")
2540 };
2541 if let Some(s) = &builder.config.rustc_error_format {
2542 message_format.push_str(",json-diagnostic-");
2543 message_format.push_str(s);
2544 }
2545 cmd.arg("--message-format").arg(message_format);
2546
2547 for arg in tail_args {
2548 cmd.arg(arg);
2549 }
2550
2551 builder.verbose(|| println!("running: {cmd:?}"));
2552
2553 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2554
2555 let Some(mut streaming_command) = streaming_command else {
2556 return true;
2557 };
2558
2559 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2563 for line in stdout.lines() {
2564 let line = t!(line);
2565 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2566 Ok(msg) => {
2567 if builder.config.json_output {
2568 println!("{line}");
2570 }
2571 cb(msg)
2572 }
2573 Err(_) => println!("{line}"),
2575 }
2576 }
2577
2578 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2580 if builder.is_verbose() && !status.success() {
2581 eprintln!(
2582 "command did not execute successfully: {cmd:?}\n\
2583 expected success, got: {status}"
2584 );
2585 }
2586
2587 status.success()
2588}
2589
2590#[derive(Deserialize)]
2591pub struct CargoTarget<'a> {
2592 crate_types: Vec<Cow<'a, str>>,
2593}
2594
2595#[derive(Deserialize)]
2596#[serde(tag = "reason", rename_all = "kebab-case")]
2597pub enum CargoMessage<'a> {
2598 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2599 BuildScriptExecuted,
2600 BuildFinished,
2601}
2602
2603pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2604 if target != "x86_64-unknown-linux-gnu"
2608 || !builder.config.is_host_target(target)
2609 || !path.exists()
2610 {
2611 return;
2612 }
2613
2614 let previous_mtime = t!(t!(path.metadata()).modified());
2615 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2616
2617 let file = t!(fs::File::open(path));
2618
2619 t!(file.set_modified(previous_mtime));
2632}
2633
2634pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2636 build_compiler.stage != 0
2637}