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