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 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
117 run.crate_or_deps("sysroot").path("library")
118 }
119
120 fn is_default_step(_builder: &Builder<'_>) -> bool {
121 true
122 }
123
124 fn make_run(run: RunConfig<'_>) {
125 let crates = std_crates_for_run_make(&run);
126 let builder = run.builder;
127
128 let force_recompile = builder.rust_info().is_managed_git_subrepository()
132 && builder.download_rustc()
133 && builder.config.has_changes_from_upstream(&["library"]);
134
135 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
136 trace!("download_rustc: {}", builder.download_rustc());
137 trace!(force_recompile);
138
139 run.builder.ensure(Std {
140 build_compiler: run.builder.compiler(run.builder.top_stage, builder.host_target),
143 target: run.target,
144 crates,
145 force_recompile,
146 extra_rust_args: &[],
147 is_for_mir_opt_tests: false,
148 });
149 }
150
151 fn run(self, builder: &Builder<'_>) -> Self::Output {
157 let target = self.target;
158
159 if self.build_compiler.stage == 0
164 && !(builder.local_rebuild && target != builder.host_target)
165 {
166 let compiler = self.build_compiler;
167 builder.ensure(StdLink::from_std(self, compiler));
168
169 return None;
170 }
171
172 let build_compiler = if builder.download_rustc() && self.force_recompile {
173 builder
176 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
177 } else {
178 self.build_compiler
179 };
180
181 if builder.download_rustc()
184 && builder.config.is_host_target(target)
185 && !self.force_recompile
186 {
187 let sysroot =
188 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
189 cp_rustc_component_to_ci_sysroot(
190 builder,
191 &sysroot,
192 builder.config.ci_rust_std_contents(),
193 );
194 return None;
195 }
196
197 if builder.config.keep_stage.contains(&build_compiler.stage)
198 || builder.config.keep_stage_std.contains(&build_compiler.stage)
199 {
200 trace!(keep_stage = ?builder.config.keep_stage);
201 trace!(keep_stage_std = ?builder.config.keep_stage_std);
202
203 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
204
205 builder.ensure(StartupObjects { compiler: build_compiler, target });
206
207 self.copy_extra_objects(builder, &build_compiler, target);
208
209 builder.ensure(StdLink::from_std(self, build_compiler));
210 return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
211 }
212
213 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
214
215 let stage = build_compiler.stage;
217
218 if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
219 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
220 let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
221
222 let msg = if build_compiler_for_std_to_uplift.host == target {
223 format!(
224 "Uplifting library (stage{} -> stage{stage})",
225 build_compiler_for_std_to_uplift.stage
226 )
227 } else {
228 format!(
229 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
230 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
231 )
232 };
233
234 builder.info(&msg);
235
236 self.copy_extra_objects(builder, &build_compiler, target);
239
240 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
241 return stage_1_stamp;
242 }
243
244 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
245
246 let mut cargo = if self.is_for_mir_opt_tests {
250 trace!("building special sysroot for mir-opt tests");
251 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
252 builder,
253 build_compiler,
254 Mode::Std,
255 SourceType::InTree,
256 target,
257 Kind::Check,
258 );
259 cargo.rustflag("-Zalways-encode-mir");
260 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
261 cargo
262 } else {
263 trace!("building regular sysroot");
264 let mut cargo = builder::Cargo::new(
265 builder,
266 build_compiler,
267 Mode::Std,
268 SourceType::InTree,
269 target,
270 Kind::Build,
271 );
272 std_cargo(builder, target, &mut cargo, &self.crates);
273 cargo
274 };
275
276 if target.is_synthetic() {
278 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
279 }
280 for rustflag in self.extra_rust_args.iter() {
281 cargo.rustflag(rustflag);
282 }
283
284 let _guard = builder.msg(
285 Kind::Build,
286 format_args!("library artifacts{}", crate_description(&self.crates)),
287 Mode::Std,
288 build_compiler,
289 target,
290 );
291
292 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
293 run_cargo(
294 builder,
295 cargo,
296 vec![],
297 &stamp,
298 target_deps,
299 self.is_for_mir_opt_tests, false,
301 );
302
303 builder.ensure(StdLink::from_std(
304 self,
305 builder.compiler(build_compiler.stage, builder.config.host_target),
306 ));
307 Some(stamp)
308 }
309
310 fn metadata(&self) -> Option<StepMetadata> {
311 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
312 }
313}
314
315fn copy_and_stamp(
316 builder: &Builder<'_>,
317 libdir: &Path,
318 sourcedir: &Path,
319 name: &str,
320 target_deps: &mut Vec<(PathBuf, DependencyType)>,
321 dependency_type: DependencyType,
322) {
323 let target = libdir.join(name);
324 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
325
326 target_deps.push((target, dependency_type));
327}
328
329fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
330 let libunwind_path = builder.ensure(llvm::Libunwind { target });
331 let libunwind_source = libunwind_path.join("libunwind.a");
332 let libunwind_target = libdir.join("libunwind.a");
333 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
334 libunwind_target
335}
336
337fn copy_third_party_objects(
339 builder: &Builder<'_>,
340 compiler: &Compiler,
341 target: TargetSelection,
342) -> Vec<(PathBuf, DependencyType)> {
343 let mut target_deps = vec![];
344
345 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
346 target_deps.extend(
349 copy_sanitizers(builder, compiler, target)
350 .into_iter()
351 .map(|d| (d, DependencyType::Target)),
352 );
353 }
354
355 if target == "x86_64-fortanix-unknown-sgx"
356 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
357 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
358 {
359 let libunwind_path =
360 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
361 target_deps.push((libunwind_path, DependencyType::Target));
362 }
363
364 target_deps
365}
366
367fn copy_self_contained_objects(
369 builder: &Builder<'_>,
370 compiler: &Compiler,
371 target: TargetSelection,
372) -> Vec<(PathBuf, DependencyType)> {
373 let libdir_self_contained =
374 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
375 t!(fs::create_dir_all(&libdir_self_contained));
376 let mut target_deps = vec![];
377
378 if target.needs_crt_begin_end() {
386 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
387 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
388 });
389 if !target.starts_with("wasm32") {
390 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
391 copy_and_stamp(
392 builder,
393 &libdir_self_contained,
394 &srcdir,
395 obj,
396 &mut target_deps,
397 DependencyType::TargetSelfContained,
398 );
399 }
400 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
401 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
402 let src = crt_path.join(obj);
403 let target = libdir_self_contained.join(obj);
404 builder.copy_link(&src, &target, FileType::NativeLibrary);
405 target_deps.push((target, DependencyType::TargetSelfContained));
406 }
407 } else {
408 for &obj in &["libc.a", "crt1-command.o"] {
411 copy_and_stamp(
412 builder,
413 &libdir_self_contained,
414 &srcdir,
415 obj,
416 &mut target_deps,
417 DependencyType::TargetSelfContained,
418 );
419 }
420 }
421 if !target.starts_with("s390x") {
422 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
423 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
424 }
425 } else if target.contains("-wasi") {
426 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
427 panic!(
428 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
429 or `$WASI_SDK_PATH` set",
430 target.triple
431 )
432 });
433
434 let srcdir = if target == "wasm32-wasip3" {
438 assert!(!srcdir.exists(), "wasip3 support is in wasi-libc, this should be updated now");
439 builder.wasi_libdir(TargetSelection::from_user("wasm32-wasip2")).unwrap()
440 } else {
441 srcdir
442 };
443 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
444 copy_and_stamp(
445 builder,
446 &libdir_self_contained,
447 &srcdir,
448 obj,
449 &mut target_deps,
450 DependencyType::TargetSelfContained,
451 );
452 }
453 } else if target.is_windows_gnu() || target.is_windows_gnullvm() {
454 for obj in ["crt2.o", "dllcrt2.o"].iter() {
455 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
456 let dst = libdir_self_contained.join(obj);
457 builder.copy_link(&src, &dst, FileType::NativeLibrary);
458 target_deps.push((dst, DependencyType::TargetSelfContained));
459 }
460 }
461
462 target_deps
463}
464
465pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
468 let mut crates = run.make_run_crates(builder::Alias::Library);
469
470 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
479 if target_is_no_std {
480 crates.retain(|c| c == "core" || c == "alloc");
481 }
482 crates
483}
484
485fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
491 if builder.config.llvm_from_ci {
493 builder.config.maybe_download_ci_llvm();
495 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
496 if ci_llvm_compiler_rt.exists() {
497 return ci_llvm_compiler_rt;
498 }
499 }
500
501 builder.require_submodule("src/llvm-project", {
503 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
504 });
505 builder.src.join("src/llvm-project/compiler-rt")
506}
507
508pub fn std_cargo(
511 builder: &Builder<'_>,
512 target: TargetSelection,
513 cargo: &mut Cargo,
514 crates: &[String],
515) {
516 if target.contains("apple") && !builder.config.dry_run() {
534 let mut cmd = builder.rustc_cmd(cargo.compiler());
538 cmd.arg("--target").arg(target.rustc_target_arg());
539 cmd.arg("--print=deployment-target");
540 let output = cmd.run_capture_stdout(builder).stdout();
541
542 let (env_var, value) = output.split_once('=').unwrap();
543 cargo.env(env_var.trim(), value.trim());
546
547 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
557 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
558 }
559 }
560
561 if let Some(path) = builder.config.profiler_path(target) {
563 cargo.env("LLVM_PROFILER_RT_LIB", path);
564 } else if builder.config.profiler_enabled(target) {
565 let compiler_rt = compiler_rt_for_profiler(builder);
566 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
570 }
571
572 let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
586 CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
587 cargo.env("LLVM_COMPILER_RT_LIB", path);
588 " compiler-builtins-c"
589 }
590 CompilerBuiltins::BuildLLVMFuncs => {
591 builder.require_submodule(
601 "src/llvm-project",
602 Some(
603 "The `build.optimized-compiler-builtins` config option \
604 requires `compiler-rt` sources from LLVM.",
605 ),
606 );
607 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
608 if !builder.config.dry_run() {
609 assert!(compiler_builtins_root.exists());
612 }
613
614 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
617 " compiler-builtins-c"
618 }
619 CompilerBuiltins::BuildRustOnly => "",
620 };
621
622 if !builder.unstable_features() {
625 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
626 }
627
628 for krate in crates {
629 cargo.args(["-p", krate]);
630 }
631
632 let mut features = String::new();
633
634 if builder.no_std(target) == Some(true) {
635 features += " compiler-builtins-mem";
636 if !target.starts_with("bpf") {
637 features.push_str(compiler_builtins_c_feature);
638 }
639
640 if crates.is_empty() {
642 cargo.args(["-p", "alloc"]);
643 }
644 cargo
645 .arg("--manifest-path")
646 .arg(builder.src.join("library/alloc/Cargo.toml"))
647 .arg("--features")
648 .arg(features);
649 } else {
650 features += &builder.std_features(target);
651 features.push_str(compiler_builtins_c_feature);
652
653 cargo
654 .arg("--features")
655 .arg(features)
656 .arg("--manifest-path")
657 .arg(builder.src.join("library/sysroot/Cargo.toml"));
658
659 if target.contains("musl")
662 && let Some(p) = builder.musl_libdir(target)
663 {
664 let root = format!("native={}", p.to_str().unwrap());
665 cargo.rustflag("-L").rustflag(&root);
666 }
667
668 if target.contains("-wasi")
669 && let Some(dir) = builder.wasi_libdir(target)
670 {
671 let root = format!("native={}", dir.to_str().unwrap());
672 cargo.rustflag("-L").rustflag(&root);
673 }
674 }
675
676 cargo.rustflag("-Cembed-bitcode=yes");
682
683 if builder.config.rust_lto == RustcLto::Off {
684 cargo.rustflag("-Clto=off");
685 }
686
687 if target.contains("riscv") {
694 cargo.rustflag("-Cforce-unwind-tables=yes");
695 }
696
697 cargo.rustflag("-Zunstable-options");
700 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
701
702 let html_root =
703 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
704 cargo.rustflag(&html_root);
705 cargo.rustdocflag(&html_root);
706
707 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
708}
709
710#[derive(Debug, Clone, PartialEq, Eq, Hash)]
719pub struct StdLink {
720 pub compiler: Compiler,
721 pub target_compiler: Compiler,
722 pub target: TargetSelection,
723 crates: Vec<String>,
725 force_recompile: bool,
727}
728
729impl StdLink {
730 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
731 Self {
732 compiler: host_compiler,
733 target_compiler: std.build_compiler,
734 target: std.target,
735 crates: std.crates,
736 force_recompile: std.force_recompile,
737 }
738 }
739}
740
741impl Step for StdLink {
742 type Output = ();
743
744 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
745 run.never()
746 }
747
748 fn run(self, builder: &Builder<'_>) {
757 let compiler = self.compiler;
758 let target_compiler = self.target_compiler;
759 let target = self.target;
760
761 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
763 let lib = builder.sysroot_libdir_relative(self.compiler);
765 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
766 compiler: self.compiler,
767 force_recompile: self.force_recompile,
768 });
769 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
770 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
771 (libdir, hostdir)
772 } else {
773 let libdir = builder.sysroot_target_libdir(target_compiler, target);
774 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
775 (libdir, hostdir)
776 };
777
778 let is_downloaded_beta_stage0 = builder
779 .build
780 .config
781 .initial_rustc
782 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
783
784 if compiler.stage == 0 && is_downloaded_beta_stage0 {
788 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
790
791 let host = compiler.host;
792 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
793 let sysroot_bin_dir = sysroot.join("bin");
794 t!(fs::create_dir_all(&sysroot_bin_dir));
795 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
796
797 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
798 t!(fs::create_dir_all(sysroot.join("lib")));
799 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
800
801 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
803 t!(fs::create_dir_all(&sysroot_codegen_backends));
804 let stage0_codegen_backends = builder
805 .out
806 .join(host)
807 .join("stage0/lib/rustlib")
808 .join(host)
809 .join("codegen-backends");
810 if stage0_codegen_backends.exists() {
811 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
812 }
813 } else if compiler.stage == 0 {
814 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
815
816 if builder.local_rebuild {
817 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
821 }
822
823 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
824 } else {
825 if builder.download_rustc() {
826 let _ = fs::remove_dir_all(&libdir);
828 let _ = fs::remove_dir_all(&hostdir);
829 }
830
831 add_to_sysroot(
832 builder,
833 &libdir,
834 &hostdir,
835 &build_stamp::libstd_stamp(builder, compiler, target),
836 );
837 }
838 }
839}
840
841fn copy_sanitizers(
843 builder: &Builder<'_>,
844 compiler: &Compiler,
845 target: TargetSelection,
846) -> Vec<PathBuf> {
847 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
848
849 if builder.config.dry_run() {
850 return Vec::new();
851 }
852
853 let mut target_deps = Vec::new();
854 let libdir = builder.sysroot_target_libdir(*compiler, target);
855
856 for runtime in &runtimes {
857 let dst = libdir.join(&runtime.name);
858 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
859
860 if target == "x86_64-apple-darwin"
864 || target == "aarch64-apple-darwin"
865 || target == "aarch64-apple-ios"
866 || target == "aarch64-apple-ios-sim"
867 || target == "x86_64-apple-ios"
868 {
869 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
871 apple_darwin_sign_file(builder, &dst);
874 }
875
876 target_deps.push(dst);
877 }
878
879 target_deps
880}
881
882fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
883 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
884}
885
886fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
887 command("codesign")
888 .arg("-f") .arg("-s")
890 .arg("-")
891 .arg(file_path)
892 .run(builder);
893}
894
895#[derive(Debug, Clone, PartialEq, Eq, Hash)]
896pub struct StartupObjects {
897 pub compiler: Compiler,
898 pub target: TargetSelection,
899}
900
901impl Step for StartupObjects {
902 type Output = Vec<(PathBuf, DependencyType)>;
903
904 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
905 run.path("library/rtstartup")
906 }
907
908 fn make_run(run: RunConfig<'_>) {
909 run.builder.ensure(StartupObjects {
910 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
911 target: run.target,
912 });
913 }
914
915 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
922 let for_compiler = self.compiler;
923 let target = self.target;
924 if !target.is_windows_gnu() {
927 return vec![];
928 }
929
930 let mut target_deps = vec![];
931
932 let src_dir = &builder.src.join("library").join("rtstartup");
933 let dst_dir = &builder.native_dir(target).join("rtstartup");
934 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
935 t!(fs::create_dir_all(dst_dir));
936
937 for file in &["rsbegin", "rsend"] {
938 let src_file = &src_dir.join(file.to_string() + ".rs");
939 let dst_file = &dst_dir.join(file.to_string() + ".o");
940 if !up_to_date(src_file, dst_file) {
941 let mut cmd = command(&builder.initial_rustc);
942 cmd.env("RUSTC_BOOTSTRAP", "1");
943 if !builder.local_rebuild {
944 cmd.arg("--cfg").arg("bootstrap");
946 }
947 cmd.arg("--target")
948 .arg(target.rustc_target_arg())
949 .arg("--emit=obj")
950 .arg("-o")
951 .arg(dst_file)
952 .arg(src_file)
953 .run(builder);
954 }
955
956 let obj = sysroot_dir.join((*file).to_string() + ".o");
957 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
958 target_deps.push((obj, DependencyType::Target));
959 }
960
961 target_deps
962 }
963}
964
965fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
966 let ci_rustc_dir = builder.config.ci_rustc_dir();
967
968 for file in contents {
969 let src = ci_rustc_dir.join(&file);
970 let dst = sysroot.join(file);
971 if src.is_dir() {
972 t!(fs::create_dir_all(dst));
973 } else {
974 builder.copy_link(&src, &dst, FileType::Regular);
975 }
976 }
977}
978
979#[derive(Clone, Debug)]
981pub struct BuiltRustc {
982 pub build_compiler: Compiler,
986}
987
988#[derive(Debug, Clone, PartialEq, Eq, Hash)]
995pub struct Rustc {
996 pub target: TargetSelection,
998 pub build_compiler: Compiler,
1000 crates: Vec<String>,
1006}
1007
1008impl Rustc {
1009 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
1010 Self { target, build_compiler, crates: Default::default() }
1011 }
1012}
1013
1014impl Step for Rustc {
1015 type Output = BuiltRustc;
1016 const IS_HOST: bool = true;
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 is_default_step(_builder: &Builder<'_>) -> bool {
1032 false
1033 }
1034
1035 fn make_run(run: RunConfig<'_>) {
1036 if run.builder.paths == vec![PathBuf::from("compiler")] {
1039 return;
1040 }
1041
1042 let crates = run.cargo_crates_in_set();
1043 run.builder.ensure(Rustc {
1044 build_compiler: run
1045 .builder
1046 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1047 target: run.target,
1048 crates,
1049 });
1050 }
1051
1052 fn run(self, builder: &Builder<'_>) -> Self::Output {
1058 let build_compiler = self.build_compiler;
1059 let target = self.target;
1060
1061 if builder.download_rustc() && build_compiler.stage != 0 {
1064 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1065
1066 let sysroot =
1067 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1068 cp_rustc_component_to_ci_sysroot(
1069 builder,
1070 &sysroot,
1071 builder.config.ci_rustc_dev_contents(),
1072 );
1073 return BuiltRustc { build_compiler };
1074 }
1075
1076 builder.std(build_compiler, target);
1079
1080 if builder.config.keep_stage.contains(&build_compiler.stage) {
1081 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1082
1083 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1084 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1085 builder.ensure(RustcLink::from_rustc(self));
1086
1087 return BuiltRustc { build_compiler };
1088 }
1089
1090 let stage = build_compiler.stage + 1;
1092
1093 if build_compiler.stage >= 2
1098 && !builder.config.full_bootstrap
1099 && target == builder.host_target
1100 {
1101 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1105
1106 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1107 builder.info(&msg);
1108
1109 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1113 uplift_build_compiler,
1115 build_compiler,
1117 target,
1118 self.crates,
1119 ));
1120
1121 return BuiltRustc { build_compiler: uplift_build_compiler };
1124 }
1125
1126 builder.std(
1132 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1133 builder.config.host_target,
1134 );
1135
1136 let mut cargo = builder::Cargo::new(
1137 builder,
1138 build_compiler,
1139 Mode::Rustc,
1140 SourceType::InTree,
1141 target,
1142 Kind::Build,
1143 );
1144
1145 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1146
1147 for krate in &*self.crates {
1151 cargo.arg("-p").arg(krate);
1152 }
1153
1154 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1155 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1157 }
1158
1159 let _guard = builder.msg(
1160 Kind::Build,
1161 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1162 Mode::Rustc,
1163 build_compiler,
1164 target,
1165 );
1166 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1167 run_cargo(
1168 builder,
1169 cargo,
1170 vec![],
1171 &stamp,
1172 vec![],
1173 false,
1174 true, );
1176
1177 let target_root_dir = stamp.path().parent().unwrap();
1178 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1184 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1185 {
1186 let rustc_driver = target_root_dir.join("librustc_driver.so");
1187 strip_debug(builder, target, &rustc_driver);
1188 }
1189
1190 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1191 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1194 }
1195
1196 builder.ensure(RustcLink::from_rustc(self));
1197 BuiltRustc { build_compiler }
1198 }
1199
1200 fn metadata(&self) -> Option<StepMetadata> {
1201 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1202 }
1203}
1204
1205pub fn rustc_cargo(
1206 builder: &Builder<'_>,
1207 cargo: &mut Cargo,
1208 target: TargetSelection,
1209 build_compiler: &Compiler,
1210 crates: &[String],
1211) {
1212 cargo
1213 .arg("--features")
1214 .arg(builder.rustc_features(builder.kind, target, crates))
1215 .arg("--manifest-path")
1216 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1217
1218 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1219
1220 cargo.rustflag("-Zon-broken-pipe=kill");
1234
1235 if builder.config.llvm_enzyme {
1238 let arch = builder.build.host_target;
1239 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1240 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1241
1242 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1243 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1244 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1245 }
1246 }
1247
1248 if builder.build.config.bootstrap_override_lld.is_used() {
1253 cargo.rustflag("-Zdefault-visibility=protected");
1254 }
1255
1256 if is_lto_stage(build_compiler) {
1257 match builder.config.rust_lto {
1258 RustcLto::Thin | RustcLto::Fat => {
1259 cargo.rustflag("-Zdylib-lto");
1262 let lto_type = match builder.config.rust_lto {
1266 RustcLto::Thin => "thin",
1267 RustcLto::Fat => "fat",
1268 _ => unreachable!(),
1269 };
1270 cargo.rustflag(&format!("-Clto={lto_type}"));
1271 cargo.rustflag("-Cembed-bitcode=yes");
1272 }
1273 RustcLto::ThinLocal => { }
1274 RustcLto::Off => {
1275 cargo.rustflag("-Clto=off");
1276 }
1277 }
1278 } else if builder.config.rust_lto == RustcLto::Off {
1279 cargo.rustflag("-Clto=off");
1280 }
1281
1282 if builder.config.bootstrap_override_lld.is_used() && !build_compiler.host.is_msvc() {
1290 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1291 }
1292
1293 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1294 panic!("Cannot use and generate PGO profiles at the same time");
1295 }
1296 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1297 if build_compiler.stage == 1 {
1298 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1299 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1302 true
1303 } else {
1304 false
1305 }
1306 } else if let Some(path) = &builder.config.rust_profile_use {
1307 if build_compiler.stage == 1 {
1308 cargo.rustflag(&format!("-Cprofile-use={path}"));
1309 if builder.is_verbose() {
1310 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1311 }
1312 true
1313 } else {
1314 false
1315 }
1316 } else {
1317 false
1318 };
1319 if is_collecting {
1320 cargo.rustflag(&format!(
1322 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1323 builder.config.src.components().count()
1324 ));
1325 }
1326
1327 if let Some(ref ccache) = builder.config.ccache
1332 && build_compiler.stage == 0
1333 && !builder.config.incremental
1334 {
1335 cargo.env("RUSTC_WRAPPER", ccache);
1336 }
1337
1338 rustc_cargo_env(builder, cargo, target);
1339}
1340
1341pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1342 cargo
1345 .env("CFG_RELEASE", builder.rust_release())
1346 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1347 .env("CFG_VERSION", builder.rust_version());
1348
1349 if builder.config.omit_git_hash {
1353 cargo.env("CFG_OMIT_GIT_HASH", "1");
1354 }
1355
1356 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
1357
1358 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1359 let target_config = builder.config.target_config.get(&target);
1360
1361 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1362
1363 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1364 cargo.env("CFG_VER_DATE", ver_date);
1365 }
1366 if let Some(ref ver_hash) = builder.rust_info().sha() {
1367 cargo.env("CFG_VER_HASH", ver_hash);
1368 }
1369 if !builder.unstable_features() {
1370 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1371 }
1372
1373 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1376 cargo.env("CFG_DEFAULT_LINKER", s);
1377 } else if let Some(ref s) = builder.config.rustc_default_linker {
1378 cargo.env("CFG_DEFAULT_LINKER", s);
1379 }
1380
1381 if let Some(linker) = target_config.map(|c| c.default_linker_linux_override) {
1383 match linker {
1384 DefaultLinuxLinkerOverride::Off => {}
1385 DefaultLinuxLinkerOverride::SelfContainedLldCc => {
1386 cargo.env("CFG_DEFAULT_LINKER_SELF_CONTAINED_LLD_CC", "1");
1387 }
1388 }
1389 }
1390
1391 if builder.config.rust_verify_llvm_ir {
1392 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1393 }
1394
1395 if builder.config.llvm_enabled(target) {
1407 let building_llvm_is_expensive =
1408 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1409 .should_build();
1410
1411 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1412 if !skip_llvm {
1413 rustc_llvm_env(builder, cargo, target)
1414 }
1415 }
1416
1417 if builder.config.jemalloc(target) && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() {
1419 if target.starts_with("aarch64") {
1422 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1423 }
1424 else if target.starts_with("loongarch") {
1426 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
1427 }
1428 }
1429}
1430
1431fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1437 if builder.config.is_rust_llvm(target) {
1438 cargo.env("LLVM_RUSTLLVM", "1");
1439 }
1440 if builder.config.llvm_enzyme {
1441 cargo.env("LLVM_ENZYME", "1");
1442 }
1443 if builder.config.llvm_offload {
1444 cargo.env("LLVM_OFFLOAD", "1");
1445 }
1446 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1447 cargo.env("LLVM_CONFIG", &host_llvm_config);
1448
1449 let mut llvm_linker_flags = String::new();
1459 if builder.config.llvm_profile_generate
1460 && target.is_msvc()
1461 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1462 {
1463 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1465 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1466 }
1467
1468 if let Some(ref s) = builder.config.llvm_ldflags {
1470 if !llvm_linker_flags.is_empty() {
1471 llvm_linker_flags.push(' ');
1472 }
1473 llvm_linker_flags.push_str(s);
1474 }
1475
1476 if !llvm_linker_flags.is_empty() {
1478 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1479 }
1480
1481 if builder.config.llvm_static_stdcpp
1484 && !target.contains("freebsd")
1485 && !target.is_msvc()
1486 && !target.contains("apple")
1487 && !target.contains("solaris")
1488 {
1489 let libstdcxx_name =
1490 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1491 let file = compiler_file(
1492 builder,
1493 &builder.cxx(target).unwrap(),
1494 target,
1495 CLang::Cxx,
1496 libstdcxx_name,
1497 );
1498 cargo.env("LLVM_STATIC_STDCPP", file);
1499 }
1500 if builder.llvm_link_shared() {
1501 cargo.env("LLVM_LINK_SHARED", "1");
1502 }
1503 if builder.config.llvm_use_libcxx {
1504 cargo.env("LLVM_USE_LIBCXX", "1");
1505 }
1506 if builder.config.llvm_assertions {
1507 cargo.env("LLVM_ASSERTIONS", "1");
1508 }
1509}
1510
1511#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1524struct RustcLink {
1525 build_compiler: Compiler,
1527 sysroot_compiler: Compiler,
1530 target: TargetSelection,
1531 crates: Vec<String>,
1533}
1534
1535impl RustcLink {
1536 fn from_rustc(rustc: Rustc) -> Self {
1539 Self {
1540 build_compiler: rustc.build_compiler,
1541 sysroot_compiler: rustc.build_compiler,
1542 target: rustc.target,
1543 crates: rustc.crates,
1544 }
1545 }
1546
1547 fn from_build_compiler_and_sysroot(
1549 build_compiler: Compiler,
1550 sysroot_compiler: Compiler,
1551 target: TargetSelection,
1552 crates: Vec<String>,
1553 ) -> Self {
1554 Self { build_compiler, sysroot_compiler, target, crates }
1555 }
1556}
1557
1558impl Step for RustcLink {
1559 type Output = ();
1560
1561 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1562 run.never()
1563 }
1564
1565 fn run(self, builder: &Builder<'_>) {
1567 let build_compiler = self.build_compiler;
1568 let sysroot_compiler = self.sysroot_compiler;
1569 let target = self.target;
1570 add_to_sysroot(
1571 builder,
1572 &builder.sysroot_target_libdir(sysroot_compiler, target),
1573 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1574 &build_stamp::librustc_stamp(builder, build_compiler, target),
1575 );
1576 }
1577}
1578
1579#[derive(Clone)]
1582pub struct GccCodegenBackendOutput {
1583 stamp: BuildStamp,
1584 gcc: GccOutput,
1585}
1586
1587#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1588pub struct GccCodegenBackend {
1589 compilers: RustcPrivateCompilers,
1590}
1591
1592impl Step for GccCodegenBackend {
1593 type Output = GccCodegenBackendOutput;
1594
1595 const IS_HOST: bool = true;
1596
1597 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1598 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1599 }
1600
1601 fn make_run(run: RunConfig<'_>) {
1602 run.builder.ensure(GccCodegenBackend {
1603 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1604 });
1605 }
1606
1607 fn run(self, builder: &Builder<'_>) -> Self::Output {
1608 let target = self.compilers.target();
1609 let build_compiler = self.compilers.build_compiler();
1610
1611 let stamp = build_stamp::codegen_backend_stamp(
1612 builder,
1613 build_compiler,
1614 target,
1615 &CodegenBackendKind::Gcc,
1616 );
1617
1618 let gcc = builder.ensure(Gcc { target });
1619
1620 if builder.config.keep_stage.contains(&build_compiler.stage) {
1621 trace!("`keep-stage` requested");
1622 builder.info(
1623 "WARNING: Using a potentially old codegen backend. \
1624 This may not behave well.",
1625 );
1626 return GccCodegenBackendOutput { stamp, gcc };
1629 }
1630
1631 let mut cargo = builder::Cargo::new(
1632 builder,
1633 build_compiler,
1634 Mode::Codegen,
1635 SourceType::InTree,
1636 target,
1637 Kind::Build,
1638 );
1639 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1640 rustc_cargo_env(builder, &mut cargo, target);
1641
1642 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1643
1644 let _guard =
1645 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1646 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1647
1648 GccCodegenBackendOutput {
1649 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1650 gcc,
1651 }
1652 }
1653
1654 fn metadata(&self) -> Option<StepMetadata> {
1655 Some(
1656 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1657 .built_by(self.compilers.build_compiler()),
1658 )
1659 }
1660}
1661
1662#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1663pub struct CraneliftCodegenBackend {
1664 pub compilers: RustcPrivateCompilers,
1665}
1666
1667impl Step for CraneliftCodegenBackend {
1668 type Output = BuildStamp;
1669 const IS_HOST: bool = true;
1670
1671 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1672 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1673 }
1674
1675 fn make_run(run: RunConfig<'_>) {
1676 run.builder.ensure(CraneliftCodegenBackend {
1677 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1678 });
1679 }
1680
1681 fn run(self, builder: &Builder<'_>) -> Self::Output {
1682 let target = self.compilers.target();
1683 let build_compiler = self.compilers.build_compiler();
1684
1685 let stamp = build_stamp::codegen_backend_stamp(
1686 builder,
1687 build_compiler,
1688 target,
1689 &CodegenBackendKind::Cranelift,
1690 );
1691
1692 if builder.config.keep_stage.contains(&build_compiler.stage) {
1693 trace!("`keep-stage` requested");
1694 builder.info(
1695 "WARNING: Using a potentially old codegen backend. \
1696 This may not behave well.",
1697 );
1698 return stamp;
1701 }
1702
1703 let mut cargo = builder::Cargo::new(
1704 builder,
1705 build_compiler,
1706 Mode::Codegen,
1707 SourceType::InTree,
1708 target,
1709 Kind::Build,
1710 );
1711 cargo
1712 .arg("--manifest-path")
1713 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1714 rustc_cargo_env(builder, &mut cargo, target);
1715
1716 let _guard = builder.msg(
1717 Kind::Build,
1718 "codegen backend cranelift",
1719 Mode::Codegen,
1720 build_compiler,
1721 target,
1722 );
1723 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1724 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1725 }
1726
1727 fn metadata(&self) -> Option<StepMetadata> {
1728 Some(
1729 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1730 .built_by(self.compilers.build_compiler()),
1731 )
1732 }
1733}
1734
1735fn write_codegen_backend_stamp(
1737 mut stamp: BuildStamp,
1738 files: Vec<PathBuf>,
1739 dry_run: bool,
1740) -> BuildStamp {
1741 if dry_run {
1742 return stamp;
1743 }
1744
1745 let mut files = files.into_iter().filter(|f| {
1746 let filename = f.file_name().unwrap().to_str().unwrap();
1747 is_dylib(f) && filename.contains("rustc_codegen_")
1748 });
1749 let codegen_backend = match files.next() {
1750 Some(f) => f,
1751 None => panic!("no dylibs built for codegen backend?"),
1752 };
1753 if let Some(f) = files.next() {
1754 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1755 }
1756
1757 let codegen_backend = codegen_backend.to_str().unwrap();
1758 stamp = stamp.add_stamp(codegen_backend);
1759 t!(stamp.write());
1760 stamp
1761}
1762
1763fn copy_codegen_backends_to_sysroot(
1770 builder: &Builder<'_>,
1771 stamp: BuildStamp,
1772 target_compiler: Compiler,
1773) {
1774 let dst = builder.sysroot_codegen_backends(target_compiler);
1783 t!(fs::create_dir_all(&dst), dst);
1784
1785 if builder.config.dry_run() {
1786 return;
1787 }
1788
1789 if stamp.path().exists() {
1790 let file = get_codegen_backend_file(&stamp);
1791 builder.copy_link(
1792 &file,
1793 &dst.join(normalize_codegen_backend_name(builder, &file)),
1794 FileType::NativeLibrary,
1795 );
1796 }
1797}
1798
1799pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1801 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1802}
1803
1804pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1806 let filename = path.file_name().unwrap().to_str().unwrap();
1807 let dash = filename.find('-').unwrap();
1810 let dot = filename.find('.').unwrap();
1811 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1812}
1813
1814pub fn compiler_file(
1815 builder: &Builder<'_>,
1816 compiler: &Path,
1817 target: TargetSelection,
1818 c: CLang,
1819 file: &str,
1820) -> PathBuf {
1821 if builder.config.dry_run() {
1822 return PathBuf::new();
1823 }
1824 let mut cmd = command(compiler);
1825 cmd.args(builder.cc_handled_clags(target, c));
1826 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1827 cmd.arg(format!("-print-file-name={file}"));
1828 let out = cmd.run_capture_stdout(builder).stdout();
1829 PathBuf::from(out.trim())
1830}
1831
1832#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1833pub struct Sysroot {
1834 pub compiler: Compiler,
1835 force_recompile: bool,
1837}
1838
1839impl Sysroot {
1840 pub(crate) fn new(compiler: Compiler) -> Self {
1841 Sysroot { compiler, force_recompile: false }
1842 }
1843}
1844
1845impl Step for Sysroot {
1846 type Output = PathBuf;
1847
1848 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1849 run.never()
1850 }
1851
1852 fn run(self, builder: &Builder<'_>) -> PathBuf {
1856 let compiler = self.compiler;
1857 let host_dir = builder.out.join(compiler.host);
1858
1859 let sysroot_dir = |stage| {
1860 if stage == 0 {
1861 host_dir.join("stage0-sysroot")
1862 } else if self.force_recompile && stage == compiler.stage {
1863 host_dir.join(format!("stage{stage}-test-sysroot"))
1864 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1865 host_dir.join("ci-rustc-sysroot")
1866 } else {
1867 host_dir.join(format!("stage{stage}"))
1868 }
1869 };
1870 let sysroot = sysroot_dir(compiler.stage);
1871 trace!(stage = ?compiler.stage, ?sysroot);
1872
1873 builder.do_if_verbose(|| {
1874 println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
1875 });
1876 let _ = fs::remove_dir_all(&sysroot);
1877 t!(fs::create_dir_all(&sysroot));
1878
1879 if compiler.stage == 0 {
1886 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1887 }
1888
1889 if builder.download_rustc() && compiler.stage != 0 {
1891 assert_eq!(
1892 builder.config.host_target, compiler.host,
1893 "Cross-compiling is not yet supported with `download-rustc`",
1894 );
1895
1896 for stage in 0..=2 {
1898 if stage != compiler.stage {
1899 let dir = sysroot_dir(stage);
1900 if !dir.ends_with("ci-rustc-sysroot") {
1901 let _ = fs::remove_dir_all(dir);
1902 }
1903 }
1904 }
1905
1906 let mut filtered_files = Vec::new();
1916 let mut add_filtered_files = |suffix, contents| {
1917 for path in contents {
1918 let path = Path::new(&path);
1919 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1920 filtered_files.push(path.file_name().unwrap().to_owned());
1921 }
1922 }
1923 };
1924 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1925 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1926 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1929
1930 let filtered_extensions = [
1931 OsStr::new("rmeta"),
1932 OsStr::new("rlib"),
1933 OsStr::new(std::env::consts::DLL_EXTENSION),
1935 ];
1936 let ci_rustc_dir = builder.config.ci_rustc_dir();
1937 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1938 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1939 return true;
1940 }
1941 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1942 return true;
1943 }
1944 filtered_files.iter().all(|f| f != path.file_name().unwrap())
1945 });
1946 }
1947
1948 if compiler.stage != 0 {
1954 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1955 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1956 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1957 if let Err(e) =
1958 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1959 {
1960 eprintln!(
1961 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1962 sysroot_lib_rustlib_src_rust.display(),
1963 builder.src.display(),
1964 e,
1965 );
1966 if builder.config.rust_remap_debuginfo {
1967 eprintln!(
1968 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1969 sysroot_lib_rustlib_src_rust.display(),
1970 );
1971 }
1972 build_helper::exit!(1);
1973 }
1974 }
1975
1976 if !builder.download_rustc() {
1978 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1979 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1980 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1981 if let Err(e) =
1982 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1983 {
1984 eprintln!(
1985 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1986 sysroot_lib_rustlib_rustcsrc_rust.display(),
1987 builder.src.display(),
1988 e,
1989 );
1990 build_helper::exit!(1);
1991 }
1992 }
1993
1994 sysroot
1995 }
1996}
1997
1998#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2005pub struct Assemble {
2006 pub target_compiler: Compiler,
2011}
2012
2013impl Step for Assemble {
2014 type Output = Compiler;
2015 const IS_HOST: bool = true;
2016
2017 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2018 run.path("compiler/rustc").path("compiler")
2019 }
2020
2021 fn make_run(run: RunConfig<'_>) {
2022 run.builder.ensure(Assemble {
2023 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2024 });
2025 }
2026
2027 fn run(self, builder: &Builder<'_>) -> Compiler {
2028 let target_compiler = self.target_compiler;
2029
2030 if target_compiler.stage == 0 {
2031 trace!("stage 0 build compiler is always available, simply returning");
2032 assert_eq!(
2033 builder.config.host_target, target_compiler.host,
2034 "Cannot obtain compiler for non-native build triple at stage 0"
2035 );
2036 return target_compiler;
2038 }
2039
2040 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2043 let libdir_bin = libdir.parent().unwrap().join("bin");
2044 t!(fs::create_dir_all(&libdir_bin));
2045
2046 if builder.config.llvm_enabled(target_compiler.host) {
2047 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2048
2049 let target = target_compiler.host;
2050 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2051 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2052 trace!("LLVM tools enabled");
2053
2054 let host_llvm_bin_dir = command(&host_llvm_config)
2055 .arg("--bindir")
2056 .cached()
2057 .run_capture_stdout(builder)
2058 .stdout()
2059 .trim()
2060 .to_string();
2061
2062 let llvm_bin_dir = if target == builder.host_target {
2063 PathBuf::from(host_llvm_bin_dir)
2064 } else {
2065 let external_llvm_config = builder
2068 .config
2069 .target_config
2070 .get(&target)
2071 .and_then(|t| t.llvm_config.clone());
2072 if let Some(external_llvm_config) = external_llvm_config {
2073 external_llvm_config.parent().unwrap().to_path_buf()
2076 } else {
2077 let host_llvm_out = builder.llvm_out(builder.host_target);
2081 let target_llvm_out = builder.llvm_out(target);
2082 if let Ok(relative_path) =
2083 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2084 {
2085 target_llvm_out.join(relative_path)
2086 } else {
2087 PathBuf::from(
2090 host_llvm_bin_dir
2091 .replace(&*builder.host_target.triple, &target.triple),
2092 )
2093 }
2094 }
2095 };
2096
2097 #[cfg(feature = "tracing")]
2104 let _llvm_tools_span =
2105 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2106 .entered();
2107 for tool in LLVM_TOOLS {
2108 trace!("installing `{tool}`");
2109 let tool_exe = exe(tool, target_compiler.host);
2110 let src_path = llvm_bin_dir.join(&tool_exe);
2111
2112 if !src_path.exists() && builder.config.llvm_from_ci {
2114 eprintln!("{} does not exist; skipping copy", src_path.display());
2115 continue;
2116 }
2117
2118 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2125 }
2126 }
2127 }
2128
2129 let maybe_install_llvm_bitcode_linker = || {
2130 if builder.config.llvm_bitcode_linker_enabled {
2131 trace!("llvm-bitcode-linker enabled, installing");
2132 let llvm_bitcode_linker = builder.ensure(
2133 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2134 builder,
2135 target_compiler,
2136 ),
2137 );
2138
2139 let bindir_self_contained = builder
2141 .sysroot(target_compiler)
2142 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2143 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2144
2145 t!(fs::create_dir_all(&bindir_self_contained));
2146 builder.copy_link(
2147 &llvm_bitcode_linker.tool_path,
2148 &bindir_self_contained.join(tool_exe),
2149 FileType::Executable,
2150 );
2151 }
2152 };
2153
2154 if builder.download_rustc() {
2156 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2157
2158 builder.std(target_compiler, target_compiler.host);
2159 let sysroot =
2160 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2161 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2164 if target_compiler.stage == builder.top_stage {
2166 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2167 }
2168
2169 maybe_install_llvm_bitcode_linker();
2172
2173 return target_compiler;
2174 }
2175
2176 debug!(
2190 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2191 target_compiler.stage - 1,
2192 builder.config.host_target,
2193 );
2194 let build_compiler =
2195 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2196
2197 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2199 debug!("`llvm_enzyme` requested");
2200 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2201 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2202 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2203 let lib_ext = std::env::consts::DLL_EXTENSION;
2204 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2205 let src_lib =
2206 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2207 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2208 let target_libdir =
2209 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2210 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2211 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2212 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2213 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2214 }
2215 }
2216
2217 debug!(
2220 ?build_compiler,
2221 "target_compiler.host" = ?target_compiler.host,
2222 "building compiler libraries to link to"
2223 );
2224
2225 let BuiltRustc { build_compiler } =
2227 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2228
2229 let stage = target_compiler.stage;
2230 let host = target_compiler.host;
2231 let (host_info, dir_name) = if build_compiler.host == host {
2232 ("".into(), "host".into())
2233 } else {
2234 (format!(" ({host})"), host.to_string())
2235 };
2236 let msg = format!(
2241 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2242 );
2243 builder.info(&msg);
2244
2245 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2247 let proc_macros = builder
2248 .read_stamp_file(&stamp)
2249 .into_iter()
2250 .filter_map(|(path, dependency_type)| {
2251 if dependency_type == DependencyType::Host {
2252 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2253 } else {
2254 None
2255 }
2256 })
2257 .collect::<HashSet<_>>();
2258
2259 let sysroot = builder.sysroot(target_compiler);
2260 let rustc_libdir = builder.rustc_libdir(target_compiler);
2261 t!(fs::create_dir_all(&rustc_libdir));
2262 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2263 for f in builder.read_dir(&src_libdir) {
2264 let filename = f.file_name().into_string().unwrap();
2265
2266 let is_proc_macro = proc_macros.contains(&filename);
2267 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2268
2269 let can_be_rustc_dynamic_dep = if builder
2273 .link_std_into_rustc_driver(target_compiler.host)
2274 && !target_compiler.host.is_windows()
2275 {
2276 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2277 !is_std
2278 } else {
2279 true
2280 };
2281
2282 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2283 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2284 }
2285 }
2286
2287 {
2288 #[cfg(feature = "tracing")]
2289 let _codegen_backend_span =
2290 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2291
2292 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2293 if builder.kind == Kind::Check && builder.top_stage == 1 {
2310 continue;
2311 }
2312
2313 let prepare_compilers = || {
2314 RustcPrivateCompilers::from_build_and_target_compiler(
2315 build_compiler,
2316 target_compiler,
2317 )
2318 };
2319
2320 match backend {
2321 CodegenBackendKind::Cranelift => {
2322 let stamp = builder
2323 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2324 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2325 }
2326 CodegenBackendKind::Gcc => {
2327 let output =
2328 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2329 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2330 output.gcc.install_to(builder, &rustc_libdir);
2333 }
2334 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2335 }
2336 }
2337 }
2338
2339 if builder.config.lld_enabled {
2340 let lld_wrapper =
2341 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2342 builder,
2343 target_compiler,
2344 ));
2345 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2346 }
2347
2348 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2349 debug!(
2350 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2351 workaround faulty homebrew `strip`s"
2352 );
2353
2354 let src_exe = exe("llvm-objcopy", target_compiler.host);
2361 let dst_exe = exe("rust-objcopy", target_compiler.host);
2362 builder.copy_link(
2363 &libdir_bin.join(src_exe),
2364 &libdir_bin.join(dst_exe),
2365 FileType::Executable,
2366 );
2367 }
2368
2369 if builder.tool_enabled("wasm-component-ld") {
2372 let wasm_component = builder.ensure(
2373 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2374 builder,
2375 target_compiler,
2376 ),
2377 );
2378 builder.copy_link(
2379 &wasm_component.tool_path,
2380 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2381 FileType::Executable,
2382 );
2383 }
2384
2385 maybe_install_llvm_bitcode_linker();
2386
2387 debug!(
2390 "target_compiler.host" = ?target_compiler.host,
2391 ?sysroot,
2392 "ensuring availability of `libLLVM.so` in compiler directory"
2393 );
2394 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2395 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2396
2397 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2399 let rustc = out_dir.join(exe("rustc-main", host));
2400 let bindir = sysroot.join("bin");
2401 t!(fs::create_dir_all(bindir));
2402 let compiler = builder.rustc(target_compiler);
2403 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2404 builder.copy_link(&rustc, &compiler, FileType::Executable);
2405
2406 target_compiler
2407 }
2408}
2409
2410#[track_caller]
2415pub fn add_to_sysroot(
2416 builder: &Builder<'_>,
2417 sysroot_dst: &Path,
2418 sysroot_host_dst: &Path,
2419 stamp: &BuildStamp,
2420) {
2421 let self_contained_dst = &sysroot_dst.join("self-contained");
2422 t!(fs::create_dir_all(sysroot_dst));
2423 t!(fs::create_dir_all(sysroot_host_dst));
2424 t!(fs::create_dir_all(self_contained_dst));
2425 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2426 let dst = match dependency_type {
2427 DependencyType::Host => sysroot_host_dst,
2428 DependencyType::Target => sysroot_dst,
2429 DependencyType::TargetSelfContained => self_contained_dst,
2430 };
2431 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2432 }
2433}
2434
2435pub fn run_cargo(
2436 builder: &Builder<'_>,
2437 cargo: Cargo,
2438 tail_args: Vec<String>,
2439 stamp: &BuildStamp,
2440 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2441 is_check: bool,
2442 rlib_only_metadata: bool,
2443) -> Vec<PathBuf> {
2444 let target_root_dir = stamp.path().parent().unwrap();
2446 let target_deps_dir = target_root_dir.join("deps");
2448 let host_root_dir = target_root_dir
2450 .parent()
2451 .unwrap() .parent()
2453 .unwrap() .join(target_root_dir.file_name().unwrap());
2455
2456 let mut deps = Vec::new();
2460 let mut toplevel = Vec::new();
2461 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2462 let (filenames_vec, crate_types) = match msg {
2463 CargoMessage::CompilerArtifact {
2464 filenames,
2465 target: CargoTarget { crate_types },
2466 ..
2467 } => {
2468 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2469 f.sort(); (f, crate_types)
2471 }
2472 _ => return,
2473 };
2474 for filename in filenames_vec {
2475 let mut keep = false;
2477 if filename.ends_with(".lib")
2478 || filename.ends_with(".a")
2479 || is_debug_info(&filename)
2480 || is_dylib(Path::new(&*filename))
2481 {
2482 keep = true;
2484 }
2485 if is_check && filename.ends_with(".rmeta") {
2486 keep = true;
2488 } else if rlib_only_metadata {
2489 if filename.contains("jemalloc_sys")
2490 || filename.contains("rustc_public_bridge")
2491 || filename.contains("rustc_public")
2492 {
2493 keep |= filename.ends_with(".rlib");
2496 } else {
2497 keep |= filename.ends_with(".rmeta");
2501 }
2502 } else {
2503 keep |= filename.ends_with(".rlib");
2505 }
2506
2507 if !keep {
2508 continue;
2509 }
2510
2511 let filename = Path::new(&*filename);
2512
2513 if filename.starts_with(&host_root_dir) {
2516 if crate_types.iter().any(|t| t == "proc-macro") {
2518 deps.push((filename.to_path_buf(), DependencyType::Host));
2519 }
2520 continue;
2521 }
2522
2523 if filename.starts_with(&target_deps_dir) {
2526 deps.push((filename.to_path_buf(), DependencyType::Target));
2527 continue;
2528 }
2529
2530 let expected_len = t!(filename.metadata()).len();
2541 let filename = filename.file_name().unwrap().to_str().unwrap();
2542 let mut parts = filename.splitn(2, '.');
2543 let file_stem = parts.next().unwrap().to_owned();
2544 let extension = parts.next().unwrap().to_owned();
2545
2546 toplevel.push((file_stem, extension, expected_len));
2547 }
2548 });
2549
2550 if !ok {
2551 crate::exit!(1);
2552 }
2553
2554 if builder.config.dry_run() {
2555 return Vec::new();
2556 }
2557
2558 let contents = target_deps_dir
2562 .read_dir()
2563 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2564 .map(|e| t!(e))
2565 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2566 .collect::<Vec<_>>();
2567 for (prefix, extension, expected_len) in toplevel {
2568 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2569 meta.len() == expected_len
2570 && filename
2571 .strip_prefix(&prefix[..])
2572 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2573 .unwrap_or(false)
2574 });
2575 let max = candidates.max_by_key(|&(_, _, metadata)| {
2576 metadata.modified().expect("mtime should be available on all relevant OSes")
2577 });
2578 let path_to_add = match max {
2579 Some(triple) => triple.0.to_str().unwrap(),
2580 None => panic!("no output generated for {prefix:?} {extension:?}"),
2581 };
2582 if is_dylib(Path::new(path_to_add)) {
2583 let candidate = format!("{path_to_add}.lib");
2584 let candidate = PathBuf::from(candidate);
2585 if candidate.exists() {
2586 deps.push((candidate, DependencyType::Target));
2587 }
2588 }
2589 deps.push((path_to_add.into(), DependencyType::Target));
2590 }
2591
2592 deps.extend(additional_target_deps);
2593 deps.sort();
2594 let mut new_contents = Vec::new();
2595 for (dep, dependency_type) in deps.iter() {
2596 new_contents.extend(match *dependency_type {
2597 DependencyType::Host => b"h",
2598 DependencyType::Target => b"t",
2599 DependencyType::TargetSelfContained => b"s",
2600 });
2601 new_contents.extend(dep.to_str().unwrap().as_bytes());
2602 new_contents.extend(b"\0");
2603 }
2604 t!(fs::write(stamp.path(), &new_contents));
2605 deps.into_iter().map(|(d, _)| d).collect()
2606}
2607
2608pub fn stream_cargo(
2609 builder: &Builder<'_>,
2610 cargo: Cargo,
2611 tail_args: Vec<String>,
2612 cb: &mut dyn FnMut(CargoMessage<'_>),
2613) -> bool {
2614 let mut cmd = cargo.into_cmd();
2615
2616 let mut message_format = if builder.config.json_output {
2619 String::from("json")
2620 } else {
2621 String::from("json-render-diagnostics")
2622 };
2623 if let Some(s) = &builder.config.rustc_error_format {
2624 message_format.push_str(",json-diagnostic-");
2625 message_format.push_str(s);
2626 }
2627 cmd.arg("--message-format").arg(message_format);
2628
2629 for arg in tail_args {
2630 cmd.arg(arg);
2631 }
2632
2633 builder.do_if_verbose(|| println!("running: {cmd:?}"));
2634
2635 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2636
2637 let Some(mut streaming_command) = streaming_command else {
2638 return true;
2639 };
2640
2641 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2645 for line in stdout.lines() {
2646 let line = t!(line);
2647 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2648 Ok(msg) => {
2649 if builder.config.json_output {
2650 println!("{line}");
2652 }
2653 cb(msg)
2654 }
2655 Err(_) => println!("{line}"),
2657 }
2658 }
2659
2660 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2662 if builder.is_verbose() && !status.success() {
2663 eprintln!(
2664 "command did not execute successfully: {cmd:?}\n\
2665 expected success, got: {status}"
2666 );
2667 }
2668
2669 status.success()
2670}
2671
2672#[derive(Deserialize)]
2673pub struct CargoTarget<'a> {
2674 crate_types: Vec<Cow<'a, str>>,
2675}
2676
2677#[derive(Deserialize)]
2678#[serde(tag = "reason", rename_all = "kebab-case")]
2679pub enum CargoMessage<'a> {
2680 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2681 BuildScriptExecuted,
2682 BuildFinished,
2683}
2684
2685pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2686 if target != "x86_64-unknown-linux-gnu"
2690 || !builder.config.is_host_target(target)
2691 || !path.exists()
2692 {
2693 return;
2694 }
2695
2696 let previous_mtime = t!(t!(path.metadata()).modified());
2697 let stamp = BuildStamp::new(path.parent().unwrap())
2698 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2699 .with_prefix("strip")
2700 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2701
2702 if !stamp.is_up_to_date() {
2705 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2706 }
2707 t!(stamp.write());
2708
2709 let file = t!(fs::File::open(path));
2710
2711 t!(file.set_modified(previous_mtime));
2724}
2725
2726pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2728 build_compiler.stage != 0
2729}