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.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, FileType::Regular);
325
326 target_deps.push((target, dependency_type));
327}
328
329fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
330 let libunwind_path = builder.ensure(llvm::Libunwind { target });
331 let libunwind_source = libunwind_path.join("libunwind.a");
332 let libunwind_target = libdir.join("libunwind.a");
333 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
334 libunwind_target
335}
336
337fn copy_third_party_objects(
339 builder: &Builder<'_>,
340 compiler: &Compiler,
341 target: TargetSelection,
342) -> Vec<(PathBuf, DependencyType)> {
343 let mut target_deps = vec![];
344
345 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
346 target_deps.extend(
349 copy_sanitizers(builder, compiler, target)
350 .into_iter()
351 .map(|d| (d, DependencyType::Target)),
352 );
353 }
354
355 if target == "x86_64-fortanix-unknown-sgx"
356 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
357 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
358 {
359 let libunwind_path =
360 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
361 target_deps.push((libunwind_path, DependencyType::Target));
362 }
363
364 target_deps
365}
366
367fn copy_self_contained_objects(
369 builder: &Builder<'_>,
370 compiler: &Compiler,
371 target: TargetSelection,
372) -> Vec<(PathBuf, DependencyType)> {
373 let libdir_self_contained =
374 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
375 t!(fs::create_dir_all(&libdir_self_contained));
376 let mut target_deps = vec![];
377
378 if target.needs_crt_begin_end() {
386 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
387 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
388 });
389 if !target.starts_with("wasm32") {
390 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
391 copy_and_stamp(
392 builder,
393 &libdir_self_contained,
394 &srcdir,
395 obj,
396 &mut target_deps,
397 DependencyType::TargetSelfContained,
398 );
399 }
400 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
401 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
402 let src = crt_path.join(obj);
403 let target = libdir_self_contained.join(obj);
404 builder.copy_link(&src, &target, FileType::NativeLibrary);
405 target_deps.push((target, DependencyType::TargetSelfContained));
406 }
407 } else {
408 for &obj in &["libc.a", "crt1-command.o"] {
411 copy_and_stamp(
412 builder,
413 &libdir_self_contained,
414 &srcdir,
415 obj,
416 &mut target_deps,
417 DependencyType::TargetSelfContained,
418 );
419 }
420 }
421 if !target.starts_with("s390x") {
422 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
423 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
424 }
425 } else if target.contains("-wasi") {
426 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
427 panic!(
428 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
429 or `$WASI_SDK_PATH` set",
430 target.triple
431 )
432 });
433 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 dst = libdir_self_contained.join(obj);
447 builder.copy_link(&src, &dst, FileType::NativeLibrary);
448 target_deps.push((dst, 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.copy_link(
794 &path,
795 &sysroot.join("lib").join(path.file_name().unwrap()),
796 FileType::Regular,
797 );
798 }
799 }
800 }
801
802 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
804 t!(fs::create_dir_all(&sysroot_codegen_backends));
805 let stage0_codegen_backends = builder
806 .out
807 .join(host)
808 .join("stage0/lib/rustlib")
809 .join(host)
810 .join("codegen-backends");
811 if stage0_codegen_backends.exists() {
812 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
813 }
814 }
815 }
816}
817
818fn copy_sanitizers(
820 builder: &Builder<'_>,
821 compiler: &Compiler,
822 target: TargetSelection,
823) -> Vec<PathBuf> {
824 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
825
826 if builder.config.dry_run() {
827 return Vec::new();
828 }
829
830 let mut target_deps = Vec::new();
831 let libdir = builder.sysroot_target_libdir(*compiler, target);
832
833 for runtime in &runtimes {
834 let dst = libdir.join(&runtime.name);
835 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
836
837 if target == "x86_64-apple-darwin"
841 || target == "aarch64-apple-darwin"
842 || target == "aarch64-apple-ios"
843 || target == "aarch64-apple-ios-sim"
844 || target == "x86_64-apple-ios"
845 {
846 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
848 apple_darwin_sign_file(builder, &dst);
851 }
852
853 target_deps.push(dst);
854 }
855
856 target_deps
857}
858
859fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
860 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
861}
862
863fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
864 command("codesign")
865 .arg("-f") .arg("-s")
867 .arg("-")
868 .arg(file_path)
869 .run(builder);
870}
871
872#[derive(Debug, Clone, PartialEq, Eq, Hash)]
873pub struct StartupObjects {
874 pub compiler: Compiler,
875 pub target: TargetSelection,
876}
877
878impl Step for StartupObjects {
879 type Output = Vec<(PathBuf, DependencyType)>;
880
881 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
882 run.path("library/rtstartup")
883 }
884
885 fn make_run(run: RunConfig<'_>) {
886 run.builder.ensure(StartupObjects {
887 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
888 target: run.target,
889 });
890 }
891
892 #[cfg_attr(
899 feature = "tracing",
900 instrument(
901 level = "trace",
902 name = "StartupObjects::run",
903 skip_all,
904 fields(compiler = ?self.compiler, target = ?self.target),
905 ),
906 )]
907 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
908 let for_compiler = self.compiler;
909 let target = self.target;
910 if !target.is_windows_gnu() {
911 return vec![];
912 }
913
914 let mut target_deps = vec![];
915
916 let src_dir = &builder.src.join("library").join("rtstartup");
917 let dst_dir = &builder.native_dir(target).join("rtstartup");
918 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
919 t!(fs::create_dir_all(dst_dir));
920
921 for file in &["rsbegin", "rsend"] {
922 let src_file = &src_dir.join(file.to_string() + ".rs");
923 let dst_file = &dst_dir.join(file.to_string() + ".o");
924 if !up_to_date(src_file, dst_file) {
925 let mut cmd = command(&builder.initial_rustc);
926 cmd.env("RUSTC_BOOTSTRAP", "1");
927 if !builder.local_rebuild {
928 cmd.arg("--cfg").arg("bootstrap");
930 }
931 cmd.arg("--target")
932 .arg(target.rustc_target_arg())
933 .arg("--emit=obj")
934 .arg("-o")
935 .arg(dst_file)
936 .arg(src_file)
937 .run(builder);
938 }
939
940 let obj = sysroot_dir.join((*file).to_string() + ".o");
941 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
942 target_deps.push((obj, DependencyType::Target));
943 }
944
945 target_deps
946 }
947}
948
949fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
950 let ci_rustc_dir = builder.config.ci_rustc_dir();
951
952 for file in contents {
953 let src = ci_rustc_dir.join(&file);
954 let dst = sysroot.join(file);
955 if src.is_dir() {
956 t!(fs::create_dir_all(dst));
957 } else {
958 builder.copy_link(&src, &dst, FileType::Regular);
959 }
960 }
961}
962
963#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
964pub struct Rustc {
965 pub target: TargetSelection,
966 pub compiler: Compiler,
968 crates: Vec<String>,
974}
975
976impl Rustc {
977 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
978 Self { target, compiler, crates: Default::default() }
979 }
980}
981
982impl Step for Rustc {
983 type Output = u32;
991 const ONLY_HOSTS: bool = true;
992 const DEFAULT: bool = false;
993
994 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
995 let mut crates = run.builder.in_tree_crates("rustc-main", None);
996 for (i, krate) in crates.iter().enumerate() {
997 if krate.name == "rustc-main" {
1000 crates.swap_remove(i);
1001 break;
1002 }
1003 }
1004 run.crates(crates)
1005 }
1006
1007 fn make_run(run: RunConfig<'_>) {
1008 let crates = run.cargo_crates_in_set();
1009 run.builder.ensure(Rustc {
1010 compiler: run
1011 .builder
1012 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1013 target: run.target,
1014 crates,
1015 });
1016 }
1017
1018 #[cfg_attr(
1024 feature = "tracing",
1025 instrument(
1026 level = "debug",
1027 name = "Rustc::run",
1028 skip_all,
1029 fields(previous_compiler = ?self.compiler, target = ?self.target),
1030 ),
1031 )]
1032 fn run(self, builder: &Builder<'_>) -> u32 {
1033 let compiler = self.compiler;
1034 let target = self.target;
1035
1036 if builder.download_rustc() && compiler.stage != 0 {
1039 trace!(stage = compiler.stage, "`download_rustc` requested");
1040
1041 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
1042 cp_rustc_component_to_ci_sysroot(
1043 builder,
1044 &sysroot,
1045 builder.config.ci_rustc_dev_contents(),
1046 );
1047 return compiler.stage;
1048 }
1049
1050 builder.ensure(Std::new(compiler, target));
1051
1052 if builder.config.keep_stage.contains(&compiler.stage) {
1053 trace!(stage = compiler.stage, "`keep-stage` requested");
1054
1055 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1056 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1057 builder.ensure(RustcLink::from_rustc(self, compiler));
1058
1059 return compiler.stage;
1060 }
1061
1062 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1063 if compiler_to_use != compiler {
1064 builder.ensure(Rustc::new(compiler_to_use, target));
1065 let msg = if compiler_to_use.host == target {
1066 format!(
1067 "Uplifting rustc (stage{} -> stage{})",
1068 compiler_to_use.stage,
1069 compiler.stage + 1
1070 )
1071 } else {
1072 format!(
1073 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1074 compiler_to_use.stage,
1075 compiler_to_use.host,
1076 compiler.stage + 1,
1077 target
1078 )
1079 };
1080 builder.info(&msg);
1081 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1082 return compiler_to_use.stage;
1083 }
1084
1085 builder.ensure(Std::new(
1087 builder.compiler(self.compiler.stage, builder.config.build),
1088 builder.config.build,
1089 ));
1090
1091 let mut cargo = builder::Cargo::new(
1092 builder,
1093 compiler,
1094 Mode::Rustc,
1095 SourceType::InTree,
1096 target,
1097 Kind::Build,
1098 );
1099
1100 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
1101
1102 for krate in &*self.crates {
1106 cargo.arg("-p").arg(krate);
1107 }
1108
1109 if builder.build.config.enable_bolt_settings && compiler.stage == 1 {
1110 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1112 }
1113
1114 let _guard = builder.msg_sysroot_tool(
1115 Kind::Build,
1116 compiler.stage,
1117 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1118 compiler.host,
1119 target,
1120 );
1121 let stamp = build_stamp::librustc_stamp(builder, compiler, target);
1122 run_cargo(
1123 builder,
1124 cargo,
1125 vec![],
1126 &stamp,
1127 vec![],
1128 false,
1129 true, );
1131
1132 let target_root_dir = stamp.path().parent().unwrap();
1133 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1139 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1140 {
1141 let rustc_driver = target_root_dir.join("librustc_driver.so");
1142 strip_debug(builder, target, &rustc_driver);
1143 }
1144
1145 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1146 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1149 }
1150
1151 builder.ensure(RustcLink::from_rustc(
1152 self,
1153 builder.compiler(compiler.stage, builder.config.build),
1154 ));
1155
1156 compiler.stage
1157 }
1158}
1159
1160pub fn rustc_cargo(
1161 builder: &Builder<'_>,
1162 cargo: &mut Cargo,
1163 target: TargetSelection,
1164 compiler: &Compiler,
1165 crates: &[String],
1166) {
1167 cargo
1168 .arg("--features")
1169 .arg(builder.rustc_features(builder.kind, target, crates))
1170 .arg("--manifest-path")
1171 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1172
1173 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1174
1175 cargo.rustflag("-Zon-broken-pipe=kill");
1189
1190 if builder.config.llvm_enzyme {
1193 let arch = builder.build.build;
1194 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1195 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1196
1197 if !builder.config.dry_run() {
1198 let llvm_config = builder.llvm_config(builder.config.build).unwrap();
1199 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1200 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1201 }
1202 }
1203
1204 if builder.build.config.lld_mode.is_used() {
1209 cargo.rustflag("-Zdefault-visibility=protected");
1210 }
1211
1212 if is_lto_stage(compiler) {
1213 match builder.config.rust_lto {
1214 RustcLto::Thin | RustcLto::Fat => {
1215 cargo.rustflag("-Zdylib-lto");
1218 let lto_type = match builder.config.rust_lto {
1222 RustcLto::Thin => "thin",
1223 RustcLto::Fat => "fat",
1224 _ => unreachable!(),
1225 };
1226 cargo.rustflag(&format!("-Clto={lto_type}"));
1227 cargo.rustflag("-Cembed-bitcode=yes");
1228 }
1229 RustcLto::ThinLocal => { }
1230 RustcLto::Off => {
1231 cargo.rustflag("-Clto=off");
1232 }
1233 }
1234 } else if builder.config.rust_lto == RustcLto::Off {
1235 cargo.rustflag("-Clto=off");
1236 }
1237
1238 if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
1246 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1247 }
1248
1249 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1250 panic!("Cannot use and generate PGO profiles at the same time");
1251 }
1252 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1253 if compiler.stage == 1 {
1254 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1255 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1258 true
1259 } else {
1260 false
1261 }
1262 } else if let Some(path) = &builder.config.rust_profile_use {
1263 if compiler.stage == 1 {
1264 cargo.rustflag(&format!("-Cprofile-use={path}"));
1265 if builder.is_verbose() {
1266 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1267 }
1268 true
1269 } else {
1270 false
1271 }
1272 } else {
1273 false
1274 };
1275 if is_collecting {
1276 cargo.rustflag(&format!(
1278 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1279 builder.config.src.components().count()
1280 ));
1281 }
1282
1283 rustc_cargo_env(builder, cargo, target, compiler.stage);
1284}
1285
1286pub fn rustc_cargo_env(
1287 builder: &Builder<'_>,
1288 cargo: &mut Cargo,
1289 target: TargetSelection,
1290 stage: u32,
1291) {
1292 cargo
1295 .env("CFG_RELEASE", builder.rust_release())
1296 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1297 .env("CFG_VERSION", builder.rust_version());
1298
1299 if builder.config.omit_git_hash {
1303 cargo.env("CFG_OMIT_GIT_HASH", "1");
1304 }
1305
1306 if let Some(backend) = builder.config.default_codegen_backend(target) {
1307 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1308 }
1309
1310 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1311 let target_config = builder.config.target_config.get(&target);
1312
1313 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1314
1315 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1316 cargo.env("CFG_VER_DATE", ver_date);
1317 }
1318 if let Some(ref ver_hash) = builder.rust_info().sha() {
1319 cargo.env("CFG_VER_HASH", ver_hash);
1320 }
1321 if !builder.unstable_features() {
1322 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1323 }
1324
1325 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1328 cargo.env("CFG_DEFAULT_LINKER", s);
1329 } else if let Some(ref s) = builder.config.rustc_default_linker {
1330 cargo.env("CFG_DEFAULT_LINKER", s);
1331 }
1332
1333 if builder.config.lld_enabled
1335 && (builder.config.channel == "dev" || builder.config.channel == "nightly")
1336 {
1337 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1338 }
1339
1340 if builder.config.rust_verify_llvm_ir {
1341 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1342 }
1343
1344 if builder.config.llvm_enzyme {
1345 cargo.rustflag("--cfg=llvm_enzyme");
1346 }
1347
1348 if builder.config.llvm_enabled(target) {
1353 let building_is_expensive =
1354 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1355 .should_build();
1356 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage;
1358 let should_skip_build = building_is_expensive && can_skip_build;
1359 if !should_skip_build {
1360 rustc_llvm_env(builder, cargo, target)
1361 }
1362 }
1363
1364 if builder.config.jemalloc(target)
1367 && target.starts_with("aarch64")
1368 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1369 {
1370 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1371 }
1372}
1373
1374fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1377 if builder.is_rust_llvm(target) {
1378 cargo.env("LLVM_RUSTLLVM", "1");
1379 }
1380 if builder.config.llvm_enzyme {
1381 cargo.env("LLVM_ENZYME", "1");
1382 }
1383 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1384 cargo.env("LLVM_CONFIG", &llvm_config);
1385
1386 let mut llvm_linker_flags = String::new();
1396 if builder.config.llvm_profile_generate && target.is_msvc() {
1397 if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
1398 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1400 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1401 }
1402 }
1403
1404 if let Some(ref s) = builder.config.llvm_ldflags {
1406 if !llvm_linker_flags.is_empty() {
1407 llvm_linker_flags.push(' ');
1408 }
1409 llvm_linker_flags.push_str(s);
1410 }
1411
1412 if !llvm_linker_flags.is_empty() {
1414 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1415 }
1416
1417 if builder.config.llvm_static_stdcpp
1420 && !target.contains("freebsd")
1421 && !target.is_msvc()
1422 && !target.contains("apple")
1423 && !target.contains("solaris")
1424 {
1425 let file = compiler_file(
1426 builder,
1427 &builder.cxx(target).unwrap(),
1428 target,
1429 CLang::Cxx,
1430 "libstdc++.a",
1431 );
1432 cargo.env("LLVM_STATIC_STDCPP", file);
1433 }
1434 if builder.llvm_link_shared() {
1435 cargo.env("LLVM_LINK_SHARED", "1");
1436 }
1437 if builder.config.llvm_use_libcxx {
1438 cargo.env("LLVM_USE_LIBCXX", "1");
1439 }
1440 if builder.config.llvm_assertions {
1441 cargo.env("LLVM_ASSERTIONS", "1");
1442 }
1443}
1444
1445#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1451struct RustcLink {
1452 pub compiler: Compiler,
1454 pub previous_stage_compiler: Compiler,
1456 pub target: TargetSelection,
1457 crates: Vec<String>,
1459}
1460
1461impl RustcLink {
1462 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1463 Self {
1464 compiler: host_compiler,
1465 previous_stage_compiler: rustc.compiler,
1466 target: rustc.target,
1467 crates: rustc.crates,
1468 }
1469 }
1470}
1471
1472impl Step for RustcLink {
1473 type Output = ();
1474
1475 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1476 run.never()
1477 }
1478
1479 #[cfg_attr(
1481 feature = "tracing",
1482 instrument(
1483 level = "trace",
1484 name = "RustcLink::run",
1485 skip_all,
1486 fields(
1487 compiler = ?self.compiler,
1488 previous_stage_compiler = ?self.previous_stage_compiler,
1489 target = ?self.target,
1490 ),
1491 ),
1492 )]
1493 fn run(self, builder: &Builder<'_>) {
1494 let compiler = self.compiler;
1495 let previous_stage_compiler = self.previous_stage_compiler;
1496 let target = self.target;
1497 add_to_sysroot(
1498 builder,
1499 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1500 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1501 &build_stamp::librustc_stamp(builder, compiler, target),
1502 );
1503 }
1504}
1505
1506#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1507pub struct CodegenBackend {
1508 pub target: TargetSelection,
1509 pub compiler: Compiler,
1510 pub backend: String,
1511}
1512
1513fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1514 let mut needs_codegen_cfg = false;
1515 for path_set in &run.paths {
1516 needs_codegen_cfg = match path_set {
1517 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1518 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1519 }
1520 }
1521 needs_codegen_cfg
1522}
1523
1524pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1525
1526fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1527 let path = path.path.to_str().unwrap();
1528
1529 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1530 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1531
1532 if path.contains(CODEGEN_BACKEND_PREFIX) {
1533 let mut needs_codegen_backend_config = true;
1534 for backend in run.builder.config.codegen_backends(run.target) {
1535 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1536 needs_codegen_backend_config = false;
1537 }
1538 }
1539 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1540 && needs_codegen_backend_config
1541 {
1542 run.builder.info(
1543 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1544 HELP: add backend to codegen-backends in bootstrap.toml.",
1545 );
1546 return true;
1547 }
1548 }
1549
1550 false
1551}
1552
1553impl Step for CodegenBackend {
1554 type Output = ();
1555 const ONLY_HOSTS: bool = true;
1556 const DEFAULT: bool = true;
1558
1559 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1560 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1561 }
1562
1563 fn make_run(run: RunConfig<'_>) {
1564 if needs_codegen_config(&run) {
1565 return;
1566 }
1567
1568 for backend in run.builder.config.codegen_backends(run.target) {
1569 if backend == "llvm" {
1570 continue; }
1572
1573 run.builder.ensure(CodegenBackend {
1574 target: run.target,
1575 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1576 backend: backend.clone(),
1577 });
1578 }
1579 }
1580
1581 #[cfg_attr(
1582 feature = "tracing",
1583 instrument(
1584 level = "debug",
1585 name = "CodegenBackend::run",
1586 skip_all,
1587 fields(
1588 compiler = ?self.compiler,
1589 target = ?self.target,
1590 backend = ?self.target,
1591 ),
1592 ),
1593 )]
1594 fn run(self, builder: &Builder<'_>) {
1595 let compiler = self.compiler;
1596 let target = self.target;
1597 let backend = self.backend;
1598
1599 builder.ensure(Rustc::new(compiler, target));
1600
1601 if builder.config.keep_stage.contains(&compiler.stage) {
1602 trace!("`keep-stage` requested");
1603 builder.info(
1604 "WARNING: Using a potentially old codegen backend. \
1605 This may not behave well.",
1606 );
1607 return;
1610 }
1611
1612 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1613 if compiler_to_use != compiler {
1614 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1615 return;
1616 }
1617
1618 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1619
1620 let mut cargo = builder::Cargo::new(
1621 builder,
1622 compiler,
1623 Mode::Codegen,
1624 SourceType::InTree,
1625 target,
1626 Kind::Build,
1627 );
1628 cargo
1629 .arg("--manifest-path")
1630 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1631 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1632
1633 if backend == "gcc" {
1637 let gcc = builder.ensure(Gcc { target });
1638 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1639 }
1640
1641 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1642
1643 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1644 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1645 if builder.config.dry_run() {
1646 return;
1647 }
1648 let mut files = files.into_iter().filter(|f| {
1649 let filename = f.file_name().unwrap().to_str().unwrap();
1650 is_dylib(f) && filename.contains("rustc_codegen_")
1651 });
1652 let codegen_backend = match files.next() {
1653 Some(f) => f,
1654 None => panic!("no dylibs built for codegen backend?"),
1655 };
1656 if let Some(f) = files.next() {
1657 panic!(
1658 "codegen backend built two dylibs:\n{}\n{}",
1659 codegen_backend.display(),
1660 f.display()
1661 );
1662 }
1663 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1664 let codegen_backend = codegen_backend.to_str().unwrap();
1665 t!(stamp.add_stamp(codegen_backend).write());
1666 }
1667}
1668
1669fn copy_codegen_backends_to_sysroot(
1676 builder: &Builder<'_>,
1677 compiler: Compiler,
1678 target_compiler: Compiler,
1679) {
1680 let target = target_compiler.host;
1681
1682 let dst = builder.sysroot_codegen_backends(target_compiler);
1691 t!(fs::create_dir_all(&dst), dst);
1692
1693 if builder.config.dry_run() {
1694 return;
1695 }
1696
1697 for backend in builder.config.codegen_backends(target) {
1698 if backend == "llvm" {
1699 continue; }
1701
1702 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1703 let dylib = t!(fs::read_to_string(stamp.path()));
1704 let file = Path::new(&dylib);
1705 let filename = file.file_name().unwrap().to_str().unwrap();
1706 let target_filename = {
1709 let dash = filename.find('-').unwrap();
1710 let dot = filename.find('.').unwrap();
1711 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1712 };
1713 builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
1714 }
1715}
1716
1717pub fn compiler_file(
1718 builder: &Builder<'_>,
1719 compiler: &Path,
1720 target: TargetSelection,
1721 c: CLang,
1722 file: &str,
1723) -> PathBuf {
1724 if builder.config.dry_run() {
1725 return PathBuf::new();
1726 }
1727 let mut cmd = command(compiler);
1728 cmd.args(builder.cc_handled_clags(target, c));
1729 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1730 cmd.arg(format!("-print-file-name={file}"));
1731 let out = cmd.run_capture_stdout(builder).stdout();
1732 PathBuf::from(out.trim())
1733}
1734
1735#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1736pub struct Sysroot {
1737 pub compiler: Compiler,
1738 force_recompile: bool,
1740}
1741
1742impl Sysroot {
1743 pub(crate) fn new(compiler: Compiler) -> Self {
1744 Sysroot { compiler, force_recompile: false }
1745 }
1746}
1747
1748impl Step for Sysroot {
1749 type Output = PathBuf;
1750
1751 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1752 run.never()
1753 }
1754
1755 #[cfg_attr(
1759 feature = "tracing",
1760 instrument(
1761 level = "debug",
1762 name = "Sysroot::run",
1763 skip_all,
1764 fields(compiler = ?self.compiler),
1765 ),
1766 )]
1767 fn run(self, builder: &Builder<'_>) -> PathBuf {
1768 let compiler = self.compiler;
1769 let host_dir = builder.out.join(compiler.host);
1770
1771 let sysroot_dir = |stage| {
1772 if stage == 0 {
1773 host_dir.join("stage0-sysroot")
1774 } else if self.force_recompile && stage == compiler.stage {
1775 host_dir.join(format!("stage{stage}-test-sysroot"))
1776 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1777 host_dir.join("ci-rustc-sysroot")
1778 } else {
1779 host_dir.join(format!("stage{}", stage))
1780 }
1781 };
1782 let sysroot = sysroot_dir(compiler.stage);
1783 trace!(stage = ?compiler.stage, ?sysroot);
1784
1785 builder
1786 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1787 let _ = fs::remove_dir_all(&sysroot);
1788 t!(fs::create_dir_all(&sysroot));
1789
1790 if compiler.stage == 0 {
1797 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1798 }
1799
1800 if builder.download_rustc() && compiler.stage != 0 {
1802 assert_eq!(
1803 builder.config.build, compiler.host,
1804 "Cross-compiling is not yet supported with `download-rustc`",
1805 );
1806
1807 for stage in 0..=2 {
1809 if stage != compiler.stage {
1810 let dir = sysroot_dir(stage);
1811 if !dir.ends_with("ci-rustc-sysroot") {
1812 let _ = fs::remove_dir_all(dir);
1813 }
1814 }
1815 }
1816
1817 let mut filtered_files = Vec::new();
1827 let mut add_filtered_files = |suffix, contents| {
1828 for path in contents {
1829 let path = Path::new(&path);
1830 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1831 filtered_files.push(path.file_name().unwrap().to_owned());
1832 }
1833 }
1834 };
1835 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1836 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1837 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1840
1841 let filtered_extensions = [
1842 OsStr::new("rmeta"),
1843 OsStr::new("rlib"),
1844 OsStr::new(std::env::consts::DLL_EXTENSION),
1846 ];
1847 let ci_rustc_dir = builder.config.ci_rustc_dir();
1848 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1849 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1850 return true;
1851 }
1852 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1853 return true;
1854 }
1855 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1856 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1857 false
1858 } else {
1859 true
1860 }
1861 });
1862 }
1863
1864 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1870 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1871 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1872 if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
1873 eprintln!(
1874 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1875 sysroot_lib_rustlib_src_rust.display(),
1876 builder.src.display(),
1877 e,
1878 );
1879 if builder.config.rust_remap_debuginfo {
1880 eprintln!(
1881 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1882 sysroot_lib_rustlib_src_rust.display(),
1883 );
1884 }
1885 build_helper::exit!(1);
1886 }
1887
1888 if !builder.download_rustc() {
1890 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1891 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1892 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1893 if let Err(e) =
1894 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1895 {
1896 eprintln!(
1897 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1898 sysroot_lib_rustlib_rustcsrc_rust.display(),
1899 builder.src.display(),
1900 e,
1901 );
1902 build_helper::exit!(1);
1903 }
1904 }
1905
1906 sysroot
1907 }
1908}
1909
1910#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1911pub struct Assemble {
1912 pub target_compiler: Compiler,
1917}
1918
1919impl Step for Assemble {
1920 type Output = Compiler;
1921 const ONLY_HOSTS: bool = true;
1922
1923 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1924 run.path("compiler/rustc").path("compiler")
1925 }
1926
1927 fn make_run(run: RunConfig<'_>) {
1928 run.builder.ensure(Assemble {
1929 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1930 });
1931 }
1932
1933 #[cfg_attr(
1939 feature = "tracing",
1940 instrument(
1941 level = "debug",
1942 name = "Assemble::run",
1943 skip_all,
1944 fields(target_compiler = ?self.target_compiler),
1945 ),
1946 )]
1947 fn run(self, builder: &Builder<'_>) -> Compiler {
1948 let target_compiler = self.target_compiler;
1949
1950 if target_compiler.stage == 0 {
1951 trace!("stage 0 build compiler is always available, simply returning");
1952 assert_eq!(
1953 builder.config.build, target_compiler.host,
1954 "Cannot obtain compiler for non-native build triple at stage 0"
1955 );
1956 return target_compiler;
1958 }
1959
1960 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
1963 let libdir_bin = libdir.parent().unwrap().join("bin");
1964 t!(fs::create_dir_all(&libdir_bin));
1965
1966 if builder.config.llvm_enabled(target_compiler.host) {
1967 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
1968
1969 let llvm::LlvmResult { llvm_config, .. } =
1970 builder.ensure(llvm::Llvm { target: target_compiler.host });
1971 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
1972 trace!("LLVM tools enabled");
1973
1974 let llvm_bin_dir =
1975 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
1976 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
1977
1978 #[cfg(feature = "tracing")]
1985 let _llvm_tools_span =
1986 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
1987 .entered();
1988 for tool in LLVM_TOOLS {
1989 trace!("installing `{tool}`");
1990 let tool_exe = exe(tool, target_compiler.host);
1991 let src_path = llvm_bin_dir.join(&tool_exe);
1992 if src_path.exists() {
1995 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2002 }
2003 }
2004 }
2005 }
2006
2007 let maybe_install_llvm_bitcode_linker = |compiler| {
2008 if builder.config.llvm_bitcode_linker_enabled {
2009 trace!("llvm-bitcode-linker enabled, installing");
2010 let llvm_bitcode_linker =
2011 builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
2012 compiler,
2013 target: target_compiler.host,
2014 extra_features: vec![],
2015 });
2016 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2017 builder.copy_link(
2018 &llvm_bitcode_linker.tool_path,
2019 &libdir_bin.join(tool_exe),
2020 FileType::Executable,
2021 );
2022 }
2023 };
2024
2025 if builder.download_rustc() {
2027 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2028
2029 builder.ensure(Std::new(target_compiler, target_compiler.host));
2030 let sysroot =
2031 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2032 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2035 if target_compiler.stage == builder.top_stage {
2037 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage=target_compiler.stage));
2038 }
2039
2040 let mut precompiled_compiler = target_compiler;
2041 precompiled_compiler.forced_compiler(true);
2042 maybe_install_llvm_bitcode_linker(precompiled_compiler);
2043
2044 return target_compiler;
2045 }
2046
2047 debug!(
2061 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2062 target_compiler.stage - 1,
2063 builder.config.build,
2064 );
2065 let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
2066
2067 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2069 debug!("`llvm_enzyme` requested");
2070 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2071 let llvm_config = builder.llvm_config(builder.config.build).unwrap();
2072 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2073 let lib_ext = std::env::consts::DLL_EXTENSION;
2074 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2075 let src_lib =
2076 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2077 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2078 let target_libdir =
2079 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2080 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2081 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2082 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2083 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2084 }
2085
2086 debug!(
2092 ?build_compiler,
2093 "target_compiler.host" = ?target_compiler.host,
2094 "building compiler libraries to link to"
2095 );
2096 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2097 debug!(
2100 "(old) build_compiler.stage" = build_compiler.stage,
2101 "(adjusted) build_compiler.stage" = actual_stage,
2102 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2103 );
2104 build_compiler.stage = actual_stage;
2105
2106 #[cfg(feature = "tracing")]
2107 let _codegen_backend_span =
2108 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2109 for backend in builder.config.codegen_backends(target_compiler.host) {
2110 if backend == "llvm" {
2111 debug!("llvm codegen backend is already built as part of rustc");
2112 continue; }
2114
2115 builder.ensure(CodegenBackend {
2116 compiler: build_compiler,
2117 target: target_compiler.host,
2118 backend: backend.clone(),
2119 });
2120 }
2121 #[cfg(feature = "tracing")]
2122 drop(_codegen_backend_span);
2123
2124 let stage = target_compiler.stage;
2125 let host = target_compiler.host;
2126 let (host_info, dir_name) = if build_compiler.host == host {
2127 ("".into(), "host".into())
2128 } else {
2129 (format!(" ({host})"), host.to_string())
2130 };
2131 let msg = format!(
2136 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2137 );
2138 builder.info(&msg);
2139
2140 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2142 let proc_macros = builder
2143 .read_stamp_file(&stamp)
2144 .into_iter()
2145 .filter_map(|(path, dependency_type)| {
2146 if dependency_type == DependencyType::Host {
2147 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2148 } else {
2149 None
2150 }
2151 })
2152 .collect::<HashSet<_>>();
2153
2154 let sysroot = builder.sysroot(target_compiler);
2155 let rustc_libdir = builder.rustc_libdir(target_compiler);
2156 t!(fs::create_dir_all(&rustc_libdir));
2157 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2158 for f in builder.read_dir(&src_libdir) {
2159 let filename = f.file_name().into_string().unwrap();
2160
2161 let is_proc_macro = proc_macros.contains(&filename);
2162 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2163
2164 let can_be_rustc_dynamic_dep = if builder
2168 .link_std_into_rustc_driver(target_compiler.host)
2169 && !target_compiler.host.is_windows()
2170 {
2171 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2172 !is_std
2173 } else {
2174 true
2175 };
2176
2177 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2178 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2179 }
2180 }
2181
2182 debug!("copying codegen backends to sysroot");
2183 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2184
2185 if builder.config.lld_enabled {
2186 builder.ensure(crate::core::build_steps::tool::LldWrapper {
2187 build_compiler,
2188 target_compiler,
2189 });
2190 }
2191
2192 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2193 debug!(
2194 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2195 workaround faulty homebrew `strip`s"
2196 );
2197
2198 let src_exe = exe("llvm-objcopy", target_compiler.host);
2205 let dst_exe = exe("rust-objcopy", target_compiler.host);
2206 builder.copy_link(
2207 &libdir_bin.join(src_exe),
2208 &libdir_bin.join(dst_exe),
2209 FileType::Executable,
2210 );
2211 }
2212
2213 if builder.tool_enabled("wasm-component-ld") {
2219 let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
2220 compiler: build_compiler,
2221 target: target_compiler.host,
2222 });
2223 builder.copy_link(
2224 &wasm_component.tool_path,
2225 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2226 FileType::Executable,
2227 );
2228 }
2229
2230 maybe_install_llvm_bitcode_linker(target_compiler);
2231
2232 debug!(
2235 "target_compiler.host" = ?target_compiler.host,
2236 ?sysroot,
2237 "ensuring availability of `libLLVM.so` in compiler directory"
2238 );
2239 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2240 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2241
2242 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2244 let rustc = out_dir.join(exe("rustc-main", host));
2245 let bindir = sysroot.join("bin");
2246 t!(fs::create_dir_all(bindir));
2247 let compiler = builder.rustc(target_compiler);
2248 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2249 builder.copy_link(&rustc, &compiler, FileType::Executable);
2250
2251 target_compiler
2252 }
2253}
2254
2255pub fn add_to_sysroot(
2260 builder: &Builder<'_>,
2261 sysroot_dst: &Path,
2262 sysroot_host_dst: &Path,
2263 stamp: &BuildStamp,
2264) {
2265 let self_contained_dst = &sysroot_dst.join("self-contained");
2266 t!(fs::create_dir_all(sysroot_dst));
2267 t!(fs::create_dir_all(sysroot_host_dst));
2268 t!(fs::create_dir_all(self_contained_dst));
2269 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2270 let dst = match dependency_type {
2271 DependencyType::Host => sysroot_host_dst,
2272 DependencyType::Target => sysroot_dst,
2273 DependencyType::TargetSelfContained => self_contained_dst,
2274 };
2275 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2276 }
2277}
2278
2279pub fn run_cargo(
2280 builder: &Builder<'_>,
2281 cargo: Cargo,
2282 tail_args: Vec<String>,
2283 stamp: &BuildStamp,
2284 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2285 is_check: bool,
2286 rlib_only_metadata: bool,
2287) -> Vec<PathBuf> {
2288 let target_root_dir = stamp.path().parent().unwrap();
2290 let target_deps_dir = target_root_dir.join("deps");
2292 let host_root_dir = target_root_dir
2294 .parent()
2295 .unwrap() .parent()
2297 .unwrap() .join(target_root_dir.file_name().unwrap());
2299
2300 let mut deps = Vec::new();
2304 let mut toplevel = Vec::new();
2305 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2306 let (filenames, crate_types) = match msg {
2307 CargoMessage::CompilerArtifact {
2308 filenames,
2309 target: CargoTarget { crate_types },
2310 ..
2311 } => (filenames, crate_types),
2312 _ => return,
2313 };
2314 for filename in filenames {
2315 let mut keep = false;
2317 if filename.ends_with(".lib")
2318 || filename.ends_with(".a")
2319 || is_debug_info(&filename)
2320 || is_dylib(Path::new(&*filename))
2321 {
2322 keep = true;
2324 }
2325 if is_check && filename.ends_with(".rmeta") {
2326 keep = true;
2328 } else if rlib_only_metadata {
2329 if filename.contains("jemalloc_sys")
2330 || filename.contains("rustc_smir")
2331 || filename.contains("stable_mir")
2332 {
2333 keep |= filename.ends_with(".rlib");
2336 } else {
2337 keep |= filename.ends_with(".rmeta");
2341 }
2342 } else {
2343 keep |= filename.ends_with(".rlib");
2345 }
2346
2347 if !keep {
2348 continue;
2349 }
2350
2351 let filename = Path::new(&*filename);
2352
2353 if filename.starts_with(&host_root_dir) {
2356 if crate_types.iter().any(|t| t == "proc-macro") {
2358 deps.push((filename.to_path_buf(), DependencyType::Host));
2359 }
2360 continue;
2361 }
2362
2363 if filename.starts_with(&target_deps_dir) {
2366 deps.push((filename.to_path_buf(), DependencyType::Target));
2367 continue;
2368 }
2369
2370 let expected_len = t!(filename.metadata()).len();
2381 let filename = filename.file_name().unwrap().to_str().unwrap();
2382 let mut parts = filename.splitn(2, '.');
2383 let file_stem = parts.next().unwrap().to_owned();
2384 let extension = parts.next().unwrap().to_owned();
2385
2386 toplevel.push((file_stem, extension, expected_len));
2387 }
2388 });
2389
2390 if !ok {
2391 crate::exit!(1);
2392 }
2393
2394 if builder.config.dry_run() {
2395 return Vec::new();
2396 }
2397
2398 let contents = t!(target_deps_dir.read_dir())
2402 .map(|e| t!(e))
2403 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2404 .collect::<Vec<_>>();
2405 for (prefix, extension, expected_len) in toplevel {
2406 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2407 meta.len() == expected_len
2408 && filename
2409 .strip_prefix(&prefix[..])
2410 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2411 .unwrap_or(false)
2412 });
2413 let max = candidates.max_by_key(|&(_, _, metadata)| {
2414 metadata.modified().expect("mtime should be available on all relevant OSes")
2415 });
2416 let path_to_add = match max {
2417 Some(triple) => triple.0.to_str().unwrap(),
2418 None => panic!("no output generated for {prefix:?} {extension:?}"),
2419 };
2420 if is_dylib(Path::new(path_to_add)) {
2421 let candidate = format!("{path_to_add}.lib");
2422 let candidate = PathBuf::from(candidate);
2423 if candidate.exists() {
2424 deps.push((candidate, DependencyType::Target));
2425 }
2426 }
2427 deps.push((path_to_add.into(), DependencyType::Target));
2428 }
2429
2430 deps.extend(additional_target_deps);
2431 deps.sort();
2432 let mut new_contents = Vec::new();
2433 for (dep, dependency_type) in deps.iter() {
2434 new_contents.extend(match *dependency_type {
2435 DependencyType::Host => b"h",
2436 DependencyType::Target => b"t",
2437 DependencyType::TargetSelfContained => b"s",
2438 });
2439 new_contents.extend(dep.to_str().unwrap().as_bytes());
2440 new_contents.extend(b"\0");
2441 }
2442 t!(fs::write(stamp.path(), &new_contents));
2443 deps.into_iter().map(|(d, _)| d).collect()
2444}
2445
2446pub fn stream_cargo(
2447 builder: &Builder<'_>,
2448 cargo: Cargo,
2449 tail_args: Vec<String>,
2450 cb: &mut dyn FnMut(CargoMessage<'_>),
2451) -> bool {
2452 let mut cmd = cargo.into_cmd();
2453
2454 #[cfg(feature = "tracing")]
2455 let _run_span = crate::trace_cmd!(cmd);
2456
2457 let cargo = cmd.as_command_mut();
2458 let mut message_format = if builder.config.json_output {
2461 String::from("json")
2462 } else {
2463 String::from("json-render-diagnostics")
2464 };
2465 if let Some(s) = &builder.config.rustc_error_format {
2466 message_format.push_str(",json-diagnostic-");
2467 message_format.push_str(s);
2468 }
2469 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
2470
2471 for arg in tail_args {
2472 cargo.arg(arg);
2473 }
2474
2475 builder.verbose(|| println!("running: {cargo:?}"));
2476
2477 if builder.config.dry_run() {
2478 return true;
2479 }
2480
2481 let mut child = match cargo.spawn() {
2482 Ok(child) => child,
2483 Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"),
2484 };
2485
2486 let stdout = BufReader::new(child.stdout.take().unwrap());
2490 for line in stdout.lines() {
2491 let line = t!(line);
2492 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2493 Ok(msg) => {
2494 if builder.config.json_output {
2495 println!("{line}");
2497 }
2498 cb(msg)
2499 }
2500 Err(_) => println!("{line}"),
2502 }
2503 }
2504
2505 let status = t!(child.wait());
2507 if builder.is_verbose() && !status.success() {
2508 eprintln!(
2509 "command did not execute successfully: {cargo:?}\n\
2510 expected success, got: {status}"
2511 );
2512 }
2513 status.success()
2514}
2515
2516#[derive(Deserialize)]
2517pub struct CargoTarget<'a> {
2518 crate_types: Vec<Cow<'a, str>>,
2519}
2520
2521#[derive(Deserialize)]
2522#[serde(tag = "reason", rename_all = "kebab-case")]
2523pub enum CargoMessage<'a> {
2524 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2525 BuildScriptExecuted,
2526 BuildFinished,
2527}
2528
2529pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2530 if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(target) || !path.exists()
2534 {
2535 return;
2536 }
2537
2538 let previous_mtime = t!(t!(path.metadata()).modified());
2539 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2540
2541 let file = t!(fs::File::open(path));
2542
2543 t!(file.set_modified(previous_mtime));
2556}
2557
2558pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2560 build_compiler.stage != 0
2561}