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::time::SystemTime;
16use std::{env, fs, str};
17
18use serde_derive::Deserialize;
19#[cfg(feature = "tracing")]
20use tracing::span;
21
22use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags};
23use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
24use crate::core::build_steps::{dist, llvm};
25use crate::core::builder;
26use crate::core::builder::{
27 Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
28};
29use crate::core::config::{
30 CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
31};
32use crate::utils::build_stamp;
33use crate::utils::build_stamp::BuildStamp;
34use crate::utils::exec::command;
35use crate::utils::helpers::{
36 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
37};
38use crate::{
39 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
40 debug, trace,
41};
42
43#[derive(Debug, Clone, PartialEq, Eq, Hash)]
45pub struct Std {
46 pub target: TargetSelection,
47 pub build_compiler: Compiler,
49 crates: Vec<String>,
53 force_recompile: bool,
56 extra_rust_args: &'static [&'static str],
57 is_for_mir_opt_tests: bool,
58}
59
60impl Std {
61 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
62 Self {
63 target,
64 build_compiler,
65 crates: Default::default(),
66 force_recompile: false,
67 extra_rust_args: &[],
68 is_for_mir_opt_tests: false,
69 }
70 }
71
72 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
73 self.force_recompile = force_recompile;
74 self
75 }
76
77 #[expect(clippy::wrong_self_convention)]
78 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
79 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
80 self
81 }
82
83 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
84 self.extra_rust_args = extra_rust_args;
85 self
86 }
87
88 fn copy_extra_objects(
89 &self,
90 builder: &Builder<'_>,
91 compiler: &Compiler,
92 target: TargetSelection,
93 ) -> Vec<(PathBuf, DependencyType)> {
94 let mut deps = Vec::new();
95 if !self.is_for_mir_opt_tests {
96 deps.extend(copy_third_party_objects(builder, compiler, target));
97 deps.extend(copy_self_contained_objects(builder, compiler, target));
98 }
99 deps
100 }
101
102 pub fn should_be_uplifted_from_stage_1(
108 builder: &Builder<'_>,
109 stage: u32,
110 target: TargetSelection,
111 ) -> bool {
112 stage > 1
113 && !builder.config.full_bootstrap
114 && (target == builder.host_target || builder.config.hosts.contains(&target))
124 }
125}
126
127impl Step for Std {
128 type Output = Option<BuildStamp>;
130
131 const DEFAULT: bool = true;
132
133 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
134 run.crate_or_deps("sysroot").path("library")
135 }
136
137 fn make_run(run: RunConfig<'_>) {
138 let crates = std_crates_for_run_make(&run);
139 let builder = run.builder;
140
141 let force_recompile = builder.rust_info().is_managed_git_subrepository()
145 && builder.download_rustc()
146 && builder.config.has_changes_from_upstream(&["library"]);
147
148 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
149 trace!("download_rustc: {}", builder.download_rustc());
150 trace!(force_recompile);
151
152 run.builder.ensure(Std {
153 build_compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
154 target: run.target,
155 crates,
156 force_recompile,
157 extra_rust_args: &[],
158 is_for_mir_opt_tests: false,
159 });
160 }
161
162 fn run(self, builder: &Builder<'_>) -> Self::Output {
168 let target = self.target;
169
170 if self.build_compiler.stage == 0
175 && !(builder.local_rebuild && target != builder.host_target)
176 {
177 let compiler = self.build_compiler;
178 builder.ensure(StdLink::from_std(self, compiler));
179
180 return None;
181 }
182
183 let build_compiler = if builder.download_rustc() && self.force_recompile {
184 builder
187 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
188 } else {
189 self.build_compiler
190 };
191
192 if builder.download_rustc()
195 && builder.config.is_host_target(target)
196 && !self.force_recompile
197 {
198 let sysroot =
199 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
200 cp_rustc_component_to_ci_sysroot(
201 builder,
202 &sysroot,
203 builder.config.ci_rust_std_contents(),
204 );
205 return None;
206 }
207
208 if builder.config.keep_stage.contains(&build_compiler.stage)
209 || builder.config.keep_stage_std.contains(&build_compiler.stage)
210 {
211 trace!(keep_stage = ?builder.config.keep_stage);
212 trace!(keep_stage_std = ?builder.config.keep_stage_std);
213
214 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
215
216 builder.ensure(StartupObjects { compiler: build_compiler, target });
217
218 self.copy_extra_objects(builder, &build_compiler, target);
219
220 builder.ensure(StdLink::from_std(self, build_compiler));
221 return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
222 }
223
224 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
225
226 let stage = build_compiler.stage;
228
229 if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage, target) {
230 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
231 let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
232
233 let msg = if build_compiler_for_std_to_uplift.host == target {
234 format!(
235 "Uplifting library (stage{} -> stage{stage})",
236 build_compiler_for_std_to_uplift.stage
237 )
238 } else {
239 format!(
240 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
241 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
242 )
243 };
244
245 builder.info(&msg);
246
247 self.copy_extra_objects(builder, &build_compiler, target);
250
251 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
252 return stage_1_stamp;
253 }
254
255 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
256
257 let mut cargo = if self.is_for_mir_opt_tests {
261 trace!("building special sysroot for mir-opt tests");
262 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
263 builder,
264 build_compiler,
265 Mode::Std,
266 SourceType::InTree,
267 target,
268 Kind::Check,
269 );
270 cargo.rustflag("-Zalways-encode-mir");
271 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
272 cargo
273 } else {
274 trace!("building regular sysroot");
275 let mut cargo = builder::Cargo::new(
276 builder,
277 build_compiler,
278 Mode::Std,
279 SourceType::InTree,
280 target,
281 Kind::Build,
282 );
283 std_cargo(builder, target, &mut cargo);
284 for krate in &*self.crates {
285 cargo.arg("-p").arg(krate);
286 }
287 cargo
288 };
289
290 if target.is_synthetic() {
292 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
293 }
294 for rustflag in self.extra_rust_args.iter() {
295 cargo.rustflag(rustflag);
296 }
297
298 let _guard = builder.msg(
299 Kind::Build,
300 format_args!("library artifacts{}", crate_description(&self.crates)),
301 Mode::Std,
302 build_compiler,
303 target,
304 );
305
306 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
307 run_cargo(
308 builder,
309 cargo,
310 vec![],
311 &stamp,
312 target_deps,
313 self.is_for_mir_opt_tests, false,
315 );
316
317 builder.ensure(StdLink::from_std(
318 self,
319 builder.compiler(build_compiler.stage, builder.config.host_target),
320 ));
321 Some(stamp)
322 }
323
324 fn metadata(&self) -> Option<StepMetadata> {
325 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
326 }
327}
328
329fn copy_and_stamp(
330 builder: &Builder<'_>,
331 libdir: &Path,
332 sourcedir: &Path,
333 name: &str,
334 target_deps: &mut Vec<(PathBuf, DependencyType)>,
335 dependency_type: DependencyType,
336) {
337 let target = libdir.join(name);
338 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
339
340 target_deps.push((target, dependency_type));
341}
342
343fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
344 let libunwind_path = builder.ensure(llvm::Libunwind { target });
345 let libunwind_source = libunwind_path.join("libunwind.a");
346 let libunwind_target = libdir.join("libunwind.a");
347 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
348 libunwind_target
349}
350
351fn copy_third_party_objects(
353 builder: &Builder<'_>,
354 compiler: &Compiler,
355 target: TargetSelection,
356) -> Vec<(PathBuf, DependencyType)> {
357 let mut target_deps = vec![];
358
359 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
360 target_deps.extend(
363 copy_sanitizers(builder, compiler, target)
364 .into_iter()
365 .map(|d| (d, DependencyType::Target)),
366 );
367 }
368
369 if target == "x86_64-fortanix-unknown-sgx"
370 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
371 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
372 {
373 let libunwind_path =
374 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
375 target_deps.push((libunwind_path, DependencyType::Target));
376 }
377
378 target_deps
379}
380
381fn copy_self_contained_objects(
383 builder: &Builder<'_>,
384 compiler: &Compiler,
385 target: TargetSelection,
386) -> Vec<(PathBuf, DependencyType)> {
387 let libdir_self_contained =
388 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
389 t!(fs::create_dir_all(&libdir_self_contained));
390 let mut target_deps = vec![];
391
392 if target.needs_crt_begin_end() {
400 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
401 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
402 });
403 if !target.starts_with("wasm32") {
404 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
405 copy_and_stamp(
406 builder,
407 &libdir_self_contained,
408 &srcdir,
409 obj,
410 &mut target_deps,
411 DependencyType::TargetSelfContained,
412 );
413 }
414 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
415 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
416 let src = crt_path.join(obj);
417 let target = libdir_self_contained.join(obj);
418 builder.copy_link(&src, &target, FileType::NativeLibrary);
419 target_deps.push((target, DependencyType::TargetSelfContained));
420 }
421 } else {
422 for &obj in &["libc.a", "crt1-command.o"] {
425 copy_and_stamp(
426 builder,
427 &libdir_self_contained,
428 &srcdir,
429 obj,
430 &mut target_deps,
431 DependencyType::TargetSelfContained,
432 );
433 }
434 }
435 if !target.starts_with("s390x") {
436 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
437 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
438 }
439 } else if target.contains("-wasi") {
440 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
441 panic!(
442 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
443 or `$WASI_SDK_PATH` set",
444 target.triple
445 )
446 });
447 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
448 copy_and_stamp(
449 builder,
450 &libdir_self_contained,
451 &srcdir,
452 obj,
453 &mut target_deps,
454 DependencyType::TargetSelfContained,
455 );
456 }
457 } else if target.is_windows_gnu() {
458 for obj in ["crt2.o", "dllcrt2.o"].iter() {
459 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
460 let dst = libdir_self_contained.join(obj);
461 builder.copy_link(&src, &dst, FileType::NativeLibrary);
462 target_deps.push((dst, DependencyType::TargetSelfContained));
463 }
464 }
465
466 target_deps
467}
468
469pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
472 let mut crates = run.make_run_crates(builder::Alias::Library);
473
474 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
483 if target_is_no_std {
484 crates.retain(|c| c == "core" || c == "alloc");
485 }
486 crates
487}
488
489fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
495 if builder.config.llvm_from_ci {
497 builder.config.maybe_download_ci_llvm();
499 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
500 if ci_llvm_compiler_rt.exists() {
501 return ci_llvm_compiler_rt;
502 }
503 }
504
505 builder.require_submodule("src/llvm-project", {
507 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
508 });
509 builder.src.join("src/llvm-project/compiler-rt")
510}
511
512pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
515 if target.contains("apple") && !builder.config.dry_run() {
533 let mut cmd = command(builder.rustc(cargo.compiler()));
537 cmd.arg("--target").arg(target.rustc_target_arg());
538 cmd.arg("--print=deployment-target");
539 let output = cmd.run_capture_stdout(builder).stdout();
540
541 let (env_var, value) = output.split_once('=').unwrap();
542 cargo.env(env_var.trim(), value.trim());
545
546 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
556 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
557 }
558 }
559
560 if let Some(path) = builder.config.profiler_path(target) {
562 cargo.env("LLVM_PROFILER_RT_LIB", path);
563 } else if builder.config.profiler_enabled(target) {
564 let compiler_rt = compiler_rt_for_profiler(builder);
565 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
569 }
570
571 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
585 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
586 cargo.env("LLVM_COMPILER_RT_LIB", path);
587 " compiler-builtins-c"
588 }
589 CompilerBuiltins::BuildLLVMFuncs => {
590 builder.require_submodule(
600 "src/llvm-project",
601 Some(
602 "The `build.optimized-compiler-builtins` config option \
603 requires `compiler-rt` sources from LLVM.",
604 ),
605 );
606 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
607 assert!(compiler_builtins_root.exists());
608 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
611 " compiler-builtins-c"
612 }
613 CompilerBuiltins::BuildRustOnly => "",
614 };
615
616 if !builder.unstable_features() {
619 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
620 }
621
622 let mut features = String::new();
623
624 if builder.no_std(target) == Some(true) {
625 features += " compiler-builtins-mem";
626 if !target.starts_with("bpf") {
627 features.push_str(compiler_builtins_c_feature);
628 }
629
630 cargo
632 .args(["-p", "alloc"])
633 .arg("--manifest-path")
634 .arg(builder.src.join("library/alloc/Cargo.toml"))
635 .arg("--features")
636 .arg(features);
637 } else {
638 features += &builder.std_features(target);
639 features.push_str(compiler_builtins_c_feature);
640
641 cargo
642 .arg("--features")
643 .arg(features)
644 .arg("--manifest-path")
645 .arg(builder.src.join("library/sysroot/Cargo.toml"));
646
647 if target.contains("musl")
650 && let Some(p) = builder.musl_libdir(target)
651 {
652 let root = format!("native={}", p.to_str().unwrap());
653 cargo.rustflag("-L").rustflag(&root);
654 }
655
656 if target.contains("-wasi")
657 && let Some(dir) = builder.wasi_libdir(target)
658 {
659 let root = format!("native={}", dir.to_str().unwrap());
660 cargo.rustflag("-L").rustflag(&root);
661 }
662 }
663
664 cargo.rustflag("-Cembed-bitcode=yes");
670
671 if builder.config.rust_lto == RustcLto::Off {
672 cargo.rustflag("-Clto=off");
673 }
674
675 if target.contains("riscv") {
682 cargo.rustflag("-Cforce-unwind-tables=yes");
683 }
684
685 cargo.rustflag("-Zunstable-options");
688 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
689
690 let html_root =
691 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
692 cargo.rustflag(&html_root);
693 cargo.rustdocflag(&html_root);
694
695 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
696}
697
698#[derive(Debug, Clone, PartialEq, Eq, Hash)]
707pub struct StdLink {
708 pub compiler: Compiler,
709 pub target_compiler: Compiler,
710 pub target: TargetSelection,
711 crates: Vec<String>,
713 force_recompile: bool,
715}
716
717impl StdLink {
718 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
719 Self {
720 compiler: host_compiler,
721 target_compiler: std.build_compiler,
722 target: std.target,
723 crates: std.crates,
724 force_recompile: std.force_recompile,
725 }
726 }
727}
728
729impl Step for StdLink {
730 type Output = ();
731
732 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
733 run.never()
734 }
735
736 fn run(self, builder: &Builder<'_>) {
745 let compiler = self.compiler;
746 let target_compiler = self.target_compiler;
747 let target = self.target;
748
749 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
751 let lib = builder.sysroot_libdir_relative(self.compiler);
753 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
754 compiler: self.compiler,
755 force_recompile: self.force_recompile,
756 });
757 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
758 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
759 (libdir, hostdir)
760 } else {
761 let libdir = builder.sysroot_target_libdir(target_compiler, target);
762 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
763 (libdir, hostdir)
764 };
765
766 let is_downloaded_beta_stage0 = builder
767 .build
768 .config
769 .initial_rustc
770 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
771
772 if compiler.stage == 0 && is_downloaded_beta_stage0 {
776 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
778
779 let host = compiler.host;
780 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
781 let sysroot_bin_dir = sysroot.join("bin");
782 t!(fs::create_dir_all(&sysroot_bin_dir));
783 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
784
785 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
786 t!(fs::create_dir_all(sysroot.join("lib")));
787 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
788
789 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
791 t!(fs::create_dir_all(&sysroot_codegen_backends));
792 let stage0_codegen_backends = builder
793 .out
794 .join(host)
795 .join("stage0/lib/rustlib")
796 .join(host)
797 .join("codegen-backends");
798 if stage0_codegen_backends.exists() {
799 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
800 }
801 } else if compiler.stage == 0 {
802 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
803
804 if builder.local_rebuild {
805 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
809 }
810
811 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
812 } else {
813 if builder.download_rustc() {
814 let _ = fs::remove_dir_all(&libdir);
816 let _ = fs::remove_dir_all(&hostdir);
817 }
818
819 add_to_sysroot(
820 builder,
821 &libdir,
822 &hostdir,
823 &build_stamp::libstd_stamp(builder, compiler, target),
824 );
825 }
826 }
827}
828
829fn copy_sanitizers(
831 builder: &Builder<'_>,
832 compiler: &Compiler,
833 target: TargetSelection,
834) -> Vec<PathBuf> {
835 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
836
837 if builder.config.dry_run() {
838 return Vec::new();
839 }
840
841 let mut target_deps = Vec::new();
842 let libdir = builder.sysroot_target_libdir(*compiler, target);
843
844 for runtime in &runtimes {
845 let dst = libdir.join(&runtime.name);
846 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
847
848 if target == "x86_64-apple-darwin"
852 || target == "aarch64-apple-darwin"
853 || target == "aarch64-apple-ios"
854 || target == "aarch64-apple-ios-sim"
855 || target == "x86_64-apple-ios"
856 {
857 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
859 apple_darwin_sign_file(builder, &dst);
862 }
863
864 target_deps.push(dst);
865 }
866
867 target_deps
868}
869
870fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
871 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
872}
873
874fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
875 command("codesign")
876 .arg("-f") .arg("-s")
878 .arg("-")
879 .arg(file_path)
880 .run(builder);
881}
882
883#[derive(Debug, Clone, PartialEq, Eq, Hash)]
884pub struct StartupObjects {
885 pub compiler: Compiler,
886 pub target: TargetSelection,
887}
888
889impl Step for StartupObjects {
890 type Output = Vec<(PathBuf, DependencyType)>;
891
892 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
893 run.path("library/rtstartup")
894 }
895
896 fn make_run(run: RunConfig<'_>) {
897 run.builder.ensure(StartupObjects {
898 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
899 target: run.target,
900 });
901 }
902
903 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
910 let for_compiler = self.compiler;
911 let target = self.target;
912 if !target.is_windows_gnu() {
913 return vec![];
914 }
915
916 let mut target_deps = vec![];
917
918 let src_dir = &builder.src.join("library").join("rtstartup");
919 let dst_dir = &builder.native_dir(target).join("rtstartup");
920 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
921 t!(fs::create_dir_all(dst_dir));
922
923 for file in &["rsbegin", "rsend"] {
924 let src_file = &src_dir.join(file.to_string() + ".rs");
925 let dst_file = &dst_dir.join(file.to_string() + ".o");
926 if !up_to_date(src_file, dst_file) {
927 let mut cmd = command(&builder.initial_rustc);
928 cmd.env("RUSTC_BOOTSTRAP", "1");
929 if !builder.local_rebuild {
930 cmd.arg("--cfg").arg("bootstrap");
932 }
933 cmd.arg("--target")
934 .arg(target.rustc_target_arg())
935 .arg("--emit=obj")
936 .arg("-o")
937 .arg(dst_file)
938 .arg(src_file)
939 .run(builder);
940 }
941
942 let obj = sysroot_dir.join((*file).to_string() + ".o");
943 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
944 target_deps.push((obj, DependencyType::Target));
945 }
946
947 target_deps
948 }
949}
950
951fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
952 let ci_rustc_dir = builder.config.ci_rustc_dir();
953
954 for file in contents {
955 let src = ci_rustc_dir.join(&file);
956 let dst = sysroot.join(file);
957 if src.is_dir() {
958 t!(fs::create_dir_all(dst));
959 } else {
960 builder.copy_link(&src, &dst, FileType::Regular);
961 }
962 }
963}
964
965#[derive(Clone, Debug)]
967pub struct BuiltRustc {
968 pub build_compiler: Compiler,
972}
973
974#[derive(Debug, Clone, PartialEq, Eq, Hash)]
981pub struct Rustc {
982 pub target: TargetSelection,
984 pub build_compiler: Compiler,
986 crates: Vec<String>,
992}
993
994impl Rustc {
995 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
996 Self { target, build_compiler, crates: Default::default() }
997 }
998}
999
1000impl Step for Rustc {
1001 type Output = BuiltRustc;
1002
1003 const IS_HOST: bool = true;
1004 const DEFAULT: bool = false;
1005
1006 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1007 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1008 for (i, krate) in crates.iter().enumerate() {
1009 if krate.name == "rustc-main" {
1012 crates.swap_remove(i);
1013 break;
1014 }
1015 }
1016 run.crates(crates)
1017 }
1018
1019 fn make_run(run: RunConfig<'_>) {
1020 if run.builder.paths == vec![PathBuf::from("compiler")] {
1023 return;
1024 }
1025
1026 let crates = run.cargo_crates_in_set();
1027 run.builder.ensure(Rustc {
1028 build_compiler: run
1029 .builder
1030 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1031 target: run.target,
1032 crates,
1033 });
1034 }
1035
1036 fn run(self, builder: &Builder<'_>) -> Self::Output {
1042 let build_compiler = self.build_compiler;
1043 let target = self.target;
1044
1045 if builder.download_rustc() && build_compiler.stage != 0 {
1048 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1049
1050 let sysroot =
1051 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1052 cp_rustc_component_to_ci_sysroot(
1053 builder,
1054 &sysroot,
1055 builder.config.ci_rustc_dev_contents(),
1056 );
1057 return BuiltRustc { build_compiler };
1058 }
1059
1060 builder.std(build_compiler, target);
1063
1064 if builder.config.keep_stage.contains(&build_compiler.stage) {
1065 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1066
1067 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1068 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1069 builder.ensure(RustcLink::from_rustc(self));
1070
1071 return BuiltRustc { build_compiler };
1072 }
1073
1074 let stage = build_compiler.stage + 1;
1076
1077 if build_compiler.stage >= 2
1082 && !builder.config.full_bootstrap
1083 && target == builder.host_target
1084 {
1085 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1089
1090 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1091 builder.info(&msg);
1092
1093 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1097 uplift_build_compiler,
1099 build_compiler,
1101 target,
1102 self.crates,
1103 ));
1104
1105 return BuiltRustc { build_compiler: uplift_build_compiler };
1108 }
1109
1110 builder.std(
1116 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1117 builder.config.host_target,
1118 );
1119
1120 let mut cargo = builder::Cargo::new(
1121 builder,
1122 build_compiler,
1123 Mode::Rustc,
1124 SourceType::InTree,
1125 target,
1126 Kind::Build,
1127 );
1128
1129 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1130
1131 for krate in &*self.crates {
1135 cargo.arg("-p").arg(krate);
1136 }
1137
1138 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1139 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1141 }
1142
1143 let _guard = builder.msg(
1144 Kind::Build,
1145 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1146 Mode::Rustc,
1147 build_compiler,
1148 target,
1149 );
1150 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1151 run_cargo(
1152 builder,
1153 cargo,
1154 vec![],
1155 &stamp,
1156 vec![],
1157 false,
1158 true, );
1160
1161 let target_root_dir = stamp.path().parent().unwrap();
1162 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1168 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1169 {
1170 let rustc_driver = target_root_dir.join("librustc_driver.so");
1171 strip_debug(builder, target, &rustc_driver);
1172 }
1173
1174 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1175 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1178 }
1179
1180 builder.ensure(RustcLink::from_rustc(self));
1181 BuiltRustc { build_compiler }
1182 }
1183
1184 fn metadata(&self) -> Option<StepMetadata> {
1185 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1186 }
1187}
1188
1189pub fn rustc_cargo(
1190 builder: &Builder<'_>,
1191 cargo: &mut Cargo,
1192 target: TargetSelection,
1193 build_compiler: &Compiler,
1194 crates: &[String],
1195) {
1196 cargo
1197 .arg("--features")
1198 .arg(builder.rustc_features(builder.kind, target, crates))
1199 .arg("--manifest-path")
1200 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1201
1202 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1203
1204 cargo.rustflag("-Zon-broken-pipe=kill");
1218
1219 if builder.config.llvm_enzyme {
1222 let arch = builder.build.host_target;
1223 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1224 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1225
1226 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1227 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1228 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1229 }
1230 }
1231
1232 if builder.build.config.lld_mode.is_used() {
1237 cargo.rustflag("-Zdefault-visibility=protected");
1238 }
1239
1240 if is_lto_stage(build_compiler) {
1241 match builder.config.rust_lto {
1242 RustcLto::Thin | RustcLto::Fat => {
1243 cargo.rustflag("-Zdylib-lto");
1246 let lto_type = match builder.config.rust_lto {
1250 RustcLto::Thin => "thin",
1251 RustcLto::Fat => "fat",
1252 _ => unreachable!(),
1253 };
1254 cargo.rustflag(&format!("-Clto={lto_type}"));
1255 cargo.rustflag("-Cembed-bitcode=yes");
1256 }
1257 RustcLto::ThinLocal => { }
1258 RustcLto::Off => {
1259 cargo.rustflag("-Clto=off");
1260 }
1261 }
1262 } else if builder.config.rust_lto == RustcLto::Off {
1263 cargo.rustflag("-Clto=off");
1264 }
1265
1266 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1274 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1275 }
1276
1277 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1278 panic!("Cannot use and generate PGO profiles at the same time");
1279 }
1280 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1281 if build_compiler.stage == 1 {
1282 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1283 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1286 true
1287 } else {
1288 false
1289 }
1290 } else if let Some(path) = &builder.config.rust_profile_use {
1291 if build_compiler.stage == 1 {
1292 cargo.rustflag(&format!("-Cprofile-use={path}"));
1293 if builder.is_verbose() {
1294 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1295 }
1296 true
1297 } else {
1298 false
1299 }
1300 } else {
1301 false
1302 };
1303 if is_collecting {
1304 cargo.rustflag(&format!(
1306 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1307 builder.config.src.components().count()
1308 ));
1309 }
1310
1311 if let Some(ref ccache) = builder.config.ccache
1316 && build_compiler.stage == 0
1317 && !builder.config.incremental
1318 {
1319 cargo.env("RUSTC_WRAPPER", ccache);
1320 }
1321
1322 rustc_cargo_env(builder, cargo, target);
1323}
1324
1325pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1326 cargo
1329 .env("CFG_RELEASE", builder.rust_release())
1330 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1331 .env("CFG_VERSION", builder.rust_version());
1332
1333 if builder.config.omit_git_hash {
1337 cargo.env("CFG_OMIT_GIT_HASH", "1");
1338 }
1339
1340 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1341
1342 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1343 let target_config = builder.config.target_config.get(&target);
1344
1345 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1346
1347 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1348 cargo.env("CFG_VER_DATE", ver_date);
1349 }
1350 if let Some(ref ver_hash) = builder.rust_info().sha() {
1351 cargo.env("CFG_VER_HASH", ver_hash);
1352 }
1353 if !builder.unstable_features() {
1354 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1355 }
1356
1357 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1360 cargo.env("CFG_DEFAULT_LINKER", s);
1361 } else if let Some(ref s) = builder.config.rustc_default_linker {
1362 cargo.env("CFG_DEFAULT_LINKER", s);
1363 }
1364
1365 if builder.config.lld_enabled {
1367 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1368 }
1369
1370 if builder.config.rust_verify_llvm_ir {
1371 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1372 }
1373
1374 if builder.config.llvm_enzyme {
1375 cargo.rustflag("--cfg=llvm_enzyme");
1376 }
1377
1378 if builder.config.llvm_enabled(target) {
1390 let building_llvm_is_expensive =
1391 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1392 .should_build();
1393
1394 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1395 if !skip_llvm {
1396 rustc_llvm_env(builder, cargo, target)
1397 }
1398 }
1399
1400 if builder.config.jemalloc(target)
1404 && target.starts_with("aarch64")
1405 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1406 {
1407 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1408 }
1409}
1410
1411fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1417 if builder.config.is_rust_llvm(target) {
1418 cargo.env("LLVM_RUSTLLVM", "1");
1419 }
1420 if builder.config.llvm_enzyme {
1421 cargo.env("LLVM_ENZYME", "1");
1422 }
1423 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1424 cargo.env("LLVM_CONFIG", &host_llvm_config);
1425
1426 let mut llvm_linker_flags = String::new();
1436 if builder.config.llvm_profile_generate
1437 && target.is_msvc()
1438 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1439 {
1440 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1442 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1443 }
1444
1445 if let Some(ref s) = builder.config.llvm_ldflags {
1447 if !llvm_linker_flags.is_empty() {
1448 llvm_linker_flags.push(' ');
1449 }
1450 llvm_linker_flags.push_str(s);
1451 }
1452
1453 if !llvm_linker_flags.is_empty() {
1455 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1456 }
1457
1458 if builder.config.llvm_static_stdcpp
1461 && !target.contains("freebsd")
1462 && !target.is_msvc()
1463 && !target.contains("apple")
1464 && !target.contains("solaris")
1465 {
1466 let libstdcxx_name =
1467 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1468 let file = compiler_file(
1469 builder,
1470 &builder.cxx(target).unwrap(),
1471 target,
1472 CLang::Cxx,
1473 libstdcxx_name,
1474 );
1475 cargo.env("LLVM_STATIC_STDCPP", file);
1476 }
1477 if builder.llvm_link_shared() {
1478 cargo.env("LLVM_LINK_SHARED", "1");
1479 }
1480 if builder.config.llvm_use_libcxx {
1481 cargo.env("LLVM_USE_LIBCXX", "1");
1482 }
1483 if builder.config.llvm_assertions {
1484 cargo.env("LLVM_ASSERTIONS", "1");
1485 }
1486}
1487
1488#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1501struct RustcLink {
1502 build_compiler: Compiler,
1504 sysroot_compiler: Compiler,
1507 target: TargetSelection,
1508 crates: Vec<String>,
1510}
1511
1512impl RustcLink {
1513 fn from_rustc(rustc: Rustc) -> Self {
1516 Self {
1517 build_compiler: rustc.build_compiler,
1518 sysroot_compiler: rustc.build_compiler,
1519 target: rustc.target,
1520 crates: rustc.crates,
1521 }
1522 }
1523
1524 fn from_build_compiler_and_sysroot(
1526 build_compiler: Compiler,
1527 sysroot_compiler: Compiler,
1528 target: TargetSelection,
1529 crates: Vec<String>,
1530 ) -> Self {
1531 Self { build_compiler, sysroot_compiler, target, crates }
1532 }
1533}
1534
1535impl Step for RustcLink {
1536 type Output = ();
1537
1538 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1539 run.never()
1540 }
1541
1542 fn run(self, builder: &Builder<'_>) {
1544 let build_compiler = self.build_compiler;
1545 let sysroot_compiler = self.sysroot_compiler;
1546 let target = self.target;
1547 add_to_sysroot(
1548 builder,
1549 &builder.sysroot_target_libdir(sysroot_compiler, target),
1550 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1551 &build_stamp::librustc_stamp(builder, build_compiler, target),
1552 );
1553 }
1554}
1555
1556#[derive(Clone)]
1559pub struct GccCodegenBackendOutput {
1560 stamp: BuildStamp,
1561 gcc: GccOutput,
1562}
1563
1564#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1565pub struct GccCodegenBackend {
1566 compilers: RustcPrivateCompilers,
1567}
1568
1569impl Step for GccCodegenBackend {
1570 type Output = GccCodegenBackendOutput;
1571
1572 const IS_HOST: bool = true;
1573
1574 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1575 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1576 }
1577
1578 fn make_run(run: RunConfig<'_>) {
1579 run.builder.ensure(GccCodegenBackend {
1580 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1581 });
1582 }
1583
1584 fn run(self, builder: &Builder<'_>) -> Self::Output {
1585 let target = self.compilers.target();
1586 let build_compiler = self.compilers.build_compiler();
1587
1588 let stamp = build_stamp::codegen_backend_stamp(
1589 builder,
1590 build_compiler,
1591 target,
1592 &CodegenBackendKind::Gcc,
1593 );
1594
1595 let gcc = builder.ensure(Gcc { target });
1596
1597 if builder.config.keep_stage.contains(&build_compiler.stage) {
1598 trace!("`keep-stage` requested");
1599 builder.info(
1600 "WARNING: Using a potentially old codegen backend. \
1601 This may not behave well.",
1602 );
1603 return GccCodegenBackendOutput { stamp, gcc };
1606 }
1607
1608 let mut cargo = builder::Cargo::new(
1609 builder,
1610 build_compiler,
1611 Mode::Codegen,
1612 SourceType::InTree,
1613 target,
1614 Kind::Build,
1615 );
1616 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1617 rustc_cargo_env(builder, &mut cargo, target);
1618
1619 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1620
1621 let _guard =
1622 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1623 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1624
1625 GccCodegenBackendOutput {
1626 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1627 gcc,
1628 }
1629 }
1630
1631 fn metadata(&self) -> Option<StepMetadata> {
1632 Some(
1633 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1634 .built_by(self.compilers.build_compiler()),
1635 )
1636 }
1637}
1638
1639#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1640pub struct CraneliftCodegenBackend {
1641 pub compilers: RustcPrivateCompilers,
1642}
1643
1644impl Step for CraneliftCodegenBackend {
1645 type Output = BuildStamp;
1646 const IS_HOST: bool = true;
1647
1648 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1649 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1650 }
1651
1652 fn make_run(run: RunConfig<'_>) {
1653 run.builder.ensure(CraneliftCodegenBackend {
1654 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1655 });
1656 }
1657
1658 fn run(self, builder: &Builder<'_>) -> Self::Output {
1659 let target = self.compilers.target();
1660 let build_compiler = self.compilers.build_compiler();
1661
1662 let stamp = build_stamp::codegen_backend_stamp(
1663 builder,
1664 build_compiler,
1665 target,
1666 &CodegenBackendKind::Cranelift,
1667 );
1668
1669 if builder.config.keep_stage.contains(&build_compiler.stage) {
1670 trace!("`keep-stage` requested");
1671 builder.info(
1672 "WARNING: Using a potentially old codegen backend. \
1673 This may not behave well.",
1674 );
1675 return stamp;
1678 }
1679
1680 let mut cargo = builder::Cargo::new(
1681 builder,
1682 build_compiler,
1683 Mode::Codegen,
1684 SourceType::InTree,
1685 target,
1686 Kind::Build,
1687 );
1688 cargo
1689 .arg("--manifest-path")
1690 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1691 rustc_cargo_env(builder, &mut cargo, target);
1692
1693 let _guard = builder.msg(
1694 Kind::Build,
1695 "codegen backend cranelift",
1696 Mode::Codegen,
1697 build_compiler,
1698 target,
1699 );
1700 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1701 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1702 }
1703
1704 fn metadata(&self) -> Option<StepMetadata> {
1705 Some(
1706 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1707 .built_by(self.compilers.build_compiler()),
1708 )
1709 }
1710}
1711
1712fn write_codegen_backend_stamp(
1714 mut stamp: BuildStamp,
1715 files: Vec<PathBuf>,
1716 dry_run: bool,
1717) -> BuildStamp {
1718 if dry_run {
1719 return stamp;
1720 }
1721
1722 let mut files = files.into_iter().filter(|f| {
1723 let filename = f.file_name().unwrap().to_str().unwrap();
1724 is_dylib(f) && filename.contains("rustc_codegen_")
1725 });
1726 let codegen_backend = match files.next() {
1727 Some(f) => f,
1728 None => panic!("no dylibs built for codegen backend?"),
1729 };
1730 if let Some(f) = files.next() {
1731 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1732 }
1733
1734 let codegen_backend = codegen_backend.to_str().unwrap();
1735 stamp = stamp.add_stamp(codegen_backend);
1736 t!(stamp.write());
1737 stamp
1738}
1739
1740fn copy_codegen_backends_to_sysroot(
1747 builder: &Builder<'_>,
1748 stamp: BuildStamp,
1749 target_compiler: Compiler,
1750) {
1751 let dst = builder.sysroot_codegen_backends(target_compiler);
1760 t!(fs::create_dir_all(&dst), dst);
1761
1762 if builder.config.dry_run() {
1763 return;
1764 }
1765
1766 if stamp.path().exists() {
1767 let file = get_codegen_backend_file(&stamp);
1768 builder.copy_link(
1769 &file,
1770 &dst.join(normalize_codegen_backend_name(builder, &file)),
1771 FileType::NativeLibrary,
1772 );
1773 }
1774}
1775
1776pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1778 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1779}
1780
1781pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1783 let filename = path.file_name().unwrap().to_str().unwrap();
1784 let dash = filename.find('-').unwrap();
1787 let dot = filename.find('.').unwrap();
1788 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1789}
1790
1791pub fn compiler_file(
1792 builder: &Builder<'_>,
1793 compiler: &Path,
1794 target: TargetSelection,
1795 c: CLang,
1796 file: &str,
1797) -> PathBuf {
1798 if builder.config.dry_run() {
1799 return PathBuf::new();
1800 }
1801 let mut cmd = command(compiler);
1802 cmd.args(builder.cc_handled_clags(target, c));
1803 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1804 cmd.arg(format!("-print-file-name={file}"));
1805 let out = cmd.run_capture_stdout(builder).stdout();
1806 PathBuf::from(out.trim())
1807}
1808
1809#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1810pub struct Sysroot {
1811 pub compiler: Compiler,
1812 force_recompile: bool,
1814}
1815
1816impl Sysroot {
1817 pub(crate) fn new(compiler: Compiler) -> Self {
1818 Sysroot { compiler, force_recompile: false }
1819 }
1820}
1821
1822impl Step for Sysroot {
1823 type Output = PathBuf;
1824
1825 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1826 run.never()
1827 }
1828
1829 fn run(self, builder: &Builder<'_>) -> PathBuf {
1833 let compiler = self.compiler;
1834 let host_dir = builder.out.join(compiler.host);
1835
1836 let sysroot_dir = |stage| {
1837 if stage == 0 {
1838 host_dir.join("stage0-sysroot")
1839 } else if self.force_recompile && stage == compiler.stage {
1840 host_dir.join(format!("stage{stage}-test-sysroot"))
1841 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1842 host_dir.join("ci-rustc-sysroot")
1843 } else {
1844 host_dir.join(format!("stage{stage}"))
1845 }
1846 };
1847 let sysroot = sysroot_dir(compiler.stage);
1848 trace!(stage = ?compiler.stage, ?sysroot);
1849
1850 builder
1851 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1852 let _ = fs::remove_dir_all(&sysroot);
1853 t!(fs::create_dir_all(&sysroot));
1854
1855 if compiler.stage == 0 {
1862 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1863 }
1864
1865 if builder.download_rustc() && compiler.stage != 0 {
1867 assert_eq!(
1868 builder.config.host_target, compiler.host,
1869 "Cross-compiling is not yet supported with `download-rustc`",
1870 );
1871
1872 for stage in 0..=2 {
1874 if stage != compiler.stage {
1875 let dir = sysroot_dir(stage);
1876 if !dir.ends_with("ci-rustc-sysroot") {
1877 let _ = fs::remove_dir_all(dir);
1878 }
1879 }
1880 }
1881
1882 let mut filtered_files = Vec::new();
1892 let mut add_filtered_files = |suffix, contents| {
1893 for path in contents {
1894 let path = Path::new(&path);
1895 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1896 filtered_files.push(path.file_name().unwrap().to_owned());
1897 }
1898 }
1899 };
1900 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1901 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1902 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1905
1906 let filtered_extensions = [
1907 OsStr::new("rmeta"),
1908 OsStr::new("rlib"),
1909 OsStr::new(std::env::consts::DLL_EXTENSION),
1911 ];
1912 let ci_rustc_dir = builder.config.ci_rustc_dir();
1913 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1914 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1915 return true;
1916 }
1917 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1918 return true;
1919 }
1920 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1921 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1922 false
1923 } else {
1924 true
1925 }
1926 });
1927 }
1928
1929 if compiler.stage != 0 {
1935 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1936 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1937 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1938 if let Err(e) =
1939 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1940 {
1941 eprintln!(
1942 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1943 sysroot_lib_rustlib_src_rust.display(),
1944 builder.src.display(),
1945 e,
1946 );
1947 if builder.config.rust_remap_debuginfo {
1948 eprintln!(
1949 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1950 sysroot_lib_rustlib_src_rust.display(),
1951 );
1952 }
1953 build_helper::exit!(1);
1954 }
1955 }
1956
1957 if !builder.download_rustc() {
1959 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1960 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1961 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1962 if let Err(e) =
1963 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1964 {
1965 eprintln!(
1966 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1967 sysroot_lib_rustlib_rustcsrc_rust.display(),
1968 builder.src.display(),
1969 e,
1970 );
1971 build_helper::exit!(1);
1972 }
1973 }
1974
1975 sysroot
1976 }
1977}
1978
1979#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1986pub struct Assemble {
1987 pub target_compiler: Compiler,
1992}
1993
1994impl Step for Assemble {
1995 type Output = Compiler;
1996 const IS_HOST: bool = true;
1997
1998 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1999 run.path("compiler/rustc").path("compiler")
2000 }
2001
2002 fn make_run(run: RunConfig<'_>) {
2003 run.builder.ensure(Assemble {
2004 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2005 });
2006 }
2007
2008 fn run(self, builder: &Builder<'_>) -> Compiler {
2009 let target_compiler = self.target_compiler;
2010
2011 if target_compiler.stage == 0 {
2012 trace!("stage 0 build compiler is always available, simply returning");
2013 assert_eq!(
2014 builder.config.host_target, target_compiler.host,
2015 "Cannot obtain compiler for non-native build triple at stage 0"
2016 );
2017 return target_compiler;
2019 }
2020
2021 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2024 let libdir_bin = libdir.parent().unwrap().join("bin");
2025 t!(fs::create_dir_all(&libdir_bin));
2026
2027 if builder.config.llvm_enabled(target_compiler.host) {
2028 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2029
2030 let target = target_compiler.host;
2031 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2032 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2033 trace!("LLVM tools enabled");
2034
2035 let host_llvm_bin_dir = command(&host_llvm_config)
2036 .arg("--bindir")
2037 .cached()
2038 .run_capture_stdout(builder)
2039 .stdout()
2040 .trim()
2041 .to_string();
2042
2043 let llvm_bin_dir = if target == builder.host_target {
2044 PathBuf::from(host_llvm_bin_dir)
2045 } else {
2046 let external_llvm_config = builder
2049 .config
2050 .target_config
2051 .get(&target)
2052 .and_then(|t| t.llvm_config.clone());
2053 if let Some(external_llvm_config) = external_llvm_config {
2054 external_llvm_config.parent().unwrap().to_path_buf()
2057 } else {
2058 let host_llvm_out = builder.llvm_out(builder.host_target);
2062 let target_llvm_out = builder.llvm_out(target);
2063 if let Ok(relative_path) =
2064 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2065 {
2066 target_llvm_out.join(relative_path)
2067 } else {
2068 PathBuf::from(
2071 host_llvm_bin_dir
2072 .replace(&*builder.host_target.triple, &target.triple),
2073 )
2074 }
2075 }
2076 };
2077
2078 #[cfg(feature = "tracing")]
2085 let _llvm_tools_span =
2086 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2087 .entered();
2088 for tool in LLVM_TOOLS {
2089 trace!("installing `{tool}`");
2090 let tool_exe = exe(tool, target_compiler.host);
2091 let src_path = llvm_bin_dir.join(&tool_exe);
2092
2093 if !src_path.exists() && builder.config.llvm_from_ci {
2095 eprintln!("{} does not exist; skipping copy", src_path.display());
2096 continue;
2097 }
2098
2099 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2106 }
2107 }
2108 }
2109
2110 let maybe_install_llvm_bitcode_linker = || {
2111 if builder.config.llvm_bitcode_linker_enabled {
2112 trace!("llvm-bitcode-linker enabled, installing");
2113 let llvm_bitcode_linker = builder.ensure(
2114 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2115 builder,
2116 target_compiler,
2117 ),
2118 );
2119
2120 let bindir_self_contained = builder
2122 .sysroot(target_compiler)
2123 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2124 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2125
2126 t!(fs::create_dir_all(&bindir_self_contained));
2127 builder.copy_link(
2128 &llvm_bitcode_linker.tool_path,
2129 &bindir_self_contained.join(tool_exe),
2130 FileType::Executable,
2131 );
2132 }
2133 };
2134
2135 if builder.download_rustc() {
2137 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2138
2139 builder.std(target_compiler, target_compiler.host);
2140 let sysroot =
2141 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2142 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2145 if target_compiler.stage == builder.top_stage {
2147 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2148 }
2149
2150 maybe_install_llvm_bitcode_linker();
2153
2154 return target_compiler;
2155 }
2156
2157 debug!(
2171 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2172 target_compiler.stage - 1,
2173 builder.config.host_target,
2174 );
2175 let build_compiler =
2176 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2177
2178 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2180 debug!("`llvm_enzyme` requested");
2181 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2182 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2183 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2184 let lib_ext = std::env::consts::DLL_EXTENSION;
2185 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2186 let src_lib =
2187 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2188 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2189 let target_libdir =
2190 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2191 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2192 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2193 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2194 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2195 }
2196 }
2197
2198 debug!(
2201 ?build_compiler,
2202 "target_compiler.host" = ?target_compiler.host,
2203 "building compiler libraries to link to"
2204 );
2205
2206 let BuiltRustc { build_compiler } =
2208 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2209
2210 let stage = target_compiler.stage;
2211 let host = target_compiler.host;
2212 let (host_info, dir_name) = if build_compiler.host == host {
2213 ("".into(), "host".into())
2214 } else {
2215 (format!(" ({host})"), host.to_string())
2216 };
2217 let msg = format!(
2222 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2223 );
2224 builder.info(&msg);
2225
2226 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2228 let proc_macros = builder
2229 .read_stamp_file(&stamp)
2230 .into_iter()
2231 .filter_map(|(path, dependency_type)| {
2232 if dependency_type == DependencyType::Host {
2233 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2234 } else {
2235 None
2236 }
2237 })
2238 .collect::<HashSet<_>>();
2239
2240 let sysroot = builder.sysroot(target_compiler);
2241 let rustc_libdir = builder.rustc_libdir(target_compiler);
2242 t!(fs::create_dir_all(&rustc_libdir));
2243 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2244 for f in builder.read_dir(&src_libdir) {
2245 let filename = f.file_name().into_string().unwrap();
2246
2247 let is_proc_macro = proc_macros.contains(&filename);
2248 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2249
2250 let can_be_rustc_dynamic_dep = if builder
2254 .link_std_into_rustc_driver(target_compiler.host)
2255 && !target_compiler.host.is_windows()
2256 {
2257 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2258 !is_std
2259 } else {
2260 true
2261 };
2262
2263 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2264 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2265 }
2266 }
2267
2268 {
2269 #[cfg(feature = "tracing")]
2270 let _codegen_backend_span =
2271 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2272
2273 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2274 if builder.kind == Kind::Check && builder.top_stage == 1 {
2291 continue;
2292 }
2293
2294 let prepare_compilers = || {
2295 RustcPrivateCompilers::from_build_and_target_compiler(
2296 build_compiler,
2297 target_compiler,
2298 )
2299 };
2300
2301 match backend {
2302 CodegenBackendKind::Cranelift => {
2303 let stamp = builder
2304 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2305 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2306 }
2307 CodegenBackendKind::Gcc => {
2308 let output =
2309 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2310 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2311 output.gcc.install_to(builder, &rustc_libdir);
2314 }
2315 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2316 }
2317 }
2318 }
2319
2320 if builder.config.lld_enabled {
2321 let lld_wrapper =
2322 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2323 builder,
2324 target_compiler,
2325 ));
2326 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2327 }
2328
2329 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2330 debug!(
2331 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2332 workaround faulty homebrew `strip`s"
2333 );
2334
2335 let src_exe = exe("llvm-objcopy", target_compiler.host);
2342 let dst_exe = exe("rust-objcopy", target_compiler.host);
2343 builder.copy_link(
2344 &libdir_bin.join(src_exe),
2345 &libdir_bin.join(dst_exe),
2346 FileType::Executable,
2347 );
2348 }
2349
2350 if builder.tool_enabled("wasm-component-ld") {
2353 let wasm_component = builder.ensure(
2354 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2355 builder,
2356 target_compiler,
2357 ),
2358 );
2359 builder.copy_link(
2360 &wasm_component.tool_path,
2361 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2362 FileType::Executable,
2363 );
2364 }
2365
2366 maybe_install_llvm_bitcode_linker();
2367
2368 debug!(
2371 "target_compiler.host" = ?target_compiler.host,
2372 ?sysroot,
2373 "ensuring availability of `libLLVM.so` in compiler directory"
2374 );
2375 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2376 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2377
2378 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2380 let rustc = out_dir.join(exe("rustc-main", host));
2381 let bindir = sysroot.join("bin");
2382 t!(fs::create_dir_all(bindir));
2383 let compiler = builder.rustc(target_compiler);
2384 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2385 builder.copy_link(&rustc, &compiler, FileType::Executable);
2386
2387 target_compiler
2388 }
2389}
2390
2391#[track_caller]
2396pub fn add_to_sysroot(
2397 builder: &Builder<'_>,
2398 sysroot_dst: &Path,
2399 sysroot_host_dst: &Path,
2400 stamp: &BuildStamp,
2401) {
2402 let self_contained_dst = &sysroot_dst.join("self-contained");
2403 t!(fs::create_dir_all(sysroot_dst));
2404 t!(fs::create_dir_all(sysroot_host_dst));
2405 t!(fs::create_dir_all(self_contained_dst));
2406 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2407 let dst = match dependency_type {
2408 DependencyType::Host => sysroot_host_dst,
2409 DependencyType::Target => sysroot_dst,
2410 DependencyType::TargetSelfContained => self_contained_dst,
2411 };
2412 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2413 }
2414}
2415
2416pub fn run_cargo(
2417 builder: &Builder<'_>,
2418 cargo: Cargo,
2419 tail_args: Vec<String>,
2420 stamp: &BuildStamp,
2421 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2422 is_check: bool,
2423 rlib_only_metadata: bool,
2424) -> Vec<PathBuf> {
2425 let target_root_dir = stamp.path().parent().unwrap();
2427 let target_deps_dir = target_root_dir.join("deps");
2429 let host_root_dir = target_root_dir
2431 .parent()
2432 .unwrap() .parent()
2434 .unwrap() .join(target_root_dir.file_name().unwrap());
2436
2437 let mut deps = Vec::new();
2441 let mut toplevel = Vec::new();
2442 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2443 let (filenames_vec, crate_types) = match msg {
2444 CargoMessage::CompilerArtifact {
2445 filenames,
2446 target: CargoTarget { crate_types },
2447 ..
2448 } => {
2449 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2450 f.sort(); (f, crate_types)
2452 }
2453 _ => return,
2454 };
2455 for filename in filenames_vec {
2456 let mut keep = false;
2458 if filename.ends_with(".lib")
2459 || filename.ends_with(".a")
2460 || is_debug_info(&filename)
2461 || is_dylib(Path::new(&*filename))
2462 {
2463 keep = true;
2465 }
2466 if is_check && filename.ends_with(".rmeta") {
2467 keep = true;
2469 } else if rlib_only_metadata {
2470 if filename.contains("jemalloc_sys")
2471 || filename.contains("rustc_public_bridge")
2472 || filename.contains("rustc_public")
2473 {
2474 keep |= filename.ends_with(".rlib");
2477 } else {
2478 keep |= filename.ends_with(".rmeta");
2482 }
2483 } else {
2484 keep |= filename.ends_with(".rlib");
2486 }
2487
2488 if !keep {
2489 continue;
2490 }
2491
2492 let filename = Path::new(&*filename);
2493
2494 if filename.starts_with(&host_root_dir) {
2497 if crate_types.iter().any(|t| t == "proc-macro") {
2499 deps.push((filename.to_path_buf(), DependencyType::Host));
2500 }
2501 continue;
2502 }
2503
2504 if filename.starts_with(&target_deps_dir) {
2507 deps.push((filename.to_path_buf(), DependencyType::Target));
2508 continue;
2509 }
2510
2511 let expected_len = t!(filename.metadata()).len();
2522 let filename = filename.file_name().unwrap().to_str().unwrap();
2523 let mut parts = filename.splitn(2, '.');
2524 let file_stem = parts.next().unwrap().to_owned();
2525 let extension = parts.next().unwrap().to_owned();
2526
2527 toplevel.push((file_stem, extension, expected_len));
2528 }
2529 });
2530
2531 if !ok {
2532 crate::exit!(1);
2533 }
2534
2535 if builder.config.dry_run() {
2536 return Vec::new();
2537 }
2538
2539 let contents = target_deps_dir
2543 .read_dir()
2544 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2545 .map(|e| t!(e))
2546 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2547 .collect::<Vec<_>>();
2548 for (prefix, extension, expected_len) in toplevel {
2549 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2550 meta.len() == expected_len
2551 && filename
2552 .strip_prefix(&prefix[..])
2553 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2554 .unwrap_or(false)
2555 });
2556 let max = candidates.max_by_key(|&(_, _, metadata)| {
2557 metadata.modified().expect("mtime should be available on all relevant OSes")
2558 });
2559 let path_to_add = match max {
2560 Some(triple) => triple.0.to_str().unwrap(),
2561 None => panic!("no output generated for {prefix:?} {extension:?}"),
2562 };
2563 if is_dylib(Path::new(path_to_add)) {
2564 let candidate = format!("{path_to_add}.lib");
2565 let candidate = PathBuf::from(candidate);
2566 if candidate.exists() {
2567 deps.push((candidate, DependencyType::Target));
2568 }
2569 }
2570 deps.push((path_to_add.into(), DependencyType::Target));
2571 }
2572
2573 deps.extend(additional_target_deps);
2574 deps.sort();
2575 let mut new_contents = Vec::new();
2576 for (dep, dependency_type) in deps.iter() {
2577 new_contents.extend(match *dependency_type {
2578 DependencyType::Host => b"h",
2579 DependencyType::Target => b"t",
2580 DependencyType::TargetSelfContained => b"s",
2581 });
2582 new_contents.extend(dep.to_str().unwrap().as_bytes());
2583 new_contents.extend(b"\0");
2584 }
2585 t!(fs::write(stamp.path(), &new_contents));
2586 deps.into_iter().map(|(d, _)| d).collect()
2587}
2588
2589pub fn stream_cargo(
2590 builder: &Builder<'_>,
2591 cargo: Cargo,
2592 tail_args: Vec<String>,
2593 cb: &mut dyn FnMut(CargoMessage<'_>),
2594) -> bool {
2595 let mut cmd = cargo.into_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 let stamp = BuildStamp::new(path.parent().unwrap())
2679 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2680 .with_prefix("strip")
2681 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2682
2683 if !stamp.is_up_to_date() {
2686 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2687 }
2688 t!(stamp.write());
2689
2690 let file = t!(fs::File::open(path));
2691
2692 t!(file.set_modified(previous_mtime));
2705}
2706
2707pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2709 build_compiler.stage != 0
2710}