1use std::borrow::Cow;
10use std::collections::HashSet;
11use std::ffi::OsStr;
12use std::io::BufReader;
13use std::io::prelude::*;
14use std::path::{Path, PathBuf};
15use std::{env, fs, str};
16
17use serde_derive::Deserialize;
18#[cfg(feature = "tracing")]
19use tracing::span;
20
21use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags};
22use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
23use crate::core::build_steps::{dist, llvm};
24use crate::core::builder;
25use crate::core::builder::{
26 Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
27};
28use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
29use crate::utils::build_stamp;
30use crate::utils::build_stamp::BuildStamp;
31use crate::utils::exec::command;
32use crate::utils::helpers::{
33 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
34};
35use crate::{
36 CLang, CodegenBackendKind, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode,
37 debug, trace,
38};
39
40#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct Std {
43 pub target: TargetSelection,
44 pub build_compiler: Compiler,
46 crates: Vec<String>,
50 force_recompile: bool,
53 extra_rust_args: &'static [&'static str],
54 is_for_mir_opt_tests: bool,
55}
56
57impl Std {
58 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
59 Self {
60 target,
61 build_compiler,
62 crates: Default::default(),
63 force_recompile: false,
64 extra_rust_args: &[],
65 is_for_mir_opt_tests: false,
66 }
67 }
68
69 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
70 self.force_recompile = force_recompile;
71 self
72 }
73
74 #[expect(clippy::wrong_self_convention)]
75 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
76 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
77 self
78 }
79
80 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
81 self.extra_rust_args = extra_rust_args;
82 self
83 }
84
85 fn copy_extra_objects(
86 &self,
87 builder: &Builder<'_>,
88 compiler: &Compiler,
89 target: TargetSelection,
90 ) -> Vec<(PathBuf, DependencyType)> {
91 let mut deps = Vec::new();
92 if !self.is_for_mir_opt_tests {
93 deps.extend(copy_third_party_objects(builder, compiler, target));
94 deps.extend(copy_self_contained_objects(builder, compiler, target));
95 }
96 deps
97 }
98}
99
100impl Step for Std {
101 type Output = ();
102 const DEFAULT: bool = true;
103
104 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
105 run.crate_or_deps("sysroot").path("library")
106 }
107
108 fn make_run(run: RunConfig<'_>) {
109 let crates = std_crates_for_run_make(&run);
110 let builder = run.builder;
111
112 let force_recompile = builder.rust_info().is_managed_git_subrepository()
116 && builder.download_rustc()
117 && builder.config.has_changes_from_upstream(&["library"]);
118
119 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
120 trace!("download_rustc: {}", builder.download_rustc());
121 trace!(force_recompile);
122
123 run.builder.ensure(Std {
124 build_compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
125 target: run.target,
126 crates,
127 force_recompile,
128 extra_rust_args: &[],
129 is_for_mir_opt_tests: false,
130 });
131 }
132
133 fn run(self, builder: &Builder<'_>) {
139 let target = self.target;
140
141 if self.build_compiler.stage == 0 {
143 let compiler = self.build_compiler;
144 builder.ensure(StdLink::from_std(self, compiler));
145
146 return;
147 }
148
149 let build_compiler = if builder.download_rustc() && self.force_recompile {
150 builder
153 .compiler(self.build_compiler.stage.saturating_sub(1), builder.config.host_target)
154 } else {
155 self.build_compiler
156 };
157
158 if builder.download_rustc()
161 && builder.config.is_host_target(target)
162 && !self.force_recompile
163 {
164 let sysroot =
165 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
166 cp_rustc_component_to_ci_sysroot(
167 builder,
168 &sysroot,
169 builder.config.ci_rust_std_contents(),
170 );
171 return;
172 }
173
174 if builder.config.keep_stage.contains(&build_compiler.stage)
175 || builder.config.keep_stage_std.contains(&build_compiler.stage)
176 {
177 trace!(keep_stage = ?builder.config.keep_stage);
178 trace!(keep_stage_std = ?builder.config.keep_stage_std);
179
180 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
181
182 builder.ensure(StartupObjects { compiler: build_compiler, target });
183
184 self.copy_extra_objects(builder, &build_compiler, target);
185
186 builder.ensure(StdLink::from_std(self, build_compiler));
187 return;
188 }
189
190 let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
191
192 let stage = build_compiler.stage;
194
195 if build_compiler.stage > 1
199 && !builder.config.full_bootstrap
200 && (target == builder.host_target || builder.config.hosts.contains(&target))
210 {
211 let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
212 builder.std(build_compiler_for_std_to_uplift, target);
213
214 let msg = if build_compiler_for_std_to_uplift.host == target {
215 format!(
216 "Uplifting library (stage{} -> stage{stage})",
217 build_compiler_for_std_to_uplift.stage
218 )
219 } else {
220 format!(
221 "Uplifting library (stage{}:{} -> stage{stage}:{target})",
222 build_compiler_for_std_to_uplift.stage, build_compiler_for_std_to_uplift.host,
223 )
224 };
225
226 builder.info(&msg);
227
228 self.copy_extra_objects(builder, &build_compiler, target);
231
232 builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
233 return;
234 }
235
236 target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
237
238 let mut cargo = if self.is_for_mir_opt_tests {
242 trace!("building special sysroot for mir-opt tests");
243 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
244 builder,
245 build_compiler,
246 Mode::Std,
247 SourceType::InTree,
248 target,
249 Kind::Check,
250 );
251 cargo.rustflag("-Zalways-encode-mir");
252 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
253 cargo
254 } else {
255 trace!("building regular sysroot");
256 let mut cargo = builder::Cargo::new(
257 builder,
258 build_compiler,
259 Mode::Std,
260 SourceType::InTree,
261 target,
262 Kind::Build,
263 );
264 std_cargo(builder, target, &mut cargo);
265 for krate in &*self.crates {
266 cargo.arg("-p").arg(krate);
267 }
268 cargo
269 };
270
271 if target.is_synthetic() {
273 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
274 }
275 for rustflag in self.extra_rust_args.iter() {
276 cargo.rustflag(rustflag);
277 }
278
279 let _guard = builder.msg(
280 Kind::Build,
281 format_args!("library artifacts{}", crate_description(&self.crates)),
282 Mode::Std,
283 build_compiler,
284 target,
285 );
286 run_cargo(
287 builder,
288 cargo,
289 vec![],
290 &build_stamp::libstd_stamp(builder, build_compiler, target),
291 target_deps,
292 self.is_for_mir_opt_tests, false,
294 );
295
296 builder.ensure(StdLink::from_std(
297 self,
298 builder.compiler(build_compiler.stage, builder.config.host_target),
299 ));
300 }
301
302 fn metadata(&self) -> Option<StepMetadata> {
303 Some(StepMetadata::build("std", self.target).built_by(self.build_compiler))
304 }
305}
306
307fn copy_and_stamp(
308 builder: &Builder<'_>,
309 libdir: &Path,
310 sourcedir: &Path,
311 name: &str,
312 target_deps: &mut Vec<(PathBuf, DependencyType)>,
313 dependency_type: DependencyType,
314) {
315 let target = libdir.join(name);
316 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
317
318 target_deps.push((target, dependency_type));
319}
320
321fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
322 let libunwind_path = builder.ensure(llvm::Libunwind { target });
323 let libunwind_source = libunwind_path.join("libunwind.a");
324 let libunwind_target = libdir.join("libunwind.a");
325 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
326 libunwind_target
327}
328
329fn copy_third_party_objects(
331 builder: &Builder<'_>,
332 compiler: &Compiler,
333 target: TargetSelection,
334) -> Vec<(PathBuf, DependencyType)> {
335 let mut target_deps = vec![];
336
337 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
338 target_deps.extend(
341 copy_sanitizers(builder, compiler, target)
342 .into_iter()
343 .map(|d| (d, DependencyType::Target)),
344 );
345 }
346
347 if target == "x86_64-fortanix-unknown-sgx"
348 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
349 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
350 {
351 let libunwind_path =
352 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
353 target_deps.push((libunwind_path, DependencyType::Target));
354 }
355
356 target_deps
357}
358
359fn copy_self_contained_objects(
361 builder: &Builder<'_>,
362 compiler: &Compiler,
363 target: TargetSelection,
364) -> Vec<(PathBuf, DependencyType)> {
365 let libdir_self_contained =
366 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
367 t!(fs::create_dir_all(&libdir_self_contained));
368 let mut target_deps = vec![];
369
370 if target.needs_crt_begin_end() {
378 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
379 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
380 });
381 if !target.starts_with("wasm32") {
382 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
383 copy_and_stamp(
384 builder,
385 &libdir_self_contained,
386 &srcdir,
387 obj,
388 &mut target_deps,
389 DependencyType::TargetSelfContained,
390 );
391 }
392 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
393 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
394 let src = crt_path.join(obj);
395 let target = libdir_self_contained.join(obj);
396 builder.copy_link(&src, &target, FileType::NativeLibrary);
397 target_deps.push((target, DependencyType::TargetSelfContained));
398 }
399 } else {
400 for &obj in &["libc.a", "crt1-command.o"] {
403 copy_and_stamp(
404 builder,
405 &libdir_self_contained,
406 &srcdir,
407 obj,
408 &mut target_deps,
409 DependencyType::TargetSelfContained,
410 );
411 }
412 }
413 if !target.starts_with("s390x") {
414 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
415 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
416 }
417 } else if target.contains("-wasi") {
418 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
419 panic!(
420 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
421 or `$WASI_SDK_PATH` set",
422 target.triple
423 )
424 });
425 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
426 copy_and_stamp(
427 builder,
428 &libdir_self_contained,
429 &srcdir,
430 obj,
431 &mut target_deps,
432 DependencyType::TargetSelfContained,
433 );
434 }
435 } else if target.is_windows_gnu() {
436 for obj in ["crt2.o", "dllcrt2.o"].iter() {
437 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
438 let dst = libdir_self_contained.join(obj);
439 builder.copy_link(&src, &dst, FileType::NativeLibrary);
440 target_deps.push((dst, DependencyType::TargetSelfContained));
441 }
442 }
443
444 target_deps
445}
446
447pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
450 let mut crates = run.make_run_crates(builder::Alias::Library);
451
452 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
461 if target_is_no_std {
462 crates.retain(|c| c == "core" || c == "alloc");
463 }
464 crates
465}
466
467fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
473 if builder.config.llvm_from_ci {
475 builder.config.maybe_download_ci_llvm();
477 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
478 if ci_llvm_compiler_rt.exists() {
479 return ci_llvm_compiler_rt;
480 }
481 }
482
483 builder.require_submodule("src/llvm-project", {
485 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
486 });
487 builder.src.join("src/llvm-project/compiler-rt")
488}
489
490pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
493 if target.contains("apple") && !builder.config.dry_run() {
511 let mut cmd = command(builder.rustc(cargo.compiler()));
515 cmd.arg("--target").arg(target.rustc_target_arg());
516 cmd.arg("--print=deployment-target");
517 let output = cmd.run_capture_stdout(builder).stdout();
518
519 let (env_var, value) = output.split_once('=').unwrap();
520 cargo.env(env_var.trim(), value.trim());
523
524 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
534 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
535 }
536 }
537
538 if let Some(path) = builder.config.profiler_path(target) {
540 cargo.env("LLVM_PROFILER_RT_LIB", path);
541 } else if builder.config.profiler_enabled(target) {
542 let compiler_rt = compiler_rt_for_profiler(builder);
543 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
547 }
548
549 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
563 builder.require_submodule(
571 "src/llvm-project",
572 Some(
573 "The `build.optimized-compiler-builtins` config option \
574 requires `compiler-rt` sources from LLVM.",
575 ),
576 );
577 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
578 assert!(compiler_builtins_root.exists());
579 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
582 " compiler-builtins-c"
583 } else {
584 ""
585 };
586
587 if !builder.unstable_features() {
590 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
591 }
592
593 let mut features = String::new();
594
595 if builder.no_std(target) == Some(true) {
596 features += " compiler-builtins-mem";
597 if !target.starts_with("bpf") {
598 features.push_str(compiler_builtins_c_feature);
599 }
600
601 cargo
603 .args(["-p", "alloc"])
604 .arg("--manifest-path")
605 .arg(builder.src.join("library/alloc/Cargo.toml"))
606 .arg("--features")
607 .arg(features);
608 } else {
609 features += &builder.std_features(target);
610 features.push_str(compiler_builtins_c_feature);
611
612 cargo
613 .arg("--features")
614 .arg(features)
615 .arg("--manifest-path")
616 .arg(builder.src.join("library/sysroot/Cargo.toml"));
617
618 if target.contains("musl")
621 && let Some(p) = builder.musl_libdir(target)
622 {
623 let root = format!("native={}", p.to_str().unwrap());
624 cargo.rustflag("-L").rustflag(&root);
625 }
626
627 if target.contains("-wasi")
628 && let Some(dir) = builder.wasi_libdir(target)
629 {
630 let root = format!("native={}", dir.to_str().unwrap());
631 cargo.rustflag("-L").rustflag(&root);
632 }
633 }
634
635 cargo.rustflag("-Cembed-bitcode=yes");
641
642 if builder.config.rust_lto == RustcLto::Off {
643 cargo.rustflag("-Clto=off");
644 }
645
646 if target.contains("riscv") {
653 cargo.rustflag("-Cforce-unwind-tables=yes");
654 }
655
656 cargo.rustflag("-Zunstable-options");
659 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
660
661 let html_root =
662 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
663 cargo.rustflag(&html_root);
664 cargo.rustdocflag(&html_root);
665
666 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
667}
668
669#[derive(Debug, Clone, PartialEq, Eq, Hash)]
678pub struct StdLink {
679 pub compiler: Compiler,
680 pub target_compiler: Compiler,
681 pub target: TargetSelection,
682 crates: Vec<String>,
684 force_recompile: bool,
686}
687
688impl StdLink {
689 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
690 Self {
691 compiler: host_compiler,
692 target_compiler: std.build_compiler,
693 target: std.target,
694 crates: std.crates,
695 force_recompile: std.force_recompile,
696 }
697 }
698}
699
700impl Step for StdLink {
701 type Output = ();
702
703 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
704 run.never()
705 }
706
707 fn run(self, builder: &Builder<'_>) {
716 let compiler = self.compiler;
717 let target_compiler = self.target_compiler;
718 let target = self.target;
719
720 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
722 let lib = builder.sysroot_libdir_relative(self.compiler);
724 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
725 compiler: self.compiler,
726 force_recompile: self.force_recompile,
727 });
728 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
729 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
730 (libdir, hostdir)
731 } else {
732 let libdir = builder.sysroot_target_libdir(target_compiler, target);
733 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
734 (libdir, hostdir)
735 };
736
737 let is_downloaded_beta_stage0 = builder
738 .build
739 .config
740 .initial_rustc
741 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
742
743 if compiler.stage == 0 && is_downloaded_beta_stage0 {
747 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
749
750 let host = compiler.host;
751 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
752 let sysroot_bin_dir = sysroot.join("bin");
753 t!(fs::create_dir_all(&sysroot_bin_dir));
754 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
755
756 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
757 t!(fs::create_dir_all(sysroot.join("lib")));
758 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
759
760 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
762 t!(fs::create_dir_all(&sysroot_codegen_backends));
763 let stage0_codegen_backends = builder
764 .out
765 .join(host)
766 .join("stage0/lib/rustlib")
767 .join(host)
768 .join("codegen-backends");
769 if stage0_codegen_backends.exists() {
770 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
771 }
772 } else if compiler.stage == 0 {
773 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
774
775 if builder.local_rebuild {
776 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
780 }
781
782 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
783 } else {
784 if builder.download_rustc() {
785 let _ = fs::remove_dir_all(&libdir);
787 let _ = fs::remove_dir_all(&hostdir);
788 }
789
790 add_to_sysroot(
791 builder,
792 &libdir,
793 &hostdir,
794 &build_stamp::libstd_stamp(builder, compiler, target),
795 );
796 }
797 }
798}
799
800fn copy_sanitizers(
802 builder: &Builder<'_>,
803 compiler: &Compiler,
804 target: TargetSelection,
805) -> Vec<PathBuf> {
806 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
807
808 if builder.config.dry_run() {
809 return Vec::new();
810 }
811
812 let mut target_deps = Vec::new();
813 let libdir = builder.sysroot_target_libdir(*compiler, target);
814
815 for runtime in &runtimes {
816 let dst = libdir.join(&runtime.name);
817 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
818
819 if target == "x86_64-apple-darwin"
823 || target == "aarch64-apple-darwin"
824 || target == "aarch64-apple-ios"
825 || target == "aarch64-apple-ios-sim"
826 || target == "x86_64-apple-ios"
827 {
828 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
830 apple_darwin_sign_file(builder, &dst);
833 }
834
835 target_deps.push(dst);
836 }
837
838 target_deps
839}
840
841fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
842 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
843}
844
845fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
846 command("codesign")
847 .arg("-f") .arg("-s")
849 .arg("-")
850 .arg(file_path)
851 .run(builder);
852}
853
854#[derive(Debug, Clone, PartialEq, Eq, Hash)]
855pub struct StartupObjects {
856 pub compiler: Compiler,
857 pub target: TargetSelection,
858}
859
860impl Step for StartupObjects {
861 type Output = Vec<(PathBuf, DependencyType)>;
862
863 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
864 run.path("library/rtstartup")
865 }
866
867 fn make_run(run: RunConfig<'_>) {
868 run.builder.ensure(StartupObjects {
869 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
870 target: run.target,
871 });
872 }
873
874 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
881 let for_compiler = self.compiler;
882 let target = self.target;
883 if !target.is_windows_gnu() {
884 return vec![];
885 }
886
887 let mut target_deps = vec![];
888
889 let src_dir = &builder.src.join("library").join("rtstartup");
890 let dst_dir = &builder.native_dir(target).join("rtstartup");
891 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
892 t!(fs::create_dir_all(dst_dir));
893
894 for file in &["rsbegin", "rsend"] {
895 let src_file = &src_dir.join(file.to_string() + ".rs");
896 let dst_file = &dst_dir.join(file.to_string() + ".o");
897 if !up_to_date(src_file, dst_file) {
898 let mut cmd = command(&builder.initial_rustc);
899 cmd.env("RUSTC_BOOTSTRAP", "1");
900 if !builder.local_rebuild {
901 cmd.arg("--cfg").arg("bootstrap");
903 }
904 cmd.arg("--target")
905 .arg(target.rustc_target_arg())
906 .arg("--emit=obj")
907 .arg("-o")
908 .arg(dst_file)
909 .arg(src_file)
910 .run(builder);
911 }
912
913 let obj = sysroot_dir.join((*file).to_string() + ".o");
914 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
915 target_deps.push((obj, DependencyType::Target));
916 }
917
918 target_deps
919 }
920}
921
922fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
923 let ci_rustc_dir = builder.config.ci_rustc_dir();
924
925 for file in contents {
926 let src = ci_rustc_dir.join(&file);
927 let dst = sysroot.join(file);
928 if src.is_dir() {
929 t!(fs::create_dir_all(dst));
930 } else {
931 builder.copy_link(&src, &dst, FileType::Regular);
932 }
933 }
934}
935
936#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
943pub struct Rustc {
944 pub target: TargetSelection,
946 pub build_compiler: Compiler,
948 crates: Vec<String>,
954}
955
956impl Rustc {
957 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
958 Self { target, build_compiler, crates: Default::default() }
959 }
960}
961
962impl Step for Rustc {
963 type Output = ();
964
965 const IS_HOST: bool = true;
966 const DEFAULT: bool = false;
967
968 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
969 let mut crates = run.builder.in_tree_crates("rustc-main", None);
970 for (i, krate) in crates.iter().enumerate() {
971 if krate.name == "rustc-main" {
974 crates.swap_remove(i);
975 break;
976 }
977 }
978 run.crates(crates)
979 }
980
981 fn make_run(run: RunConfig<'_>) {
982 if run.builder.paths == vec![PathBuf::from("compiler")] {
985 return;
986 }
987
988 let crates = run.cargo_crates_in_set();
989 run.builder.ensure(Rustc {
990 build_compiler: run
991 .builder
992 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
993 target: run.target,
994 crates,
995 });
996 }
997
998 fn run(self, builder: &Builder<'_>) {
1004 let build_compiler = self.build_compiler;
1005 let target = self.target;
1006
1007 if builder.download_rustc() && build_compiler.stage != 0 {
1010 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1011
1012 let sysroot =
1013 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1014 cp_rustc_component_to_ci_sysroot(
1015 builder,
1016 &sysroot,
1017 builder.config.ci_rustc_dev_contents(),
1018 );
1019 return;
1020 }
1021
1022 builder.std(build_compiler, target);
1025
1026 if builder.config.keep_stage.contains(&build_compiler.stage) {
1027 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1028
1029 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1030 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1031 builder.ensure(RustcLink::from_rustc(self, build_compiler));
1032
1033 return;
1034 }
1035
1036 let stage = build_compiler.stage + 1;
1038
1039 if build_compiler.stage >= 2
1042 && !builder.config.full_bootstrap
1043 && (target == builder.host_target || builder.hosts.contains(&target))
1044 {
1045 let stage_to_uplift = if target == builder.host_target { 1 } else { 2 };
1048 let rustc_to_uplift = builder.compiler(stage_to_uplift, target);
1049 let msg = if rustc_to_uplift.host == target {
1050 format!("Uplifting rustc (stage{} -> stage{stage})", rustc_to_uplift.stage,)
1051 } else {
1052 format!(
1053 "Uplifting rustc (stage{}:{} -> stage{stage}:{target})",
1054 rustc_to_uplift.stage, rustc_to_uplift.host,
1055 )
1056 };
1057 builder.info(&msg);
1058 builder.ensure(RustcLink::from_rustc(self, rustc_to_uplift));
1059 return;
1060 }
1061
1062 builder.std(
1068 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1069 builder.config.host_target,
1070 );
1071
1072 let mut cargo = builder::Cargo::new(
1073 builder,
1074 build_compiler,
1075 Mode::Rustc,
1076 SourceType::InTree,
1077 target,
1078 Kind::Build,
1079 );
1080
1081 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1082
1083 for krate in &*self.crates {
1087 cargo.arg("-p").arg(krate);
1088 }
1089
1090 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1091 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1093 }
1094
1095 let _guard = builder.msg(
1096 Kind::Build,
1097 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1098 Mode::Rustc,
1099 build_compiler,
1100 target,
1101 );
1102 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1103 run_cargo(
1104 builder,
1105 cargo,
1106 vec![],
1107 &stamp,
1108 vec![],
1109 false,
1110 true, );
1112
1113 let target_root_dir = stamp.path().parent().unwrap();
1114 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1120 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1121 {
1122 let rustc_driver = target_root_dir.join("librustc_driver.so");
1123 strip_debug(builder, target, &rustc_driver);
1124 }
1125
1126 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1127 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1130 }
1131
1132 builder.ensure(RustcLink::from_rustc(
1133 self,
1134 builder.compiler(build_compiler.stage, builder.config.host_target),
1135 ));
1136 }
1137
1138 fn metadata(&self) -> Option<StepMetadata> {
1139 Some(StepMetadata::build("rustc", self.target).built_by(self.build_compiler))
1140 }
1141}
1142
1143pub fn rustc_cargo(
1144 builder: &Builder<'_>,
1145 cargo: &mut Cargo,
1146 target: TargetSelection,
1147 build_compiler: &Compiler,
1148 crates: &[String],
1149) {
1150 cargo
1151 .arg("--features")
1152 .arg(builder.rustc_features(builder.kind, target, crates))
1153 .arg("--manifest-path")
1154 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1155
1156 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1157
1158 cargo.rustflag("-Zon-broken-pipe=kill");
1172
1173 if builder.config.llvm_enzyme {
1176 let arch = builder.build.host_target;
1177 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1178 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1179
1180 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1181 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1182 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1183 }
1184 }
1185
1186 if builder.build.config.lld_mode.is_used() {
1191 cargo.rustflag("-Zdefault-visibility=protected");
1192 }
1193
1194 if is_lto_stage(build_compiler) {
1195 match builder.config.rust_lto {
1196 RustcLto::Thin | RustcLto::Fat => {
1197 cargo.rustflag("-Zdylib-lto");
1200 let lto_type = match builder.config.rust_lto {
1204 RustcLto::Thin => "thin",
1205 RustcLto::Fat => "fat",
1206 _ => unreachable!(),
1207 };
1208 cargo.rustflag(&format!("-Clto={lto_type}"));
1209 cargo.rustflag("-Cembed-bitcode=yes");
1210 }
1211 RustcLto::ThinLocal => { }
1212 RustcLto::Off => {
1213 cargo.rustflag("-Clto=off");
1214 }
1215 }
1216 } else if builder.config.rust_lto == RustcLto::Off {
1217 cargo.rustflag("-Clto=off");
1218 }
1219
1220 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1228 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1229 }
1230
1231 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1232 panic!("Cannot use and generate PGO profiles at the same time");
1233 }
1234 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1235 if build_compiler.stage == 1 {
1236 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1237 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1240 true
1241 } else {
1242 false
1243 }
1244 } else if let Some(path) = &builder.config.rust_profile_use {
1245 if build_compiler.stage == 1 {
1246 cargo.rustflag(&format!("-Cprofile-use={path}"));
1247 if builder.is_verbose() {
1248 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1249 }
1250 true
1251 } else {
1252 false
1253 }
1254 } else {
1255 false
1256 };
1257 if is_collecting {
1258 cargo.rustflag(&format!(
1260 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1261 builder.config.src.components().count()
1262 ));
1263 }
1264
1265 if let Some(ref ccache) = builder.config.ccache
1270 && build_compiler.stage == 0
1271 && !builder.config.incremental
1272 {
1273 cargo.env("RUSTC_WRAPPER", ccache);
1274 }
1275
1276 rustc_cargo_env(builder, cargo, target);
1277}
1278
1279pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1280 cargo
1283 .env("CFG_RELEASE", builder.rust_release())
1284 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1285 .env("CFG_VERSION", builder.rust_version());
1286
1287 if builder.config.omit_git_hash {
1291 cargo.env("CFG_OMIT_GIT_HASH", "1");
1292 }
1293
1294 if let Some(backend) = builder.config.default_codegen_backend(target) {
1295 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
1296 }
1297
1298 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1299 let target_config = builder.config.target_config.get(&target);
1300
1301 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1302
1303 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1304 cargo.env("CFG_VER_DATE", ver_date);
1305 }
1306 if let Some(ref ver_hash) = builder.rust_info().sha() {
1307 cargo.env("CFG_VER_HASH", ver_hash);
1308 }
1309 if !builder.unstable_features() {
1310 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1311 }
1312
1313 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1316 cargo.env("CFG_DEFAULT_LINKER", s);
1317 } else if let Some(ref s) = builder.config.rustc_default_linker {
1318 cargo.env("CFG_DEFAULT_LINKER", s);
1319 }
1320
1321 if builder.config.lld_enabled {
1323 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1324 }
1325
1326 if builder.config.rust_verify_llvm_ir {
1327 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1328 }
1329
1330 if builder.config.llvm_enzyme {
1331 cargo.rustflag("--cfg=llvm_enzyme");
1332 }
1333
1334 if builder.config.llvm_enabled(target) {
1346 let building_llvm_is_expensive =
1347 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1348 .should_build();
1349
1350 let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
1351 if !skip_llvm {
1352 rustc_llvm_env(builder, cargo, target)
1353 }
1354 }
1355
1356 if builder.config.jemalloc(target)
1360 && target.starts_with("aarch64")
1361 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1362 {
1363 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1364 }
1365}
1366
1367fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1373 if builder.config.is_rust_llvm(target) {
1374 cargo.env("LLVM_RUSTLLVM", "1");
1375 }
1376 if builder.config.llvm_enzyme {
1377 cargo.env("LLVM_ENZYME", "1");
1378 }
1379 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1380 cargo.env("LLVM_CONFIG", &llvm_config);
1381
1382 let mut llvm_linker_flags = String::new();
1392 if builder.config.llvm_profile_generate
1393 && target.is_msvc()
1394 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1395 {
1396 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1398 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1399 }
1400
1401 if let Some(ref s) = builder.config.llvm_ldflags {
1403 if !llvm_linker_flags.is_empty() {
1404 llvm_linker_flags.push(' ');
1405 }
1406 llvm_linker_flags.push_str(s);
1407 }
1408
1409 if !llvm_linker_flags.is_empty() {
1411 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1412 }
1413
1414 if builder.config.llvm_static_stdcpp
1417 && !target.contains("freebsd")
1418 && !target.is_msvc()
1419 && !target.contains("apple")
1420 && !target.contains("solaris")
1421 {
1422 let libstdcxx_name =
1423 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1424 let file = compiler_file(
1425 builder,
1426 &builder.cxx(target).unwrap(),
1427 target,
1428 CLang::Cxx,
1429 libstdcxx_name,
1430 );
1431 cargo.env("LLVM_STATIC_STDCPP", file);
1432 }
1433 if builder.llvm_link_shared() {
1434 cargo.env("LLVM_LINK_SHARED", "1");
1435 }
1436 if builder.config.llvm_use_libcxx {
1437 cargo.env("LLVM_USE_LIBCXX", "1");
1438 }
1439 if builder.config.llvm_assertions {
1440 cargo.env("LLVM_ASSERTIONS", "1");
1441 }
1442}
1443
1444#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1450struct RustcLink {
1451 pub compiler: Compiler,
1453 pub previous_stage_compiler: Compiler,
1455 pub target: TargetSelection,
1456 crates: Vec<String>,
1458}
1459
1460impl RustcLink {
1461 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1462 Self {
1463 compiler: host_compiler,
1464 previous_stage_compiler: rustc.build_compiler,
1465 target: rustc.target,
1466 crates: rustc.crates,
1467 }
1468 }
1469}
1470
1471impl Step for RustcLink {
1472 type Output = ();
1473
1474 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1475 run.never()
1476 }
1477
1478 fn run(self, builder: &Builder<'_>) {
1480 let compiler = self.compiler;
1481 let previous_stage_compiler = self.previous_stage_compiler;
1482 let target = self.target;
1483 add_to_sysroot(
1484 builder,
1485 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1486 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1487 &build_stamp::librustc_stamp(builder, compiler, target),
1488 );
1489 }
1490}
1491
1492#[derive(Clone)]
1495pub struct GccCodegenBackendOutput {
1496 stamp: BuildStamp,
1497 gcc: GccOutput,
1498}
1499
1500#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1501pub struct GccCodegenBackend {
1502 compilers: RustcPrivateCompilers,
1503}
1504
1505impl Step for GccCodegenBackend {
1506 type Output = GccCodegenBackendOutput;
1507
1508 const IS_HOST: bool = true;
1509
1510 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1511 run.alias("rustc_codegen_gcc").alias("cg_gcc")
1512 }
1513
1514 fn make_run(run: RunConfig<'_>) {
1515 run.builder.ensure(GccCodegenBackend {
1516 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1517 });
1518 }
1519
1520 fn run(self, builder: &Builder<'_>) -> Self::Output {
1521 let target = self.compilers.target();
1522 let build_compiler = self.compilers.build_compiler();
1523
1524 let stamp = build_stamp::codegen_backend_stamp(
1525 builder,
1526 build_compiler,
1527 target,
1528 &CodegenBackendKind::Gcc,
1529 );
1530
1531 let gcc = builder.ensure(Gcc { target });
1532
1533 if builder.config.keep_stage.contains(&build_compiler.stage) {
1534 trace!("`keep-stage` requested");
1535 builder.info(
1536 "WARNING: Using a potentially old codegen backend. \
1537 This may not behave well.",
1538 );
1539 return GccCodegenBackendOutput { stamp, gcc };
1542 }
1543
1544 let mut cargo = builder::Cargo::new(
1545 builder,
1546 build_compiler,
1547 Mode::Codegen,
1548 SourceType::InTree,
1549 target,
1550 Kind::Build,
1551 );
1552 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
1553 rustc_cargo_env(builder, &mut cargo, target);
1554
1555 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1556
1557 let _guard =
1558 builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
1559 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1560
1561 GccCodegenBackendOutput {
1562 stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
1563 gcc,
1564 }
1565 }
1566
1567 fn metadata(&self) -> Option<StepMetadata> {
1568 Some(
1569 StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
1570 .built_by(self.compilers.build_compiler()),
1571 )
1572 }
1573}
1574
1575#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1576pub struct CraneliftCodegenBackend {
1577 pub compilers: RustcPrivateCompilers,
1578}
1579
1580impl Step for CraneliftCodegenBackend {
1581 type Output = BuildStamp;
1582 const IS_HOST: bool = true;
1583
1584 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1585 run.alias("rustc_codegen_cranelift").alias("cg_clif")
1586 }
1587
1588 fn make_run(run: RunConfig<'_>) {
1589 run.builder.ensure(CraneliftCodegenBackend {
1590 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1591 });
1592 }
1593
1594 fn run(self, builder: &Builder<'_>) -> Self::Output {
1595 let target = self.compilers.target();
1596 let build_compiler = self.compilers.build_compiler();
1597
1598 let stamp = build_stamp::codegen_backend_stamp(
1599 builder,
1600 build_compiler,
1601 target,
1602 &CodegenBackendKind::Cranelift,
1603 );
1604
1605 if builder.config.keep_stage.contains(&build_compiler.stage) {
1606 trace!("`keep-stage` requested");
1607 builder.info(
1608 "WARNING: Using a potentially old codegen backend. \
1609 This may not behave well.",
1610 );
1611 return stamp;
1614 }
1615
1616 let mut cargo = builder::Cargo::new(
1617 builder,
1618 build_compiler,
1619 Mode::Codegen,
1620 SourceType::InTree,
1621 target,
1622 Kind::Build,
1623 );
1624 cargo
1625 .arg("--manifest-path")
1626 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
1627 rustc_cargo_env(builder, &mut cargo, target);
1628
1629 let _guard = builder.msg(
1630 Kind::Build,
1631 "codegen backend cranelift",
1632 Mode::Codegen,
1633 build_compiler,
1634 target,
1635 );
1636 let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
1637 write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
1638 }
1639
1640 fn metadata(&self) -> Option<StepMetadata> {
1641 Some(
1642 StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
1643 .built_by(self.compilers.build_compiler()),
1644 )
1645 }
1646}
1647
1648fn write_codegen_backend_stamp(
1650 mut stamp: BuildStamp,
1651 files: Vec<PathBuf>,
1652 dry_run: bool,
1653) -> BuildStamp {
1654 if dry_run {
1655 return stamp;
1656 }
1657
1658 let mut files = files.into_iter().filter(|f| {
1659 let filename = f.file_name().unwrap().to_str().unwrap();
1660 is_dylib(f) && filename.contains("rustc_codegen_")
1661 });
1662 let codegen_backend = match files.next() {
1663 Some(f) => f,
1664 None => panic!("no dylibs built for codegen backend?"),
1665 };
1666 if let Some(f) = files.next() {
1667 panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
1668 }
1669
1670 let codegen_backend = codegen_backend.to_str().unwrap();
1671 stamp = stamp.add_stamp(codegen_backend);
1672 t!(stamp.write());
1673 stamp
1674}
1675
1676fn copy_codegen_backends_to_sysroot(
1683 builder: &Builder<'_>,
1684 stamp: BuildStamp,
1685 target_compiler: Compiler,
1686) {
1687 let dst = builder.sysroot_codegen_backends(target_compiler);
1696 t!(fs::create_dir_all(&dst), dst);
1697
1698 if builder.config.dry_run() {
1699 return;
1700 }
1701
1702 if stamp.path().exists() {
1703 let file = get_codegen_backend_file(&stamp);
1704 builder.copy_link(
1705 &file,
1706 &dst.join(normalize_codegen_backend_name(builder, &file)),
1707 FileType::NativeLibrary,
1708 );
1709 }
1710}
1711
1712pub fn get_codegen_backend_file(stamp: &BuildStamp) -> PathBuf {
1714 PathBuf::from(t!(fs::read_to_string(stamp.path())))
1715}
1716
1717pub fn normalize_codegen_backend_name(builder: &Builder<'_>, path: &Path) -> String {
1719 let filename = path.file_name().unwrap().to_str().unwrap();
1720 let dash = filename.find('-').unwrap();
1723 let dot = filename.find('.').unwrap();
1724 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1725}
1726
1727pub fn compiler_file(
1728 builder: &Builder<'_>,
1729 compiler: &Path,
1730 target: TargetSelection,
1731 c: CLang,
1732 file: &str,
1733) -> PathBuf {
1734 if builder.config.dry_run() {
1735 return PathBuf::new();
1736 }
1737 let mut cmd = command(compiler);
1738 cmd.args(builder.cc_handled_clags(target, c));
1739 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1740 cmd.arg(format!("-print-file-name={file}"));
1741 let out = cmd.run_capture_stdout(builder).stdout();
1742 PathBuf::from(out.trim())
1743}
1744
1745#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1746pub struct Sysroot {
1747 pub compiler: Compiler,
1748 force_recompile: bool,
1750}
1751
1752impl Sysroot {
1753 pub(crate) fn new(compiler: Compiler) -> Self {
1754 Sysroot { compiler, force_recompile: false }
1755 }
1756}
1757
1758impl Step for Sysroot {
1759 type Output = PathBuf;
1760
1761 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1762 run.never()
1763 }
1764
1765 fn run(self, builder: &Builder<'_>) -> PathBuf {
1769 let compiler = self.compiler;
1770 let host_dir = builder.out.join(compiler.host);
1771
1772 let sysroot_dir = |stage| {
1773 if stage == 0 {
1774 host_dir.join("stage0-sysroot")
1775 } else if self.force_recompile && stage == compiler.stage {
1776 host_dir.join(format!("stage{stage}-test-sysroot"))
1777 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1778 host_dir.join("ci-rustc-sysroot")
1779 } else {
1780 host_dir.join(format!("stage{stage}"))
1781 }
1782 };
1783 let sysroot = sysroot_dir(compiler.stage);
1784 trace!(stage = ?compiler.stage, ?sysroot);
1785
1786 builder
1787 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1788 let _ = fs::remove_dir_all(&sysroot);
1789 t!(fs::create_dir_all(&sysroot));
1790
1791 if compiler.stage == 0 {
1798 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1799 }
1800
1801 if builder.download_rustc() && compiler.stage != 0 {
1803 assert_eq!(
1804 builder.config.host_target, compiler.host,
1805 "Cross-compiling is not yet supported with `download-rustc`",
1806 );
1807
1808 for stage in 0..=2 {
1810 if stage != compiler.stage {
1811 let dir = sysroot_dir(stage);
1812 if !dir.ends_with("ci-rustc-sysroot") {
1813 let _ = fs::remove_dir_all(dir);
1814 }
1815 }
1816 }
1817
1818 let mut filtered_files = Vec::new();
1828 let mut add_filtered_files = |suffix, contents| {
1829 for path in contents {
1830 let path = Path::new(&path);
1831 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1832 filtered_files.push(path.file_name().unwrap().to_owned());
1833 }
1834 }
1835 };
1836 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1837 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1838 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1841
1842 let filtered_extensions = [
1843 OsStr::new("rmeta"),
1844 OsStr::new("rlib"),
1845 OsStr::new(std::env::consts::DLL_EXTENSION),
1847 ];
1848 let ci_rustc_dir = builder.config.ci_rustc_dir();
1849 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1850 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1851 return true;
1852 }
1853 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1854 return true;
1855 }
1856 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1857 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1858 false
1859 } else {
1860 true
1861 }
1862 });
1863 }
1864
1865 if compiler.stage != 0 {
1871 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1872 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1873 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1874 if let Err(e) =
1875 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1876 {
1877 eprintln!(
1878 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1879 sysroot_lib_rustlib_src_rust.display(),
1880 builder.src.display(),
1881 e,
1882 );
1883 if builder.config.rust_remap_debuginfo {
1884 eprintln!(
1885 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1886 sysroot_lib_rustlib_src_rust.display(),
1887 );
1888 }
1889 build_helper::exit!(1);
1890 }
1891 }
1892
1893 if !builder.download_rustc() {
1895 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1896 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1897 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1898 if let Err(e) =
1899 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1900 {
1901 eprintln!(
1902 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1903 sysroot_lib_rustlib_rustcsrc_rust.display(),
1904 builder.src.display(),
1905 e,
1906 );
1907 build_helper::exit!(1);
1908 }
1909 }
1910
1911 sysroot
1912 }
1913}
1914
1915#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1922pub struct Assemble {
1923 pub target_compiler: Compiler,
1928}
1929
1930impl Step for Assemble {
1931 type Output = Compiler;
1932 const IS_HOST: bool = true;
1933
1934 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1935 run.path("compiler/rustc").path("compiler")
1936 }
1937
1938 fn make_run(run: RunConfig<'_>) {
1939 run.builder.ensure(Assemble {
1940 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1941 });
1942 }
1943
1944 fn run(self, builder: &Builder<'_>) -> Compiler {
1945 let target_compiler = self.target_compiler;
1946
1947 if target_compiler.stage == 0 {
1948 trace!("stage 0 build compiler is always available, simply returning");
1949 assert_eq!(
1950 builder.config.host_target, target_compiler.host,
1951 "Cannot obtain compiler for non-native build triple at stage 0"
1952 );
1953 return target_compiler;
1955 }
1956
1957 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
1960 let libdir_bin = libdir.parent().unwrap().join("bin");
1961 t!(fs::create_dir_all(&libdir_bin));
1962
1963 if builder.config.llvm_enabled(target_compiler.host) {
1964 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
1965
1966 let llvm::LlvmResult { llvm_config, .. } =
1967 builder.ensure(llvm::Llvm { target: target_compiler.host });
1968 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
1969 trace!("LLVM tools enabled");
1970
1971 let llvm_bin_dir =
1972 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
1973 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
1974
1975 #[cfg(feature = "tracing")]
1982 let _llvm_tools_span =
1983 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
1984 .entered();
1985 for tool in LLVM_TOOLS {
1986 trace!("installing `{tool}`");
1987 let tool_exe = exe(tool, target_compiler.host);
1988 let src_path = llvm_bin_dir.join(&tool_exe);
1989
1990 if !src_path.exists() && builder.config.llvm_from_ci {
1992 eprintln!("{} does not exist; skipping copy", src_path.display());
1993 continue;
1994 }
1995
1996 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2003 }
2004 }
2005 }
2006
2007 let maybe_install_llvm_bitcode_linker = || {
2008 if builder.config.llvm_bitcode_linker_enabled {
2009 trace!("llvm-bitcode-linker enabled, installing");
2010 let llvm_bitcode_linker = builder.ensure(
2011 crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
2012 builder,
2013 target_compiler,
2014 ),
2015 );
2016
2017 let bindir_self_contained = builder
2019 .sysroot(target_compiler)
2020 .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
2021 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2022
2023 t!(fs::create_dir_all(&bindir_self_contained));
2024 builder.copy_link(
2025 &llvm_bitcode_linker.tool_path,
2026 &bindir_self_contained.join(tool_exe),
2027 FileType::Executable,
2028 );
2029 }
2030 };
2031
2032 if builder.download_rustc() {
2034 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2035
2036 builder.std(target_compiler, target_compiler.host);
2037 let sysroot =
2038 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2039 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2042 if target_compiler.stage == builder.top_stage {
2044 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2045 }
2046
2047 maybe_install_llvm_bitcode_linker();
2050
2051 return target_compiler;
2052 }
2053
2054 debug!(
2068 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2069 target_compiler.stage - 1,
2070 builder.config.host_target,
2071 );
2072 let build_compiler =
2073 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2074
2075 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2077 debug!("`llvm_enzyme` requested");
2078 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2079 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2080 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2081 let lib_ext = std::env::consts::DLL_EXTENSION;
2082 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2083 let src_lib =
2084 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2085 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2086 let target_libdir =
2087 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2088 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2089 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2090 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2091 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2092 }
2093 }
2094
2095 debug!(
2098 ?build_compiler,
2099 "target_compiler.host" = ?target_compiler.host,
2100 "building compiler libraries to link to"
2101 );
2102 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2103
2104 let stage = target_compiler.stage;
2105 let host = target_compiler.host;
2106 let (host_info, dir_name) = if build_compiler.host == host {
2107 ("".into(), "host".into())
2108 } else {
2109 (format!(" ({host})"), host.to_string())
2110 };
2111 let msg = format!(
2116 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2117 );
2118 builder.info(&msg);
2119
2120 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2122 let proc_macros = builder
2123 .read_stamp_file(&stamp)
2124 .into_iter()
2125 .filter_map(|(path, dependency_type)| {
2126 if dependency_type == DependencyType::Host {
2127 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2128 } else {
2129 None
2130 }
2131 })
2132 .collect::<HashSet<_>>();
2133
2134 let sysroot = builder.sysroot(target_compiler);
2135 let rustc_libdir = builder.rustc_libdir(target_compiler);
2136 t!(fs::create_dir_all(&rustc_libdir));
2137 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2138 for f in builder.read_dir(&src_libdir) {
2139 let filename = f.file_name().into_string().unwrap();
2140
2141 let is_proc_macro = proc_macros.contains(&filename);
2142 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2143
2144 let can_be_rustc_dynamic_dep = if builder
2148 .link_std_into_rustc_driver(target_compiler.host)
2149 && !target_compiler.host.is_windows()
2150 {
2151 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2152 !is_std
2153 } else {
2154 true
2155 };
2156
2157 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2158 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2159 }
2160 }
2161
2162 {
2163 #[cfg(feature = "tracing")]
2164 let _codegen_backend_span =
2165 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2166
2167 for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
2168 if builder.kind == Kind::Check && builder.top_stage == 1 {
2185 continue;
2186 }
2187
2188 let prepare_compilers = || {
2189 RustcPrivateCompilers::from_build_and_target_compiler(
2190 build_compiler,
2191 target_compiler,
2192 )
2193 };
2194
2195 match backend {
2196 CodegenBackendKind::Cranelift => {
2197 let stamp = builder
2198 .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
2199 copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
2200 }
2201 CodegenBackendKind::Gcc => {
2202 let output =
2203 builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
2204 copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
2205 output.gcc.install_to(builder, &rustc_libdir);
2208 }
2209 CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
2210 }
2211 }
2212 }
2213
2214 if builder.config.lld_enabled {
2215 let lld_wrapper =
2216 builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
2217 builder,
2218 target_compiler,
2219 ));
2220 copy_lld_artifacts(builder, lld_wrapper, target_compiler);
2221 }
2222
2223 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2224 debug!(
2225 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2226 workaround faulty homebrew `strip`s"
2227 );
2228
2229 let src_exe = exe("llvm-objcopy", target_compiler.host);
2236 let dst_exe = exe("rust-objcopy", target_compiler.host);
2237 builder.copy_link(
2238 &libdir_bin.join(src_exe),
2239 &libdir_bin.join(dst_exe),
2240 FileType::Executable,
2241 );
2242 }
2243
2244 if builder.tool_enabled("wasm-component-ld") {
2247 let wasm_component = builder.ensure(
2248 crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
2249 builder,
2250 target_compiler,
2251 ),
2252 );
2253 builder.copy_link(
2254 &wasm_component.tool_path,
2255 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2256 FileType::Executable,
2257 );
2258 }
2259
2260 maybe_install_llvm_bitcode_linker();
2261
2262 debug!(
2265 "target_compiler.host" = ?target_compiler.host,
2266 ?sysroot,
2267 "ensuring availability of `libLLVM.so` in compiler directory"
2268 );
2269 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2270 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2271
2272 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2274 let rustc = out_dir.join(exe("rustc-main", host));
2275 let bindir = sysroot.join("bin");
2276 t!(fs::create_dir_all(bindir));
2277 let compiler = builder.rustc(target_compiler);
2278 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2279 builder.copy_link(&rustc, &compiler, FileType::Executable);
2280
2281 target_compiler
2282 }
2283}
2284
2285pub fn add_to_sysroot(
2290 builder: &Builder<'_>,
2291 sysroot_dst: &Path,
2292 sysroot_host_dst: &Path,
2293 stamp: &BuildStamp,
2294) {
2295 let self_contained_dst = &sysroot_dst.join("self-contained");
2296 t!(fs::create_dir_all(sysroot_dst));
2297 t!(fs::create_dir_all(sysroot_host_dst));
2298 t!(fs::create_dir_all(self_contained_dst));
2299 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2300 let dst = match dependency_type {
2301 DependencyType::Host => sysroot_host_dst,
2302 DependencyType::Target => sysroot_dst,
2303 DependencyType::TargetSelfContained => self_contained_dst,
2304 };
2305 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2306 }
2307}
2308
2309pub fn run_cargo(
2310 builder: &Builder<'_>,
2311 cargo: Cargo,
2312 tail_args: Vec<String>,
2313 stamp: &BuildStamp,
2314 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2315 is_check: bool,
2316 rlib_only_metadata: bool,
2317) -> Vec<PathBuf> {
2318 let target_root_dir = stamp.path().parent().unwrap();
2320 let target_deps_dir = target_root_dir.join("deps");
2322 let host_root_dir = target_root_dir
2324 .parent()
2325 .unwrap() .parent()
2327 .unwrap() .join(target_root_dir.file_name().unwrap());
2329
2330 let mut deps = Vec::new();
2334 let mut toplevel = Vec::new();
2335 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2336 let (filenames_vec, crate_types) = match msg {
2337 CargoMessage::CompilerArtifact {
2338 filenames,
2339 target: CargoTarget { crate_types },
2340 ..
2341 } => {
2342 let mut f: Vec<String> = filenames.into_iter().map(|s| s.into_owned()).collect();
2343 f.sort(); (f, crate_types)
2345 }
2346 _ => return,
2347 };
2348 for filename in filenames_vec {
2349 let mut keep = false;
2351 if filename.ends_with(".lib")
2352 || filename.ends_with(".a")
2353 || is_debug_info(&filename)
2354 || is_dylib(Path::new(&*filename))
2355 {
2356 keep = true;
2358 }
2359 if is_check && filename.ends_with(".rmeta") {
2360 keep = true;
2362 } else if rlib_only_metadata {
2363 if filename.contains("jemalloc_sys")
2364 || filename.contains("rustc_public_bridge")
2365 || filename.contains("rustc_public")
2366 {
2367 keep |= filename.ends_with(".rlib");
2370 } else {
2371 keep |= filename.ends_with(".rmeta");
2375 }
2376 } else {
2377 keep |= filename.ends_with(".rlib");
2379 }
2380
2381 if !keep {
2382 continue;
2383 }
2384
2385 let filename = Path::new(&*filename);
2386
2387 if filename.starts_with(&host_root_dir) {
2390 if crate_types.iter().any(|t| t == "proc-macro") {
2392 deps.push((filename.to_path_buf(), DependencyType::Host));
2393 }
2394 continue;
2395 }
2396
2397 if filename.starts_with(&target_deps_dir) {
2400 deps.push((filename.to_path_buf(), DependencyType::Target));
2401 continue;
2402 }
2403
2404 let expected_len = t!(filename.metadata()).len();
2415 let filename = filename.file_name().unwrap().to_str().unwrap();
2416 let mut parts = filename.splitn(2, '.');
2417 let file_stem = parts.next().unwrap().to_owned();
2418 let extension = parts.next().unwrap().to_owned();
2419
2420 toplevel.push((file_stem, extension, expected_len));
2421 }
2422 });
2423
2424 if !ok {
2425 crate::exit!(1);
2426 }
2427
2428 if builder.config.dry_run() {
2429 return Vec::new();
2430 }
2431
2432 let contents = target_deps_dir
2436 .read_dir()
2437 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2438 .map(|e| t!(e))
2439 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2440 .collect::<Vec<_>>();
2441 for (prefix, extension, expected_len) in toplevel {
2442 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2443 meta.len() == expected_len
2444 && filename
2445 .strip_prefix(&prefix[..])
2446 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2447 .unwrap_or(false)
2448 });
2449 let max = candidates.max_by_key(|&(_, _, metadata)| {
2450 metadata.modified().expect("mtime should be available on all relevant OSes")
2451 });
2452 let path_to_add = match max {
2453 Some(triple) => triple.0.to_str().unwrap(),
2454 None => panic!("no output generated for {prefix:?} {extension:?}"),
2455 };
2456 if is_dylib(Path::new(path_to_add)) {
2457 let candidate = format!("{path_to_add}.lib");
2458 let candidate = PathBuf::from(candidate);
2459 if candidate.exists() {
2460 deps.push((candidate, DependencyType::Target));
2461 }
2462 }
2463 deps.push((path_to_add.into(), DependencyType::Target));
2464 }
2465
2466 deps.extend(additional_target_deps);
2467 deps.sort();
2468 let mut new_contents = Vec::new();
2469 for (dep, dependency_type) in deps.iter() {
2470 new_contents.extend(match *dependency_type {
2471 DependencyType::Host => b"h",
2472 DependencyType::Target => b"t",
2473 DependencyType::TargetSelfContained => b"s",
2474 });
2475 new_contents.extend(dep.to_str().unwrap().as_bytes());
2476 new_contents.extend(b"\0");
2477 }
2478 t!(fs::write(stamp.path(), &new_contents));
2479 deps.into_iter().map(|(d, _)| d).collect()
2480}
2481
2482pub fn stream_cargo(
2483 builder: &Builder<'_>,
2484 cargo: Cargo,
2485 tail_args: Vec<String>,
2486 cb: &mut dyn FnMut(CargoMessage<'_>),
2487) -> bool {
2488 let mut cmd = cargo.into_cmd();
2489
2490 #[cfg(feature = "tracing")]
2491 let _run_span = crate::utils::tracing::trace_cmd(&cmd);
2492
2493 let mut message_format = if builder.config.json_output {
2496 String::from("json")
2497 } else {
2498 String::from("json-render-diagnostics")
2499 };
2500 if let Some(s) = &builder.config.rustc_error_format {
2501 message_format.push_str(",json-diagnostic-");
2502 message_format.push_str(s);
2503 }
2504 cmd.arg("--message-format").arg(message_format);
2505
2506 for arg in tail_args {
2507 cmd.arg(arg);
2508 }
2509
2510 builder.verbose(|| println!("running: {cmd:?}"));
2511
2512 let streaming_command = cmd.stream_capture_stdout(&builder.config.exec_ctx);
2513
2514 let Some(mut streaming_command) = streaming_command else {
2515 return true;
2516 };
2517
2518 let stdout = BufReader::new(streaming_command.stdout.take().unwrap());
2522 for line in stdout.lines() {
2523 let line = t!(line);
2524 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2525 Ok(msg) => {
2526 if builder.config.json_output {
2527 println!("{line}");
2529 }
2530 cb(msg)
2531 }
2532 Err(_) => println!("{line}"),
2534 }
2535 }
2536
2537 let status = t!(streaming_command.wait(&builder.config.exec_ctx));
2539 if builder.is_verbose() && !status.success() {
2540 eprintln!(
2541 "command did not execute successfully: {cmd:?}\n\
2542 expected success, got: {status}"
2543 );
2544 }
2545
2546 status.success()
2547}
2548
2549#[derive(Deserialize)]
2550pub struct CargoTarget<'a> {
2551 crate_types: Vec<Cow<'a, str>>,
2552}
2553
2554#[derive(Deserialize)]
2555#[serde(tag = "reason", rename_all = "kebab-case")]
2556pub enum CargoMessage<'a> {
2557 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2558 BuildScriptExecuted,
2559 BuildFinished,
2560}
2561
2562pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2563 if target != "x86_64-unknown-linux-gnu"
2567 || !builder.config.is_host_target(target)
2568 || !path.exists()
2569 {
2570 return;
2571 }
2572
2573 let previous_mtime = t!(t!(path.metadata()).modified());
2574 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2575
2576 let file = t!(fs::File::open(path));
2577
2578 t!(file.set_modified(previous_mtime));
2591}
2592
2593pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2595 build_compiler.stage != 0
2596}