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::process::Stdio;
16use std::{env, fs, str};
17
18use serde_derive::Deserialize;
19#[cfg(feature = "tracing")]
20use tracing::{instrument, span};
21
22use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
23use crate::core::build_steps::tool::SourceType;
24use crate::core::build_steps::{dist, llvm};
25use crate::core::builder;
26use crate::core::builder::{
27 Builder, Cargo, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath, 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::{CLang, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
37
38#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct Std {
40 pub target: TargetSelection,
41 pub compiler: Compiler,
42 crates: Vec<String>,
46 force_recompile: bool,
49 extra_rust_args: &'static [&'static str],
50 is_for_mir_opt_tests: bool,
51}
52
53impl Std {
54 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
55 Self {
56 target,
57 compiler,
58 crates: Default::default(),
59 force_recompile: false,
60 extra_rust_args: &[],
61 is_for_mir_opt_tests: false,
62 }
63 }
64
65 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
66 self.force_recompile = force_recompile;
67 self
68 }
69
70 #[expect(clippy::wrong_self_convention)]
71 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
72 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
73 self
74 }
75
76 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
77 self.extra_rust_args = extra_rust_args;
78 self
79 }
80
81 fn copy_extra_objects(
82 &self,
83 builder: &Builder<'_>,
84 compiler: &Compiler,
85 target: TargetSelection,
86 ) -> Vec<(PathBuf, DependencyType)> {
87 let mut deps = Vec::new();
88 if !self.is_for_mir_opt_tests {
89 deps.extend(copy_third_party_objects(builder, compiler, target));
90 deps.extend(copy_self_contained_objects(builder, compiler, target));
91 }
92 deps
93 }
94}
95
96impl Step for Std {
97 type Output = ();
98 const DEFAULT: bool = true;
99
100 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
101 run.crate_or_deps("sysroot").path("library")
102 }
103
104 #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
105 fn make_run(run: RunConfig<'_>) {
106 let crates = std_crates_for_run_make(&run);
107 let builder = run.builder;
108
109 let force_recompile = builder.rust_info().is_managed_git_subrepository()
113 && builder.download_rustc()
114 && builder.config.has_changes_from_upstream(&["library"]);
115
116 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
117 trace!("download_rustc: {}", builder.download_rustc());
118 trace!(force_recompile);
119
120 run.builder.ensure(Std {
121 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
122 target: run.target,
123 crates,
124 force_recompile,
125 extra_rust_args: &[],
126 is_for_mir_opt_tests: false,
127 });
128 }
129
130 #[cfg_attr(
136 feature = "tracing",
137 instrument(
138 level = "debug",
139 name = "Std::run",
140 skip_all,
141 fields(
142 target = ?self.target,
143 compiler = ?self.compiler,
144 force_recompile = self.force_recompile
145 ),
146 ),
147 )]
148 fn run(self, builder: &Builder<'_>) {
149 let target = self.target;
150
151 if self.compiler.stage == 0 {
153 let compiler = self.compiler;
154 builder.ensure(StdLink::from_std(self, compiler));
155
156 return;
157 }
158
159 let compiler = if builder.download_rustc() && self.force_recompile {
160 builder.compiler(self.compiler.stage.saturating_sub(1), builder.config.build)
163 } else {
164 self.compiler
165 };
166
167 if builder.download_rustc()
170 && builder.config.is_host_target(target)
171 && !self.force_recompile
172 {
173 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
174 cp_rustc_component_to_ci_sysroot(
175 builder,
176 &sysroot,
177 builder.config.ci_rust_std_contents(),
178 );
179 return;
180 }
181
182 if builder.config.keep_stage.contains(&compiler.stage)
183 || builder.config.keep_stage_std.contains(&compiler.stage)
184 {
185 trace!(keep_stage = ?builder.config.keep_stage);
186 trace!(keep_stage_std = ?builder.config.keep_stage_std);
187
188 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
189
190 builder.ensure(StartupObjects { compiler, target });
191
192 self.copy_extra_objects(builder, &compiler, target);
193
194 builder.ensure(StdLink::from_std(self, compiler));
195 return;
196 }
197
198 builder.require_submodule("library/stdarch", None);
199
200 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
201
202 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
203 trace!(?compiler_to_use);
204
205 if compiler_to_use != compiler
206 && compiler.stage > 1
211 {
212 trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
213
214 builder.ensure(Std::new(compiler_to_use, target));
215 let msg = if compiler_to_use.host == target {
216 format!(
217 "Uplifting library (stage{} -> stage{})",
218 compiler_to_use.stage, compiler.stage
219 )
220 } else {
221 format!(
222 "Uplifting library (stage{}:{} -> stage{}:{})",
223 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
224 )
225 };
226 builder.info(&msg);
227
228 self.copy_extra_objects(builder, &compiler, target);
231
232 builder.ensure(StdLink::from_std(self, compiler_to_use));
233 return;
234 }
235
236 trace!(
237 ?compiler_to_use,
238 ?compiler,
239 "compiler == compiler_to_use, handling not-cross-compile scenario"
240 );
241
242 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
243
244 let mut cargo = if self.is_for_mir_opt_tests {
248 trace!("building special sysroot for mir-opt tests");
249 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
250 builder,
251 compiler,
252 Mode::Std,
253 SourceType::InTree,
254 target,
255 Kind::Check,
256 );
257 cargo.rustflag("-Zalways-encode-mir");
258 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
259 cargo
260 } else {
261 trace!("building regular sysroot");
262 let mut cargo = builder::Cargo::new(
263 builder,
264 compiler,
265 Mode::Std,
266 SourceType::InTree,
267 target,
268 Kind::Build,
269 );
270 std_cargo(builder, target, compiler.stage, &mut cargo);
271 for krate in &*self.crates {
272 cargo.arg("-p").arg(krate);
273 }
274 cargo
275 };
276
277 if target.is_synthetic() {
279 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
280 }
281 for rustflag in self.extra_rust_args.iter() {
282 cargo.rustflag(rustflag);
283 }
284
285 let _guard = builder.msg(
286 Kind::Build,
287 compiler.stage,
288 format_args!("library artifacts{}", crate_description(&self.crates)),
289 compiler.host,
290 target,
291 );
292 run_cargo(
293 builder,
294 cargo,
295 vec![],
296 &build_stamp::libstd_stamp(builder, compiler, target),
297 target_deps,
298 self.is_for_mir_opt_tests, false,
300 );
301
302 builder.ensure(StdLink::from_std(
303 self,
304 builder.compiler(compiler.stage, builder.config.build),
305 ));
306 }
307}
308
309fn copy_and_stamp(
310 builder: &Builder<'_>,
311 libdir: &Path,
312 sourcedir: &Path,
313 name: &str,
314 target_deps: &mut Vec<(PathBuf, DependencyType)>,
315 dependency_type: DependencyType,
316) {
317 let target = libdir.join(name);
318 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
319
320 target_deps.push((target, dependency_type));
321}
322
323fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
324 let libunwind_path = builder.ensure(llvm::Libunwind { target });
325 let libunwind_source = libunwind_path.join("libunwind.a");
326 let libunwind_target = libdir.join("libunwind.a");
327 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
328 libunwind_target
329}
330
331fn copy_third_party_objects(
333 builder: &Builder<'_>,
334 compiler: &Compiler,
335 target: TargetSelection,
336) -> Vec<(PathBuf, DependencyType)> {
337 let mut target_deps = vec![];
338
339 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
340 target_deps.extend(
343 copy_sanitizers(builder, compiler, target)
344 .into_iter()
345 .map(|d| (d, DependencyType::Target)),
346 );
347 }
348
349 if target == "x86_64-fortanix-unknown-sgx"
350 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
351 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
352 {
353 let libunwind_path =
354 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
355 target_deps.push((libunwind_path, DependencyType::Target));
356 }
357
358 target_deps
359}
360
361fn copy_self_contained_objects(
363 builder: &Builder<'_>,
364 compiler: &Compiler,
365 target: TargetSelection,
366) -> Vec<(PathBuf, DependencyType)> {
367 let libdir_self_contained =
368 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
369 t!(fs::create_dir_all(&libdir_self_contained));
370 let mut target_deps = vec![];
371
372 if target.needs_crt_begin_end() {
380 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
381 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
382 });
383 if !target.starts_with("wasm32") {
384 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
385 copy_and_stamp(
386 builder,
387 &libdir_self_contained,
388 &srcdir,
389 obj,
390 &mut target_deps,
391 DependencyType::TargetSelfContained,
392 );
393 }
394 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
395 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
396 let src = crt_path.join(obj);
397 let target = libdir_self_contained.join(obj);
398 builder.copy_link(&src, &target, FileType::NativeLibrary);
399 target_deps.push((target, DependencyType::TargetSelfContained));
400 }
401 } else {
402 for &obj in &["libc.a", "crt1-command.o"] {
405 copy_and_stamp(
406 builder,
407 &libdir_self_contained,
408 &srcdir,
409 obj,
410 &mut target_deps,
411 DependencyType::TargetSelfContained,
412 );
413 }
414 }
415 if !target.starts_with("s390x") {
416 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
417 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
418 }
419 } else if target.contains("-wasi") {
420 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
421 panic!(
422 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
423 or `$WASI_SDK_PATH` set",
424 target.triple
425 )
426 });
427 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
428 copy_and_stamp(
429 builder,
430 &libdir_self_contained,
431 &srcdir,
432 obj,
433 &mut target_deps,
434 DependencyType::TargetSelfContained,
435 );
436 }
437 } else if target.is_windows_gnu() {
438 for obj in ["crt2.o", "dllcrt2.o"].iter() {
439 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
440 let dst = libdir_self_contained.join(obj);
441 builder.copy_link(&src, &dst, FileType::NativeLibrary);
442 target_deps.push((dst, DependencyType::TargetSelfContained));
443 }
444 }
445
446 target_deps
447}
448
449pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
451 if cfg!(test) {
453 return vec![];
454 }
455
456 let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
457 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
458
459 if target_is_no_std {
461 vec![]
462 }
463 else if has_alias {
465 run.make_run_crates(builder::Alias::Library)
466 } else {
467 run.cargo_crates_in_set()
468 }
469}
470
471fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
477 if builder.config.llvm_from_ci {
479 builder.config.maybe_download_ci_llvm();
481 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
482 if ci_llvm_compiler_rt.exists() {
483 return ci_llvm_compiler_rt;
484 }
485 }
486
487 builder.require_submodule("src/llvm-project", {
489 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
490 });
491 builder.src.join("src/llvm-project/compiler-rt")
492}
493
494pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
497 if target.contains("apple") && !builder.config.dry_run() {
515 let mut cmd = command(builder.rustc(cargo.compiler()));
519 cmd.arg("--target").arg(target.rustc_target_arg());
520 cmd.arg("--print=deployment-target");
521 let output = cmd.run_capture_stdout(builder).stdout();
522
523 let (env_var, value) = output.split_once('=').unwrap();
524 cargo.env(env_var.trim(), value.trim());
527
528 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
538 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
539 }
540 }
541
542 if let Some(path) = builder.config.profiler_path(target) {
544 cargo.env("LLVM_PROFILER_RT_LIB", path);
545 } else if builder.config.profiler_enabled(target) {
546 let compiler_rt = compiler_rt_for_profiler(builder);
547 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
551 }
552
553 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
567 builder.require_submodule(
575 "src/llvm-project",
576 Some(
577 "The `build.optimized-compiler-builtins` config option \
578 requires `compiler-rt` sources from LLVM.",
579 ),
580 );
581 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
582 assert!(compiler_builtins_root.exists());
583 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
586 " compiler-builtins-c"
587 } else {
588 ""
589 };
590
591 if !builder.unstable_features() {
594 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
595 }
596
597 let mut features = String::new();
598
599 if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
600 {
601 features += "compiler-builtins-no-f16-f128 ";
602 }
603
604 if builder.no_std(target) == Some(true) {
605 features += " compiler-builtins-mem";
606 if !target.starts_with("bpf") {
607 features.push_str(compiler_builtins_c_feature);
608 }
609
610 cargo
612 .args(["-p", "alloc"])
613 .arg("--manifest-path")
614 .arg(builder.src.join("library/alloc/Cargo.toml"))
615 .arg("--features")
616 .arg(features);
617 } else {
618 features += &builder.std_features(target);
619 features.push_str(compiler_builtins_c_feature);
620
621 cargo
622 .arg("--features")
623 .arg(features)
624 .arg("--manifest-path")
625 .arg(builder.src.join("library/sysroot/Cargo.toml"));
626
627 if target.contains("musl")
630 && let Some(p) = builder.musl_libdir(target)
631 {
632 let root = format!("native={}", p.to_str().unwrap());
633 cargo.rustflag("-L").rustflag(&root);
634 }
635
636 if target.contains("-wasi")
637 && let Some(dir) = builder.wasi_libdir(target)
638 {
639 let root = format!("native={}", dir.to_str().unwrap());
640 cargo.rustflag("-L").rustflag(&root);
641 }
642 }
643
644 if stage >= 1 {
653 cargo.rustflag("-Cembed-bitcode=yes");
654 }
655 if builder.config.rust_lto == RustcLto::Off {
656 cargo.rustflag("-Clto=off");
657 }
658
659 if target.contains("riscv") {
666 cargo.rustflag("-Cforce-unwind-tables=yes");
667 }
668
669 cargo.rustflag("-Cforce-frame-pointers=yes");
672
673 let html_root =
674 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
675 cargo.rustflag(&html_root);
676 cargo.rustdocflag(&html_root);
677
678 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
679}
680
681#[derive(Debug, Clone, PartialEq, Eq, Hash)]
682struct StdLink {
683 pub compiler: Compiler,
684 pub target_compiler: Compiler,
685 pub target: TargetSelection,
686 crates: Vec<String>,
688 force_recompile: bool,
690}
691
692impl StdLink {
693 fn from_std(std: Std, host_compiler: Compiler) -> Self {
694 Self {
695 compiler: host_compiler,
696 target_compiler: std.compiler,
697 target: std.target,
698 crates: std.crates,
699 force_recompile: std.force_recompile,
700 }
701 }
702}
703
704impl Step for StdLink {
705 type Output = ();
706
707 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
708 run.never()
709 }
710
711 #[cfg_attr(
720 feature = "tracing",
721 instrument(
722 level = "trace",
723 name = "StdLink::run",
724 skip_all,
725 fields(
726 compiler = ?self.compiler,
727 target_compiler = ?self.target_compiler,
728 target = ?self.target
729 ),
730 ),
731 )]
732 fn run(self, builder: &Builder<'_>) {
733 let compiler = self.compiler;
734 let target_compiler = self.target_compiler;
735 let target = self.target;
736
737 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
739 let lib = builder.sysroot_libdir_relative(self.compiler);
741 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
742 compiler: self.compiler,
743 force_recompile: self.force_recompile,
744 });
745 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
746 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
747 (libdir, hostdir)
748 } else {
749 let libdir = builder.sysroot_target_libdir(target_compiler, target);
750 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
751 (libdir, hostdir)
752 };
753
754 let is_downloaded_beta_stage0 = builder
755 .build
756 .config
757 .initial_rustc
758 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
759
760 if compiler.stage == 0 && is_downloaded_beta_stage0 {
764 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
766
767 let host = compiler.host;
768 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
769 let sysroot_bin_dir = sysroot.join("bin");
770 t!(fs::create_dir_all(&sysroot_bin_dir));
771 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
772
773 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
774 t!(fs::create_dir_all(sysroot.join("lib")));
775 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
776
777 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
779 t!(fs::create_dir_all(&sysroot_codegen_backends));
780 let stage0_codegen_backends = builder
781 .out
782 .join(host)
783 .join("stage0/lib/rustlib")
784 .join(host)
785 .join("codegen-backends");
786 if stage0_codegen_backends.exists() {
787 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
788 }
789 } else if compiler.stage == 0 {
790 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
791
792 if builder.local_rebuild {
793 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
797 }
798
799 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
800 } else {
801 if builder.download_rustc() {
802 let _ = fs::remove_dir_all(&libdir);
804 let _ = fs::remove_dir_all(&hostdir);
805 }
806
807 add_to_sysroot(
808 builder,
809 &libdir,
810 &hostdir,
811 &build_stamp::libstd_stamp(builder, compiler, target),
812 );
813 }
814 }
815}
816
817fn copy_sanitizers(
819 builder: &Builder<'_>,
820 compiler: &Compiler,
821 target: TargetSelection,
822) -> Vec<PathBuf> {
823 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
824
825 if builder.config.dry_run() {
826 return Vec::new();
827 }
828
829 let mut target_deps = Vec::new();
830 let libdir = builder.sysroot_target_libdir(*compiler, target);
831
832 for runtime in &runtimes {
833 let dst = libdir.join(&runtime.name);
834 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
835
836 if target == "x86_64-apple-darwin"
840 || target == "aarch64-apple-darwin"
841 || target == "aarch64-apple-ios"
842 || target == "aarch64-apple-ios-sim"
843 || target == "x86_64-apple-ios"
844 {
845 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
847 apple_darwin_sign_file(builder, &dst);
850 }
851
852 target_deps.push(dst);
853 }
854
855 target_deps
856}
857
858fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
859 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
860}
861
862fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
863 command("codesign")
864 .arg("-f") .arg("-s")
866 .arg("-")
867 .arg(file_path)
868 .run(builder);
869}
870
871#[derive(Debug, Clone, PartialEq, Eq, Hash)]
872pub struct StartupObjects {
873 pub compiler: Compiler,
874 pub target: TargetSelection,
875}
876
877impl Step for StartupObjects {
878 type Output = Vec<(PathBuf, DependencyType)>;
879
880 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
881 run.path("library/rtstartup")
882 }
883
884 fn make_run(run: RunConfig<'_>) {
885 run.builder.ensure(StartupObjects {
886 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
887 target: run.target,
888 });
889 }
890
891 #[cfg_attr(
898 feature = "tracing",
899 instrument(
900 level = "trace",
901 name = "StartupObjects::run",
902 skip_all,
903 fields(compiler = ?self.compiler, target = ?self.target),
904 ),
905 )]
906 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
907 let for_compiler = self.compiler;
908 let target = self.target;
909 if !target.is_windows_gnu() {
910 return vec![];
911 }
912
913 let mut target_deps = vec![];
914
915 let src_dir = &builder.src.join("library").join("rtstartup");
916 let dst_dir = &builder.native_dir(target).join("rtstartup");
917 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
918 t!(fs::create_dir_all(dst_dir));
919
920 for file in &["rsbegin", "rsend"] {
921 let src_file = &src_dir.join(file.to_string() + ".rs");
922 let dst_file = &dst_dir.join(file.to_string() + ".o");
923 if !up_to_date(src_file, dst_file) {
924 let mut cmd = command(&builder.initial_rustc);
925 cmd.env("RUSTC_BOOTSTRAP", "1");
926 if !builder.local_rebuild {
927 cmd.arg("--cfg").arg("bootstrap");
929 }
930 cmd.arg("--target")
931 .arg(target.rustc_target_arg())
932 .arg("--emit=obj")
933 .arg("-o")
934 .arg(dst_file)
935 .arg(src_file)
936 .run(builder);
937 }
938
939 let obj = sysroot_dir.join((*file).to_string() + ".o");
940 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
941 target_deps.push((obj, DependencyType::Target));
942 }
943
944 target_deps
945 }
946}
947
948fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
949 let ci_rustc_dir = builder.config.ci_rustc_dir();
950
951 for file in contents {
952 let src = ci_rustc_dir.join(&file);
953 let dst = sysroot.join(file);
954 if src.is_dir() {
955 t!(fs::create_dir_all(dst));
956 } else {
957 builder.copy_link(&src, &dst, FileType::Regular);
958 }
959 }
960}
961
962#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
963pub struct Rustc {
964 pub target: TargetSelection,
965 pub compiler: Compiler,
967 crates: Vec<String>,
973}
974
975impl Rustc {
976 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
977 Self { target, compiler, crates: Default::default() }
978 }
979}
980
981impl Step for Rustc {
982 type Output = u32;
990 const ONLY_HOSTS: bool = true;
991 const DEFAULT: bool = false;
992
993 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
994 let mut crates = run.builder.in_tree_crates("rustc-main", None);
995 for (i, krate) in crates.iter().enumerate() {
996 if krate.name == "rustc-main" {
999 crates.swap_remove(i);
1000 break;
1001 }
1002 }
1003 run.crates(crates)
1004 }
1005
1006 fn make_run(run: RunConfig<'_>) {
1007 let crates = run.cargo_crates_in_set();
1008 run.builder.ensure(Rustc {
1009 compiler: run
1010 .builder
1011 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1012 target: run.target,
1013 crates,
1014 });
1015 }
1016
1017 #[cfg_attr(
1023 feature = "tracing",
1024 instrument(
1025 level = "debug",
1026 name = "Rustc::run",
1027 skip_all,
1028 fields(previous_compiler = ?self.compiler, target = ?self.target),
1029 ),
1030 )]
1031 fn run(self, builder: &Builder<'_>) -> u32 {
1032 let compiler = self.compiler;
1033 let target = self.target;
1034
1035 if builder.download_rustc() && compiler.stage != 0 {
1038 trace!(stage = compiler.stage, "`download_rustc` requested");
1039
1040 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
1041 cp_rustc_component_to_ci_sysroot(
1042 builder,
1043 &sysroot,
1044 builder.config.ci_rustc_dev_contents(),
1045 );
1046 return compiler.stage;
1047 }
1048
1049 builder.ensure(Std::new(compiler, target));
1050
1051 if builder.config.keep_stage.contains(&compiler.stage) {
1052 trace!(stage = compiler.stage, "`keep-stage` requested");
1053
1054 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1055 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1056 builder.ensure(RustcLink::from_rustc(self, compiler));
1057
1058 return compiler.stage;
1059 }
1060
1061 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1062 if compiler_to_use != compiler {
1063 builder.ensure(Rustc::new(compiler_to_use, target));
1064 let msg = if compiler_to_use.host == target {
1065 format!(
1066 "Uplifting rustc (stage{} -> stage{})",
1067 compiler_to_use.stage,
1068 compiler.stage + 1
1069 )
1070 } else {
1071 format!(
1072 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1073 compiler_to_use.stage,
1074 compiler_to_use.host,
1075 compiler.stage + 1,
1076 target
1077 )
1078 };
1079 builder.info(&msg);
1080 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1081 return compiler_to_use.stage;
1082 }
1083
1084 builder.ensure(Std::new(
1086 builder.compiler(self.compiler.stage, builder.config.build),
1087 builder.config.build,
1088 ));
1089
1090 let mut cargo = builder::Cargo::new(
1091 builder,
1092 compiler,
1093 Mode::Rustc,
1094 SourceType::InTree,
1095 target,
1096 Kind::Build,
1097 );
1098
1099 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
1100
1101 for krate in &*self.crates {
1105 cargo.arg("-p").arg(krate);
1106 }
1107
1108 if builder.build.config.enable_bolt_settings && compiler.stage == 1 {
1109 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1111 }
1112
1113 let _guard = builder.msg_sysroot_tool(
1114 Kind::Build,
1115 compiler.stage,
1116 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1117 compiler.host,
1118 target,
1119 );
1120 let stamp = build_stamp::librustc_stamp(builder, compiler, target);
1121 run_cargo(
1122 builder,
1123 cargo,
1124 vec![],
1125 &stamp,
1126 vec![],
1127 false,
1128 true, );
1130
1131 let target_root_dir = stamp.path().parent().unwrap();
1132 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1138 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1139 {
1140 let rustc_driver = target_root_dir.join("librustc_driver.so");
1141 strip_debug(builder, target, &rustc_driver);
1142 }
1143
1144 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1145 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1148 }
1149
1150 builder.ensure(RustcLink::from_rustc(
1151 self,
1152 builder.compiler(compiler.stage, builder.config.build),
1153 ));
1154
1155 compiler.stage
1156 }
1157}
1158
1159pub fn rustc_cargo(
1160 builder: &Builder<'_>,
1161 cargo: &mut Cargo,
1162 target: TargetSelection,
1163 compiler: &Compiler,
1164 crates: &[String],
1165) {
1166 cargo
1167 .arg("--features")
1168 .arg(builder.rustc_features(builder.kind, target, crates))
1169 .arg("--manifest-path")
1170 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1171
1172 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1173
1174 cargo.rustflag("-Zon-broken-pipe=kill");
1188
1189 if builder.config.llvm_enzyme {
1192 let arch = builder.build.build;
1193 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1194 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1195
1196 if let Some(llvm_config) = builder.llvm_config(builder.config.build) {
1197 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1198 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1199 }
1200 }
1201
1202 if builder.build.config.lld_mode.is_used() {
1207 cargo.rustflag("-Zdefault-visibility=protected");
1208 }
1209
1210 if is_lto_stage(compiler) {
1211 match builder.config.rust_lto {
1212 RustcLto::Thin | RustcLto::Fat => {
1213 cargo.rustflag("-Zdylib-lto");
1216 let lto_type = match builder.config.rust_lto {
1220 RustcLto::Thin => "thin",
1221 RustcLto::Fat => "fat",
1222 _ => unreachable!(),
1223 };
1224 cargo.rustflag(&format!("-Clto={lto_type}"));
1225 cargo.rustflag("-Cembed-bitcode=yes");
1226 }
1227 RustcLto::ThinLocal => { }
1228 RustcLto::Off => {
1229 cargo.rustflag("-Clto=off");
1230 }
1231 }
1232 } else if builder.config.rust_lto == RustcLto::Off {
1233 cargo.rustflag("-Clto=off");
1234 }
1235
1236 if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
1244 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1245 }
1246
1247 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1248 panic!("Cannot use and generate PGO profiles at the same time");
1249 }
1250 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1251 if compiler.stage == 1 {
1252 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1253 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1256 true
1257 } else {
1258 false
1259 }
1260 } else if let Some(path) = &builder.config.rust_profile_use {
1261 if compiler.stage == 1 {
1262 cargo.rustflag(&format!("-Cprofile-use={path}"));
1263 if builder.is_verbose() {
1264 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1265 }
1266 true
1267 } else {
1268 false
1269 }
1270 } else {
1271 false
1272 };
1273 if is_collecting {
1274 cargo.rustflag(&format!(
1276 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1277 builder.config.src.components().count()
1278 ));
1279 }
1280
1281 if let Some(ref ccache) = builder.config.ccache
1286 && compiler.stage == 0
1287 && !builder.config.incremental
1288 {
1289 cargo.env("RUSTC_WRAPPER", ccache);
1290 }
1291
1292 rustc_cargo_env(builder, cargo, target, compiler.stage);
1293}
1294
1295pub fn rustc_cargo_env(
1296 builder: &Builder<'_>,
1297 cargo: &mut Cargo,
1298 target: TargetSelection,
1299 stage: u32,
1300) {
1301 cargo
1304 .env("CFG_RELEASE", builder.rust_release())
1305 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1306 .env("CFG_VERSION", builder.rust_version());
1307
1308 if builder.config.omit_git_hash {
1312 cargo.env("CFG_OMIT_GIT_HASH", "1");
1313 }
1314
1315 if let Some(backend) = builder.config.default_codegen_backend(target) {
1316 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1317 }
1318
1319 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1320 let target_config = builder.config.target_config.get(&target);
1321
1322 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1323
1324 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1325 cargo.env("CFG_VER_DATE", ver_date);
1326 }
1327 if let Some(ref ver_hash) = builder.rust_info().sha() {
1328 cargo.env("CFG_VER_HASH", ver_hash);
1329 }
1330 if !builder.unstable_features() {
1331 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1332 }
1333
1334 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1337 cargo.env("CFG_DEFAULT_LINKER", s);
1338 } else if let Some(ref s) = builder.config.rustc_default_linker {
1339 cargo.env("CFG_DEFAULT_LINKER", s);
1340 }
1341
1342 if builder.config.lld_enabled
1344 && (builder.config.channel == "dev" || builder.config.channel == "nightly")
1345 {
1346 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1347 }
1348
1349 if builder.config.rust_verify_llvm_ir {
1350 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1351 }
1352
1353 if builder.config.llvm_enzyme {
1354 cargo.rustflag("--cfg=llvm_enzyme");
1355 }
1356
1357 if builder.config.llvm_enabled(target) {
1362 let building_is_expensive =
1363 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1364 .should_build();
1365 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage;
1367 let should_skip_build = building_is_expensive && can_skip_build;
1368 if !should_skip_build {
1369 rustc_llvm_env(builder, cargo, target)
1370 }
1371 }
1372
1373 if builder.config.jemalloc(target)
1376 && target.starts_with("aarch64")
1377 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1378 {
1379 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1380 }
1381}
1382
1383fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1386 if builder.config.is_rust_llvm(target) {
1387 cargo.env("LLVM_RUSTLLVM", "1");
1388 }
1389 if builder.config.llvm_enzyme {
1390 cargo.env("LLVM_ENZYME", "1");
1391 }
1392 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1393 cargo.env("LLVM_CONFIG", &llvm_config);
1394
1395 let mut llvm_linker_flags = String::new();
1405 if builder.config.llvm_profile_generate
1406 && target.is_msvc()
1407 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1408 {
1409 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1411 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1412 }
1413
1414 if let Some(ref s) = builder.config.llvm_ldflags {
1416 if !llvm_linker_flags.is_empty() {
1417 llvm_linker_flags.push(' ');
1418 }
1419 llvm_linker_flags.push_str(s);
1420 }
1421
1422 if !llvm_linker_flags.is_empty() {
1424 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1425 }
1426
1427 if builder.config.llvm_static_stdcpp
1430 && !target.contains("freebsd")
1431 && !target.is_msvc()
1432 && !target.contains("apple")
1433 && !target.contains("solaris")
1434 {
1435 let libstdcxx_name =
1436 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1437 let file = compiler_file(
1438 builder,
1439 &builder.cxx(target).unwrap(),
1440 target,
1441 CLang::Cxx,
1442 libstdcxx_name,
1443 );
1444 cargo.env("LLVM_STATIC_STDCPP", file);
1445 }
1446 if builder.llvm_link_shared() {
1447 cargo.env("LLVM_LINK_SHARED", "1");
1448 }
1449 if builder.config.llvm_use_libcxx {
1450 cargo.env("LLVM_USE_LIBCXX", "1");
1451 }
1452 if builder.config.llvm_assertions {
1453 cargo.env("LLVM_ASSERTIONS", "1");
1454 }
1455}
1456
1457#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1463struct RustcLink {
1464 pub compiler: Compiler,
1466 pub previous_stage_compiler: Compiler,
1468 pub target: TargetSelection,
1469 crates: Vec<String>,
1471}
1472
1473impl RustcLink {
1474 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1475 Self {
1476 compiler: host_compiler,
1477 previous_stage_compiler: rustc.compiler,
1478 target: rustc.target,
1479 crates: rustc.crates,
1480 }
1481 }
1482}
1483
1484impl Step for RustcLink {
1485 type Output = ();
1486
1487 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1488 run.never()
1489 }
1490
1491 #[cfg_attr(
1493 feature = "tracing",
1494 instrument(
1495 level = "trace",
1496 name = "RustcLink::run",
1497 skip_all,
1498 fields(
1499 compiler = ?self.compiler,
1500 previous_stage_compiler = ?self.previous_stage_compiler,
1501 target = ?self.target,
1502 ),
1503 ),
1504 )]
1505 fn run(self, builder: &Builder<'_>) {
1506 let compiler = self.compiler;
1507 let previous_stage_compiler = self.previous_stage_compiler;
1508 let target = self.target;
1509 add_to_sysroot(
1510 builder,
1511 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1512 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1513 &build_stamp::librustc_stamp(builder, compiler, target),
1514 );
1515 }
1516}
1517
1518#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1519pub struct CodegenBackend {
1520 pub target: TargetSelection,
1521 pub compiler: Compiler,
1522 pub backend: String,
1523}
1524
1525fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1526 let mut needs_codegen_cfg = false;
1527 for path_set in &run.paths {
1528 needs_codegen_cfg = match path_set {
1529 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1530 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1531 }
1532 }
1533 needs_codegen_cfg
1534}
1535
1536pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1537
1538fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1539 let path = path.path.to_str().unwrap();
1540
1541 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1542 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1543
1544 if path.contains(CODEGEN_BACKEND_PREFIX) {
1545 let mut needs_codegen_backend_config = true;
1546 for backend in run.builder.config.codegen_backends(run.target) {
1547 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1548 needs_codegen_backend_config = false;
1549 }
1550 }
1551 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1552 && needs_codegen_backend_config
1553 {
1554 run.builder.info(
1555 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1556 HELP: add backend to codegen-backends in bootstrap.toml.",
1557 );
1558 return true;
1559 }
1560 }
1561
1562 false
1563}
1564
1565impl Step for CodegenBackend {
1566 type Output = ();
1567 const ONLY_HOSTS: bool = true;
1568 const DEFAULT: bool = true;
1570
1571 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1572 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1573 }
1574
1575 fn make_run(run: RunConfig<'_>) {
1576 if needs_codegen_config(&run) {
1577 return;
1578 }
1579
1580 for backend in run.builder.config.codegen_backends(run.target) {
1581 if backend == "llvm" {
1582 continue; }
1584
1585 run.builder.ensure(CodegenBackend {
1586 target: run.target,
1587 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1588 backend: backend.clone(),
1589 });
1590 }
1591 }
1592
1593 #[cfg_attr(
1594 feature = "tracing",
1595 instrument(
1596 level = "debug",
1597 name = "CodegenBackend::run",
1598 skip_all,
1599 fields(
1600 compiler = ?self.compiler,
1601 target = ?self.target,
1602 backend = ?self.target,
1603 ),
1604 ),
1605 )]
1606 fn run(self, builder: &Builder<'_>) {
1607 let compiler = self.compiler;
1608 let target = self.target;
1609 let backend = self.backend;
1610
1611 builder.ensure(Rustc::new(compiler, target));
1612
1613 if builder.config.keep_stage.contains(&compiler.stage) {
1614 trace!("`keep-stage` requested");
1615 builder.info(
1616 "WARNING: Using a potentially old codegen backend. \
1617 This may not behave well.",
1618 );
1619 return;
1622 }
1623
1624 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1625 if compiler_to_use != compiler {
1626 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1627 return;
1628 }
1629
1630 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1631
1632 let mut cargo = builder::Cargo::new(
1633 builder,
1634 compiler,
1635 Mode::Codegen,
1636 SourceType::InTree,
1637 target,
1638 Kind::Build,
1639 );
1640 cargo
1641 .arg("--manifest-path")
1642 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1643 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1644
1645 if backend == "gcc" {
1649 let gcc = builder.ensure(Gcc { target });
1650 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1651 }
1652
1653 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1654
1655 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1656 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1657 if builder.config.dry_run() {
1658 return;
1659 }
1660 let mut files = files.into_iter().filter(|f| {
1661 let filename = f.file_name().unwrap().to_str().unwrap();
1662 is_dylib(f) && filename.contains("rustc_codegen_")
1663 });
1664 let codegen_backend = match files.next() {
1665 Some(f) => f,
1666 None => panic!("no dylibs built for codegen backend?"),
1667 };
1668 if let Some(f) = files.next() {
1669 panic!(
1670 "codegen backend built two dylibs:\n{}\n{}",
1671 codegen_backend.display(),
1672 f.display()
1673 );
1674 }
1675 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1676 let codegen_backend = codegen_backend.to_str().unwrap();
1677 t!(stamp.add_stamp(codegen_backend).write());
1678 }
1679}
1680
1681fn copy_codegen_backends_to_sysroot(
1688 builder: &Builder<'_>,
1689 compiler: Compiler,
1690 target_compiler: Compiler,
1691) {
1692 let target = target_compiler.host;
1693
1694 let dst = builder.sysroot_codegen_backends(target_compiler);
1703 t!(fs::create_dir_all(&dst), dst);
1704
1705 if builder.config.dry_run() {
1706 return;
1707 }
1708
1709 for backend in builder.config.codegen_backends(target) {
1710 if backend == "llvm" {
1711 continue; }
1713
1714 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1715 let dylib = t!(fs::read_to_string(stamp.path()));
1716 let file = Path::new(&dylib);
1717 let filename = file.file_name().unwrap().to_str().unwrap();
1718 let target_filename = {
1721 let dash = filename.find('-').unwrap();
1722 let dot = filename.find('.').unwrap();
1723 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1724 };
1725 builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
1726 }
1727}
1728
1729pub fn compiler_file(
1730 builder: &Builder<'_>,
1731 compiler: &Path,
1732 target: TargetSelection,
1733 c: CLang,
1734 file: &str,
1735) -> PathBuf {
1736 if builder.config.dry_run() {
1737 return PathBuf::new();
1738 }
1739 let mut cmd = command(compiler);
1740 cmd.args(builder.cc_handled_clags(target, c));
1741 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1742 cmd.arg(format!("-print-file-name={file}"));
1743 let out = cmd.run_capture_stdout(builder).stdout();
1744 PathBuf::from(out.trim())
1745}
1746
1747#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1748pub struct Sysroot {
1749 pub compiler: Compiler,
1750 force_recompile: bool,
1752}
1753
1754impl Sysroot {
1755 pub(crate) fn new(compiler: Compiler) -> Self {
1756 Sysroot { compiler, force_recompile: false }
1757 }
1758}
1759
1760impl Step for Sysroot {
1761 type Output = PathBuf;
1762
1763 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1764 run.never()
1765 }
1766
1767 #[cfg_attr(
1771 feature = "tracing",
1772 instrument(
1773 level = "debug",
1774 name = "Sysroot::run",
1775 skip_all,
1776 fields(compiler = ?self.compiler),
1777 ),
1778 )]
1779 fn run(self, builder: &Builder<'_>) -> PathBuf {
1780 let compiler = self.compiler;
1781 let host_dir = builder.out.join(compiler.host);
1782
1783 let sysroot_dir = |stage| {
1784 if stage == 0 {
1785 host_dir.join("stage0-sysroot")
1786 } else if self.force_recompile && stage == compiler.stage {
1787 host_dir.join(format!("stage{stage}-test-sysroot"))
1788 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1789 host_dir.join("ci-rustc-sysroot")
1790 } else {
1791 host_dir.join(format!("stage{stage}"))
1792 }
1793 };
1794 let sysroot = sysroot_dir(compiler.stage);
1795 trace!(stage = ?compiler.stage, ?sysroot);
1796
1797 builder
1798 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1799 let _ = fs::remove_dir_all(&sysroot);
1800 t!(fs::create_dir_all(&sysroot));
1801
1802 if compiler.stage == 0 {
1809 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1810 }
1811
1812 if builder.download_rustc() && compiler.stage != 0 {
1814 assert_eq!(
1815 builder.config.build, compiler.host,
1816 "Cross-compiling is not yet supported with `download-rustc`",
1817 );
1818
1819 for stage in 0..=2 {
1821 if stage != compiler.stage {
1822 let dir = sysroot_dir(stage);
1823 if !dir.ends_with("ci-rustc-sysroot") {
1824 let _ = fs::remove_dir_all(dir);
1825 }
1826 }
1827 }
1828
1829 let mut filtered_files = Vec::new();
1839 let mut add_filtered_files = |suffix, contents| {
1840 for path in contents {
1841 let path = Path::new(&path);
1842 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1843 filtered_files.push(path.file_name().unwrap().to_owned());
1844 }
1845 }
1846 };
1847 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1848 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1849 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1852
1853 let filtered_extensions = [
1854 OsStr::new("rmeta"),
1855 OsStr::new("rlib"),
1856 OsStr::new(std::env::consts::DLL_EXTENSION),
1858 ];
1859 let ci_rustc_dir = builder.config.ci_rustc_dir();
1860 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1861 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1862 return true;
1863 }
1864 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1865 return true;
1866 }
1867 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1868 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1869 false
1870 } else {
1871 true
1872 }
1873 });
1874 }
1875
1876 if compiler.stage != 0 {
1882 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1883 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1884 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1885 if let Err(e) =
1886 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1887 {
1888 eprintln!(
1889 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1890 sysroot_lib_rustlib_src_rust.display(),
1891 builder.src.display(),
1892 e,
1893 );
1894 if builder.config.rust_remap_debuginfo {
1895 eprintln!(
1896 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1897 sysroot_lib_rustlib_src_rust.display(),
1898 );
1899 }
1900 build_helper::exit!(1);
1901 }
1902 }
1903
1904 if !builder.download_rustc() {
1906 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1907 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1908 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1909 if let Err(e) =
1910 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1911 {
1912 eprintln!(
1913 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1914 sysroot_lib_rustlib_rustcsrc_rust.display(),
1915 builder.src.display(),
1916 e,
1917 );
1918 build_helper::exit!(1);
1919 }
1920 }
1921
1922 sysroot
1923 }
1924}
1925
1926#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1927pub struct Assemble {
1928 pub target_compiler: Compiler,
1933}
1934
1935impl Step for Assemble {
1936 type Output = Compiler;
1937 const ONLY_HOSTS: bool = true;
1938
1939 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1940 run.path("compiler/rustc").path("compiler")
1941 }
1942
1943 fn make_run(run: RunConfig<'_>) {
1944 run.builder.ensure(Assemble {
1945 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1946 });
1947 }
1948
1949 #[cfg_attr(
1955 feature = "tracing",
1956 instrument(
1957 level = "debug",
1958 name = "Assemble::run",
1959 skip_all,
1960 fields(target_compiler = ?self.target_compiler),
1961 ),
1962 )]
1963 fn run(self, builder: &Builder<'_>) -> Compiler {
1964 let target_compiler = self.target_compiler;
1965
1966 if target_compiler.stage == 0 {
1967 trace!("stage 0 build compiler is always available, simply returning");
1968 assert_eq!(
1969 builder.config.build, target_compiler.host,
1970 "Cannot obtain compiler for non-native build triple at stage 0"
1971 );
1972 return target_compiler;
1974 }
1975
1976 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
1979 let libdir_bin = libdir.parent().unwrap().join("bin");
1980 t!(fs::create_dir_all(&libdir_bin));
1981
1982 if builder.config.llvm_enabled(target_compiler.host) {
1983 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
1984
1985 let llvm::LlvmResult { llvm_config, .. } =
1986 builder.ensure(llvm::Llvm { target: target_compiler.host });
1987 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
1988 trace!("LLVM tools enabled");
1989
1990 let llvm_bin_dir =
1991 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
1992 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
1993
1994 #[cfg(feature = "tracing")]
2001 let _llvm_tools_span =
2002 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2003 .entered();
2004 for tool in LLVM_TOOLS {
2005 trace!("installing `{tool}`");
2006 let tool_exe = exe(tool, target_compiler.host);
2007 let src_path = llvm_bin_dir.join(&tool_exe);
2008
2009 if !src_path.exists() && builder.config.llvm_from_ci {
2011 eprintln!("{} does not exist; skipping copy", src_path.display());
2012 continue;
2013 }
2014
2015 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2022 }
2023 }
2024 }
2025
2026 let maybe_install_llvm_bitcode_linker = |compiler| {
2027 if builder.config.llvm_bitcode_linker_enabled {
2028 trace!("llvm-bitcode-linker enabled, installing");
2029 let llvm_bitcode_linker =
2030 builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
2031 compiler,
2032 target: target_compiler.host,
2033 extra_features: vec![],
2034 });
2035 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2036 builder.copy_link(
2037 &llvm_bitcode_linker.tool_path,
2038 &libdir_bin.join(tool_exe),
2039 FileType::Executable,
2040 );
2041 }
2042 };
2043
2044 if builder.download_rustc() {
2046 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2047
2048 builder.ensure(Std::new(target_compiler, target_compiler.host));
2049 let sysroot =
2050 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2051 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2054 if target_compiler.stage == builder.top_stage {
2056 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage=target_compiler.stage));
2057 }
2058
2059 let mut precompiled_compiler = target_compiler;
2060 precompiled_compiler.forced_compiler(true);
2061 maybe_install_llvm_bitcode_linker(precompiled_compiler);
2062
2063 return target_compiler;
2064 }
2065
2066 debug!(
2080 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2081 target_compiler.stage - 1,
2082 builder.config.build,
2083 );
2084 let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
2085
2086 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2088 debug!("`llvm_enzyme` requested");
2089 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2090 let llvm_config = builder.llvm_config(builder.config.build).unwrap();
2091 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2092 let lib_ext = std::env::consts::DLL_EXTENSION;
2093 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2094 let src_lib =
2095 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2096 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2097 let target_libdir =
2098 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2099 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2100 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2101 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2102 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2103 }
2104
2105 debug!(
2111 ?build_compiler,
2112 "target_compiler.host" = ?target_compiler.host,
2113 "building compiler libraries to link to"
2114 );
2115 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2116 debug!(
2119 "(old) build_compiler.stage" = build_compiler.stage,
2120 "(adjusted) build_compiler.stage" = actual_stage,
2121 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2122 );
2123 build_compiler.stage = actual_stage;
2124
2125 #[cfg(feature = "tracing")]
2126 let _codegen_backend_span =
2127 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2128 for backend in builder.config.codegen_backends(target_compiler.host) {
2129 if backend == "llvm" {
2130 debug!("llvm codegen backend is already built as part of rustc");
2131 continue; }
2133
2134 builder.ensure(CodegenBackend {
2135 compiler: build_compiler,
2136 target: target_compiler.host,
2137 backend: backend.clone(),
2138 });
2139 }
2140 #[cfg(feature = "tracing")]
2141 drop(_codegen_backend_span);
2142
2143 let stage = target_compiler.stage;
2144 let host = target_compiler.host;
2145 let (host_info, dir_name) = if build_compiler.host == host {
2146 ("".into(), "host".into())
2147 } else {
2148 (format!(" ({host})"), host.to_string())
2149 };
2150 let msg = format!(
2155 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2156 );
2157 builder.info(&msg);
2158
2159 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2161 let proc_macros = builder
2162 .read_stamp_file(&stamp)
2163 .into_iter()
2164 .filter_map(|(path, dependency_type)| {
2165 if dependency_type == DependencyType::Host {
2166 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2167 } else {
2168 None
2169 }
2170 })
2171 .collect::<HashSet<_>>();
2172
2173 let sysroot = builder.sysroot(target_compiler);
2174 let rustc_libdir = builder.rustc_libdir(target_compiler);
2175 t!(fs::create_dir_all(&rustc_libdir));
2176 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2177 for f in builder.read_dir(&src_libdir) {
2178 let filename = f.file_name().into_string().unwrap();
2179
2180 let is_proc_macro = proc_macros.contains(&filename);
2181 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2182
2183 let can_be_rustc_dynamic_dep = if builder
2187 .link_std_into_rustc_driver(target_compiler.host)
2188 && !target_compiler.host.is_windows()
2189 {
2190 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2191 !is_std
2192 } else {
2193 true
2194 };
2195
2196 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2197 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2198 }
2199 }
2200
2201 debug!("copying codegen backends to sysroot");
2202 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2203
2204 if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) {
2205 builder.ensure(crate::core::build_steps::tool::LldWrapper {
2206 build_compiler,
2207 target_compiler,
2208 });
2209 }
2210
2211 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2212 debug!(
2213 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2214 workaround faulty homebrew `strip`s"
2215 );
2216
2217 let src_exe = exe("llvm-objcopy", target_compiler.host);
2224 let dst_exe = exe("rust-objcopy", target_compiler.host);
2225 builder.copy_link(
2226 &libdir_bin.join(src_exe),
2227 &libdir_bin.join(dst_exe),
2228 FileType::Executable,
2229 );
2230 }
2231
2232 if builder.tool_enabled("wasm-component-ld") {
2238 let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
2239 compiler: build_compiler,
2240 target: target_compiler.host,
2241 });
2242 builder.copy_link(
2243 &wasm_component.tool_path,
2244 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2245 FileType::Executable,
2246 );
2247 }
2248
2249 maybe_install_llvm_bitcode_linker(target_compiler);
2250
2251 debug!(
2254 "target_compiler.host" = ?target_compiler.host,
2255 ?sysroot,
2256 "ensuring availability of `libLLVM.so` in compiler directory"
2257 );
2258 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2259 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2260
2261 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2263 let rustc = out_dir.join(exe("rustc-main", host));
2264 let bindir = sysroot.join("bin");
2265 t!(fs::create_dir_all(bindir));
2266 let compiler = builder.rustc(target_compiler);
2267 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2268 builder.copy_link(&rustc, &compiler, FileType::Executable);
2269
2270 target_compiler
2271 }
2272}
2273
2274pub fn add_to_sysroot(
2279 builder: &Builder<'_>,
2280 sysroot_dst: &Path,
2281 sysroot_host_dst: &Path,
2282 stamp: &BuildStamp,
2283) {
2284 let self_contained_dst = &sysroot_dst.join("self-contained");
2285 t!(fs::create_dir_all(sysroot_dst));
2286 t!(fs::create_dir_all(sysroot_host_dst));
2287 t!(fs::create_dir_all(self_contained_dst));
2288 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2289 let dst = match dependency_type {
2290 DependencyType::Host => sysroot_host_dst,
2291 DependencyType::Target => sysroot_dst,
2292 DependencyType::TargetSelfContained => self_contained_dst,
2293 };
2294 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2295 }
2296}
2297
2298pub fn run_cargo(
2299 builder: &Builder<'_>,
2300 cargo: Cargo,
2301 tail_args: Vec<String>,
2302 stamp: &BuildStamp,
2303 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2304 is_check: bool,
2305 rlib_only_metadata: bool,
2306) -> Vec<PathBuf> {
2307 let target_root_dir = stamp.path().parent().unwrap();
2309 let target_deps_dir = target_root_dir.join("deps");
2311 let host_root_dir = target_root_dir
2313 .parent()
2314 .unwrap() .parent()
2316 .unwrap() .join(target_root_dir.file_name().unwrap());
2318
2319 let mut deps = Vec::new();
2323 let mut toplevel = Vec::new();
2324 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2325 let (filenames, crate_types) = match msg {
2326 CargoMessage::CompilerArtifact {
2327 filenames,
2328 target: CargoTarget { crate_types },
2329 ..
2330 } => (filenames, crate_types),
2331 _ => return,
2332 };
2333 for filename in filenames {
2334 let mut keep = false;
2336 if filename.ends_with(".lib")
2337 || filename.ends_with(".a")
2338 || is_debug_info(&filename)
2339 || is_dylib(Path::new(&*filename))
2340 {
2341 keep = true;
2343 }
2344 if is_check && filename.ends_with(".rmeta") {
2345 keep = true;
2347 } else if rlib_only_metadata {
2348 if filename.contains("jemalloc_sys")
2349 || filename.contains("rustc_smir")
2350 || filename.contains("stable_mir")
2351 {
2352 keep |= filename.ends_with(".rlib");
2355 } else {
2356 keep |= filename.ends_with(".rmeta");
2360 }
2361 } else {
2362 keep |= filename.ends_with(".rlib");
2364 }
2365
2366 if !keep {
2367 continue;
2368 }
2369
2370 let filename = Path::new(&*filename);
2371
2372 if filename.starts_with(&host_root_dir) {
2375 if crate_types.iter().any(|t| t == "proc-macro") {
2377 deps.push((filename.to_path_buf(), DependencyType::Host));
2378 }
2379 continue;
2380 }
2381
2382 if filename.starts_with(&target_deps_dir) {
2385 deps.push((filename.to_path_buf(), DependencyType::Target));
2386 continue;
2387 }
2388
2389 let expected_len = t!(filename.metadata()).len();
2400 let filename = filename.file_name().unwrap().to_str().unwrap();
2401 let mut parts = filename.splitn(2, '.');
2402 let file_stem = parts.next().unwrap().to_owned();
2403 let extension = parts.next().unwrap().to_owned();
2404
2405 toplevel.push((file_stem, extension, expected_len));
2406 }
2407 });
2408
2409 if !ok {
2410 crate::exit!(1);
2411 }
2412
2413 if builder.config.dry_run() {
2414 return Vec::new();
2415 }
2416
2417 let contents = target_deps_dir
2421 .read_dir()
2422 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2423 .map(|e| t!(e))
2424 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2425 .collect::<Vec<_>>();
2426 for (prefix, extension, expected_len) in toplevel {
2427 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2428 meta.len() == expected_len
2429 && filename
2430 .strip_prefix(&prefix[..])
2431 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2432 .unwrap_or(false)
2433 });
2434 let max = candidates.max_by_key(|&(_, _, metadata)| {
2435 metadata.modified().expect("mtime should be available on all relevant OSes")
2436 });
2437 let path_to_add = match max {
2438 Some(triple) => triple.0.to_str().unwrap(),
2439 None => panic!("no output generated for {prefix:?} {extension:?}"),
2440 };
2441 if is_dylib(Path::new(path_to_add)) {
2442 let candidate = format!("{path_to_add}.lib");
2443 let candidate = PathBuf::from(candidate);
2444 if candidate.exists() {
2445 deps.push((candidate, DependencyType::Target));
2446 }
2447 }
2448 deps.push((path_to_add.into(), DependencyType::Target));
2449 }
2450
2451 deps.extend(additional_target_deps);
2452 deps.sort();
2453 let mut new_contents = Vec::new();
2454 for (dep, dependency_type) in deps.iter() {
2455 new_contents.extend(match *dependency_type {
2456 DependencyType::Host => b"h",
2457 DependencyType::Target => b"t",
2458 DependencyType::TargetSelfContained => b"s",
2459 });
2460 new_contents.extend(dep.to_str().unwrap().as_bytes());
2461 new_contents.extend(b"\0");
2462 }
2463 t!(fs::write(stamp.path(), &new_contents));
2464 deps.into_iter().map(|(d, _)| d).collect()
2465}
2466
2467pub fn stream_cargo(
2468 builder: &Builder<'_>,
2469 cargo: Cargo,
2470 tail_args: Vec<String>,
2471 cb: &mut dyn FnMut(CargoMessage<'_>),
2472) -> bool {
2473 let mut cmd = cargo.into_cmd();
2474
2475 #[cfg(feature = "tracing")]
2476 let _run_span = crate::trace_cmd!(cmd);
2477
2478 let cargo = cmd.as_command_mut();
2479 let mut message_format = if builder.config.json_output {
2482 String::from("json")
2483 } else {
2484 String::from("json-render-diagnostics")
2485 };
2486 if let Some(s) = &builder.config.rustc_error_format {
2487 message_format.push_str(",json-diagnostic-");
2488 message_format.push_str(s);
2489 }
2490 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
2491
2492 for arg in tail_args {
2493 cargo.arg(arg);
2494 }
2495
2496 builder.verbose(|| println!("running: {cargo:?}"));
2497
2498 if builder.config.dry_run() {
2499 return true;
2500 }
2501
2502 let mut child = match cargo.spawn() {
2503 Ok(child) => child,
2504 Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"),
2505 };
2506
2507 let stdout = BufReader::new(child.stdout.take().unwrap());
2511 for line in stdout.lines() {
2512 let line = t!(line);
2513 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2514 Ok(msg) => {
2515 if builder.config.json_output {
2516 println!("{line}");
2518 }
2519 cb(msg)
2520 }
2521 Err(_) => println!("{line}"),
2523 }
2524 }
2525
2526 let status = t!(child.wait());
2528 if builder.is_verbose() && !status.success() {
2529 eprintln!(
2530 "command did not execute successfully: {cargo:?}\n\
2531 expected success, got: {status}"
2532 );
2533 }
2534 status.success()
2535}
2536
2537#[derive(Deserialize)]
2538pub struct CargoTarget<'a> {
2539 crate_types: Vec<Cow<'a, str>>,
2540}
2541
2542#[derive(Deserialize)]
2543#[serde(tag = "reason", rename_all = "kebab-case")]
2544pub enum CargoMessage<'a> {
2545 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2546 BuildScriptExecuted,
2547 BuildFinished,
2548}
2549
2550pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2551 if target != "x86_64-unknown-linux-gnu"
2555 || !builder.config.is_host_target(target)
2556 || !path.exists()
2557 {
2558 return;
2559 }
2560
2561 let previous_mtime = t!(t!(path.metadata()).modified());
2562 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2563
2564 let file = t!(fs::File::open(path));
2565
2566 t!(file.set_modified(previous_mtime));
2579}
2580
2581pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2583 build_compiler.stage != 0
2584}