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::toml::target::DefaultLinuxLinkerOverride;
30use crate::core::config::{
31 CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
32};
33use crate::utils::build_stamp;
34use crate::utils::build_stamp::BuildStamp;
35use crate::utils::exec::command;
36use crate::utils::helpers::{
37 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
38};
39use crate::{
40 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
41 debug, trace,
42};
43
44#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub struct Std {
47 pub target: TargetSelection,
48 pub build_compiler: Compiler,
50 crates: Vec<String>,
54 force_recompile: bool,
57 extra_rust_args: &'static [&'static str],
58 is_for_mir_opt_tests: bool,
59}
60
61impl Std {
62 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
63 Self {
64 target,
65 build_compiler,
66 crates: Default::default(),
67 force_recompile: false,
68 extra_rust_args: &[],
69 is_for_mir_opt_tests: false,
70 }
71 }
72
73 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
74 self.force_recompile = force_recompile;
75 self
76 }
77
78 #[expect(clippy::wrong_self_convention)]
79 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
80 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
81 self
82 }
83
84 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
85 self.extra_rust_args = extra_rust_args;
86 self
87 }
88
89 fn copy_extra_objects(
90 &self,
91 builder: &Builder<'_>,
92 compiler: &Compiler,
93 target: TargetSelection,
94 ) -> Vec<(PathBuf, DependencyType)> {
95 let mut deps = Vec::new();
96 if !self.is_for_mir_opt_tests {
97 deps.extend(copy_third_party_objects(builder, compiler, target));
98 deps.extend(copy_self_contained_objects(builder, compiler, target));
99 }
100 deps
101 }
102
103 pub fn should_be_uplifted_from_stage_1(builder: &Builder<'_>, stage: u32) -> bool {
108 stage > 1 && !builder.config.full_bootstrap
109 }
110}
111
112impl Step for Std {
113 type Output = Option<BuildStamp>;
115
116 const DEFAULT: bool = true;
117
118 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
119 run.crate_or_deps("sysroot").path("library")
120 }
121
122 fn make_run(run: RunConfig<'_>) {
123 let crates = std_crates_for_run_make(&run);
124 let builder = run.builder;
125
126 let force_recompile = builder.rust_info().is_managed_git_subrepository()
130 && builder.download_rustc()
131 && builder.config.has_changes_from_upstream(&["library"]);
132
133 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
134 trace!("download_rustc: {}", builder.download_rustc());
135 trace!(force_recompile);
136
137 run.builder.ensure(Std {
138 build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target),
141 target: run.target,
142 crates,
143 force_recompile,
144 extra_rust_args: &[],
145 is_for_mir_opt_tests: false,
146 });
147 }
148
149 fn run(self, builder: &Builder<'_>) -> Self::Output {
155 let target = self.target;
156
157 if self.build_compiler.stage == 0
162 && !(builder.local_rebuild && target != builder.host_target)
163 {
164 let compiler = self.build_compiler;
165 builder.ensure(StdLink::from_std(self, compiler));
166
167 return None;
168 }
169
170 let build_compiler = if builder.download_rustc() && self.force_recompile {
171 builder
174 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
175 } else {
176 self.build_compiler
177 };
178
179 if builder.download_rustc()
182 && builder.config.is_host_target(target)
183 && !self.force_recompile
184 {
185 let sysroot =
186 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
187 cp_rustc_component_to_ci_sysroot(
188 builder,
189 &sysroot,
190 builder.config.ci_rust_std_contents(),
191 );
192 return None;
193 }
194
195 if builder.config.keep_stage.contains(&build_compiler.stage)
196 || builder.config.keep_stage_std.contains(&build_compiler.stage)
197 {
198 trace!(keep_stage = ?builder.config.keep_stage);
199 trace!(keep_stage_std = ?builder.config.keep_stage_std);
200
201 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
202
203 builder.ensure(StartupObjects { compiler: build_compiler, target });
204
205 self.copy_extra_objects(builder, &build_compiler, target);
206
207 builder.ensure(StdLink::from_std(self, build_compiler));
208 return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
209 }
210
211 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
212
213 let stage = build_compiler.stage;
215
216 if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
217 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
218 let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
219
220 let msg = if build_compiler_for_std_to_uplift.host == target {
221 format!(
222 "Uplifting library (stage{} -> stage{stage})",
223 build_compiler_for_std_to_uplift.stage
224 )
225 } else {
226 format!(
227 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
228 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
229 )
230 };
231
232 builder.info(&msg);
233
234 self.copy_extra_objects(builder, &build_compiler, target);
237
238 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
239 return stage_1_stamp;
240 }
241
242 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
243
244 let mut cargo = if self.is_for_mir_opt_tests {
248 trace!("building special sysroot for mir-opt tests");
249 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
250 builder,
251 build_compiler,
252 Mode::Std,
253 SourceType::InTree,
254 target,
255 Kind::Check,
256 );
257 cargo.rustflag("-Zalways-encode-mir");
258 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
259 cargo
260 } else {
261 trace!("building regular sysroot");
262 let mut cargo = builder::Cargo::new(
263 builder,
264 build_compiler,
265 Mode::Std,
266 SourceType::InTree,
267 target,
268 Kind::Build,
269 );
270 std_cargo(builder, target, &mut cargo, &self.crates);
271 cargo
272 };
273
274 if target.is_synthetic() {
276 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
277 }
278 for rustflag in self.extra_rust_args.iter() {
279 cargo.rustflag(rustflag);
280 }
281
282 let _guard = builder.msg(
283 Kind::Build,
284 format_args!("library artifacts{}", crate_description(&self.crates)),
285 Mode::Std,
286 build_compiler,
287 target,
288 );
289
290 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
291 run_cargo(
292 builder,
293 cargo,
294 vec![],
295 &stamp,
296 target_deps,
297 self.is_for_mir_opt_tests, false,
299 );
300
301 builder.ensure(StdLink::from_std(
302 self,
303 builder.compiler(build_compiler.stage, builder.config.host_target),
304 ));
305 Some(stamp)
306 }
307
308 fn metadata(&self) -> Option<StepMetadata> {
309 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
310 }
311}
312
313fn copy_and_stamp(
314 builder: &Builder<'_>,
315 libdir: &Path,
316 sourcedir: &Path,
317 name: &str,
318 target_deps: &mut Vec<(PathBuf, DependencyType)>,
319 dependency_type: DependencyType,
320) {
321 let target = libdir.join(name);
322 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
323
324 target_deps.push((target, dependency_type));
325}
326
327fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
328 let libunwind_path = builder.ensure(llvm::Libunwind { target });
329 let libunwind_source = libunwind_path.join("libunwind.a");
330 let libunwind_target = libdir.join("libunwind.a");
331 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
332 libunwind_target
333}
334
335fn copy_third_party_objects(
337 builder: &Builder<'_>,
338 compiler: &Compiler,
339 target: TargetSelection,
340) -> Vec<(PathBuf, DependencyType)> {
341 let mut target_deps = vec![];
342
343 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
344 target_deps.extend(
347 copy_sanitizers(builder, compiler, target)
348 .into_iter()
349 .map(|d| (d, DependencyType::Target)),
350 );
351 }
352
353 if target == "x86_64-fortanix-unknown-sgx"
354 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
355 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
356 {
357 let libunwind_path =
358 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
359 target_deps.push((libunwind_path, DependencyType::Target));
360 }
361
362 target_deps
363}
364
365fn copy_self_contained_objects(
367 builder: &Builder<'_>,
368 compiler: &Compiler,
369 target: TargetSelection,
370) -> Vec<(PathBuf, DependencyType)> {
371 let libdir_self_contained =
372 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
373 t!(fs::create_dir_all(&libdir_self_contained));
374 let mut target_deps = vec![];
375
376 if target.needs_crt_begin_end() {
384 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
385 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
386 });
387 if !target.starts_with("wasm32") {
388 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
389 copy_and_stamp(
390 builder,
391 &libdir_self_contained,
392 &srcdir,
393 obj,
394 &mut target_deps,
395 DependencyType::TargetSelfContained,
396 );
397 }
398 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
399 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
400 let src = crt_path.join(obj);
401 let target = libdir_self_contained.join(obj);
402 builder.copy_link(&src, &target, FileType::NativeLibrary);
403 target_deps.push((target, DependencyType::TargetSelfContained));
404 }
405 } else {
406 for &obj in &["libc.a", "crt1-command.o"] {
409 copy_and_stamp(
410 builder,
411 &libdir_self_contained,
412 &srcdir,
413 obj,
414 &mut target_deps,
415 DependencyType::TargetSelfContained,
416 );
417 }
418 }
419 if !target.starts_with("s390x") {
420 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
421 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
422 }
423 } else if target.contains("-wasi") {
424 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
425 panic!(
426 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
427 or `$WASI_SDK_PATH` set",
428 target.triple
429 )
430 });
431
432 let srcdir = if target == "wasm32-wasip3" {
436 assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now");
437 builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap()
438 } else {
439 srcdir
440 };
441 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
442 copy_and_stamp(
443 builder,
444 &libdir_self_contained,
445 &srcdir,
446 obj,
447 &mut target_deps,
448 DependencyType::TargetSelfContained,
449 );
450 }
451 } else if target.is_windows_gnu() || target.is_windows_gnullvm() {
452 for obj in ["crt2.o", "dllcrt2.o"].iter() {
453 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
454 let dst = libdir_self_contained.join(obj);
455 builder.copy_link(&src, &dst, FileType::NativeLibrary);
456 target_deps.push((dst, DependencyType::TargetSelfContained));
457 }
458 }
459
460 target_deps
461}
462
463pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
466 let mut crates = run.make_run_crates(builder::Alias::Library);
467
468 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
477 if target_is_no_std {
478 crates.retain(|c| c == "core" || c == "alloc");
479 }
480 crates
481}
482
483fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
489 if builder.config.llvm_from_ci {
491 builder.config.maybe_download_ci_llvm();
493 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
494 if ci_llvm_compiler_rt.exists() {
495 return ci_llvm_compiler_rt;
496 }
497 }
498
499 builder.require_submodule("src/llvm-project", {
501 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
502 });
503 builder.src.join("src/llvm-project/compiler-rt")
504}
505
506pub fn std_cargo(
509 builder: &Builder<'_>,
510 target: TargetSelection,
511 cargo: &mut Cargo,
512 crates: &[String],
513) {
514 if target.contains("apple") && !builder.config.dry_run() {
532 let mut cmd = builder.rustc_cmd(cargo.compiler());
536 cmd.arg("--target").arg(target.rustc_target_arg());
537 cmd.arg("--print=deployment-target");
538 let output = cmd.run_capture_stdout(builder).stdout();
539
540 let (env_var, value) = output.split_once('=').unwrap();
541 cargo.env(env_var.trim(), value.trim());
544
545 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
555 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
556 }
557 }
558
559 if let Some(path) = builder.config.profiler_path(target) {
561 cargo.env("LLVM_PROFILER_RT_LIB", path);
562 } else if builder.config.profiler_enabled(target) {
563 let compiler_rt = compiler_rt_for_profiler(builder);
564 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
568 }
569
570 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
584 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
585 cargo.env("LLVM_COMPILER_RT_LIB", path);
586 " compiler-builtins-c"
587 }
588 CompilerBuiltins::BuildLLVMFuncs => {
589 builder.require_submodule(
599 "src/llvm-project",
600 Some(
601 "The `build.optimized-compiler-builtins` config option \
602 requires `compiler-rt` sources from LLVM.",
603 ),
604 );
605 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
606 if !builder.config.dry_run() {
607 assert!(compiler_builtins_root.exists());
610 }
611
612 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
615 " compiler-builtins-c"
616 }
617 CompilerBuiltins::BuildRustOnly => "",
618 };
619
620 if !builder.unstable_features() {
623 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
624 }
625
626 for krate in crates {
627 cargo.args(["-p", krate]);
628 }
629
630 let mut features = String::new();
631
632 if builder.no_std(target) == Some(true) {
633 features += " compiler-builtins-mem";
634 if !target.starts_with("bpf") {
635 features.push_str(compiler_builtins_c_feature);
636 }
637
638 if crates.is_empty() {
640 cargo.args(["-p", "alloc"]);
641 }
642 cargo
643 .arg("--manifest-path")
644 .arg(builder.src.join("library/alloc/Cargo.toml"))
645 .arg("--features")
646 .arg(features);
647 } else {
648 features += &builder.std_features(target);
649 features.push_str(compiler_builtins_c_feature);
650
651 cargo
652 .arg("--features")
653 .arg(features)
654 .arg("--manifest-path")
655 .arg(builder.src.join("library/sysroot/Cargo.toml"));
656
657 if target.contains("musl")
660 && let Some(p) = builder.musl_libdir(target)
661 {
662 let root = format!("native={}", p.to_str().unwrap());
663 cargo.rustflag("-L").rustflag(&root);
664 }
665
666 if target.contains("-wasi")
667 && let Some(dir) = builder.wasi_libdir(target)
668 {
669 let root = format!("native={}", dir.to_str().unwrap());
670 cargo.rustflag("-L").rustflag(&root);
671 }
672 }
673
674 cargo.rustflag("-Cembed-bitcode=yes");
680
681 if builder.config.rust_lto == RustcLto::Off {
682 cargo.rustflag("-Clto=off");
683 }
684
685 if target.contains("riscv") {
692 cargo.rustflag("-Cforce-unwind-tables=yes");
693 }
694
695 cargo.rustflag("-Zunstable-options");
698 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
699
700 let html_root =
701 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
702 cargo.rustflag(&html_root);
703 cargo.rustdocflag(&html_root);
704
705 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
706}
707
708#[derive(Debug, Clone, PartialEq, Eq, Hash)]
717pub struct StdLink {
718 pub compiler: Compiler,
719 pub target_compiler: Compiler,
720 pub target: TargetSelection,
721 crates: Vec<String>,
723 force_recompile: bool,
725}
726
727impl StdLink {
728 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
729 Self {
730 compiler: host_compiler,
731 target_compiler: std.build_compiler,
732 target: std.target,
733 crates: std.crates,
734 force_recompile: std.force_recompile,
735 }
736 }
737}
738
739impl Step for StdLink {
740 type Output = ();
741
742 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
743 run.never()
744 }
745
746 fn run(self, builder: &Builder<'_>) {
755 let compiler = self.compiler;
756 let target_compiler = self.target_compiler;
757 let target = self.target;
758
759 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
761 let lib = builder.sysroot_libdir_relative(self.compiler);
763 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
764 compiler: self.compiler,
765 force_recompile: self.force_recompile,
766 });
767 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
768 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
769 (libdir, hostdir)
770 } else {
771 let libdir = builder.sysroot_target_libdir(target_compiler, target);
772 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
773 (libdir, hostdir)
774 };
775
776 let is_downloaded_beta_stage0 = builder
777 .build
778 .config
779 .initial_rustc
780 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
781
782 if compiler.stage == 0 && is_downloaded_beta_stage0 {
786 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
788
789 let host = compiler.host;
790 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
791 let sysroot_bin_dir = sysroot.join("bin");
792 t!(fs::create_dir_all(&sysroot_bin_dir));
793 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
794
795 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
796 t!(fs::create_dir_all(sysroot.join("lib")));
797 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
798
799 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
801 t!(fs::create_dir_all(&sysroot_codegen_backends));
802 let stage0_codegen_backends = builder
803 .out
804 .join(host)
805 .join("stage0/lib/rustlib")
806 .join(host)
807 .join("codegen-backends");
808 if stage0_codegen_backends.exists() {
809 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
810 }
811 } else if compiler.stage == 0 {
812 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
813
814 if builder.local_rebuild {
815 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
819 }
820
821 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
822 } else {
823 if builder.download_rustc() {
824 let _ = fs::remove_dir_all(&libdir);
826 let _ = fs::remove_dir_all(&hostdir);
827 }
828
829 add_to_sysroot(
830 builder,
831 &libdir,
832 &hostdir,
833 &build_stamp::libstd_stamp(builder, compiler, target),
834 );
835 }
836 }
837}
838
839fn copy_sanitizers(
841 builder: &Builder<'_>,
842 compiler: &Compiler,
843 target: TargetSelection,
844) -> Vec<PathBuf> {
845 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
846
847 if builder.config.dry_run() {
848 return Vec::new();
849 }
850
851 let mut target_deps = Vec::new();
852 let libdir = builder.sysroot_target_libdir(*compiler, target);
853
854 for runtime in &runtimes {
855 let dst = libdir.join(&runtime.name);
856 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
857
858 if target == "x86_64-apple-darwin"
862 || target == "aarch64-apple-darwin"
863 || target == "aarch64-apple-ios"
864 || target == "aarch64-apple-ios-sim"
865 || target == "x86_64-apple-ios"
866 {
867 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
869 apple_darwin_sign_file(builder, &dst);
872 }
873
874 target_deps.push(dst);
875 }
876
877 target_deps
878}
879
880fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
881 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
882}
883
884fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
885 command("codesign")
886 .arg("-f") .arg("-s")
888 .arg("-")
889 .arg(file_path)
890 .run(builder);
891}
892
893#[derive(Debug, Clone, PartialEq, Eq, Hash)]
894pub struct StartupObjects {
895 pub compiler: Compiler,
896 pub target: TargetSelection,
897}
898
899impl Step for StartupObjects {
900 type Output = Vec<(PathBuf, DependencyType)>;
901
902 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
903 run.path("library/rtstartup")
904 }
905
906 fn make_run(run: RunConfig<'_>) {
907 run.builder.ensure(StartupObjects {
908 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
909 target: run.target,
910 });
911 }
912
913 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
920 let for_compiler = self.compiler;
921 let target = self.target;
922 if !target.is_windows_gnu() {
925 return vec![];
926 }
927
928 let mut target_deps = vec![];
929
930 let src_dir = &builder.src.join("library").join("rtstartup");
931 let dst_dir = &builder.native_dir(target).join("rtstartup");
932 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
933 t!(fs::create_dir_all(dst_dir));
934
935 for file in &["rsbegin", "rsend"] {
936 let src_file = &src_dir.join(file.to_string() + ".rs");
937 let dst_file = &dst_dir.join(file.to_string() + ".o");
938 if !up_to_date(src_file, dst_file) {
939 let mut cmd = command(&builder.initial_rustc);
940 cmd.env("RUSTC_BOOTSTRAP", "1");
941 if !builder.local_rebuild {
942 cmd.arg("--cfg").arg("bootstrap");
944 }
945 cmd.arg("--target")
946 .arg(target.rustc_target_arg())
947 .arg("--emit=obj")
948 .arg("-o")
949 .arg(dst_file)
950 .arg(src_file)
951 .run(builder);
952 }
953
954 let obj = sysroot_dir.join((*file).to_string() + ".o");
955 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
956 target_deps.push((obj, DependencyType::Target));
957 }
958
959 target_deps
960 }
961}
962
963fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
964 let ci_rustc_dir = builder.config.ci_rustc_dir();
965
966 for file in contents {
967 let src = ci_rustc_dir.join(&file);
968 let dst = sysroot.join(file);
969 if src.is_dir() {
970 t!(fs::create_dir_all(dst));
971 } else {
972 builder.copy_link(&src, &dst, FileType::Regular);
973 }
974 }
975}
976
977#[derive(Clone, Debug)]
979pub struct BuiltRustc {
980 pub build_compiler: Compiler,
984}
985
986#[derive(Debug, Clone, PartialEq, Eq, Hash)]
993pub struct Rustc {
994 pub target: TargetSelection,
996 pub build_compiler: Compiler,
998 crates: Vec<String>,
1004}
1005
1006impl Rustc {
1007 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
1008 Self { target, build_compiler, crates: Default::default() }
1009 }
1010}
1011
1012impl Step for Rustc {
1013 type Output = BuiltRustc;
1014
1015 const IS_HOST: bool = true;
1016 const DEFAULT: bool = false;
1017
1018 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1019 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1020 for (i, krate) in crates.iter().enumerate() {
1021 if krate.name == "rustc-main" {
1024 crates.swap_remove(i);
1025 break;
1026 }
1027 }
1028 run.crates(crates)
1029 }
1030
1031 fn make_run(run: RunConfig<'_>) {
1032 if run.builder.paths == vec![PathBuf::from("compiler")] {
1035 return;
1036 }
1037
1038 let crates = run.cargo_crates_in_set();
1039 run.builder.ensure(Rustc {
1040 build_compiler: run
1041 .builder
1042 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1043 target: run.target,
1044 crates,
1045 });
1046 }
1047
1048 fn run(self, builder: &Builder<'_>) -> Self::Output {
1054 let build_compiler = self.build_compiler;
1055 let target = self.target;
1056
1057 if builder.download_rustc() && build_compiler.stage != 0 {
1060 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1061
1062 let sysroot =
1063 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1064 cp_rustc_component_to_ci_sysroot(
1065 builder,
1066 &sysroot,
1067 builder.config.ci_rustc_dev_contents(),
1068 );
1069 return BuiltRustc { build_compiler };
1070 }
1071
1072 builder.std(build_compiler, target);
1075
1076 if builder.config.keep_stage.contains(&build_compiler.stage) {
1077 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1078
1079 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1080 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1081 builder.ensure(RustcLink::from_rustc(self));
1082
1083 return BuiltRustc { build_compiler };
1084 }
1085
1086 let stage = build_compiler.stage + 1;
1088
1089 if build_compiler.stage >= 2
1094 && !builder.config.full_bootstrap
1095 && target == builder.host_target
1096 {
1097 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1101
1102 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1103 builder.info(&msg);
1104
1105 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1109 uplift_build_compiler,
1111 build_compiler,
1113 target,
1114 self.crates,
1115 ));
1116
1117 return BuiltRustc { build_compiler: uplift_build_compiler };
1120 }
1121
1122 builder.std(
1128 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1129 builder.config.host_target,
1130 );
1131
1132 let mut cargo = builder::Cargo::new(
1133 builder,
1134 build_compiler,
1135 Mode::Rustc,
1136 SourceType::InTree,
1137 target,
1138 Kind::Build,
1139 );
1140
1141 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1142
1143 for krate in &*self.crates {
1147 cargo.arg("-p").arg(krate);
1148 }
1149
1150 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1151 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1153 }
1154
1155 let _guard = builder.msg(
1156 Kind::Build,
1157 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1158 Mode::Rustc,
1159 build_compiler,
1160 target,
1161 );
1162 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1163 run_cargo(
1164 builder,
1165 cargo,
1166 vec![],
1167 &stamp,
1168 vec![],
1169 false,
1170 true, );
1172
1173 let target_root_dir = stamp.path().parent().unwrap();
1174 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1180 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1181 {
1182 let rustc_driver = target_root_dir.join("librustc_driver.so");
1183 strip_debug(builder, target, &rustc_driver);
1184 }
1185
1186 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1187 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1190 }
1191
1192 builder.ensure(RustcLink::from_rustc(self));
1193 BuiltRustc { build_compiler }
1194 }
1195
1196 fn metadata(&self) -> Option<StepMetadata> {
1197 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1198 }
1199}
1200
1201pub fn rustc_cargo(
1202 builder: &Builder<'_>,
1203 cargo: &mut Cargo,
1204 target: TargetSelection,
1205 build_compiler: &Compiler,
1206 crates: &[String],
1207) {
1208 cargo
1209 .arg("--features")
1210 .arg(builder.rustc_features(builder.kind, target, crates))
1211 .arg("--manifest-path")
1212 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1213
1214 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1215
1216 cargo.rustflag("-Zon-broken-pipe=kill");
1230
1231 if builder.config.llvm_enzyme {
1234 let arch = builder.build.host_target;
1235 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1236 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1237
1238 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1239 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1240 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1241 }
1242 }
1243
1244 if builder.build.config.bootstrap_override_lld.is_used() {
1249 cargo.rustflag("-Zdefault-visibility=protected");
1250 }
1251
1252 if is_lto_stage(build_compiler) {
1253 match builder.config.rust_lto {
1254 RustcLto::Thin | RustcLto::Fat => {
1255 cargo.rustflag("-Zdylib-lto");
1258 let lto_type = match builder.config.rust_lto {
1262 RustcLto::Thin => "thin",
1263 RustcLto::Fat => "fat",
1264 _ => unreachable!(),
1265 };
1266 cargo.rustflag(&format!("-Clto={lto_type}"));
1267 cargo.rustflag("-Cembed-bitcode=yes");
1268 }
1269 RustcLto::ThinLocal => { }
1270 RustcLto::Off => {
1271 cargo.rustflag("-Clto=off");
1272 }
1273 }
1274 } else if builder.config.rust_lto == RustcLto::Off {
1275 cargo.rustflag("-Clto=off");
1276 }
1277
1278 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1286 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1287 }
1288
1289 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1290 panic!("Cannot use and generate PGO profiles at the same time");
1291 }
1292 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1293 if build_compiler.stage == 1 {
1294 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1295 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1298 true
1299 } else {
1300 false
1301 }
1302 } else if let Some(path) = &builder.config.rust_profile_use {
1303 if build_compiler.stage == 1 {
1304 cargo.rustflag(&format!("-Cprofile-use={path}"));
1305 if builder.is_verbose() {
1306 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1307 }
1308 true
1309 } else {
1310 false
1311 }
1312 } else {
1313 false
1314 };
1315 if is_collecting {
1316 cargo.rustflag(&format!(
1318 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1319 builder.config.src.components().count()
1320 ));
1321 }
1322
1323 if let Some(ref ccache) = builder.config.ccache
1328 && build_compiler.stage == 0
1329 && !builder.config.incremental
1330 {
1331 cargo.env("RUSTC_WRAPPER", ccache);
1332 }
1333
1334 rustc_cargo_env(builder, cargo, target);
1335}
1336
1337pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1338 cargo
1341 .env("CFG_RELEASE", builder.rust_release())
1342 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1343 .env("CFG_VERSION", builder.rust_version());
1344
1345 if builder.config.omit_git_hash {
1349 cargo.env("CFG_OMIT_GIT_HASH", "1");
1350 }
1351
1352 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1353
1354 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1355 let target_config = builder.config.target_config.get(&target);
1356
1357 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1358
1359 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1360 cargo.env("CFG_VER_DATE", ver_date);
1361 }
1362 if let Some(ref ver_hash) = builder.rust_info().sha() {
1363 cargo.env("CFG_VER_HASH", ver_hash);
1364 }
1365 if !builder.unstable_features() {
1366 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1367 }
1368
1369 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1372 cargo.env("CFG_DEFAULT_LINKER", s);
1373 } else if let Some(ref s) = builder.config.rustc_default_linker {
1374 cargo.env("CFG_DEFAULT_LINKER", s);
1375 }
1376
1377 if let Some(linker) = target_config.map(|c| c.default_linker_linux_override) {
1379 match linker {
1380 DefaultLinuxLinkerOverride::Off => {}
1381 DefaultLinuxLinkerOverride::SelfContainedLldCc => {
1382 cargo.env("CFG_DEFAULT_LINKER_SELF_CONTAINED_LLD_CC", "1");
1383 }
1384 }
1385 }
1386
1387 if builder.config.rust_verify_llvm_ir {
1388 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1389 }
1390
1391 if builder.config.llvm_enabled(target) {
1403 let building_llvm_is_expensive =
1404 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1405 .should_build();
1406
1407 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1408 if !skip_llvm {
1409 rustc_llvm_env(builder, cargo, target)
1410 }
1411 }
1412
1413 if builder.config.jemalloc(target) && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
1415 if target.starts_with("aarch64") {
1418 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1419 }
1420 else if target.starts_with("loongarch") {
1422 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1423 }
1424 }
1425}
1426
1427fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1433 if builder.config.is_rust_llvm(target) {
1434 cargo.env("LLVM_RUSTLLVM", "1");
1435 }
1436 if builder.config.llvm_enzyme {
1437 cargo.env("LLVM_ENZYME", "1");
1438 }
1439 if builder.config.llvm_offload {
1440 cargo.env("LLVM_OFFLOAD", "1");
1441 }
1442 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1443 cargo.env("LLVM_CONFIG", &host_llvm_config);
1444
1445 let mut llvm_linker_flags = String::new();
1455 if builder.config.llvm_profile_generate
1456 && target.is_msvc()
1457 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1458 {
1459 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1461 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1462 }
1463
1464 if let Some(ref s) = builder.config.llvm_ldflags {
1466 if !llvm_linker_flags.is_empty() {
1467 llvm_linker_flags.push(' ');
1468 }
1469 llvm_linker_flags.push_str(s);
1470 }
1471
1472 if !llvm_linker_flags.is_empty() {
1474 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1475 }
1476
1477 if builder.config.llvm_static_stdcpp
1480 && !target.contains("freebsd")
1481 && !target.is_msvc()
1482 && !target.contains("apple")
1483 && !target.contains("solaris")
1484 {
1485 let libstdcxx_name =
1486 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1487 let file = compiler_file(
1488 builder,
1489 &builder.cxx(target).unwrap(),
1490 target,
1491 CLang::Cxx,
1492 libstdcxx_name,
1493 );
1494 cargo.env("LLVM_STATIC_STDCPP", file);
1495 }
1496 if builder.llvm_link_shared() {
1497 cargo.env("LLVM_LINK_SHARED", "1");
1498 }
1499 if builder.config.llvm_use_libcxx {
1500 cargo.env("LLVM_USE_LIBCXX", "1");
1501 }
1502 if builder.config.llvm_assertions {
1503 cargo.env("LLVM_ASSERTIONS", "1");
1504 }
1505}
1506
1507#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1520struct RustcLink {
1521 build_compiler: Compiler,
1523 sysroot_compiler: Compiler,
1526 target: TargetSelection,
1527 crates: Vec<String>,
1529}
1530
1531impl RustcLink {
1532 fn from_rustc(rustc: Rustc) -> Self {
1535 Self {
1536 build_compiler: rustc.build_compiler,
1537 sysroot_compiler: rustc.build_compiler,
1538 target: rustc.target,
1539 crates: rustc.crates,
1540 }
1541 }
1542
1543 fn from_build_compiler_and_sysroot(
1545 build_compiler: Compiler,
1546 sysroot_compiler: Compiler,
1547 target: TargetSelection,
1548 crates: Vec<String>,
1549 ) -> Self {
1550 Self { build_compiler, sysroot_compiler, target, crates }
1551 }
1552}
1553
1554impl Step for RustcLink {
1555 type Output = ();
1556
1557 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1558 run.never()
1559 }
1560
1561 fn run(self, builder: &Builder<'_>) {
1563 let build_compiler = self.build_compiler;
1564 let sysroot_compiler = self.sysroot_compiler;
1565 let target = self.target;
1566 add_to_sysroot(
1567 builder,
1568 &builder.sysroot_target_libdir(sysroot_compiler, target),
1569 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1570 &build_stamp::librustc_stamp(builder, build_compiler, target),
1571 );
1572 }
1573}
1574
1575#[derive(Clone)]
1578pub struct GccCodegenBackendOutput {
1579 stamp: BuildStamp,
1580 gcc: GccOutput,
1581}
1582
1583#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1584pub struct GccCodegenBackend {
1585 compilers: RustcPrivateCompilers,
1586}
1587
1588impl Step for GccCodegenBackend {
1589 type Output = GccCodegenBackendOutput;
1590
1591 const IS_HOST: bool = true;
1592
1593 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1594 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1595 }
1596
1597 fn make_run(run: RunConfig<'_>) {
1598 run.builder.ensure(GccCodegenBackend {
1599 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1600 });
1601 }
1602
1603 fn run(self, builder: &Builder<'_>) -> Self::Output {
1604 let target = self.compilers.target();
1605 let build_compiler = self.compilers.build_compiler();
1606
1607 let stamp = build_stamp::codegen_backend_stamp(
1608 builder,
1609 build_compiler,
1610 target,
1611 &CodegenBackendKind::Gcc,
1612 );
1613
1614 let gcc = builder.ensure(Gcc { target });
1615
1616 if builder.config.keep_stage.contains(&build_compiler.stage) {
1617 trace!("`keep-stage` requested");
1618 builder.info(
1619 "WARNING: Using a potentially old codegen backend. \
1620 This may not behave well.",
1621 );
1622 return GccCodegenBackendOutput { stamp, gcc };
1625 }
1626
1627 let mut cargo = builder::Cargo::new(
1628 builder,
1629 build_compiler,
1630 Mode::Codegen,
1631 SourceType::InTree,
1632 target,
1633 Kind::Build,
1634 );
1635 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1636 rustc_cargo_env(builder, &mut cargo, target);
1637
1638 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1639
1640 let _guard =
1641 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1642 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1643
1644 GccCodegenBackendOutput {
1645 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1646 gcc,
1647 }
1648 }
1649
1650 fn metadata(&self) -> Option<StepMetadata> {
1651 Some(
1652 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1653 .built_by(self.compilers.build_compiler()),
1654 )
1655 }
1656}
1657
1658#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1659pub struct CraneliftCodegenBackend {
1660 pub compilers: RustcPrivateCompilers,
1661}
1662
1663impl Step for CraneliftCodegenBackend {
1664 type Output = BuildStamp;
1665 const IS_HOST: bool = true;
1666
1667 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1668 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1669 }
1670
1671 fn make_run(run: RunConfig<'_>) {
1672 run.builder.ensure(CraneliftCodegenBackend {
1673 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1674 });
1675 }
1676
1677 fn run(self, builder: &Builder<'_>) -> Self::Output {
1678 let target = self.compilers.target();
1679 let build_compiler = self.compilers.build_compiler();
1680
1681 let stamp = build_stamp::codegen_backend_stamp(
1682 builder,
1683 build_compiler,
1684 target,
1685 &CodegenBackendKind::Cranelift,
1686 );
1687
1688 if builder.config.keep_stage.contains(&build_compiler.stage) {
1689 trace!("`keep-stage` requested");
1690 builder.info(
1691 "WARNING: Using a potentially old codegen backend. \
1692 This may not behave well.",
1693 );
1694 return stamp;
1697 }
1698
1699 let mut cargo = builder::Cargo::new(
1700 builder,
1701 build_compiler,
1702 Mode::Codegen,
1703 SourceType::InTree,
1704 target,
1705 Kind::Build,
1706 );
1707 cargo
1708 .arg("--manifest-path")
1709 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1710 rustc_cargo_env(builder, &mut cargo, target);
1711
1712 let _guard = builder.msg(
1713 Kind::Build,
1714 "codegen backend cranelift",
1715 Mode::Codegen,
1716 build_compiler,
1717 target,
1718 );
1719 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1720 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1721 }
1722
1723 fn metadata(&self) -> Option<StepMetadata> {
1724 Some(
1725 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1726 .built_by(self.compilers.build_compiler()),
1727 )
1728 }
1729}
1730
1731fn write_codegen_backend_stamp(
1733 mut stamp: BuildStamp,
1734 files: Vec<PathBuf>,
1735 dry_run: bool,
1736) -> BuildStamp {
1737 if dry_run {
1738 return stamp;
1739 }
1740
1741 let mut files = files.into_iter().filter(|f| {
1742 let filename = f.file_name().unwrap().to_str().unwrap();
1743 is_dylib(f) && filename.contains("rustc_codegen_")
1744 });
1745 let codegen_backend = match files.next() {
1746 Some(f) => f,
1747 None => panic!("no dylibs built for codegen backend?"),
1748 };
1749 if let Some(f) = files.next() {
1750 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1751 }
1752
1753 let codegen_backend = codegen_backend.to_str().unwrap();
1754 stamp = stamp.add_stamp(codegen_backend);
1755 t!(stamp.write());
1756 stamp
1757}
1758
1759fn copy_codegen_backends_to_sysroot(
1766 builder: &Builder<'_>,
1767 stamp: BuildStamp,
1768 target_compiler: Compiler,
1769) {
1770 let dst = builder.sysroot_codegen_backends(target_compiler);
1779 t!(fs::create_dir_all(&dst), dst);
1780
1781 if builder.config.dry_run() {
1782 return;
1783 }
1784
1785 if stamp.path().exists() {
1786 let file = get_codegen_backend_file(&stamp);
1787 builder.copy_link(
1788 &file,
1789 &dst.join(normalize_codegen_backend_name(builder, &file)),
1790 FileType::NativeLibrary,
1791 );
1792 }
1793}
1794
1795pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1797 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1798}
1799
1800pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1802 let filename = path.file_name().unwrap().to_str().unwrap();
1803 let dash = filename.find('-').unwrap();
1806 let dot = filename.find('.').unwrap();
1807 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1808}
1809
1810pub fn compiler_file(
1811 builder: &Builder<'_>,
1812 compiler: &Path,
1813 target: TargetSelection,
1814 c: CLang,
1815 file: &str,
1816) -> PathBuf {
1817 if builder.config.dry_run() {
1818 return PathBuf::new();
1819 }
1820 let mut cmd = command(compiler);
1821 cmd.args(builder.cc_handled_clags(target, c));
1822 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1823 cmd.arg(format!("-print-file-name={file}"));
1824 let out = cmd.run_capture_stdout(builder).stdout();
1825 PathBuf::from(out.trim())
1826}
1827
1828#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1829pub struct Sysroot {
1830 pub compiler: Compiler,
1831 force_recompile: bool,
1833}
1834
1835impl Sysroot {
1836 pub(crate) fn new(compiler: Compiler) -> Self {
1837 Sysroot { compiler, force_recompile: false }
1838 }
1839}
1840
1841impl Step for Sysroot {
1842 type Output = PathBuf;
1843
1844 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1845 run.never()
1846 }
1847
1848 fn run(self, builder: &Builder<'_>) -> PathBuf {
1852 let compiler = self.compiler;
1853 let host_dir = builder.out.join(compiler.host);
1854
1855 let sysroot_dir = |stage| {
1856 if stage == 0 {
1857 host_dir.join("stage0-sysroot")
1858 } else if self.force_recompile && stage == compiler.stage {
1859 host_dir.join(format!("stage{stage}-test-sysroot"))
1860 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1861 host_dir.join("ci-rustc-sysroot")
1862 } else {
1863 host_dir.join(format!("stage{stage}"))
1864 }
1865 };
1866 let sysroot = sysroot_dir(compiler.stage);
1867 trace!(stage = ?compiler.stage, ?sysroot);
1868
1869 builder.do_if_verbose(|| {
1870 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1871 });
1872 let _ = fs::remove_dir_all(&sysroot);
1873 t!(fs::create_dir_all(&sysroot));
1874
1875 if compiler.stage == 0 {
1882 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1883 }
1884
1885 if builder.download_rustc() && compiler.stage != 0 {
1887 assert_eq!(
1888 builder.config.host_target, compiler.host,
1889 "Cross-compiling is not yet supported with `download-rustc`",
1890 );
1891
1892 for stage in 0..=2 {
1894 if stage != compiler.stage {
1895 let dir = sysroot_dir(stage);
1896 if !dir.ends_with("ci-rustc-sysroot") {
1897 let _ = fs::remove_dir_all(dir);
1898 }
1899 }
1900 }
1901
1902 let mut filtered_files = Vec::new();
1912 let mut add_filtered_files = |suffix, contents| {
1913 for path in contents {
1914 let path = Path::new(&path);
1915 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1916 filtered_files.push(path.file_name().unwrap().to_owned());
1917 }
1918 }
1919 };
1920 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1921 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1922 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1925
1926 let filtered_extensions = [
1927 OsStr::new("rmeta"),
1928 OsStr::new("rlib"),
1929 OsStr::new(std::env::consts::DLL_EXTENSION),
1931 ];
1932 let ci_rustc_dir = builder.config.ci_rustc_dir();
1933 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1934 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1935 return true;
1936 }
1937 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1938 return true;
1939 }
1940 filtered_files.iter().all(|f| f != path.file_name().unwrap())
1941 });
1942 }
1943
1944 if compiler.stage != 0 {
1950 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1951 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1952 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1953 if let Err(e) =
1954 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1955 {
1956 eprintln!(
1957 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1958 sysroot_lib_rustlib_src_rust.display(),
1959 builder.src.display(),
1960 e,
1961 );
1962 if builder.config.rust_remap_debuginfo {
1963 eprintln!(
1964 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1965 sysroot_lib_rustlib_src_rust.display(),
1966 );
1967 }
1968 build_helper::exit!(1);
1969 }
1970 }
1971
1972 if !builder.download_rustc() {
1974 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1975 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1976 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1977 if let Err(e) =
1978 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1979 {
1980 eprintln!(
1981 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1982 sysroot_lib_rustlib_rustcsrc_rust.display(),
1983 builder.src.display(),
1984 e,
1985 );
1986 build_helper::exit!(1);
1987 }
1988 }
1989
1990 sysroot
1991 }
1992}
1993
1994#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2001pub struct Assemble {
2002 pub target_compiler: Compiler,
2007}
2008
2009impl Step for Assemble {
2010 type Output = Compiler;
2011 const IS_HOST: bool = true;
2012
2013 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2014 run.path("compiler/rustc").path("compiler")
2015 }
2016
2017 fn make_run(run: RunConfig<'_>) {
2018 run.builder.ensure(Assemble {
2019 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2020 });
2021 }
2022
2023 fn run(self, builder: &Builder<'_>) -> Compiler {
2024 let target_compiler = self.target_compiler;
2025
2026 if target_compiler.stage == 0 {
2027 trace!("stage 0 build compiler is always available, simply returning");
2028 assert_eq!(
2029 builder.config.host_target, target_compiler.host,
2030 "Cannot obtain compiler for non-native build triple at stage 0"
2031 );
2032 return target_compiler;
2034 }
2035
2036 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2039 let libdir_bin = libdir.parent().unwrap().join("bin");
2040 t!(fs::create_dir_all(&libdir_bin));
2041
2042 if builder.config.llvm_enabled(target_compiler.host) {
2043 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2044
2045 let target = target_compiler.host;
2046 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2047 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2048 trace!("LLVM tools enabled");
2049
2050 let host_llvm_bin_dir = command(&host_llvm_config)
2051 .arg("--bindir")
2052 .cached()
2053 .run_capture_stdout(builder)
2054 .stdout()
2055 .trim()
2056 .to_string();
2057
2058 let llvm_bin_dir = if target == builder.host_target {
2059 PathBuf::from(host_llvm_bin_dir)
2060 } else {
2061 let external_llvm_config = builder
2064 .config
2065 .target_config
2066 .get(&target)
2067 .and_then(|t| t.llvm_config.clone());
2068 if let Some(external_llvm_config) = external_llvm_config {
2069 external_llvm_config.parent().unwrap().to_path_buf()
2072 } else {
2073 let host_llvm_out = builder.llvm_out(builder.host_target);
2077 let target_llvm_out = builder.llvm_out(target);
2078 if let Ok(relative_path) =
2079 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2080 {
2081 target_llvm_out.join(relative_path)
2082 } else {
2083 PathBuf::from(
2086 host_llvm_bin_dir
2087 .replace(&*builder.host_target.triple, &target.triple),
2088 )
2089 }
2090 }
2091 };
2092
2093 #[cfg(feature = "tracing")]
2100 let _llvm_tools_span =
2101 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2102 .entered();
2103 for tool in LLVM_TOOLS {
2104 trace!("installing `{tool}`");
2105 let tool_exe = exe(tool, target_compiler.host);
2106 let src_path = llvm_bin_dir.join(&tool_exe);
2107
2108 if !src_path.exists() && builder.config.llvm_from_ci {
2110 eprintln!("{} does not exist; skipping copy", src_path.display());
2111 continue;
2112 }
2113
2114 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2121 }
2122 }
2123 }
2124
2125 let maybe_install_llvm_bitcode_linker = || {
2126 if builder.config.llvm_bitcode_linker_enabled {
2127 trace!("llvm-bitcode-linker enabled, installing");
2128 let llvm_bitcode_linker = builder.ensure(
2129 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2130 builder,
2131 target_compiler,
2132 ),
2133 );
2134
2135 let bindir_self_contained = builder
2137 .sysroot(target_compiler)
2138 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2139 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2140
2141 t!(fs::create_dir_all(&bindir_self_contained));
2142 builder.copy_link(
2143 &llvm_bitcode_linker.tool_path,
2144 &bindir_self_contained.join(tool_exe),
2145 FileType::Executable,
2146 );
2147 }
2148 };
2149
2150 if builder.download_rustc() {
2152 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2153
2154 builder.std(target_compiler, target_compiler.host);
2155 let sysroot =
2156 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2157 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2160 if target_compiler.stage == builder.top_stage {
2162 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2163 }
2164
2165 maybe_install_llvm_bitcode_linker();
2168
2169 return target_compiler;
2170 }
2171
2172 debug!(
2186 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2187 target_compiler.stage - 1,
2188 builder.config.host_target,
2189 );
2190 let build_compiler =
2191 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2192
2193 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2195 debug!("`llvm_enzyme` requested");
2196 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2197 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2198 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2199 let lib_ext = std::env::consts::DLL_EXTENSION;
2200 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2201 let src_lib =
2202 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2203 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2204 let target_libdir =
2205 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2206 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2207 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2208 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2209 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2210 }
2211 }
2212
2213 debug!(
2216 ?build_compiler,
2217 "target_compiler.host" = ?target_compiler.host,
2218 "building compiler libraries to link to"
2219 );
2220
2221 let BuiltRustc { build_compiler } =
2223 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2224
2225 let stage = target_compiler.stage;
2226 let host = target_compiler.host;
2227 let (host_info, dir_name) = if build_compiler.host == host {
2228 ("".into(), "host".into())
2229 } else {
2230 (format!(" ({host})"), host.to_string())
2231 };
2232 let msg = format!(
2237 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2238 );
2239 builder.info(&msg);
2240
2241 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2243 let proc_macros = builder
2244 .read_stamp_file(&stamp)
2245 .into_iter()
2246 .filter_map(|(path, dependency_type)| {
2247 if dependency_type == DependencyType::Host {
2248 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2249 } else {
2250 None
2251 }
2252 })
2253 .collect::<HashSet<_>>();
2254
2255 let sysroot = builder.sysroot(target_compiler);
2256 let rustc_libdir = builder.rustc_libdir(target_compiler);
2257 t!(fs::create_dir_all(&rustc_libdir));
2258 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2259 for f in builder.read_dir(&src_libdir) {
2260 let filename = f.file_name().into_string().unwrap();
2261
2262 let is_proc_macro = proc_macros.contains(&filename);
2263 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2264
2265 let can_be_rustc_dynamic_dep = if builder
2269 .link_std_into_rustc_driver(target_compiler.host)
2270 && !target_compiler.host.is_windows()
2271 {
2272 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2273 !is_std
2274 } else {
2275 true
2276 };
2277
2278 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2279 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2280 }
2281 }
2282
2283 {
2284 #[cfg(feature = "tracing")]
2285 let _codegen_backend_span =
2286 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2287
2288 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2289 if builder.kind == Kind::Check && builder.top_stage == 1 {
2306 continue;
2307 }
2308
2309 let prepare_compilers = || {
2310 RustcPrivateCompilers::from_build_and_target_compiler(
2311 build_compiler,
2312 target_compiler,
2313 )
2314 };
2315
2316 match backend {
2317 CodegenBackendKind::Cranelift => {
2318 let stamp = builder
2319 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2320 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2321 }
2322 CodegenBackendKind::Gcc => {
2323 let output =
2324 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2325 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2326 output.gcc.install_to(builder, &rustc_libdir);
2329 }
2330 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2331 }
2332 }
2333 }
2334
2335 if builder.config.lld_enabled {
2336 let lld_wrapper =
2337 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2338 builder,
2339 target_compiler,
2340 ));
2341 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2342 }
2343
2344 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2345 debug!(
2346 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2347 workaround faulty homebrew `strip`s"
2348 );
2349
2350 let src_exe = exe("llvm-objcopy", target_compiler.host);
2357 let dst_exe = exe("rust-objcopy", target_compiler.host);
2358 builder.copy_link(
2359 &libdir_bin.join(src_exe),
2360 &libdir_bin.join(dst_exe),
2361 FileType::Executable,
2362 );
2363 }
2364
2365 if builder.tool_enabled("wasm-component-ld") {
2368 let wasm_component = builder.ensure(
2369 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2370 builder,
2371 target_compiler,
2372 ),
2373 );
2374 builder.copy_link(
2375 &wasm_component.tool_path,
2376 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2377 FileType::Executable,
2378 );
2379 }
2380
2381 maybe_install_llvm_bitcode_linker();
2382
2383 debug!(
2386 "target_compiler.host" = ?target_compiler.host,
2387 ?sysroot,
2388 "ensuring availability of `libLLVM.so` in compiler directory"
2389 );
2390 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2391 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2392
2393 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2395 let rustc = out_dir.join(exe("rustc-main", host));
2396 let bindir = sysroot.join("bin");
2397 t!(fs::create_dir_all(bindir));
2398 let compiler = builder.rustc(target_compiler);
2399 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2400 builder.copy_link(&rustc, &compiler, FileType::Executable);
2401
2402 target_compiler
2403 }
2404}
2405
2406#[track_caller]
2411pub fn add_to_sysroot(
2412 builder: &Builder<'_>,
2413 sysroot_dst: &Path,
2414 sysroot_host_dst: &Path,
2415 stamp: &BuildStamp,
2416) {
2417 let self_contained_dst = &sysroot_dst.join("self-contained");
2418 t!(fs::create_dir_all(sysroot_dst));
2419 t!(fs::create_dir_all(sysroot_host_dst));
2420 t!(fs::create_dir_all(self_contained_dst));
2421 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2422 let dst = match dependency_type {
2423 DependencyType::Host => sysroot_host_dst,
2424 DependencyType::Target => sysroot_dst,
2425 DependencyType::TargetSelfContained => self_contained_dst,
2426 };
2427 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2428 }
2429}
2430
2431pub fn run_cargo(
2432 builder: &Builder<'_>,
2433 cargo: Cargo,
2434 tail_args: Vec<String>,
2435 stamp: &BuildStamp,
2436 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2437 is_check: bool,
2438 rlib_only_metadata: bool,
2439) -> Vec<PathBuf> {
2440 let target_root_dir = stamp.path().parent().unwrap();
2442 let target_deps_dir = target_root_dir.join("deps");
2444 let host_root_dir = target_root_dir
2446 .parent()
2447 .unwrap() .parent()
2449 .unwrap() .join(target_root_dir.file_name().unwrap());
2451
2452 let mut deps = Vec::new();
2456 let mut toplevel = Vec::new();
2457 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2458 let (filenames_vec, crate_types) = match msg {
2459 CargoMessage::CompilerArtifact {
2460 filenames,
2461 target: CargoTarget { crate_types },
2462 ..
2463 } => {
2464 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2465 f.sort(); (f, crate_types)
2467 }
2468 _ => return,
2469 };
2470 for filename in filenames_vec {
2471 let mut keep = false;
2473 if filename.ends_with(".lib")
2474 || filename.ends_with(".a")
2475 || is_debug_info(&filename)
2476 || is_dylib(Path::new(&*filename))
2477 {
2478 keep = true;
2480 }
2481 if is_check && filename.ends_with(".rmeta") {
2482 keep = true;
2484 } else if rlib_only_metadata {
2485 if filename.contains("jemalloc_sys")
2486 || filename.contains("rustc_public_bridge")
2487 || filename.contains("rustc_public")
2488 {
2489 keep |= filename.ends_with(".rlib");
2492 } else {
2493 keep |= filename.ends_with(".rmeta");
2497 }
2498 } else {
2499 keep |= filename.ends_with(".rlib");
2501 }
2502
2503 if !keep {
2504 continue;
2505 }
2506
2507 let filename = Path::new(&*filename);
2508
2509 if filename.starts_with(&host_root_dir) {
2512 if crate_types.iter().any(|t| t == "proc-macro") {
2514 deps.push((filename.to_path_buf(), DependencyType::Host));
2515 }
2516 continue;
2517 }
2518
2519 if filename.starts_with(&target_deps_dir) {
2522 deps.push((filename.to_path_buf(), DependencyType::Target));
2523 continue;
2524 }
2525
2526 let expected_len = t!(filename.metadata()).len();
2537 let filename = filename.file_name().unwrap().to_str().unwrap();
2538 let mut parts = filename.splitn(2, '.');
2539 let file_stem = parts.next().unwrap().to_owned();
2540 let extension = parts.next().unwrap().to_owned();
2541
2542 toplevel.push((file_stem, extension, expected_len));
2543 }
2544 });
2545
2546 if !ok {
2547 crate::exit!(1);
2548 }
2549
2550 if builder.config.dry_run() {
2551 return Vec::new();
2552 }
2553
2554 let contents = target_deps_dir
2558 .read_dir()
2559 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2560 .map(|e| t!(e))
2561 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2562 .collect::<Vec<_>>();
2563 for (prefix, extension, expected_len) in toplevel {
2564 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2565 meta.len() == expected_len
2566 && filename
2567 .strip_prefix(&prefix[..])
2568 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2569 .unwrap_or(false)
2570 });
2571 let max = candidates.max_by_key(|&(_, _, metadata)| {
2572 metadata.modified().expect("mtime should be available on all relevant OSes")
2573 });
2574 let path_to_add = match max {
2575 Some(triple) => triple.0.to_str().unwrap(),
2576 None => panic!("no output generated for {prefix:?} {extension:?}"),
2577 };
2578 if is_dylib(Path::new(path_to_add)) {
2579 let candidate = format!("{path_to_add}.lib");
2580 let candidate = PathBuf::from(candidate);
2581 if candidate.exists() {
2582 deps.push((candidate, DependencyType::Target));
2583 }
2584 }
2585 deps.push((path_to_add.into(), DependencyType::Target));
2586 }
2587
2588 deps.extend(additional_target_deps);
2589 deps.sort();
2590 let mut new_contents = Vec::new();
2591 for (dep, dependency_type) in deps.iter() {
2592 new_contents.extend(match *dependency_type {
2593 DependencyType::Host => b"h",
2594 DependencyType::Target => b"t",
2595 DependencyType::TargetSelfContained => b"s",
2596 });
2597 new_contents.extend(dep.to_str().unwrap().as_bytes());
2598 new_contents.extend(b"\0");
2599 }
2600 t!(fs::write(stamp.path(), &new_contents));
2601 deps.into_iter().map(|(d, _)| d).collect()
2602}
2603
2604pub fn stream_cargo(
2605 builder: &Builder<'_>,
2606 cargo: Cargo,
2607 tail_args: Vec<String>,
2608 cb: &mut dyn FnMut(CargoMessage<'_>),
2609) -> bool {
2610 let mut cmd = cargo.into_cmd();
2611
2612 let mut message_format = if builder.config.json_output {
2615 String::from("json")
2616 } else {
2617 String::from("json-render-diagnostics")
2618 };
2619 if let Some(s) = &builder.config.rustc_error_format {
2620 message_format.push_str(",json-diagnostic-");
2621 message_format.push_str(s);
2622 }
2623 cmd.arg("--message-format").arg(message_format);
2624
2625 for arg in tail_args {
2626 cmd.arg(arg);
2627 }
2628
2629 builder.do_if_verbose(|| println!("running: {cmd:?}"));
2630
2631 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2632
2633 let Some(mut streaming_command) = streaming_command else {
2634 return true;
2635 };
2636
2637 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2641 for line in stdout.lines() {
2642 let line = t!(line);
2643 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2644 Ok(msg) => {
2645 if builder.config.json_output {
2646 println!("{line}");
2648 }
2649 cb(msg)
2650 }
2651 Err(_) => println!("{line}"),
2653 }
2654 }
2655
2656 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2658 if builder.is_verbose() && !status.success() {
2659 eprintln!(
2660 "command did not execute successfully: {cmd:?}\n\
2661 expected success, got: {status}"
2662 );
2663 }
2664
2665 status.success()
2666}
2667
2668#[derive(Deserialize)]
2669pub struct CargoTarget<'a> {
2670 crate_types: Vec<Cow<'a, str>>,
2671}
2672
2673#[derive(Deserialize)]
2674#[serde(tag = "reason", rename_all = "kebab-case")]
2675pub enum CargoMessage<'a> {
2676 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2677 BuildScriptExecuted,
2678 BuildFinished,
2679}
2680
2681pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2682 if target != "x86_64-unknown-linux-gnu"
2686 || !builder.config.is_host_target(target)
2687 || !path.exists()
2688 {
2689 return;
2690 }
2691
2692 let previous_mtime = t!(t!(path.metadata()).modified());
2693 let stamp = BuildStamp::new(path.parent().unwrap())
2694 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2695 .with_prefix("strip")
2696 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2697
2698 if !stamp.is_up_to_date() {
2701 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2702 }
2703 t!(stamp.write());
2704
2705 let file = t!(fs::File::open(path));
2706
2707 t!(file.set_modified(previous_mtime));
2720}
2721
2722pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2724 build_compiler.stage != 0
2725}