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::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
30use crate::utils::build_stamp;
31use crate::utils::build_stamp::BuildStamp;
32use crate::utils::exec::command;
33use crate::utils::helpers::{
34 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
35};
36use crate::{
37 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
38 debug, trace,
39};
40
41#[derive(Debug, Clone, PartialEq, Eq, Hash)]
43pub struct Std {
44 pub target: TargetSelection,
45 pub build_compiler: Compiler,
47 crates: Vec<String>,
51 force_recompile: bool,
54 extra_rust_args: &'static [&'static str],
55 is_for_mir_opt_tests: bool,
56}
57
58impl Std {
59 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
60 Self {
61 target,
62 build_compiler,
63 crates: Default::default(),
64 force_recompile: false,
65 extra_rust_args: &[],
66 is_for_mir_opt_tests: false,
67 }
68 }
69
70 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
71 self.force_recompile = force_recompile;
72 self
73 }
74
75 #[expect(clippy::wrong_self_convention)]
76 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
77 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
78 self
79 }
80
81 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
82 self.extra_rust_args = extra_rust_args;
83 self
84 }
85
86 fn copy_extra_objects(
87 &self,
88 builder: &Builder<'_>,
89 compiler: &Compiler,
90 target: TargetSelection,
91 ) -> Vec<(PathBuf, DependencyType)> {
92 let mut deps = Vec::new();
93 if !self.is_for_mir_opt_tests {
94 deps.extend(copy_third_party_objects(builder, compiler, target));
95 deps.extend(copy_self_contained_objects(builder, compiler, target));
96 }
97 deps
98 }
99}
100
101impl Step for Std {
102 type Output = ();
103 const DEFAULT: bool = true;
104
105 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
106 run.crate_or_deps("sysroot").path("library")
107 }
108
109 fn make_run(run: RunConfig<'_>) {
110 let crates = std_crates_for_run_make(&run);
111 let builder = run.builder;
112
113 let force_recompile = builder.rust_info().is_managed_git_subrepository()
117 && builder.download_rustc()
118 && builder.config.has_changes_from_upstream(&["library"]);
119
120 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
121 trace!("download_rustc: {}", builder.download_rustc());
122 trace!(force_recompile);
123
124 run.builder.ensure(Std {
125 build_compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
126 target: run.target,
127 crates,
128 force_recompile,
129 extra_rust_args: &[],
130 is_for_mir_opt_tests: false,
131 });
132 }
133
134 fn run(self, builder: &Builder<'_>) {
140 let target = self.target;
141
142 if self.build_compiler.stage == 0 {
144 let compiler = self.build_compiler;
145 builder.ensure(StdLink::from_std(self, compiler));
146
147 return;
148 }
149
150 let build_compiler = if builder.download_rustc() && self.force_recompile {
151 builder
154 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
155 } else {
156 self.build_compiler
157 };
158
159 if builder.download_rustc()
162 && builder.config.is_host_target(target)
163 && !self.force_recompile
164 {
165 let sysroot =
166 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
167 cp_rustc_component_to_ci_sysroot(
168 builder,
169 &sysroot,
170 builder.config.ci_rust_std_contents(),
171 );
172 return;
173 }
174
175 if builder.config.keep_stage.contains(&build_compiler.stage)
176 || builder.config.keep_stage_std.contains(&build_compiler.stage)
177 {
178 trace!(keep_stage = ?builder.config.keep_stage);
179 trace!(keep_stage_std = ?builder.config.keep_stage_std);
180
181 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
182
183 builder.ensure(StartupObjects { compiler: build_compiler, target });
184
185 self.copy_extra_objects(builder, &build_compiler, target);
186
187 builder.ensure(StdLink::from_std(self, build_compiler));
188 return;
189 }
190
191 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
192
193 let stage = build_compiler.stage;
195
196 if build_compiler.stage > 1
200 && !builder.config.full_bootstrap
201 && (target == builder.host_target || builder.config.hosts.contains(&target))
211 {
212 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
213 builder.std(build_compiler_for_std_to_uplift, target);
214
215 let msg = if build_compiler_for_std_to_uplift.host == target {
216 format!(
217 "Uplifting library (stage{} -> stage{stage})",
218 build_compiler_for_std_to_uplift.stage
219 )
220 } else {
221 format!(
222 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
223 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
224 )
225 };
226
227 builder.info(&msg);
228
229 self.copy_extra_objects(builder, &build_compiler, target);
232
233 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
234 return;
235 }
236
237 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
238
239 let mut cargo = if self.is_for_mir_opt_tests {
243 trace!("building special sysroot for mir-opt tests");
244 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
245 builder,
246 build_compiler,
247 Mode::Std,
248 SourceType::InTree,
249 target,
250 Kind::Check,
251 );
252 cargo.rustflag("-Zalways-encode-mir");
253 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
254 cargo
255 } else {
256 trace!("building regular sysroot");
257 let mut cargo = builder::Cargo::new(
258 builder,
259 build_compiler,
260 Mode::Std,
261 SourceType::InTree,
262 target,
263 Kind::Build,
264 );
265 std_cargo(builder, target, &mut cargo);
266 for krate in &*self.crates {
267 cargo.arg("-p").arg(krate);
268 }
269 cargo
270 };
271
272 if target.is_synthetic() {
274 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
275 }
276 for rustflag in self.extra_rust_args.iter() {
277 cargo.rustflag(rustflag);
278 }
279
280 let _guard = builder.msg(
281 Kind::Build,
282 format_args!("library artifacts{}", crate_description(&self.crates)),
283 Mode::Std,
284 build_compiler,
285 target,
286 );
287 run_cargo(
288 builder,
289 cargo,
290 vec![],
291 &build_stamp::libstd_stamp(builder, build_compiler, target),
292 target_deps,
293 self.is_for_mir_opt_tests, false,
295 );
296
297 builder.ensure(StdLink::from_std(
298 self,
299 builder.compiler(build_compiler.stage, builder.config.host_target),
300 ));
301 }
302
303 fn metadata(&self) -> Option<StepMetadata> {
304 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
305 }
306}
307
308fn copy_and_stamp(
309 builder: &Builder<'_>,
310 libdir: &Path,
311 sourcedir: &Path,
312 name: &str,
313 target_deps: &mut Vec<(PathBuf, DependencyType)>,
314 dependency_type: DependencyType,
315) {
316 let target = libdir.join(name);
317 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
318
319 target_deps.push((target, dependency_type));
320}
321
322fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
323 let libunwind_path = builder.ensure(llvm::Libunwind { target });
324 let libunwind_source = libunwind_path.join("libunwind.a");
325 let libunwind_target = libdir.join("libunwind.a");
326 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
327 libunwind_target
328}
329
330fn copy_third_party_objects(
332 builder: &Builder<'_>,
333 compiler: &Compiler,
334 target: TargetSelection,
335) -> Vec<(PathBuf, DependencyType)> {
336 let mut target_deps = vec![];
337
338 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
339 target_deps.extend(
342 copy_sanitizers(builder, compiler, target)
343 .into_iter()
344 .map(|d| (d, DependencyType::Target)),
345 );
346 }
347
348 if target == "x86_64-fortanix-unknown-sgx"
349 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
350 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
351 {
352 let libunwind_path =
353 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
354 target_deps.push((libunwind_path, DependencyType::Target));
355 }
356
357 target_deps
358}
359
360fn copy_self_contained_objects(
362 builder: &Builder<'_>,
363 compiler: &Compiler,
364 target: TargetSelection,
365) -> Vec<(PathBuf, DependencyType)> {
366 let libdir_self_contained =
367 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
368 t!(fs::create_dir_all(&libdir_self_contained));
369 let mut target_deps = vec![];
370
371 if target.needs_crt_begin_end() {
379 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
380 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
381 });
382 if !target.starts_with("wasm32") {
383 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
384 copy_and_stamp(
385 builder,
386 &libdir_self_contained,
387 &srcdir,
388 obj,
389 &mut target_deps,
390 DependencyType::TargetSelfContained,
391 );
392 }
393 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
394 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
395 let src = crt_path.join(obj);
396 let target = libdir_self_contained.join(obj);
397 builder.copy_link(&src, &target, FileType::NativeLibrary);
398 target_deps.push((target, DependencyType::TargetSelfContained));
399 }
400 } else {
401 for &obj in &["libc.a", "crt1-command.o"] {
404 copy_and_stamp(
405 builder,
406 &libdir_self_contained,
407 &srcdir,
408 obj,
409 &mut target_deps,
410 DependencyType::TargetSelfContained,
411 );
412 }
413 }
414 if !target.starts_with("s390x") {
415 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
416 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
417 }
418 } else if target.contains("-wasi") {
419 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
420 panic!(
421 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
422 or `$WASI_SDK_PATH` set",
423 target.triple
424 )
425 });
426 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
427 copy_and_stamp(
428 builder,
429 &libdir_self_contained,
430 &srcdir,
431 obj,
432 &mut target_deps,
433 DependencyType::TargetSelfContained,
434 );
435 }
436 } else if target.is_windows_gnu() {
437 for obj in ["crt2.o", "dllcrt2.o"].iter() {
438 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
439 let dst = libdir_self_contained.join(obj);
440 builder.copy_link(&src, &dst, FileType::NativeLibrary);
441 target_deps.push((dst, DependencyType::TargetSelfContained));
442 }
443 }
444
445 target_deps
446}
447
448pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
451 let mut crates = run.make_run_crates(builder::Alias::Library);
452
453 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
462 if target_is_no_std {
463 crates.retain(|c| c == "core" || c == "alloc");
464 }
465 crates
466}
467
468fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
474 if builder.config.llvm_from_ci {
476 builder.config.maybe_download_ci_llvm();
478 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
479 if ci_llvm_compiler_rt.exists() {
480 return ci_llvm_compiler_rt;
481 }
482 }
483
484 builder.require_submodule("src/llvm-project", {
486 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
487 });
488 builder.src.join("src/llvm-project/compiler-rt")
489}
490
491pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
494 if target.contains("apple") && !builder.config.dry_run() {
512 let mut cmd = command(builder.rustc(cargo.compiler()));
516 cmd.arg("--target").arg(target.rustc_target_arg());
517 cmd.arg("--print=deployment-target");
518 let output = cmd.run_capture_stdout(builder).stdout();
519
520 let (env_var, value) = output.split_once('=').unwrap();
521 cargo.env(env_var.trim(), value.trim());
524
525 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
535 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
536 }
537 }
538
539 if let Some(path) = builder.config.profiler_path(target) {
541 cargo.env("LLVM_PROFILER_RT_LIB", path);
542 } else if builder.config.profiler_enabled(target) {
543 let compiler_rt = compiler_rt_for_profiler(builder);
544 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
548 }
549
550 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
564 builder.require_submodule(
572 "src/llvm-project",
573 Some(
574 "The `build.optimized-compiler-builtins` config option \
575 requires `compiler-rt` sources from LLVM.",
576 ),
577 );
578 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
579 assert!(compiler_builtins_root.exists());
580 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
583 " compiler-builtins-c"
584 } else {
585 ""
586 };
587
588 if !builder.unstable_features() {
591 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
592 }
593
594 let mut features = String::new();
595
596 if builder.no_std(target) == Some(true) {
597 features += " compiler-builtins-mem";
598 if !target.starts_with("bpf") {
599 features.push_str(compiler_builtins_c_feature);
600 }
601
602 cargo
604 .args(["-p", "alloc"])
605 .arg("--manifest-path")
606 .arg(builder.src.join("library/alloc/Cargo.toml"))
607 .arg("--features")
608 .arg(features);
609 } else {
610 features += &builder.std_features(target);
611 features.push_str(compiler_builtins_c_feature);
612
613 cargo
614 .arg("--features")
615 .arg(features)
616 .arg("--manifest-path")
617 .arg(builder.src.join("library/sysroot/Cargo.toml"));
618
619 if target.contains("musl")
622 && let Some(p) = builder.musl_libdir(target)
623 {
624 let root = format!("native={}", p.to_str().unwrap());
625 cargo.rustflag("-L").rustflag(&root);
626 }
627
628 if target.contains("-wasi")
629 && let Some(dir) = builder.wasi_libdir(target)
630 {
631 let root = format!("native={}", dir.to_str().unwrap());
632 cargo.rustflag("-L").rustflag(&root);
633 }
634 }
635
636 cargo.rustflag("-Cembed-bitcode=yes");
642
643 if builder.config.rust_lto == RustcLto::Off {
644 cargo.rustflag("-Clto=off");
645 }
646
647 if target.contains("riscv") {
654 cargo.rustflag("-Cforce-unwind-tables=yes");
655 }
656
657 cargo.rustflag("-Zunstable-options");
660 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
661
662 let html_root =
663 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
664 cargo.rustflag(&html_root);
665 cargo.rustdocflag(&html_root);
666
667 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
668}
669
670#[derive(Debug, Clone, PartialEq, Eq, Hash)]
679pub struct StdLink {
680 pub compiler: Compiler,
681 pub target_compiler: Compiler,
682 pub target: TargetSelection,
683 crates: Vec<String>,
685 force_recompile: bool,
687}
688
689impl StdLink {
690 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
691 Self {
692 compiler: host_compiler,
693 target_compiler: std.build_compiler,
694 target: std.target,
695 crates: std.crates,
696 force_recompile: std.force_recompile,
697 }
698 }
699}
700
701impl Step for StdLink {
702 type Output = ();
703
704 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
705 run.never()
706 }
707
708 fn run(self, builder: &Builder<'_>) {
717 let compiler = self.compiler;
718 let target_compiler = self.target_compiler;
719 let target = self.target;
720
721 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
723 let lib = builder.sysroot_libdir_relative(self.compiler);
725 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
726 compiler: self.compiler,
727 force_recompile: self.force_recompile,
728 });
729 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
730 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
731 (libdir, hostdir)
732 } else {
733 let libdir = builder.sysroot_target_libdir(target_compiler, target);
734 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
735 (libdir, hostdir)
736 };
737
738 let is_downloaded_beta_stage0 = builder
739 .build
740 .config
741 .initial_rustc
742 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
743
744 if compiler.stage == 0 && is_downloaded_beta_stage0 {
748 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
750
751 let host = compiler.host;
752 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
753 let sysroot_bin_dir = sysroot.join("bin");
754 t!(fs::create_dir_all(&sysroot_bin_dir));
755 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
756
757 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
758 t!(fs::create_dir_all(sysroot.join("lib")));
759 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
760
761 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
763 t!(fs::create_dir_all(&sysroot_codegen_backends));
764 let stage0_codegen_backends = builder
765 .out
766 .join(host)
767 .join("stage0/lib/rustlib")
768 .join(host)
769 .join("codegen-backends");
770 if stage0_codegen_backends.exists() {
771 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
772 }
773 } else if compiler.stage == 0 {
774 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
775
776 if builder.local_rebuild {
777 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
781 }
782
783 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
784 } else {
785 if builder.download_rustc() {
786 let _ = fs::remove_dir_all(&libdir);
788 let _ = fs::remove_dir_all(&hostdir);
789 }
790
791 add_to_sysroot(
792 builder,
793 &libdir,
794 &hostdir,
795 &build_stamp::libstd_stamp(builder, compiler, target),
796 );
797 }
798 }
799}
800
801fn copy_sanitizers(
803 builder: &Builder<'_>,
804 compiler: &Compiler,
805 target: TargetSelection,
806) -> Vec<PathBuf> {
807 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
808
809 if builder.config.dry_run() {
810 return Vec::new();
811 }
812
813 let mut target_deps = Vec::new();
814 let libdir = builder.sysroot_target_libdir(*compiler, target);
815
816 for runtime in &runtimes {
817 let dst = libdir.join(&runtime.name);
818 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
819
820 if target == "x86_64-apple-darwin"
824 || target == "aarch64-apple-darwin"
825 || target == "aarch64-apple-ios"
826 || target == "aarch64-apple-ios-sim"
827 || target == "x86_64-apple-ios"
828 {
829 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
831 apple_darwin_sign_file(builder, &dst);
834 }
835
836 target_deps.push(dst);
837 }
838
839 target_deps
840}
841
842fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
843 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
844}
845
846fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
847 command("codesign")
848 .arg("-f") .arg("-s")
850 .arg("-")
851 .arg(file_path)
852 .run(builder);
853}
854
855#[derive(Debug, Clone, PartialEq, Eq, Hash)]
856pub struct StartupObjects {
857 pub compiler: Compiler,
858 pub target: TargetSelection,
859}
860
861impl Step for StartupObjects {
862 type Output = Vec<(PathBuf, DependencyType)>;
863
864 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
865 run.path("library/rtstartup")
866 }
867
868 fn make_run(run: RunConfig<'_>) {
869 run.builder.ensure(StartupObjects {
870 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
871 target: run.target,
872 });
873 }
874
875 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
882 let for_compiler = self.compiler;
883 let target = self.target;
884 if !target.is_windows_gnu() {
885 return vec![];
886 }
887
888 let mut target_deps = vec![];
889
890 let src_dir = &builder.src.join("library").join("rtstartup");
891 let dst_dir = &builder.native_dir(target).join("rtstartup");
892 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
893 t!(fs::create_dir_all(dst_dir));
894
895 for file in &["rsbegin", "rsend"] {
896 let src_file = &src_dir.join(file.to_string() + ".rs");
897 let dst_file = &dst_dir.join(file.to_string() + ".o");
898 if !up_to_date(src_file, dst_file) {
899 let mut cmd = command(&builder.initial_rustc);
900 cmd.env("RUSTC_BOOTSTRAP", "1");
901 if !builder.local_rebuild {
902 cmd.arg("--cfg").arg("bootstrap");
904 }
905 cmd.arg("--target")
906 .arg(target.rustc_target_arg())
907 .arg("--emit=obj")
908 .arg("-o")
909 .arg(dst_file)
910 .arg(src_file)
911 .run(builder);
912 }
913
914 let obj = sysroot_dir.join((*file).to_string() + ".o");
915 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
916 target_deps.push((obj, DependencyType::Target));
917 }
918
919 target_deps
920 }
921}
922
923fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
924 let ci_rustc_dir = builder.config.ci_rustc_dir();
925
926 for file in contents {
927 let src = ci_rustc_dir.join(&file);
928 let dst = sysroot.join(file);
929 if src.is_dir() {
930 t!(fs::create_dir_all(dst));
931 } else {
932 builder.copy_link(&src, &dst, FileType::Regular);
933 }
934 }
935}
936
937#[derive(Clone, Debug)]
939pub struct BuiltRustc {
940 pub build_compiler: Compiler,
944}
945
946#[derive(Debug, Clone, PartialEq, Eq, Hash)]
953pub struct Rustc {
954 pub target: TargetSelection,
956 pub build_compiler: Compiler,
958 crates: Vec<String>,
964}
965
966impl Rustc {
967 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
968 Self { target, build_compiler, crates: Default::default() }
969 }
970}
971
972impl Step for Rustc {
973 type Output = BuiltRustc;
974
975 const IS_HOST: bool = true;
976 const DEFAULT: bool = false;
977
978 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
979 let mut crates = run.builder.in_tree_crates("rustc-main", None);
980 for (i, krate) in crates.iter().enumerate() {
981 if krate.name == "rustc-main" {
984 crates.swap_remove(i);
985 break;
986 }
987 }
988 run.crates(crates)
989 }
990
991 fn make_run(run: RunConfig<'_>) {
992 if run.builder.paths == vec![PathBuf::from("compiler")] {
995 return;
996 }
997
998 let crates = run.cargo_crates_in_set();
999 run.builder.ensure(Rustc {
1000 build_compiler: run
1001 .builder
1002 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1003 target: run.target,
1004 crates,
1005 });
1006 }
1007
1008 fn run(self, builder: &Builder<'_>) -> Self::Output {
1014 let build_compiler = self.build_compiler;
1015 let target = self.target;
1016
1017 if builder.download_rustc() && build_compiler.stage != 0 {
1020 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1021
1022 let sysroot =
1023 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1024 cp_rustc_component_to_ci_sysroot(
1025 builder,
1026 &sysroot,
1027 builder.config.ci_rustc_dev_contents(),
1028 );
1029 return BuiltRustc { build_compiler };
1030 }
1031
1032 builder.std(build_compiler, target);
1035
1036 if builder.config.keep_stage.contains(&build_compiler.stage) {
1037 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1038
1039 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1040 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1041 builder.ensure(RustcLink::from_rustc(self));
1042
1043 return BuiltRustc { build_compiler };
1044 }
1045
1046 let stage = build_compiler.stage + 1;
1048
1049 if build_compiler.stage >= 2
1054 && !builder.config.full_bootstrap
1055 && target == builder.host_target
1056 {
1057 let uplift_build_compiler = builder.compiler(1, build_compiler.host);
1061
1062 let msg = format!("Uplifting rustc from stage2 to stage{stage})");
1063 builder.info(&msg);
1064
1065 builder.ensure(RustcLink::from_build_compiler_and_sysroot(
1069 uplift_build_compiler,
1071 build_compiler,
1073 target,
1074 self.crates,
1075 ));
1076
1077 return BuiltRustc { build_compiler: uplift_build_compiler };
1080 }
1081
1082 builder.std(
1088 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1089 builder.config.host_target,
1090 );
1091
1092 let mut cargo = builder::Cargo::new(
1093 builder,
1094 build_compiler,
1095 Mode::Rustc,
1096 SourceType::InTree,
1097 target,
1098 Kind::Build,
1099 );
1100
1101 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1102
1103 for krate in &*self.crates {
1107 cargo.arg("-p").arg(krate);
1108 }
1109
1110 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1111 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1113 }
1114
1115 let _guard = builder.msg(
1116 Kind::Build,
1117 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1118 Mode::Rustc,
1119 build_compiler,
1120 target,
1121 );
1122 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1123 run_cargo(
1124 builder,
1125 cargo,
1126 vec![],
1127 &stamp,
1128 vec![],
1129 false,
1130 true, );
1132
1133 let target_root_dir = stamp.path().parent().unwrap();
1134 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1140 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1141 {
1142 let rustc_driver = target_root_dir.join("librustc_driver.so");
1143 strip_debug(builder, target, &rustc_driver);
1144 }
1145
1146 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1147 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1150 }
1151
1152 builder.ensure(RustcLink::from_rustc(self));
1153 BuiltRustc { build_compiler }
1154 }
1155
1156 fn metadata(&self) -> Option<StepMetadata> {
1157 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1158 }
1159}
1160
1161pub fn rustc_cargo(
1162 builder: &Builder<'_>,
1163 cargo: &mut Cargo,
1164 target: TargetSelection,
1165 build_compiler: &Compiler,
1166 crates: &[String],
1167) {
1168 cargo
1169 .arg("--features")
1170 .arg(builder.rustc_features(builder.kind, target, crates))
1171 .arg("--manifest-path")
1172 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1173
1174 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1175
1176 cargo.rustflag("-Zon-broken-pipe=kill");
1190
1191 if builder.config.llvm_enzyme {
1194 let arch = builder.build.host_target;
1195 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1196 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1197
1198 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1199 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1200 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1201 }
1202 }
1203
1204 if builder.build.config.lld_mode.is_used() {
1209 cargo.rustflag("-Zdefault-visibility=protected");
1210 }
1211
1212 if is_lto_stage(build_compiler) {
1213 match builder.config.rust_lto {
1214 RustcLto::Thin | RustcLto::Fat => {
1215 cargo.rustflag("-Zdylib-lto");
1218 let lto_type = match builder.config.rust_lto {
1222 RustcLto::Thin => "thin",
1223 RustcLto::Fat => "fat",
1224 _ => unreachable!(),
1225 };
1226 cargo.rustflag(&format!("-Clto={lto_type}"));
1227 cargo.rustflag("-Cembed-bitcode=yes");
1228 }
1229 RustcLto::ThinLocal => { }
1230 RustcLto::Off => {
1231 cargo.rustflag("-Clto=off");
1232 }
1233 }
1234 } else if builder.config.rust_lto == RustcLto::Off {
1235 cargo.rustflag("-Clto=off");
1236 }
1237
1238 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1246 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1247 }
1248
1249 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1250 panic!("Cannot use and generate PGO profiles at the same time");
1251 }
1252 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1253 if build_compiler.stage == 1 {
1254 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1255 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1258 true
1259 } else {
1260 false
1261 }
1262 } else if let Some(path) = &builder.config.rust_profile_use {
1263 if build_compiler.stage == 1 {
1264 cargo.rustflag(&format!("-Cprofile-use={path}"));
1265 if builder.is_verbose() {
1266 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1267 }
1268 true
1269 } else {
1270 false
1271 }
1272 } else {
1273 false
1274 };
1275 if is_collecting {
1276 cargo.rustflag(&format!(
1278 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1279 builder.config.src.components().count()
1280 ));
1281 }
1282
1283 if let Some(ref ccache) = builder.config.ccache
1288 && build_compiler.stage == 0
1289 && !builder.config.incremental
1290 {
1291 cargo.env("RUSTC_WRAPPER", ccache);
1292 }
1293
1294 rustc_cargo_env(builder, cargo, target);
1295}
1296
1297pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1298 cargo
1301 .env("CFG_RELEASE", builder.rust_release())
1302 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1303 .env("CFG_VERSION", builder.rust_version());
1304
1305 if builder.config.omit_git_hash {
1309 cargo.env("CFG_OMIT_GIT_HASH", "1");
1310 }
1311
1312 if let Some(backend) = builder.config.default_codegen_backend(target) {
1313 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
1314 }
1315
1316 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1317 let target_config = builder.config.target_config.get(&target);
1318
1319 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1320
1321 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1322 cargo.env("CFG_VER_DATE", ver_date);
1323 }
1324 if let Some(ref ver_hash) = builder.rust_info().sha() {
1325 cargo.env("CFG_VER_HASH", ver_hash);
1326 }
1327 if !builder.unstable_features() {
1328 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1329 }
1330
1331 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1334 cargo.env("CFG_DEFAULT_LINKER", s);
1335 } else if let Some(ref s) = builder.config.rustc_default_linker {
1336 cargo.env("CFG_DEFAULT_LINKER", s);
1337 }
1338
1339 if builder.config.lld_enabled {
1341 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1342 }
1343
1344 if builder.config.rust_verify_llvm_ir {
1345 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1346 }
1347
1348 if builder.config.llvm_enzyme {
1349 cargo.rustflag("--cfg=llvm_enzyme");
1350 }
1351
1352 if builder.config.llvm_enabled(target) {
1364 let building_llvm_is_expensive =
1365 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1366 .should_build();
1367
1368 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1369 if !skip_llvm {
1370 rustc_llvm_env(builder, cargo, target)
1371 }
1372 }
1373
1374 if builder.config.jemalloc(target)
1378 && target.starts_with("aarch64")
1379 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1380 {
1381 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1382 }
1383}
1384
1385fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1391 if builder.config.is_rust_llvm(target) {
1392 cargo.env("LLVM_RUSTLLVM", "1");
1393 }
1394 if builder.config.llvm_enzyme {
1395 cargo.env("LLVM_ENZYME", "1");
1396 }
1397 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1398 cargo.env("LLVM_CONFIG", &host_llvm_config);
1399
1400 let mut llvm_linker_flags = String::new();
1410 if builder.config.llvm_profile_generate
1411 && target.is_msvc()
1412 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1413 {
1414 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1416 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1417 }
1418
1419 if let Some(ref s) = builder.config.llvm_ldflags {
1421 if !llvm_linker_flags.is_empty() {
1422 llvm_linker_flags.push(' ');
1423 }
1424 llvm_linker_flags.push_str(s);
1425 }
1426
1427 if !llvm_linker_flags.is_empty() {
1429 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1430 }
1431
1432 if builder.config.llvm_static_stdcpp
1435 && !target.contains("freebsd")
1436 && !target.is_msvc()
1437 && !target.contains("apple")
1438 && !target.contains("solaris")
1439 {
1440 let libstdcxx_name =
1441 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1442 let file = compiler_file(
1443 builder,
1444 &builder.cxx(target).unwrap(),
1445 target,
1446 CLang::Cxx,
1447 libstdcxx_name,
1448 );
1449 cargo.env("LLVM_STATIC_STDCPP", file);
1450 }
1451 if builder.llvm_link_shared() {
1452 cargo.env("LLVM_LINK_SHARED", "1");
1453 }
1454 if builder.config.llvm_use_libcxx {
1455 cargo.env("LLVM_USE_LIBCXX", "1");
1456 }
1457 if builder.config.llvm_assertions {
1458 cargo.env("LLVM_ASSERTIONS", "1");
1459 }
1460}
1461
1462#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1475struct RustcLink {
1476 build_compiler: Compiler,
1478 sysroot_compiler: Compiler,
1481 target: TargetSelection,
1482 crates: Vec<String>,
1484}
1485
1486impl RustcLink {
1487 fn from_rustc(rustc: Rustc) -> Self {
1490 Self {
1491 build_compiler: rustc.build_compiler,
1492 sysroot_compiler: rustc.build_compiler,
1493 target: rustc.target,
1494 crates: rustc.crates,
1495 }
1496 }
1497
1498 fn from_build_compiler_and_sysroot(
1500 build_compiler: Compiler,
1501 sysroot_compiler: Compiler,
1502 target: TargetSelection,
1503 crates: Vec<String>,
1504 ) -> Self {
1505 Self { build_compiler, sysroot_compiler, target, crates }
1506 }
1507}
1508
1509impl Step for RustcLink {
1510 type Output = ();
1511
1512 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1513 run.never()
1514 }
1515
1516 fn run(self, builder: &Builder<'_>) {
1518 let build_compiler = self.build_compiler;
1519 let sysroot_compiler = self.sysroot_compiler;
1520 let target = self.target;
1521 add_to_sysroot(
1522 builder,
1523 &builder.sysroot_target_libdir(sysroot_compiler, target),
1524 &builder.sysroot_target_libdir(sysroot_compiler, sysroot_compiler.host),
1525 &build_stamp::librustc_stamp(builder, build_compiler, target),
1526 );
1527 }
1528}
1529
1530#[derive(Clone)]
1533pub struct GccCodegenBackendOutput {
1534 stamp: BuildStamp,
1535 gcc: GccOutput,
1536}
1537
1538#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1539pub struct GccCodegenBackend {
1540 compilers: RustcPrivateCompilers,
1541}
1542
1543impl Step for GccCodegenBackend {
1544 type Output = GccCodegenBackendOutput;
1545
1546 const IS_HOST: bool = true;
1547
1548 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1549 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1550 }
1551
1552 fn make_run(run: RunConfig<'_>) {
1553 run.builder.ensure(GccCodegenBackend {
1554 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1555 });
1556 }
1557
1558 fn run(self, builder: &Builder<'_>) -> Self::Output {
1559 let target = self.compilers.target();
1560 let build_compiler = self.compilers.build_compiler();
1561
1562 let stamp = build_stamp::codegen_backend_stamp(
1563 builder,
1564 build_compiler,
1565 target,
1566 &CodegenBackendKind::Gcc,
1567 );
1568
1569 let gcc = builder.ensure(Gcc { target });
1570
1571 if builder.config.keep_stage.contains(&build_compiler.stage) {
1572 trace!("`keep-stage` requested");
1573 builder.info(
1574 "WARNING: Using a potentially old codegen backend. \
1575 This may not behave well.",
1576 );
1577 return GccCodegenBackendOutput { stamp, gcc };
1580 }
1581
1582 let mut cargo = builder::Cargo::new(
1583 builder,
1584 build_compiler,
1585 Mode::Codegen,
1586 SourceType::InTree,
1587 target,
1588 Kind::Build,
1589 );
1590 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1591 rustc_cargo_env(builder, &mut cargo, target);
1592
1593 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1594
1595 let _guard =
1596 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1597 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1598
1599 GccCodegenBackendOutput {
1600 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1601 gcc,
1602 }
1603 }
1604
1605 fn metadata(&self) -> Option<StepMetadata> {
1606 Some(
1607 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1608 .built_by(self.compilers.build_compiler()),
1609 )
1610 }
1611}
1612
1613#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1614pub struct CraneliftCodegenBackend {
1615 pub compilers: RustcPrivateCompilers,
1616}
1617
1618impl Step for CraneliftCodegenBackend {
1619 type Output = BuildStamp;
1620 const IS_HOST: bool = true;
1621
1622 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1623 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1624 }
1625
1626 fn make_run(run: RunConfig<'_>) {
1627 run.builder.ensure(CraneliftCodegenBackend {
1628 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1629 });
1630 }
1631
1632 fn run(self, builder: &Builder<'_>) -> Self::Output {
1633 let target = self.compilers.target();
1634 let build_compiler = self.compilers.build_compiler();
1635
1636 let stamp = build_stamp::codegen_backend_stamp(
1637 builder,
1638 build_compiler,
1639 target,
1640 &CodegenBackendKind::Cranelift,
1641 );
1642
1643 if builder.config.keep_stage.contains(&build_compiler.stage) {
1644 trace!("`keep-stage` requested");
1645 builder.info(
1646 "WARNING: Using a potentially old codegen backend. \
1647 This may not behave well.",
1648 );
1649 return stamp;
1652 }
1653
1654 let mut cargo = builder::Cargo::new(
1655 builder,
1656 build_compiler,
1657 Mode::Codegen,
1658 SourceType::InTree,
1659 target,
1660 Kind::Build,
1661 );
1662 cargo
1663 .arg("--manifest-path")
1664 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1665 rustc_cargo_env(builder, &mut cargo, target);
1666
1667 let _guard = builder.msg(
1668 Kind::Build,
1669 "codegen backend cranelift",
1670 Mode::Codegen,
1671 build_compiler,
1672 target,
1673 );
1674 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1675 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1676 }
1677
1678 fn metadata(&self) -> Option<StepMetadata> {
1679 Some(
1680 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1681 .built_by(self.compilers.build_compiler()),
1682 )
1683 }
1684}
1685
1686fn write_codegen_backend_stamp(
1688 mut stamp: BuildStamp,
1689 files: Vec<PathBuf>,
1690 dry_run: bool,
1691) -> BuildStamp {
1692 if dry_run {
1693 return stamp;
1694 }
1695
1696 let mut files = files.into_iter().filter(|f| {
1697 let filename = f.file_name().unwrap().to_str().unwrap();
1698 is_dylib(f) && filename.contains("rustc_codegen_")
1699 });
1700 let codegen_backend = match files.next() {
1701 Some(f) => f,
1702 None => panic!("no dylibs built for codegen backend?"),
1703 };
1704 if let Some(f) = files.next() {
1705 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1706 }
1707
1708 let codegen_backend = codegen_backend.to_str().unwrap();
1709 stamp = stamp.add_stamp(codegen_backend);
1710 t!(stamp.write());
1711 stamp
1712}
1713
1714fn copy_codegen_backends_to_sysroot(
1721 builder: &Builder<'_>,
1722 stamp: BuildStamp,
1723 target_compiler: Compiler,
1724) {
1725 let dst = builder.sysroot_codegen_backends(target_compiler);
1734 t!(fs::create_dir_all(&dst), dst);
1735
1736 if builder.config.dry_run() {
1737 return;
1738 }
1739
1740 if stamp.path().exists() {
1741 let file = get_codegen_backend_file(&stamp);
1742 builder.copy_link(
1743 &file,
1744 &dst.join(normalize_codegen_backend_name(builder, &file)),
1745 FileType::NativeLibrary,
1746 );
1747 }
1748}
1749
1750pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1752 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1753}
1754
1755pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1757 let filename = path.file_name().unwrap().to_str().unwrap();
1758 let dash = filename.find('-').unwrap();
1761 let dot = filename.find('.').unwrap();
1762 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1763}
1764
1765pub fn compiler_file(
1766 builder: &Builder<'_>,
1767 compiler: &Path,
1768 target: TargetSelection,
1769 c: CLang,
1770 file: &str,
1771) -> PathBuf {
1772 if builder.config.dry_run() {
1773 return PathBuf::new();
1774 }
1775 let mut cmd = command(compiler);
1776 cmd.args(builder.cc_handled_clags(target, c));
1777 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1778 cmd.arg(format!("-print-file-name={file}"));
1779 let out = cmd.run_capture_stdout(builder).stdout();
1780 PathBuf::from(out.trim())
1781}
1782
1783#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1784pub struct Sysroot {
1785 pub compiler: Compiler,
1786 force_recompile: bool,
1788}
1789
1790impl Sysroot {
1791 pub(crate) fn new(compiler: Compiler) -> Self {
1792 Sysroot { compiler, force_recompile: false }
1793 }
1794}
1795
1796impl Step for Sysroot {
1797 type Output = PathBuf;
1798
1799 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1800 run.never()
1801 }
1802
1803 fn run(self, builder: &Builder<'_>) -> PathBuf {
1807 let compiler = self.compiler;
1808 let host_dir = builder.out.join(compiler.host);
1809
1810 let sysroot_dir = |stage| {
1811 if stage == 0 {
1812 host_dir.join("stage0-sysroot")
1813 } else if self.force_recompile && stage == compiler.stage {
1814 host_dir.join(format!("stage{stage}-test-sysroot"))
1815 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1816 host_dir.join("ci-rustc-sysroot")
1817 } else {
1818 host_dir.join(format!("stage{stage}"))
1819 }
1820 };
1821 let sysroot = sysroot_dir(compiler.stage);
1822 trace!(stage = ?compiler.stage, ?sysroot);
1823
1824 builder
1825 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1826 let _ = fs::remove_dir_all(&sysroot);
1827 t!(fs::create_dir_all(&sysroot));
1828
1829 if compiler.stage == 0 {
1836 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1837 }
1838
1839 if builder.download_rustc() && compiler.stage != 0 {
1841 assert_eq!(
1842 builder.config.host_target, compiler.host,
1843 "Cross-compiling is not yet supported with `download-rustc`",
1844 );
1845
1846 for stage in 0..=2 {
1848 if stage != compiler.stage {
1849 let dir = sysroot_dir(stage);
1850 if !dir.ends_with("ci-rustc-sysroot") {
1851 let _ = fs::remove_dir_all(dir);
1852 }
1853 }
1854 }
1855
1856 let mut filtered_files = Vec::new();
1866 let mut add_filtered_files = |suffix, contents| {
1867 for path in contents {
1868 let path = Path::new(&path);
1869 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1870 filtered_files.push(path.file_name().unwrap().to_owned());
1871 }
1872 }
1873 };
1874 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1875 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1876 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1879
1880 let filtered_extensions = [
1881 OsStr::new("rmeta"),
1882 OsStr::new("rlib"),
1883 OsStr::new(std::env::consts::DLL_EXTENSION),
1885 ];
1886 let ci_rustc_dir = builder.config.ci_rustc_dir();
1887 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1888 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1889 return true;
1890 }
1891 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1892 return true;
1893 }
1894 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1895 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1896 false
1897 } else {
1898 true
1899 }
1900 });
1901 }
1902
1903 if compiler.stage != 0 {
1909 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1910 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1911 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1912 if let Err(e) =
1913 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1914 {
1915 eprintln!(
1916 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1917 sysroot_lib_rustlib_src_rust.display(),
1918 builder.src.display(),
1919 e,
1920 );
1921 if builder.config.rust_remap_debuginfo {
1922 eprintln!(
1923 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1924 sysroot_lib_rustlib_src_rust.display(),
1925 );
1926 }
1927 build_helper::exit!(1);
1928 }
1929 }
1930
1931 if !builder.download_rustc() {
1933 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1934 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1935 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1936 if let Err(e) =
1937 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1938 {
1939 eprintln!(
1940 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1941 sysroot_lib_rustlib_rustcsrc_rust.display(),
1942 builder.src.display(),
1943 e,
1944 );
1945 build_helper::exit!(1);
1946 }
1947 }
1948
1949 sysroot
1950 }
1951}
1952
1953#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1960pub struct Assemble {
1961 pub target_compiler: Compiler,
1966}
1967
1968impl Step for Assemble {
1969 type Output = Compiler;
1970 const IS_HOST: bool = true;
1971
1972 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1973 run.path("compiler/rustc").path("compiler")
1974 }
1975
1976 fn make_run(run: RunConfig<'_>) {
1977 run.builder.ensure(Assemble {
1978 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1979 });
1980 }
1981
1982 fn run(self, builder: &Builder<'_>) -> Compiler {
1983 let target_compiler = self.target_compiler;
1984
1985 if target_compiler.stage == 0 {
1986 trace!("stage 0 build compiler is always available, simply returning");
1987 assert_eq!(
1988 builder.config.host_target, target_compiler.host,
1989 "Cannot obtain compiler for non-native build triple at stage 0"
1990 );
1991 return target_compiler;
1993 }
1994
1995 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
1998 let libdir_bin = libdir.parent().unwrap().join("bin");
1999 t!(fs::create_dir_all(&libdir_bin));
2000
2001 if builder.config.llvm_enabled(target_compiler.host) {
2002 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2003
2004 let target = target_compiler.host;
2005 let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
2006 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2007 trace!("LLVM tools enabled");
2008
2009 let host_llvm_bin_dir = command(&host_llvm_config)
2010 .arg("--bindir")
2011 .run_capture_stdout(builder)
2012 .stdout()
2013 .trim()
2014 .to_string();
2015
2016 let llvm_bin_dir = if target == builder.host_target {
2017 PathBuf::from(host_llvm_bin_dir)
2018 } else {
2019 let external_llvm_config = builder
2022 .config
2023 .target_config
2024 .get(&target)
2025 .and_then(|t| t.llvm_config.clone());
2026 if let Some(external_llvm_config) = external_llvm_config {
2027 external_llvm_config.parent().unwrap().to_path_buf()
2030 } else {
2031 let host_llvm_out = builder.llvm_out(builder.host_target);
2035 let target_llvm_out = builder.llvm_out(target);
2036 if let Ok(relative_path) =
2037 Path::new(&host_llvm_bin_dir).strip_prefix(host_llvm_out)
2038 {
2039 target_llvm_out.join(relative_path)
2040 } else {
2041 PathBuf::from(
2044 host_llvm_bin_dir
2045 .replace(&*builder.host_target.triple, &target.triple),
2046 )
2047 }
2048 }
2049 };
2050
2051 #[cfg(feature = "tracing")]
2058 let _llvm_tools_span =
2059 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2060 .entered();
2061 for tool in LLVM_TOOLS {
2062 trace!("installing `{tool}`");
2063 let tool_exe = exe(tool, target_compiler.host);
2064 let src_path = llvm_bin_dir.join(&tool_exe);
2065
2066 if !src_path.exists() && builder.config.llvm_from_ci {
2068 eprintln!("{} does not exist; skipping copy", src_path.display());
2069 continue;
2070 }
2071
2072 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2079 }
2080 }
2081 }
2082
2083 let maybe_install_llvm_bitcode_linker = || {
2084 if builder.config.llvm_bitcode_linker_enabled {
2085 trace!("llvm-bitcode-linker enabled, installing");
2086 let llvm_bitcode_linker = builder.ensure(
2087 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2088 builder,
2089 target_compiler,
2090 ),
2091 );
2092
2093 let bindir_self_contained = builder
2095 .sysroot(target_compiler)
2096 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2097 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2098
2099 t!(fs::create_dir_all(&bindir_self_contained));
2100 builder.copy_link(
2101 &llvm_bitcode_linker.tool_path,
2102 &bindir_self_contained.join(tool_exe),
2103 FileType::Executable,
2104 );
2105 }
2106 };
2107
2108 if builder.download_rustc() {
2110 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2111
2112 builder.std(target_compiler, target_compiler.host);
2113 let sysroot =
2114 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2115 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2118 if target_compiler.stage == builder.top_stage {
2120 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2121 }
2122
2123 maybe_install_llvm_bitcode_linker();
2126
2127 return target_compiler;
2128 }
2129
2130 debug!(
2144 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2145 target_compiler.stage - 1,
2146 builder.config.host_target,
2147 );
2148 let build_compiler =
2149 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2150
2151 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2153 debug!("`llvm_enzyme` requested");
2154 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2155 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2156 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2157 let lib_ext = std::env::consts::DLL_EXTENSION;
2158 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2159 let src_lib =
2160 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2161 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2162 let target_libdir =
2163 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2164 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2165 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2166 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2167 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2168 }
2169 }
2170
2171 debug!(
2174 ?build_compiler,
2175 "target_compiler.host" = ?target_compiler.host,
2176 "building compiler libraries to link to"
2177 );
2178
2179 let BuiltRustc { build_compiler } =
2181 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2182
2183 let stage = target_compiler.stage;
2184 let host = target_compiler.host;
2185 let (host_info, dir_name) = if build_compiler.host == host {
2186 ("".into(), "host".into())
2187 } else {
2188 (format!(" ({host})"), host.to_string())
2189 };
2190 let msg = format!(
2195 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2196 );
2197 builder.info(&msg);
2198
2199 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2201 let proc_macros = builder
2202 .read_stamp_file(&stamp)
2203 .into_iter()
2204 .filter_map(|(path, dependency_type)| {
2205 if dependency_type == DependencyType::Host {
2206 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2207 } else {
2208 None
2209 }
2210 })
2211 .collect::<HashSet<_>>();
2212
2213 let sysroot = builder.sysroot(target_compiler);
2214 let rustc_libdir = builder.rustc_libdir(target_compiler);
2215 t!(fs::create_dir_all(&rustc_libdir));
2216 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2217 for f in builder.read_dir(&src_libdir) {
2218 let filename = f.file_name().into_string().unwrap();
2219
2220 let is_proc_macro = proc_macros.contains(&filename);
2221 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2222
2223 let can_be_rustc_dynamic_dep = if builder
2227 .link_std_into_rustc_driver(target_compiler.host)
2228 && !target_compiler.host.is_windows()
2229 {
2230 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2231 !is_std
2232 } else {
2233 true
2234 };
2235
2236 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2237 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2238 }
2239 }
2240
2241 {
2242 #[cfg(feature = "tracing")]
2243 let _codegen_backend_span =
2244 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2245
2246 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2247 if builder.kind == Kind::Check && builder.top_stage == 1 {
2264 continue;
2265 }
2266
2267 let prepare_compilers = || {
2268 RustcPrivateCompilers::from_build_and_target_compiler(
2269 build_compiler,
2270 target_compiler,
2271 )
2272 };
2273
2274 match backend {
2275 CodegenBackendKind::Cranelift => {
2276 let stamp = builder
2277 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2278 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2279 }
2280 CodegenBackendKind::Gcc => {
2281 let output =
2282 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2283 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2284 output.gcc.install_to(builder, &rustc_libdir);
2287 }
2288 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2289 }
2290 }
2291 }
2292
2293 if builder.config.lld_enabled {
2294 let lld_wrapper =
2295 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2296 builder,
2297 target_compiler,
2298 ));
2299 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2300 }
2301
2302 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2303 debug!(
2304 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2305 workaround faulty homebrew `strip`s"
2306 );
2307
2308 let src_exe = exe("llvm-objcopy", target_compiler.host);
2315 let dst_exe = exe("rust-objcopy", target_compiler.host);
2316 builder.copy_link(
2317 &libdir_bin.join(src_exe),
2318 &libdir_bin.join(dst_exe),
2319 FileType::Executable,
2320 );
2321 }
2322
2323 if builder.tool_enabled("wasm-component-ld") {
2326 let wasm_component = builder.ensure(
2327 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2328 builder,
2329 target_compiler,
2330 ),
2331 );
2332 builder.copy_link(
2333 &wasm_component.tool_path,
2334 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2335 FileType::Executable,
2336 );
2337 }
2338
2339 maybe_install_llvm_bitcode_linker();
2340
2341 debug!(
2344 "target_compiler.host" = ?target_compiler.host,
2345 ?sysroot,
2346 "ensuring availability of `libLLVM.so` in compiler directory"
2347 );
2348 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2349 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2350
2351 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2353 let rustc = out_dir.join(exe("rustc-main", host));
2354 let bindir = sysroot.join("bin");
2355 t!(fs::create_dir_all(bindir));
2356 let compiler = builder.rustc(target_compiler);
2357 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2358 builder.copy_link(&rustc, &compiler, FileType::Executable);
2359
2360 target_compiler
2361 }
2362}
2363
2364#[track_caller]
2369pub fn add_to_sysroot(
2370 builder: &Builder<'_>,
2371 sysroot_dst: &Path,
2372 sysroot_host_dst: &Path,
2373 stamp: &BuildStamp,
2374) {
2375 let self_contained_dst = &sysroot_dst.join("self-contained");
2376 t!(fs::create_dir_all(sysroot_dst));
2377 t!(fs::create_dir_all(sysroot_host_dst));
2378 t!(fs::create_dir_all(self_contained_dst));
2379 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2380 let dst = match dependency_type {
2381 DependencyType::Host => sysroot_host_dst,
2382 DependencyType::Target => sysroot_dst,
2383 DependencyType::TargetSelfContained => self_contained_dst,
2384 };
2385 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2386 }
2387}
2388
2389pub fn run_cargo(
2390 builder: &Builder<'_>,
2391 cargo: Cargo,
2392 tail_args: Vec<String>,
2393 stamp: &BuildStamp,
2394 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2395 is_check: bool,
2396 rlib_only_metadata: bool,
2397) -> Vec<PathBuf> {
2398 let target_root_dir = stamp.path().parent().unwrap();
2400 let target_deps_dir = target_root_dir.join("deps");
2402 let host_root_dir = target_root_dir
2404 .parent()
2405 .unwrap() .parent()
2407 .unwrap() .join(target_root_dir.file_name().unwrap());
2409
2410 let mut deps = Vec::new();
2414 let mut toplevel = Vec::new();
2415 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2416 let (filenames_vec, crate_types) = match msg {
2417 CargoMessage::CompilerArtifact {
2418 filenames,
2419 target: CargoTarget { crate_types },
2420 ..
2421 } => {
2422 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2423 f.sort(); (f, crate_types)
2425 }
2426 _ => return,
2427 };
2428 for filename in filenames_vec {
2429 let mut keep = false;
2431 if filename.ends_with(".lib")
2432 || filename.ends_with(".a")
2433 || is_debug_info(&filename)
2434 || is_dylib(Path::new(&*filename))
2435 {
2436 keep = true;
2438 }
2439 if is_check && filename.ends_with(".rmeta") {
2440 keep = true;
2442 } else if rlib_only_metadata {
2443 if filename.contains("jemalloc_sys")
2444 || filename.contains("rustc_public_bridge")
2445 || filename.contains("rustc_public")
2446 {
2447 keep |= filename.ends_with(".rlib");
2450 } else {
2451 keep |= filename.ends_with(".rmeta");
2455 }
2456 } else {
2457 keep |= filename.ends_with(".rlib");
2459 }
2460
2461 if !keep {
2462 continue;
2463 }
2464
2465 let filename = Path::new(&*filename);
2466
2467 if filename.starts_with(&host_root_dir) {
2470 if crate_types.iter().any(|t| t == "proc-macro") {
2472 deps.push((filename.to_path_buf(), DependencyType::Host));
2473 }
2474 continue;
2475 }
2476
2477 if filename.starts_with(&target_deps_dir) {
2480 deps.push((filename.to_path_buf(), DependencyType::Target));
2481 continue;
2482 }
2483
2484 let expected_len = t!(filename.metadata()).len();
2495 let filename = filename.file_name().unwrap().to_str().unwrap();
2496 let mut parts = filename.splitn(2, '.');
2497 let file_stem = parts.next().unwrap().to_owned();
2498 let extension = parts.next().unwrap().to_owned();
2499
2500 toplevel.push((file_stem, extension, expected_len));
2501 }
2502 });
2503
2504 if !ok {
2505 crate::exit!(1);
2506 }
2507
2508 if builder.config.dry_run() {
2509 return Vec::new();
2510 }
2511
2512 let contents = target_deps_dir
2516 .read_dir()
2517 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2518 .map(|e| t!(e))
2519 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2520 .collect::<Vec<_>>();
2521 for (prefix, extension, expected_len) in toplevel {
2522 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2523 meta.len() == expected_len
2524 && filename
2525 .strip_prefix(&prefix[..])
2526 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2527 .unwrap_or(false)
2528 });
2529 let max = candidates.max_by_key(|&(_, _, metadata)| {
2530 metadata.modified().expect("mtime should be available on all relevant OSes")
2531 });
2532 let path_to_add = match max {
2533 Some(triple) => triple.0.to_str().unwrap(),
2534 None => panic!("no output generated for {prefix:?} {extension:?}"),
2535 };
2536 if is_dylib(Path::new(path_to_add)) {
2537 let candidate = format!("{path_to_add}.lib");
2538 let candidate = PathBuf::from(candidate);
2539 if candidate.exists() {
2540 deps.push((candidate, DependencyType::Target));
2541 }
2542 }
2543 deps.push((path_to_add.into(), DependencyType::Target));
2544 }
2545
2546 deps.extend(additional_target_deps);
2547 deps.sort();
2548 let mut new_contents = Vec::new();
2549 for (dep, dependency_type) in deps.iter() {
2550 new_contents.extend(match *dependency_type {
2551 DependencyType::Host => b"h",
2552 DependencyType::Target => b"t",
2553 DependencyType::TargetSelfContained => b"s",
2554 });
2555 new_contents.extend(dep.to_str().unwrap().as_bytes());
2556 new_contents.extend(b"\0");
2557 }
2558 t!(fs::write(stamp.path(), &new_contents));
2559 deps.into_iter().map(|(d, _)| d).collect()
2560}
2561
2562pub fn stream_cargo(
2563 builder: &Builder<'_>,
2564 cargo: Cargo,
2565 tail_args: Vec<String>,
2566 cb: &mut dyn FnMut(CargoMessage<'_>),
2567) -> bool {
2568 let mut cmd = cargo.into_cmd();
2569
2570 let mut message_format = if builder.config.json_output {
2573 String::from("json")
2574 } else {
2575 String::from("json-render-diagnostics")
2576 };
2577 if let Some(s) = &builder.config.rustc_error_format {
2578 message_format.push_str(",json-diagnostic-");
2579 message_format.push_str(s);
2580 }
2581 cmd.arg("--message-format").arg(message_format);
2582
2583 for arg in tail_args {
2584 cmd.arg(arg);
2585 }
2586
2587 builder.verbose(|| println!("running: {cmd:?}"));
2588
2589 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2590
2591 let Some(mut streaming_command) = streaming_command else {
2592 return true;
2593 };
2594
2595 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2599 for line in stdout.lines() {
2600 let line = t!(line);
2601 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2602 Ok(msg) => {
2603 if builder.config.json_output {
2604 println!("{line}");
2606 }
2607 cb(msg)
2608 }
2609 Err(_) => println!("{line}"),
2611 }
2612 }
2613
2614 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2616 if builder.is_verbose() && !status.success() {
2617 eprintln!(
2618 "command did not execute successfully: {cmd:?}\n\
2619 expected success, got: {status}"
2620 );
2621 }
2622
2623 status.success()
2624}
2625
2626#[derive(Deserialize)]
2627pub struct CargoTarget<'a> {
2628 crate_types: Vec<Cow<'a, str>>,
2629}
2630
2631#[derive(Deserialize)]
2632#[serde(tag = "reason", rename_all = "kebab-case")]
2633pub enum CargoMessage<'a> {
2634 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2635 BuildScriptExecuted,
2636 BuildFinished,
2637}
2638
2639pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2640 if target != "x86_64-unknown-linux-gnu"
2644 || !builder.config.is_host_target(target)
2645 || !path.exists()
2646 {
2647 return;
2648 }
2649
2650 let previous_mtime = t!(t!(path.metadata()).modified());
2651 let stamp = BuildStamp::new(path.parent().unwrap())
2652 .with_prefix(path.file_name().unwrap().to_str().unwrap())
2653 .with_prefix("strip")
2654 .add_stamp(previous_mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos());
2655
2656 if !stamp.is_up_to_date() {
2659 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2660 }
2661 t!(stamp.write());
2662
2663 let file = t!(fs::File::open(path));
2664
2665 t!(file.set_modified(previous_mtime));
2678}
2679
2680pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2682 build_compiler.stage != 0
2683}