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, 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.last_modified_commit(&["library"], "download-rustc", true).is_none();
115
116 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
117 trace!("download_rustc: {}", builder.download_rustc());
118 trace!(
119 "last modified commit: {:?}",
120 builder.config.last_modified_commit(&["library"], "download-rustc", true)
121 );
122 trace!(force_recompile);
123
124 run.builder.ensure(Std {
125 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
126 target: run.target,
127 crates,
128 force_recompile,
129 extra_rust_args: &[],
130 is_for_mir_opt_tests: false,
131 });
132 }
133
134 #[cfg_attr(
140 feature = "tracing",
141 instrument(
142 level = "debug",
143 name = "Std::run",
144 skip_all,
145 fields(
146 target = ?self.target,
147 compiler = ?self.compiler,
148 force_recompile = self.force_recompile
149 ),
150 ),
151 )]
152 fn run(self, builder: &Builder<'_>) {
153 let target = self.target;
154 let compiler = self.compiler;
155
156 if builder.download_rustc() && builder.is_builder_target(target)
159 && compiler.stage != 0
162 && !self.force_recompile
163 {
164 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
165 cp_rustc_component_to_ci_sysroot(
166 builder,
167 &sysroot,
168 builder.config.ci_rust_std_contents(),
169 );
170 return;
171 }
172
173 if builder.config.keep_stage.contains(&compiler.stage)
174 || builder.config.keep_stage_std.contains(&compiler.stage)
175 {
176 trace!(keep_stage = ?builder.config.keep_stage);
177 trace!(keep_stage_std = ?builder.config.keep_stage_std);
178
179 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
180
181 builder.ensure(StartupObjects { compiler, target });
182
183 self.copy_extra_objects(builder, &compiler, target);
184
185 builder.ensure(StdLink::from_std(self, compiler));
186 return;
187 }
188
189 builder.require_submodule("library/stdarch", None);
190
191 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
192
193 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
194 trace!(?compiler_to_use);
195
196 if compiler_to_use != compiler {
197 trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
198
199 builder.ensure(Std::new(compiler_to_use, target));
200 let msg = if compiler_to_use.host == target {
201 format!(
202 "Uplifting library (stage{} -> stage{})",
203 compiler_to_use.stage, compiler.stage
204 )
205 } else {
206 format!(
207 "Uplifting library (stage{}:{} -> stage{}:{})",
208 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
209 )
210 };
211 builder.info(&msg);
212
213 self.copy_extra_objects(builder, &compiler, target);
216
217 builder.ensure(StdLink::from_std(self, compiler_to_use));
218 return;
219 }
220
221 trace!(
222 ?compiler_to_use,
223 ?compiler,
224 "compiler == compiler_to_use, handling not-cross-compile scenario"
225 );
226
227 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
228
229 if compiler.stage == 0 && builder.is_builder_target(compiler.host) {
233 trace!(
234 "(build == host) copying linking components to `stage0-sysroot` for bootstrapping"
235 );
236 let src_sysroot_bin = builder
238 .rustc_snapshot_sysroot()
239 .join("lib")
240 .join("rustlib")
241 .join(compiler.host)
242 .join("bin");
243 if src_sysroot_bin.exists() {
244 let target_sysroot_bin = builder.sysroot_target_bindir(compiler, target);
245 t!(fs::create_dir_all(&target_sysroot_bin));
246 builder.cp_link_r(&src_sysroot_bin, &target_sysroot_bin);
247 }
248 }
249
250 let mut cargo = if self.is_for_mir_opt_tests {
254 trace!("building special sysroot for mir-opt tests");
255 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
256 builder,
257 compiler,
258 Mode::Std,
259 SourceType::InTree,
260 target,
261 Kind::Check,
262 );
263 cargo.rustflag("-Zalways-encode-mir");
264 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
265 cargo
266 } else {
267 trace!("building regular sysroot");
268 let mut cargo = builder::Cargo::new(
269 builder,
270 compiler,
271 Mode::Std,
272 SourceType::InTree,
273 target,
274 Kind::Build,
275 );
276 std_cargo(builder, target, compiler.stage, &mut cargo);
277 for krate in &*self.crates {
278 cargo.arg("-p").arg(krate);
279 }
280 cargo
281 };
282
283 if target.is_synthetic() {
285 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
286 }
287 for rustflag in self.extra_rust_args.iter() {
288 cargo.rustflag(rustflag);
289 }
290
291 let _guard = builder.msg(
292 Kind::Build,
293 compiler.stage,
294 format_args!("library artifacts{}", crate_description(&self.crates)),
295 compiler.host,
296 target,
297 );
298 run_cargo(
299 builder,
300 cargo,
301 vec![],
302 &build_stamp::libstd_stamp(builder, compiler, target),
303 target_deps,
304 self.is_for_mir_opt_tests, false,
306 );
307
308 builder.ensure(StdLink::from_std(
309 self,
310 builder.compiler(compiler.stage, builder.config.build),
311 ));
312 }
313}
314
315fn copy_and_stamp(
316 builder: &Builder<'_>,
317 libdir: &Path,
318 sourcedir: &Path,
319 name: &str,
320 target_deps: &mut Vec<(PathBuf, DependencyType)>,
321 dependency_type: DependencyType,
322) {
323 let target = libdir.join(name);
324 builder.copy_link(&sourcedir.join(name), &target);
325
326 target_deps.push((target, dependency_type));
327}
328
329fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
330 let libunwind_path = builder.ensure(llvm::Libunwind { target });
331 let libunwind_source = libunwind_path.join("libunwind.a");
332 let libunwind_target = libdir.join("libunwind.a");
333 builder.copy_link(&libunwind_source, &libunwind_target);
334 libunwind_target
335}
336
337fn copy_third_party_objects(
339 builder: &Builder<'_>,
340 compiler: &Compiler,
341 target: TargetSelection,
342) -> Vec<(PathBuf, DependencyType)> {
343 let mut target_deps = vec![];
344
345 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
346 target_deps.extend(
349 copy_sanitizers(builder, compiler, target)
350 .into_iter()
351 .map(|d| (d, DependencyType::Target)),
352 );
353 }
354
355 if target == "x86_64-fortanix-unknown-sgx"
356 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
357 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
358 {
359 let libunwind_path =
360 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
361 target_deps.push((libunwind_path, DependencyType::Target));
362 }
363
364 target_deps
365}
366
367fn copy_self_contained_objects(
369 builder: &Builder<'_>,
370 compiler: &Compiler,
371 target: TargetSelection,
372) -> Vec<(PathBuf, DependencyType)> {
373 let libdir_self_contained =
374 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
375 t!(fs::create_dir_all(&libdir_self_contained));
376 let mut target_deps = vec![];
377
378 if target.needs_crt_begin_end() {
386 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
387 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
388 });
389 if !target.starts_with("wasm32") {
390 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
391 copy_and_stamp(
392 builder,
393 &libdir_self_contained,
394 &srcdir,
395 obj,
396 &mut target_deps,
397 DependencyType::TargetSelfContained,
398 );
399 }
400 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
401 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
402 let src = crt_path.join(obj);
403 let target = libdir_self_contained.join(obj);
404 builder.copy_link(&src, &target);
405 target_deps.push((target, DependencyType::TargetSelfContained));
406 }
407 } else {
408 for &obj in &["libc.a", "crt1-command.o"] {
411 copy_and_stamp(
412 builder,
413 &libdir_self_contained,
414 &srcdir,
415 obj,
416 &mut target_deps,
417 DependencyType::TargetSelfContained,
418 );
419 }
420 }
421 if !target.starts_with("s390x") {
422 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
423 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
424 }
425 } else if target.contains("-wasi") {
426 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
427 panic!(
428 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
429 or `$WASI_SDK_PATH` set",
430 target.triple
431 )
432 });
433 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
434 copy_and_stamp(
435 builder,
436 &libdir_self_contained,
437 &srcdir,
438 obj,
439 &mut target_deps,
440 DependencyType::TargetSelfContained,
441 );
442 }
443 } else if target.is_windows_gnu() {
444 for obj in ["crt2.o", "dllcrt2.o"].iter() {
445 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
446 let target = libdir_self_contained.join(obj);
447 builder.copy_link(&src, &target);
448 target_deps.push((target, DependencyType::TargetSelfContained));
449 }
450 }
451
452 target_deps
453}
454
455pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
457 if cfg!(test) {
459 return vec![];
460 }
461
462 let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
463 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
464
465 if target_is_no_std {
467 vec![]
468 }
469 else if has_alias {
471 run.make_run_crates(builder::Alias::Library)
472 } else {
473 run.cargo_crates_in_set()
474 }
475}
476
477fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
483 if builder.config.llvm_from_ci {
485 builder.config.maybe_download_ci_llvm();
487 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
488 if ci_llvm_compiler_rt.exists() {
489 return ci_llvm_compiler_rt;
490 }
491 }
492
493 builder.require_submodule("src/llvm-project", {
495 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
496 });
497 builder.src.join("src/llvm-project/compiler-rt")
498}
499
500pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
503 if target.contains("apple") && !builder.config.dry_run() {
521 let mut cmd = command(builder.rustc(cargo.compiler()));
525 cmd.arg("--target").arg(target.rustc_target_arg());
526 cmd.arg("--print=deployment-target");
527 let output = cmd.run_capture_stdout(builder).stdout();
528
529 let (env_var, value) = output.split_once('=').unwrap();
530 cargo.env(env_var.trim(), value.trim());
533
534 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
544 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
545 }
546 }
547
548 if let Some(path) = builder.config.profiler_path(target) {
550 cargo.env("LLVM_PROFILER_RT_LIB", path);
551 } else if builder.config.profiler_enabled(target) {
552 let compiler_rt = compiler_rt_for_profiler(builder);
553 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
557 }
558
559 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
573 builder.require_submodule(
581 "src/llvm-project",
582 Some(
583 "The `build.optimized-compiler-builtins` config option \
584 requires `compiler-rt` sources from LLVM.",
585 ),
586 );
587 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
588 assert!(compiler_builtins_root.exists());
589 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
592 " compiler-builtins-c"
593 } else {
594 ""
595 };
596
597 if !builder.unstable_features() {
600 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
601 }
602
603 let mut features = String::new();
604
605 if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
606 {
607 features += "compiler-builtins-no-f16-f128 ";
608 }
609
610 if builder.no_std(target) == Some(true) {
611 features += " compiler-builtins-mem";
612 if !target.starts_with("bpf") {
613 features.push_str(compiler_builtins_c_feature);
614 }
615
616 cargo
618 .args(["-p", "alloc"])
619 .arg("--manifest-path")
620 .arg(builder.src.join("library/alloc/Cargo.toml"))
621 .arg("--features")
622 .arg(features);
623 } else {
624 features += &builder.std_features(target);
625 features.push_str(compiler_builtins_c_feature);
626
627 cargo
628 .arg("--features")
629 .arg(features)
630 .arg("--manifest-path")
631 .arg(builder.src.join("library/sysroot/Cargo.toml"));
632
633 if target.contains("musl") {
636 if let Some(p) = builder.musl_libdir(target) {
637 let root = format!("native={}", p.to_str().unwrap());
638 cargo.rustflag("-L").rustflag(&root);
639 }
640 }
641
642 if target.contains("-wasi") {
643 if let Some(dir) = builder.wasi_libdir(target) {
644 let root = format!("native={}", dir.to_str().unwrap());
645 cargo.rustflag("-L").rustflag(&root);
646 }
647 }
648 }
649
650 if stage >= 1 {
659 cargo.rustflag("-Cembed-bitcode=yes");
660 }
661 if builder.config.rust_lto == RustcLto::Off {
662 cargo.rustflag("-Clto=off");
663 }
664
665 if target.contains("riscv") {
672 cargo.rustflag("-Cforce-unwind-tables=yes");
673 }
674
675 cargo.rustflag("-Cforce-frame-pointers=yes");
678
679 let html_root =
680 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
681 cargo.rustflag(&html_root);
682 cargo.rustdocflag(&html_root);
683
684 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
685}
686
687#[derive(Debug, Clone, PartialEq, Eq, Hash)]
688struct StdLink {
689 pub compiler: Compiler,
690 pub target_compiler: Compiler,
691 pub target: TargetSelection,
692 crates: Vec<String>,
694 force_recompile: bool,
696}
697
698impl StdLink {
699 fn from_std(std: Std, host_compiler: Compiler) -> Self {
700 Self {
701 compiler: host_compiler,
702 target_compiler: std.compiler,
703 target: std.target,
704 crates: std.crates,
705 force_recompile: std.force_recompile,
706 }
707 }
708}
709
710impl Step for StdLink {
711 type Output = ();
712
713 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
714 run.never()
715 }
716
717 #[cfg_attr(
726 feature = "tracing",
727 instrument(
728 level = "trace",
729 name = "StdLink::run",
730 skip_all,
731 fields(
732 compiler = ?self.compiler,
733 target_compiler = ?self.target_compiler,
734 target = ?self.target
735 ),
736 ),
737 )]
738 fn run(self, builder: &Builder<'_>) {
739 let compiler = self.compiler;
740 let target_compiler = self.target_compiler;
741 let target = self.target;
742
743 let (libdir, hostdir) = if self.force_recompile && builder.download_rustc() {
745 let lib = builder.sysroot_libdir_relative(self.compiler);
747 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
748 compiler: self.compiler,
749 force_recompile: self.force_recompile,
750 });
751 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
752 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
753 (libdir, hostdir)
754 } else {
755 let libdir = builder.sysroot_target_libdir(target_compiler, target);
756 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
757 (libdir, hostdir)
758 };
759
760 add_to_sysroot(
761 builder,
762 &libdir,
763 &hostdir,
764 &build_stamp::libstd_stamp(builder, compiler, target),
765 );
766
767 if compiler.stage == 0
771 && builder
772 .build
773 .config
774 .initial_rustc
775 .starts_with(builder.out.join(compiler.host).join("stage0/bin"))
776 {
777 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
779
780 let host = compiler.host;
781 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
782 let sysroot_bin_dir = sysroot.join("bin");
783 t!(fs::create_dir_all(&sysroot_bin_dir));
784 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
785
786 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
788 if let Ok(files) = fs::read_dir(stage0_lib_dir) {
789 for file in files {
790 let file = t!(file);
791 let path = file.path();
792 if path.is_file() {
793 builder
794 .copy_link(&path, &sysroot.join("lib").join(path.file_name().unwrap()));
795 }
796 }
797 }
798
799 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
801 t!(fs::create_dir_all(&sysroot_codegen_backends));
802 let stage0_codegen_backends = builder
803 .out
804 .join(host)
805 .join("stage0/lib/rustlib")
806 .join(host)
807 .join("codegen-backends");
808 if stage0_codegen_backends.exists() {
809 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
810 }
811 }
812 }
813}
814
815fn copy_sanitizers(
817 builder: &Builder<'_>,
818 compiler: &Compiler,
819 target: TargetSelection,
820) -> Vec<PathBuf> {
821 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
822
823 if builder.config.dry_run() {
824 return Vec::new();
825 }
826
827 let mut target_deps = Vec::new();
828 let libdir = builder.sysroot_target_libdir(*compiler, target);
829
830 for runtime in &runtimes {
831 let dst = libdir.join(&runtime.name);
832 builder.copy_link(&runtime.path, &dst);
833
834 if target == "x86_64-apple-darwin"
838 || target == "aarch64-apple-darwin"
839 || target == "aarch64-apple-ios"
840 || target == "aarch64-apple-ios-sim"
841 || target == "x86_64-apple-ios"
842 {
843 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
845 apple_darwin_sign_file(builder, &dst);
848 }
849
850 target_deps.push(dst);
851 }
852
853 target_deps
854}
855
856fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
857 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
858}
859
860fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
861 command("codesign")
862 .arg("-f") .arg("-s")
864 .arg("-")
865 .arg(file_path)
866 .run(builder);
867}
868
869#[derive(Debug, Clone, PartialEq, Eq, Hash)]
870pub struct StartupObjects {
871 pub compiler: Compiler,
872 pub target: TargetSelection,
873}
874
875impl Step for StartupObjects {
876 type Output = Vec<(PathBuf, DependencyType)>;
877
878 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
879 run.path("library/rtstartup")
880 }
881
882 fn make_run(run: RunConfig<'_>) {
883 run.builder.ensure(StartupObjects {
884 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
885 target: run.target,
886 });
887 }
888
889 #[cfg_attr(
896 feature = "tracing",
897 instrument(
898 level = "trace",
899 name = "StartupObjects::run",
900 skip_all,
901 fields(compiler = ?self.compiler, target = ?self.target),
902 ),
903 )]
904 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
905 let for_compiler = self.compiler;
906 let target = self.target;
907 if !target.is_windows_gnu() {
908 return vec![];
909 }
910
911 let mut target_deps = vec![];
912
913 let src_dir = &builder.src.join("library").join("rtstartup");
914 let dst_dir = &builder.native_dir(target).join("rtstartup");
915 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
916 t!(fs::create_dir_all(dst_dir));
917
918 for file in &["rsbegin", "rsend"] {
919 let src_file = &src_dir.join(file.to_string() + ".rs");
920 let dst_file = &dst_dir.join(file.to_string() + ".o");
921 if !up_to_date(src_file, dst_file) {
922 let mut cmd = command(&builder.initial_rustc);
923 cmd.env("RUSTC_BOOTSTRAP", "1");
924 if !builder.local_rebuild {
925 cmd.arg("--cfg").arg("bootstrap");
927 }
928 cmd.arg("--target")
929 .arg(target.rustc_target_arg())
930 .arg("--emit=obj")
931 .arg("-o")
932 .arg(dst_file)
933 .arg(src_file)
934 .run(builder);
935 }
936
937 let target = sysroot_dir.join((*file).to_string() + ".o");
938 builder.copy_link(dst_file, &target);
939 target_deps.push((target, DependencyType::Target));
940 }
941
942 target_deps
943 }
944}
945
946fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
947 let ci_rustc_dir = builder.config.ci_rustc_dir();
948
949 for file in contents {
950 let src = ci_rustc_dir.join(&file);
951 let dst = sysroot.join(file);
952 if src.is_dir() {
953 t!(fs::create_dir_all(dst));
954 } else {
955 builder.copy_link(&src, &dst);
956 }
957 }
958}
959
960#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
961pub struct Rustc {
962 pub target: TargetSelection,
963 pub compiler: Compiler,
965 crates: Vec<String>,
971}
972
973impl Rustc {
974 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
975 Self { target, compiler, crates: Default::default() }
976 }
977}
978
979impl Step for Rustc {
980 type Output = u32;
988 const ONLY_HOSTS: bool = true;
989 const DEFAULT: bool = false;
990
991 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
992 let mut crates = run.builder.in_tree_crates("rustc-main", None);
993 for (i, krate) in crates.iter().enumerate() {
994 if krate.name == "rustc-main" {
997 crates.swap_remove(i);
998 break;
999 }
1000 }
1001 run.crates(crates)
1002 }
1003
1004 fn make_run(run: RunConfig<'_>) {
1005 let crates = run.cargo_crates_in_set();
1006 run.builder.ensure(Rustc {
1007 compiler: run
1008 .builder
1009 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1010 target: run.target,
1011 crates,
1012 });
1013 }
1014
1015 #[cfg_attr(
1021 feature = "tracing",
1022 instrument(
1023 level = "debug",
1024 name = "Rustc::run",
1025 skip_all,
1026 fields(previous_compiler = ?self.compiler, target = ?self.target),
1027 ),
1028 )]
1029 fn run(self, builder: &Builder<'_>) -> u32 {
1030 let compiler = self.compiler;
1031 let target = self.target;
1032
1033 if builder.download_rustc() && compiler.stage != 0 {
1036 trace!(stage = compiler.stage, "`download_rustc` requested");
1037
1038 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
1039 cp_rustc_component_to_ci_sysroot(
1040 builder,
1041 &sysroot,
1042 builder.config.ci_rustc_dev_contents(),
1043 );
1044 return compiler.stage;
1045 }
1046
1047 builder.ensure(Std::new(compiler, target));
1048
1049 if builder.config.keep_stage.contains(&compiler.stage) {
1050 trace!(stage = compiler.stage, "`keep-stage` requested");
1051
1052 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1053 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1054 builder.ensure(RustcLink::from_rustc(self, compiler));
1055
1056 return compiler.stage;
1057 }
1058
1059 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1060 if compiler_to_use != compiler {
1061 builder.ensure(Rustc::new(compiler_to_use, target));
1062 let msg = if compiler_to_use.host == target {
1063 format!(
1064 "Uplifting rustc (stage{} -> stage{})",
1065 compiler_to_use.stage,
1066 compiler.stage + 1
1067 )
1068 } else {
1069 format!(
1070 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1071 compiler_to_use.stage,
1072 compiler_to_use.host,
1073 compiler.stage + 1,
1074 target
1075 )
1076 };
1077 builder.info(&msg);
1078 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1079 return compiler_to_use.stage;
1080 }
1081
1082 builder.ensure(Std::new(
1084 builder.compiler(self.compiler.stage, builder.config.build),
1085 builder.config.build,
1086 ));
1087
1088 let mut cargo = builder::Cargo::new(
1089 builder,
1090 compiler,
1091 Mode::Rustc,
1092 SourceType::InTree,
1093 target,
1094 Kind::Build,
1095 );
1096
1097 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
1098
1099 for krate in &*self.crates {
1103 cargo.arg("-p").arg(krate);
1104 }
1105
1106 if builder.build.config.enable_bolt_settings && compiler.stage == 1 {
1107 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1109 }
1110
1111 let _guard = builder.msg_sysroot_tool(
1112 Kind::Build,
1113 compiler.stage,
1114 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1115 compiler.host,
1116 target,
1117 );
1118 let stamp = build_stamp::librustc_stamp(builder, compiler, target);
1119 run_cargo(
1120 builder,
1121 cargo,
1122 vec![],
1123 &stamp,
1124 vec![],
1125 false,
1126 true, );
1128
1129 let target_root_dir = stamp.path().parent().unwrap();
1130 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1136 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1137 {
1138 let rustc_driver = target_root_dir.join("librustc_driver.so");
1139 strip_debug(builder, target, &rustc_driver);
1140 }
1141
1142 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1143 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1146 }
1147
1148 builder.ensure(RustcLink::from_rustc(
1149 self,
1150 builder.compiler(compiler.stage, builder.config.build),
1151 ));
1152
1153 compiler.stage
1154 }
1155}
1156
1157pub fn rustc_cargo(
1158 builder: &Builder<'_>,
1159 cargo: &mut Cargo,
1160 target: TargetSelection,
1161 compiler: &Compiler,
1162 crates: &[String],
1163) {
1164 cargo
1165 .arg("--features")
1166 .arg(builder.rustc_features(builder.kind, target, crates))
1167 .arg("--manifest-path")
1168 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1169
1170 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1171
1172 cargo.rustflag("-Zon-broken-pipe=kill");
1186
1187 if builder.config.llvm_enzyme {
1190 let arch = builder.build.build;
1191 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1192 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1193
1194 if !builder.config.dry_run() {
1195 let llvm_config = builder.llvm_config(builder.config.build).unwrap();
1196 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1197 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1198 }
1199 }
1200
1201 if builder.build.config.lld_mode.is_used() {
1206 cargo.rustflag("-Zdefault-visibility=protected");
1207 }
1208
1209 if is_lto_stage(compiler) {
1210 match builder.config.rust_lto {
1211 RustcLto::Thin | RustcLto::Fat => {
1212 cargo.rustflag("-Zdylib-lto");
1215 let lto_type = match builder.config.rust_lto {
1219 RustcLto::Thin => "thin",
1220 RustcLto::Fat => "fat",
1221 _ => unreachable!(),
1222 };
1223 cargo.rustflag(&format!("-Clto={lto_type}"));
1224 cargo.rustflag("-Cembed-bitcode=yes");
1225 }
1226 RustcLto::ThinLocal => { }
1227 RustcLto::Off => {
1228 cargo.rustflag("-Clto=off");
1229 }
1230 }
1231 } else if builder.config.rust_lto == RustcLto::Off {
1232 cargo.rustflag("-Clto=off");
1233 }
1234
1235 if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
1243 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1244 }
1245
1246 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1247 panic!("Cannot use and generate PGO profiles at the same time");
1248 }
1249 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1250 if compiler.stage == 1 {
1251 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1252 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1255 true
1256 } else {
1257 false
1258 }
1259 } else if let Some(path) = &builder.config.rust_profile_use {
1260 if compiler.stage == 1 {
1261 cargo.rustflag(&format!("-Cprofile-use={path}"));
1262 if builder.is_verbose() {
1263 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1264 }
1265 true
1266 } else {
1267 false
1268 }
1269 } else {
1270 false
1271 };
1272 if is_collecting {
1273 cargo.rustflag(&format!(
1275 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1276 builder.config.src.components().count()
1277 ));
1278 }
1279
1280 rustc_cargo_env(builder, cargo, target, compiler.stage);
1281}
1282
1283pub fn rustc_cargo_env(
1284 builder: &Builder<'_>,
1285 cargo: &mut Cargo,
1286 target: TargetSelection,
1287 stage: u32,
1288) {
1289 cargo
1292 .env("CFG_RELEASE", builder.rust_release())
1293 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1294 .env("CFG_VERSION", builder.rust_version());
1295
1296 if builder.config.omit_git_hash {
1300 cargo.env("CFG_OMIT_GIT_HASH", "1");
1301 }
1302
1303 if let Some(backend) = builder.config.default_codegen_backend(target) {
1304 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1305 }
1306
1307 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1308 let target_config = builder.config.target_config.get(&target);
1309
1310 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1311
1312 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1313 cargo.env("CFG_VER_DATE", ver_date);
1314 }
1315 if let Some(ref ver_hash) = builder.rust_info().sha() {
1316 cargo.env("CFG_VER_HASH", ver_hash);
1317 }
1318 if !builder.unstable_features() {
1319 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1320 }
1321
1322 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1325 cargo.env("CFG_DEFAULT_LINKER", s);
1326 } else if let Some(ref s) = builder.config.rustc_default_linker {
1327 cargo.env("CFG_DEFAULT_LINKER", s);
1328 }
1329
1330 if builder.config.lld_enabled
1332 && (builder.config.channel == "dev" || builder.config.channel == "nightly")
1333 {
1334 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1335 }
1336
1337 if builder.config.rust_verify_llvm_ir {
1338 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1339 }
1340
1341 if builder.config.llvm_enzyme {
1342 cargo.rustflag("--cfg=llvm_enzyme");
1343 }
1344
1345 if builder.config.llvm_enabled(target) {
1350 let building_is_expensive =
1351 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1352 .should_build();
1353 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage;
1355 let should_skip_build = building_is_expensive && can_skip_build;
1356 if !should_skip_build {
1357 rustc_llvm_env(builder, cargo, target)
1358 }
1359 }
1360
1361 if builder.config.jemalloc(target)
1364 && target.starts_with("aarch64")
1365 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1366 {
1367 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1368 }
1369}
1370
1371fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1374 if builder.is_rust_llvm(target) {
1375 cargo.env("LLVM_RUSTLLVM", "1");
1376 }
1377 if builder.config.llvm_enzyme {
1378 cargo.env("LLVM_ENZYME", "1");
1379 }
1380 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1381 cargo.env("LLVM_CONFIG", &llvm_config);
1382
1383 let mut llvm_linker_flags = String::new();
1393 if builder.config.llvm_profile_generate && target.is_msvc() {
1394 if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
1395 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1397 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1398 }
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 file = compiler_file(
1423 builder,
1424 &builder.cxx(target).unwrap(),
1425 target,
1426 CLang::Cxx,
1427 "libstdc++.a",
1428 );
1429 cargo.env("LLVM_STATIC_STDCPP", file);
1430 }
1431 if builder.llvm_link_shared() {
1432 cargo.env("LLVM_LINK_SHARED", "1");
1433 }
1434 if builder.config.llvm_use_libcxx {
1435 cargo.env("LLVM_USE_LIBCXX", "1");
1436 }
1437 if builder.config.llvm_assertions {
1438 cargo.env("LLVM_ASSERTIONS", "1");
1439 }
1440}
1441
1442#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1448struct RustcLink {
1449 pub compiler: Compiler,
1451 pub previous_stage_compiler: Compiler,
1453 pub target: TargetSelection,
1454 crates: Vec<String>,
1456}
1457
1458impl RustcLink {
1459 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1460 Self {
1461 compiler: host_compiler,
1462 previous_stage_compiler: rustc.compiler,
1463 target: rustc.target,
1464 crates: rustc.crates,
1465 }
1466 }
1467}
1468
1469impl Step for RustcLink {
1470 type Output = ();
1471
1472 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1473 run.never()
1474 }
1475
1476 #[cfg_attr(
1478 feature = "tracing",
1479 instrument(
1480 level = "trace",
1481 name = "RustcLink::run",
1482 skip_all,
1483 fields(
1484 compiler = ?self.compiler,
1485 previous_stage_compiler = ?self.previous_stage_compiler,
1486 target = ?self.target,
1487 ),
1488 ),
1489 )]
1490 fn run(self, builder: &Builder<'_>) {
1491 let compiler = self.compiler;
1492 let previous_stage_compiler = self.previous_stage_compiler;
1493 let target = self.target;
1494 add_to_sysroot(
1495 builder,
1496 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1497 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1498 &build_stamp::librustc_stamp(builder, compiler, target),
1499 );
1500 }
1501}
1502
1503#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1504pub struct CodegenBackend {
1505 pub target: TargetSelection,
1506 pub compiler: Compiler,
1507 pub backend: String,
1508}
1509
1510fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1511 let mut needs_codegen_cfg = false;
1512 for path_set in &run.paths {
1513 needs_codegen_cfg = match path_set {
1514 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1515 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1516 }
1517 }
1518 needs_codegen_cfg
1519}
1520
1521pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1522
1523fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1524 let path = path.path.to_str().unwrap();
1525
1526 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1527 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1528
1529 if path.contains(CODEGEN_BACKEND_PREFIX) {
1530 let mut needs_codegen_backend_config = true;
1531 for backend in run.builder.config.codegen_backends(run.target) {
1532 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1533 needs_codegen_backend_config = false;
1534 }
1535 }
1536 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1537 && needs_codegen_backend_config
1538 {
1539 run.builder.info(
1540 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1541 HELP: add backend to codegen-backends in bootstrap.toml.",
1542 );
1543 return true;
1544 }
1545 }
1546
1547 false
1548}
1549
1550impl Step for CodegenBackend {
1551 type Output = ();
1552 const ONLY_HOSTS: bool = true;
1553 const DEFAULT: bool = true;
1555
1556 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1557 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1558 }
1559
1560 fn make_run(run: RunConfig<'_>) {
1561 if needs_codegen_config(&run) {
1562 return;
1563 }
1564
1565 for backend in run.builder.config.codegen_backends(run.target) {
1566 if backend == "llvm" {
1567 continue; }
1569
1570 run.builder.ensure(CodegenBackend {
1571 target: run.target,
1572 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1573 backend: backend.clone(),
1574 });
1575 }
1576 }
1577
1578 #[cfg_attr(
1579 feature = "tracing",
1580 instrument(
1581 level = "debug",
1582 name = "CodegenBackend::run",
1583 skip_all,
1584 fields(
1585 compiler = ?self.compiler,
1586 target = ?self.target,
1587 backend = ?self.target,
1588 ),
1589 ),
1590 )]
1591 fn run(self, builder: &Builder<'_>) {
1592 let compiler = self.compiler;
1593 let target = self.target;
1594 let backend = self.backend;
1595
1596 builder.ensure(Rustc::new(compiler, target));
1597
1598 if builder.config.keep_stage.contains(&compiler.stage) {
1599 trace!("`keep-stage` requested");
1600 builder.info(
1601 "WARNING: Using a potentially old codegen backend. \
1602 This may not behave well.",
1603 );
1604 return;
1607 }
1608
1609 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1610 if compiler_to_use != compiler {
1611 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1612 return;
1613 }
1614
1615 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1616
1617 let mut cargo = builder::Cargo::new(
1618 builder,
1619 compiler,
1620 Mode::Codegen,
1621 SourceType::InTree,
1622 target,
1623 Kind::Build,
1624 );
1625 cargo
1626 .arg("--manifest-path")
1627 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1628 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1629
1630 if backend == "gcc" {
1634 let gcc = builder.ensure(Gcc { target });
1635 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1636 }
1637
1638 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1639
1640 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1641 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1642 if builder.config.dry_run() {
1643 return;
1644 }
1645 let mut files = files.into_iter().filter(|f| {
1646 let filename = f.file_name().unwrap().to_str().unwrap();
1647 is_dylib(f) && filename.contains("rustc_codegen_")
1648 });
1649 let codegen_backend = match files.next() {
1650 Some(f) => f,
1651 None => panic!("no dylibs built for codegen backend?"),
1652 };
1653 if let Some(f) = files.next() {
1654 panic!(
1655 "codegen backend built two dylibs:\n{}\n{}",
1656 codegen_backend.display(),
1657 f.display()
1658 );
1659 }
1660 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1661 let codegen_backend = codegen_backend.to_str().unwrap();
1662 t!(stamp.add_stamp(codegen_backend).write());
1663 }
1664}
1665
1666fn copy_codegen_backends_to_sysroot(
1673 builder: &Builder<'_>,
1674 compiler: Compiler,
1675 target_compiler: Compiler,
1676) {
1677 let target = target_compiler.host;
1678
1679 let dst = builder.sysroot_codegen_backends(target_compiler);
1688 t!(fs::create_dir_all(&dst), dst);
1689
1690 if builder.config.dry_run() {
1691 return;
1692 }
1693
1694 for backend in builder.config.codegen_backends(target) {
1695 if backend == "llvm" {
1696 continue; }
1698
1699 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1700 let dylib = t!(fs::read_to_string(stamp.path()));
1701 let file = Path::new(&dylib);
1702 let filename = file.file_name().unwrap().to_str().unwrap();
1703 let target_filename = {
1706 let dash = filename.find('-').unwrap();
1707 let dot = filename.find('.').unwrap();
1708 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1709 };
1710 builder.copy_link(file, &dst.join(target_filename));
1711 }
1712}
1713
1714pub fn compiler_file(
1715 builder: &Builder<'_>,
1716 compiler: &Path,
1717 target: TargetSelection,
1718 c: CLang,
1719 file: &str,
1720) -> PathBuf {
1721 if builder.config.dry_run() {
1722 return PathBuf::new();
1723 }
1724 let mut cmd = command(compiler);
1725 cmd.args(builder.cc_handled_clags(target, c));
1726 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1727 cmd.arg(format!("-print-file-name={file}"));
1728 let out = cmd.run_capture_stdout(builder).stdout();
1729 PathBuf::from(out.trim())
1730}
1731
1732#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1733pub struct Sysroot {
1734 pub compiler: Compiler,
1735 force_recompile: bool,
1737}
1738
1739impl Sysroot {
1740 pub(crate) fn new(compiler: Compiler) -> Self {
1741 Sysroot { compiler, force_recompile: false }
1742 }
1743}
1744
1745impl Step for Sysroot {
1746 type Output = PathBuf;
1747
1748 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1749 run.never()
1750 }
1751
1752 #[cfg_attr(
1756 feature = "tracing",
1757 instrument(
1758 level = "debug",
1759 name = "Sysroot::run",
1760 skip_all,
1761 fields(compiler = ?self.compiler),
1762 ),
1763 )]
1764 fn run(self, builder: &Builder<'_>) -> PathBuf {
1765 let compiler = self.compiler;
1766 let host_dir = builder.out.join(compiler.host);
1767
1768 let sysroot_dir = |stage| {
1769 if stage == 0 {
1770 host_dir.join("stage0-sysroot")
1771 } else if self.force_recompile && stage == compiler.stage {
1772 host_dir.join(format!("stage{stage}-test-sysroot"))
1773 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1774 host_dir.join("ci-rustc-sysroot")
1775 } else {
1776 host_dir.join(format!("stage{}", stage))
1777 }
1778 };
1779 let sysroot = sysroot_dir(compiler.stage);
1780 trace!(stage = ?compiler.stage, ?sysroot);
1781
1782 builder
1783 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1784 let _ = fs::remove_dir_all(&sysroot);
1785 t!(fs::create_dir_all(&sysroot));
1786
1787 if compiler.stage == 0 {
1794 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1795 }
1796
1797 if builder.download_rustc() && compiler.stage != 0 {
1799 assert_eq!(
1800 builder.config.build, compiler.host,
1801 "Cross-compiling is not yet supported with `download-rustc`",
1802 );
1803
1804 for stage in 0..=2 {
1806 if stage != compiler.stage {
1807 let dir = sysroot_dir(stage);
1808 if !dir.ends_with("ci-rustc-sysroot") {
1809 let _ = fs::remove_dir_all(dir);
1810 }
1811 }
1812 }
1813
1814 let mut filtered_files = Vec::new();
1824 let mut add_filtered_files = |suffix, contents| {
1825 for path in contents {
1826 let path = Path::new(&path);
1827 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1828 filtered_files.push(path.file_name().unwrap().to_owned());
1829 }
1830 }
1831 };
1832 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1833 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1834 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1837
1838 let filtered_extensions = [
1839 OsStr::new("rmeta"),
1840 OsStr::new("rlib"),
1841 OsStr::new(std::env::consts::DLL_EXTENSION),
1843 ];
1844 let ci_rustc_dir = builder.config.ci_rustc_dir();
1845 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1846 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1847 return true;
1848 }
1849 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1850 return true;
1851 }
1852 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1853 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1854 false
1855 } else {
1856 true
1857 }
1858 });
1859 }
1860
1861 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1867 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1868 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1869 if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
1870 eprintln!(
1871 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1872 sysroot_lib_rustlib_src_rust.display(),
1873 builder.src.display(),
1874 e,
1875 );
1876 if builder.config.rust_remap_debuginfo {
1877 eprintln!(
1878 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1879 sysroot_lib_rustlib_src_rust.display(),
1880 );
1881 }
1882 build_helper::exit!(1);
1883 }
1884
1885 if !builder.download_rustc() {
1887 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1888 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1889 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1890 if let Err(e) =
1891 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1892 {
1893 eprintln!(
1894 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1895 sysroot_lib_rustlib_rustcsrc_rust.display(),
1896 builder.src.display(),
1897 e,
1898 );
1899 build_helper::exit!(1);
1900 }
1901 }
1902
1903 sysroot
1904 }
1905}
1906
1907#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1908pub struct Assemble {
1909 pub target_compiler: Compiler,
1914}
1915
1916impl Step for Assemble {
1917 type Output = Compiler;
1918 const ONLY_HOSTS: bool = true;
1919
1920 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1921 run.path("compiler/rustc").path("compiler")
1922 }
1923
1924 fn make_run(run: RunConfig<'_>) {
1925 run.builder.ensure(Assemble {
1926 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1927 });
1928 }
1929
1930 #[cfg_attr(
1936 feature = "tracing",
1937 instrument(
1938 level = "debug",
1939 name = "Assemble::run",
1940 skip_all,
1941 fields(target_compiler = ?self.target_compiler),
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.build, 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 if src_path.exists() {
1992 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
1999 }
2000 }
2001 }
2002 }
2003
2004 let maybe_install_llvm_bitcode_linker = |compiler| {
2005 if builder.config.llvm_bitcode_linker_enabled {
2006 trace!("llvm-bitcode-linker enabled, installing");
2007 let llvm_bitcode_linker =
2008 builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
2009 compiler,
2010 target: target_compiler.host,
2011 extra_features: vec![],
2012 });
2013 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2014 builder.copy_link(&llvm_bitcode_linker.tool_path, &libdir_bin.join(tool_exe));
2015 }
2016 };
2017
2018 if builder.download_rustc() {
2020 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2021
2022 builder.ensure(Std::new(target_compiler, target_compiler.host));
2023 let sysroot =
2024 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2025 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2028 if target_compiler.stage == builder.top_stage {
2030 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage=target_compiler.stage));
2031 }
2032
2033 let mut precompiled_compiler = target_compiler;
2034 precompiled_compiler.forced_compiler(true);
2035 maybe_install_llvm_bitcode_linker(precompiled_compiler);
2036
2037 return target_compiler;
2038 }
2039
2040 debug!(
2054 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2055 target_compiler.stage - 1,
2056 builder.config.build,
2057 );
2058 let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
2059
2060 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2062 debug!("`llvm_enzyme` requested");
2063 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2064 let llvm_config = builder.llvm_config(builder.config.build).unwrap();
2065 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2066 let lib_ext = std::env::consts::DLL_EXTENSION;
2067 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2068 let src_lib =
2069 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2070 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2071 let target_libdir =
2072 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2073 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2074 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2075 builder.copy_link(&src_lib, &dst_lib);
2076 builder.copy_link(&src_lib, &target_dst_lib);
2077 }
2078
2079 debug!(
2085 ?build_compiler,
2086 "target_compiler.host" = ?target_compiler.host,
2087 "building compiler libraries to link to"
2088 );
2089 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2090 debug!(
2093 "(old) build_compiler.stage" = build_compiler.stage,
2094 "(adjusted) build_compiler.stage" = actual_stage,
2095 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2096 );
2097 build_compiler.stage = actual_stage;
2098
2099 #[cfg(feature = "tracing")]
2100 let _codegen_backend_span =
2101 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2102 for backend in builder.config.codegen_backends(target_compiler.host) {
2103 if backend == "llvm" {
2104 debug!("llvm codegen backend is already built as part of rustc");
2105 continue; }
2107
2108 builder.ensure(CodegenBackend {
2109 compiler: build_compiler,
2110 target: target_compiler.host,
2111 backend: backend.clone(),
2112 });
2113 }
2114 #[cfg(feature = "tracing")]
2115 drop(_codegen_backend_span);
2116
2117 let stage = target_compiler.stage;
2118 let host = target_compiler.host;
2119 let (host_info, dir_name) = if build_compiler.host == host {
2120 ("".into(), "host".into())
2121 } else {
2122 (format!(" ({host})"), host.to_string())
2123 };
2124 let msg = format!(
2129 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2130 );
2131 builder.info(&msg);
2132
2133 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2135 let proc_macros = builder
2136 .read_stamp_file(&stamp)
2137 .into_iter()
2138 .filter_map(|(path, dependency_type)| {
2139 if dependency_type == DependencyType::Host {
2140 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2141 } else {
2142 None
2143 }
2144 })
2145 .collect::<HashSet<_>>();
2146
2147 let sysroot = builder.sysroot(target_compiler);
2148 let rustc_libdir = builder.rustc_libdir(target_compiler);
2149 t!(fs::create_dir_all(&rustc_libdir));
2150 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2151 for f in builder.read_dir(&src_libdir) {
2152 let filename = f.file_name().into_string().unwrap();
2153
2154 let is_proc_macro = proc_macros.contains(&filename);
2155 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2156
2157 let can_be_rustc_dynamic_dep = if builder
2161 .link_std_into_rustc_driver(target_compiler.host)
2162 && !target_compiler.host.is_windows()
2163 {
2164 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2165 !is_std
2166 } else {
2167 true
2168 };
2169
2170 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2171 builder.copy_link(&f.path(), &rustc_libdir.join(&filename));
2172 }
2173 }
2174
2175 debug!("copying codegen backends to sysroot");
2176 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2177
2178 if builder.config.lld_enabled {
2179 builder.ensure(crate::core::build_steps::tool::LldWrapper {
2180 build_compiler,
2181 target_compiler,
2182 });
2183 }
2184
2185 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2186 debug!(
2187 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2188 workaround faulty homebrew `strip`s"
2189 );
2190
2191 let src_exe = exe("llvm-objcopy", target_compiler.host);
2198 let dst_exe = exe("rust-objcopy", target_compiler.host);
2199 builder.copy_link(&libdir_bin.join(src_exe), &libdir_bin.join(dst_exe));
2200 }
2201
2202 if builder.tool_enabled("wasm-component-ld") {
2208 let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
2209 compiler: build_compiler,
2210 target: target_compiler.host,
2211 });
2212 builder.copy_link(
2213 &wasm_component.tool_path,
2214 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2215 );
2216 }
2217
2218 maybe_install_llvm_bitcode_linker(target_compiler);
2219
2220 debug!(
2223 "target_compiler.host" = ?target_compiler.host,
2224 ?sysroot,
2225 "ensuring availability of `libLLVM.so` in compiler directory"
2226 );
2227 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2228 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2229
2230 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2232 let rustc = out_dir.join(exe("rustc-main", host));
2233 let bindir = sysroot.join("bin");
2234 t!(fs::create_dir_all(bindir));
2235 let compiler = builder.rustc(target_compiler);
2236 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2237 builder.copy_link(&rustc, &compiler);
2238
2239 target_compiler
2240 }
2241}
2242
2243pub fn add_to_sysroot(
2248 builder: &Builder<'_>,
2249 sysroot_dst: &Path,
2250 sysroot_host_dst: &Path,
2251 stamp: &BuildStamp,
2252) {
2253 let self_contained_dst = &sysroot_dst.join("self-contained");
2254 t!(fs::create_dir_all(sysroot_dst));
2255 t!(fs::create_dir_all(sysroot_host_dst));
2256 t!(fs::create_dir_all(self_contained_dst));
2257 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2258 let dst = match dependency_type {
2259 DependencyType::Host => sysroot_host_dst,
2260 DependencyType::Target => sysroot_dst,
2261 DependencyType::TargetSelfContained => self_contained_dst,
2262 };
2263 builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
2264 }
2265}
2266
2267pub fn run_cargo(
2268 builder: &Builder<'_>,
2269 cargo: Cargo,
2270 tail_args: Vec<String>,
2271 stamp: &BuildStamp,
2272 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2273 is_check: bool,
2274 rlib_only_metadata: bool,
2275) -> Vec<PathBuf> {
2276 let target_root_dir = stamp.path().parent().unwrap();
2278 let target_deps_dir = target_root_dir.join("deps");
2280 let host_root_dir = target_root_dir
2282 .parent()
2283 .unwrap() .parent()
2285 .unwrap() .join(target_root_dir.file_name().unwrap());
2287
2288 let mut deps = Vec::new();
2292 let mut toplevel = Vec::new();
2293 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2294 let (filenames, crate_types) = match msg {
2295 CargoMessage::CompilerArtifact {
2296 filenames,
2297 target: CargoTarget { crate_types },
2298 ..
2299 } => (filenames, crate_types),
2300 _ => return,
2301 };
2302 for filename in filenames {
2303 let mut keep = false;
2305 if filename.ends_with(".lib")
2306 || filename.ends_with(".a")
2307 || is_debug_info(&filename)
2308 || is_dylib(Path::new(&*filename))
2309 {
2310 keep = true;
2312 }
2313 if is_check && filename.ends_with(".rmeta") {
2314 keep = true;
2316 } else if rlib_only_metadata {
2317 if filename.contains("jemalloc_sys")
2318 || filename.contains("rustc_smir")
2319 || filename.contains("stable_mir")
2320 {
2321 keep |= filename.ends_with(".rlib");
2324 } else {
2325 keep |= filename.ends_with(".rmeta");
2329 }
2330 } else {
2331 keep |= filename.ends_with(".rlib");
2333 }
2334
2335 if !keep {
2336 continue;
2337 }
2338
2339 let filename = Path::new(&*filename);
2340
2341 if filename.starts_with(&host_root_dir) {
2344 if crate_types.iter().any(|t| t == "proc-macro") {
2346 deps.push((filename.to_path_buf(), DependencyType::Host));
2347 }
2348 continue;
2349 }
2350
2351 if filename.starts_with(&target_deps_dir) {
2354 deps.push((filename.to_path_buf(), DependencyType::Target));
2355 continue;
2356 }
2357
2358 let expected_len = t!(filename.metadata()).len();
2369 let filename = filename.file_name().unwrap().to_str().unwrap();
2370 let mut parts = filename.splitn(2, '.');
2371 let file_stem = parts.next().unwrap().to_owned();
2372 let extension = parts.next().unwrap().to_owned();
2373
2374 toplevel.push((file_stem, extension, expected_len));
2375 }
2376 });
2377
2378 if !ok {
2379 crate::exit!(1);
2380 }
2381
2382 if builder.config.dry_run() {
2383 return Vec::new();
2384 }
2385
2386 let contents = t!(target_deps_dir.read_dir())
2390 .map(|e| t!(e))
2391 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2392 .collect::<Vec<_>>();
2393 for (prefix, extension, expected_len) in toplevel {
2394 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2395 meta.len() == expected_len
2396 && filename
2397 .strip_prefix(&prefix[..])
2398 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2399 .unwrap_or(false)
2400 });
2401 let max = candidates.max_by_key(|&(_, _, metadata)| {
2402 metadata.modified().expect("mtime should be available on all relevant OSes")
2403 });
2404 let path_to_add = match max {
2405 Some(triple) => triple.0.to_str().unwrap(),
2406 None => panic!("no output generated for {prefix:?} {extension:?}"),
2407 };
2408 if is_dylib(Path::new(path_to_add)) {
2409 let candidate = format!("{path_to_add}.lib");
2410 let candidate = PathBuf::from(candidate);
2411 if candidate.exists() {
2412 deps.push((candidate, DependencyType::Target));
2413 }
2414 }
2415 deps.push((path_to_add.into(), DependencyType::Target));
2416 }
2417
2418 deps.extend(additional_target_deps);
2419 deps.sort();
2420 let mut new_contents = Vec::new();
2421 for (dep, dependency_type) in deps.iter() {
2422 new_contents.extend(match *dependency_type {
2423 DependencyType::Host => b"h",
2424 DependencyType::Target => b"t",
2425 DependencyType::TargetSelfContained => b"s",
2426 });
2427 new_contents.extend(dep.to_str().unwrap().as_bytes());
2428 new_contents.extend(b"\0");
2429 }
2430 t!(fs::write(stamp.path(), &new_contents));
2431 deps.into_iter().map(|(d, _)| d).collect()
2432}
2433
2434pub fn stream_cargo(
2435 builder: &Builder<'_>,
2436 cargo: Cargo,
2437 tail_args: Vec<String>,
2438 cb: &mut dyn FnMut(CargoMessage<'_>),
2439) -> bool {
2440 let mut cmd = cargo.into_cmd();
2441
2442 #[cfg(feature = "tracing")]
2443 let _run_span = crate::trace_cmd!(cmd);
2444
2445 let cargo = cmd.as_command_mut();
2446 let mut message_format = if builder.config.json_output {
2449 String::from("json")
2450 } else {
2451 String::from("json-render-diagnostics")
2452 };
2453 if let Some(s) = &builder.config.rustc_error_format {
2454 message_format.push_str(",json-diagnostic-");
2455 message_format.push_str(s);
2456 }
2457 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
2458
2459 for arg in tail_args {
2460 cargo.arg(arg);
2461 }
2462
2463 builder.verbose(|| println!("running: {cargo:?}"));
2464
2465 if builder.config.dry_run() {
2466 return true;
2467 }
2468
2469 let mut child = match cargo.spawn() {
2470 Ok(child) => child,
2471 Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"),
2472 };
2473
2474 let stdout = BufReader::new(child.stdout.take().unwrap());
2478 for line in stdout.lines() {
2479 let line = t!(line);
2480 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2481 Ok(msg) => {
2482 if builder.config.json_output {
2483 println!("{line}");
2485 }
2486 cb(msg)
2487 }
2488 Err(_) => println!("{line}"),
2490 }
2491 }
2492
2493 let status = t!(child.wait());
2495 if builder.is_verbose() && !status.success() {
2496 eprintln!(
2497 "command did not execute successfully: {cargo:?}\n\
2498 expected success, got: {status}"
2499 );
2500 }
2501 status.success()
2502}
2503
2504#[derive(Deserialize)]
2505pub struct CargoTarget<'a> {
2506 crate_types: Vec<Cow<'a, str>>,
2507}
2508
2509#[derive(Deserialize)]
2510#[serde(tag = "reason", rename_all = "kebab-case")]
2511pub enum CargoMessage<'a> {
2512 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2513 BuildScriptExecuted,
2514 BuildFinished,
2515}
2516
2517pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2518 if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(target) || !path.exists()
2522 {
2523 return;
2524 }
2525
2526 let previous_mtime = t!(t!(path.metadata()).modified());
2527 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2528
2529 let file = t!(fs::File::open(path));
2530
2531 t!(file.set_modified(previous_mtime));
2544}
2545
2546pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2548 build_compiler.stage != 0
2549}