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, StepMetadata, TaskPath,
28 crate_description,
29};
30use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
31use crate::utils::build_stamp;
32use crate::utils::build_stamp::BuildStamp;
33use crate::utils::exec::command;
34use crate::utils::helpers::{
35 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
36};
37use crate::{CLang, Compiler, DependencyType, FileType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
38
39#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub struct Std {
42 pub target: TargetSelection,
43 pub compiler: Compiler,
44 crates: Vec<String>,
48 force_recompile: bool,
51 extra_rust_args: &'static [&'static str],
52 is_for_mir_opt_tests: bool,
53}
54
55impl Std {
56 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
57 Self {
58 target,
59 compiler,
60 crates: Default::default(),
61 force_recompile: false,
62 extra_rust_args: &[],
63 is_for_mir_opt_tests: false,
64 }
65 }
66
67 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
68 self.force_recompile = force_recompile;
69 self
70 }
71
72 #[expect(clippy::wrong_self_convention)]
73 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
74 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
75 self
76 }
77
78 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
79 self.extra_rust_args = extra_rust_args;
80 self
81 }
82
83 fn copy_extra_objects(
84 &self,
85 builder: &Builder<'_>,
86 compiler: &Compiler,
87 target: TargetSelection,
88 ) -> Vec<(PathBuf, DependencyType)> {
89 let mut deps = Vec::new();
90 if !self.is_for_mir_opt_tests {
91 deps.extend(copy_third_party_objects(builder, compiler, target));
92 deps.extend(copy_self_contained_objects(builder, compiler, target));
93 }
94 deps
95 }
96}
97
98impl Step for Std {
99 type Output = ();
100 const DEFAULT: bool = true;
101
102 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
103 run.crate_or_deps("sysroot").path("library")
104 }
105
106 #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
107 fn make_run(run: RunConfig<'_>) {
108 let crates = std_crates_for_run_make(&run);
109 let builder = run.builder;
110
111 let force_recompile = builder.rust_info().is_managed_git_subrepository()
115 && builder.download_rustc()
116 && builder.config.has_changes_from_upstream(&["library"]);
117
118 trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
119 trace!("download_rustc: {}", builder.download_rustc());
120 trace!(force_recompile);
121
122 run.builder.ensure(Std {
123 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
124 target: run.target,
125 crates,
126 force_recompile,
127 extra_rust_args: &[],
128 is_for_mir_opt_tests: false,
129 });
130 }
131
132 #[cfg_attr(
138 feature = "tracing",
139 instrument(
140 level = "debug",
141 name = "Std::run",
142 skip_all,
143 fields(
144 target = ?self.target,
145 compiler = ?self.compiler,
146 force_recompile = self.force_recompile
147 ),
148 ),
149 )]
150 fn run(self, builder: &Builder<'_>) {
151 let target = self.target;
152
153 if self.compiler.stage == 0 {
155 let compiler = self.compiler;
156 builder.ensure(StdLink::from_std(self, compiler));
157
158 return;
159 }
160
161 let compiler = if builder.download_rustc() && self.force_recompile {
162 builder.compiler(self.compiler.stage.saturating_sub(1), builder.config.host_target)
165 } else {
166 self.compiler
167 };
168
169 if builder.download_rustc()
172 && builder.config.is_host_target(target)
173 && !self.force_recompile
174 {
175 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
176 cp_rustc_component_to_ci_sysroot(
177 builder,
178 &sysroot,
179 builder.config.ci_rust_std_contents(),
180 );
181 return;
182 }
183
184 if builder.config.keep_stage.contains(&compiler.stage)
185 || builder.config.keep_stage_std.contains(&compiler.stage)
186 {
187 trace!(keep_stage = ?builder.config.keep_stage);
188 trace!(keep_stage_std = ?builder.config.keep_stage_std);
189
190 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
191
192 builder.ensure(StartupObjects { compiler, target });
193
194 self.copy_extra_objects(builder, &compiler, target);
195
196 builder.ensure(StdLink::from_std(self, compiler));
197 return;
198 }
199
200 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
201
202 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
203 trace!(?compiler_to_use);
204
205 if compiler_to_use != compiler
206 && compiler.stage > 1
211 {
212 trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
213
214 builder.std(compiler_to_use, target);
215 let msg = if compiler_to_use.host == target {
216 format!(
217 "Uplifting library (stage{} -> stage{})",
218 compiler_to_use.stage, compiler.stage
219 )
220 } else {
221 format!(
222 "Uplifting library (stage{}:{} -> stage{}:{})",
223 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
224 )
225 };
226 builder.info(&msg);
227
228 self.copy_extra_objects(builder, &compiler, target);
231
232 builder.ensure(StdLink::from_std(self, compiler_to_use));
233 return;
234 }
235
236 trace!(
237 ?compiler_to_use,
238 ?compiler,
239 "compiler == compiler_to_use, handling not-cross-compile scenario"
240 );
241
242 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
243
244 let mut cargo = if self.is_for_mir_opt_tests {
248 trace!("building special sysroot for mir-opt tests");
249 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
250 builder,
251 compiler,
252 Mode::Std,
253 SourceType::InTree,
254 target,
255 Kind::Check,
256 );
257 cargo.rustflag("-Zalways-encode-mir");
258 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
259 cargo
260 } else {
261 trace!("building regular sysroot");
262 let mut cargo = builder::Cargo::new(
263 builder,
264 compiler,
265 Mode::Std,
266 SourceType::InTree,
267 target,
268 Kind::Build,
269 );
270 std_cargo(builder, target, compiler.stage, &mut cargo);
271 for krate in &*self.crates {
272 cargo.arg("-p").arg(krate);
273 }
274 cargo
275 };
276
277 if target.is_synthetic() {
279 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
280 }
281 for rustflag in self.extra_rust_args.iter() {
282 cargo.rustflag(rustflag);
283 }
284
285 let _guard = builder.msg(
286 Kind::Build,
287 compiler.stage,
288 format_args!("library artifacts{}", crate_description(&self.crates)),
289 compiler.host,
290 target,
291 );
292 run_cargo(
293 builder,
294 cargo,
295 vec![],
296 &build_stamp::libstd_stamp(builder, compiler, target),
297 target_deps,
298 self.is_for_mir_opt_tests, false,
300 );
301
302 builder.ensure(StdLink::from_std(
303 self,
304 builder.compiler(compiler.stage, builder.config.host_target),
305 ));
306 }
307
308 fn metadata(&self) -> Option<StepMetadata> {
309 Some(
310 StepMetadata::build("std", self.target)
311 .built_by(self.compiler)
312 .stage(self.compiler.stage),
313 )
314 }
315}
316
317fn copy_and_stamp(
318 builder: &Builder<'_>,
319 libdir: &Path,
320 sourcedir: &Path,
321 name: &str,
322 target_deps: &mut Vec<(PathBuf, DependencyType)>,
323 dependency_type: DependencyType,
324) {
325 let target = libdir.join(name);
326 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
327
328 target_deps.push((target, dependency_type));
329}
330
331fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
332 let libunwind_path = builder.ensure(llvm::Libunwind { target });
333 let libunwind_source = libunwind_path.join("libunwind.a");
334 let libunwind_target = libdir.join("libunwind.a");
335 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
336 libunwind_target
337}
338
339fn copy_third_party_objects(
341 builder: &Builder<'_>,
342 compiler: &Compiler,
343 target: TargetSelection,
344) -> Vec<(PathBuf, DependencyType)> {
345 let mut target_deps = vec![];
346
347 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
348 target_deps.extend(
351 copy_sanitizers(builder, compiler, target)
352 .into_iter()
353 .map(|d| (d, DependencyType::Target)),
354 );
355 }
356
357 if target == "x86_64-fortanix-unknown-sgx"
358 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
359 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
360 {
361 let libunwind_path =
362 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
363 target_deps.push((libunwind_path, DependencyType::Target));
364 }
365
366 target_deps
367}
368
369fn copy_self_contained_objects(
371 builder: &Builder<'_>,
372 compiler: &Compiler,
373 target: TargetSelection,
374) -> Vec<(PathBuf, DependencyType)> {
375 let libdir_self_contained =
376 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
377 t!(fs::create_dir_all(&libdir_self_contained));
378 let mut target_deps = vec![];
379
380 if target.needs_crt_begin_end() {
388 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
389 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
390 });
391 if !target.starts_with("wasm32") {
392 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
393 copy_and_stamp(
394 builder,
395 &libdir_self_contained,
396 &srcdir,
397 obj,
398 &mut target_deps,
399 DependencyType::TargetSelfContained,
400 );
401 }
402 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
403 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
404 let src = crt_path.join(obj);
405 let target = libdir_self_contained.join(obj);
406 builder.copy_link(&src, &target, FileType::NativeLibrary);
407 target_deps.push((target, DependencyType::TargetSelfContained));
408 }
409 } else {
410 for &obj in &["libc.a", "crt1-command.o"] {
413 copy_and_stamp(
414 builder,
415 &libdir_self_contained,
416 &srcdir,
417 obj,
418 &mut target_deps,
419 DependencyType::TargetSelfContained,
420 );
421 }
422 }
423 if !target.starts_with("s390x") {
424 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
425 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
426 }
427 } else if target.contains("-wasi") {
428 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
429 panic!(
430 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
431 or `$WASI_SDK_PATH` set",
432 target.triple
433 )
434 });
435 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
436 copy_and_stamp(
437 builder,
438 &libdir_self_contained,
439 &srcdir,
440 obj,
441 &mut target_deps,
442 DependencyType::TargetSelfContained,
443 );
444 }
445 } else if target.is_windows_gnu() {
446 for obj in ["crt2.o", "dllcrt2.o"].iter() {
447 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
448 let dst = libdir_self_contained.join(obj);
449 builder.copy_link(&src, &dst, FileType::NativeLibrary);
450 target_deps.push((dst, DependencyType::TargetSelfContained));
451 }
452 }
453
454 target_deps
455}
456
457pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
459 if cfg!(test) {
461 return vec![];
462 }
463
464 let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
465 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
466
467 if target_is_no_std {
469 vec![]
470 }
471 else if has_alias {
473 run.make_run_crates(builder::Alias::Library)
474 } else {
475 run.cargo_crates_in_set()
476 }
477}
478
479fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
485 if builder.config.llvm_from_ci {
487 builder.config.maybe_download_ci_llvm();
489 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
490 if ci_llvm_compiler_rt.exists() {
491 return ci_llvm_compiler_rt;
492 }
493 }
494
495 builder.require_submodule("src/llvm-project", {
497 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
498 });
499 builder.src.join("src/llvm-project/compiler-rt")
500}
501
502pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
505 if target.contains("apple") && !builder.config.dry_run() {
523 let mut cmd = command(builder.rustc(cargo.compiler()));
527 cmd.arg("--target").arg(target.rustc_target_arg());
528 cmd.arg("--print=deployment-target");
529 let output = cmd.run_capture_stdout(builder).stdout();
530
531 let (env_var, value) = output.split_once('=').unwrap();
532 cargo.env(env_var.trim(), value.trim());
535
536 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
546 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
547 }
548 }
549
550 if let Some(path) = builder.config.profiler_path(target) {
552 cargo.env("LLVM_PROFILER_RT_LIB", path);
553 } else if builder.config.profiler_enabled(target) {
554 let compiler_rt = compiler_rt_for_profiler(builder);
555 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
559 }
560
561 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
575 builder.require_submodule(
583 "src/llvm-project",
584 Some(
585 "The `build.optimized-compiler-builtins` config option \
586 requires `compiler-rt` sources from LLVM.",
587 ),
588 );
589 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
590 assert!(compiler_builtins_root.exists());
591 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
594 " compiler-builtins-c"
595 } else {
596 ""
597 };
598
599 if !builder.unstable_features() {
602 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
603 }
604
605 let mut features = String::new();
606
607 if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
608 {
609 features += "compiler-builtins-no-f16-f128 ";
610 }
611
612 if builder.no_std(target) == Some(true) {
613 features += " compiler-builtins-mem";
614 if !target.starts_with("bpf") {
615 features.push_str(compiler_builtins_c_feature);
616 }
617
618 cargo
620 .args(["-p", "alloc"])
621 .arg("--manifest-path")
622 .arg(builder.src.join("library/alloc/Cargo.toml"))
623 .arg("--features")
624 .arg(features);
625 } else {
626 features += &builder.std_features(target);
627 features.push_str(compiler_builtins_c_feature);
628
629 cargo
630 .arg("--features")
631 .arg(features)
632 .arg("--manifest-path")
633 .arg(builder.src.join("library/sysroot/Cargo.toml"));
634
635 if target.contains("musl")
638 && let Some(p) = builder.musl_libdir(target)
639 {
640 let root = format!("native={}", p.to_str().unwrap());
641 cargo.rustflag("-L").rustflag(&root);
642 }
643
644 if target.contains("-wasi")
645 && let Some(dir) = builder.wasi_libdir(target)
646 {
647 let root = format!("native={}", dir.to_str().unwrap());
648 cargo.rustflag("-L").rustflag(&root);
649 }
650 }
651
652 if stage >= 1 {
661 cargo.rustflag("-Cembed-bitcode=yes");
662 }
663 if builder.config.rust_lto == RustcLto::Off {
664 cargo.rustflag("-Clto=off");
665 }
666
667 if target.contains("riscv") {
674 cargo.rustflag("-Cforce-unwind-tables=yes");
675 }
676
677 cargo.rustflag("-Zunstable-options");
680 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
681
682 let html_root =
683 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
684 cargo.rustflag(&html_root);
685 cargo.rustdocflag(&html_root);
686
687 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
688}
689
690#[derive(Debug, Clone, PartialEq, Eq, Hash)]
691pub struct StdLink {
692 pub compiler: Compiler,
693 pub target_compiler: Compiler,
694 pub target: TargetSelection,
695 crates: Vec<String>,
697 force_recompile: bool,
699}
700
701impl StdLink {
702 pub fn from_std(std: Std, host_compiler: Compiler) -> Self {
703 Self {
704 compiler: host_compiler,
705 target_compiler: std.compiler,
706 target: std.target,
707 crates: std.crates,
708 force_recompile: std.force_recompile,
709 }
710 }
711}
712
713impl Step for StdLink {
714 type Output = ();
715
716 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
717 run.never()
718 }
719
720 #[cfg_attr(
729 feature = "tracing",
730 instrument(
731 level = "trace",
732 name = "StdLink::run",
733 skip_all,
734 fields(
735 compiler = ?self.compiler,
736 target_compiler = ?self.target_compiler,
737 target = ?self.target
738 ),
739 ),
740 )]
741 fn run(self, builder: &Builder<'_>) {
742 let compiler = self.compiler;
743 let target_compiler = self.target_compiler;
744 let target = self.target;
745
746 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
748 let lib = builder.sysroot_libdir_relative(self.compiler);
750 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
751 compiler: self.compiler,
752 force_recompile: self.force_recompile,
753 });
754 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
755 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
756 (libdir, hostdir)
757 } else {
758 let libdir = builder.sysroot_target_libdir(target_compiler, target);
759 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
760 (libdir, hostdir)
761 };
762
763 let is_downloaded_beta_stage0 = builder
764 .build
765 .config
766 .initial_rustc
767 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
768
769 if compiler.stage == 0 && is_downloaded_beta_stage0 {
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");
783 t!(fs::create_dir_all(sysroot.join("lib")));
784 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
785
786 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
788 t!(fs::create_dir_all(&sysroot_codegen_backends));
789 let stage0_codegen_backends = builder
790 .out
791 .join(host)
792 .join("stage0/lib/rustlib")
793 .join(host)
794 .join("codegen-backends");
795 if stage0_codegen_backends.exists() {
796 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
797 }
798 } else if compiler.stage == 0 {
799 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
800
801 if builder.local_rebuild {
802 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
806 }
807
808 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
809 } else {
810 if builder.download_rustc() {
811 let _ = fs::remove_dir_all(&libdir);
813 let _ = fs::remove_dir_all(&hostdir);
814 }
815
816 add_to_sysroot(
817 builder,
818 &libdir,
819 &hostdir,
820 &build_stamp::libstd_stamp(builder, compiler, target),
821 );
822 }
823 }
824}
825
826fn copy_sanitizers(
828 builder: &Builder<'_>,
829 compiler: &Compiler,
830 target: TargetSelection,
831) -> Vec<PathBuf> {
832 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
833
834 if builder.config.dry_run() {
835 return Vec::new();
836 }
837
838 let mut target_deps = Vec::new();
839 let libdir = builder.sysroot_target_libdir(*compiler, target);
840
841 for runtime in &runtimes {
842 let dst = libdir.join(&runtime.name);
843 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
844
845 if target == "x86_64-apple-darwin"
849 || target == "aarch64-apple-darwin"
850 || target == "aarch64-apple-ios"
851 || target == "aarch64-apple-ios-sim"
852 || target == "x86_64-apple-ios"
853 {
854 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
856 apple_darwin_sign_file(builder, &dst);
859 }
860
861 target_deps.push(dst);
862 }
863
864 target_deps
865}
866
867fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
868 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
869}
870
871fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
872 command("codesign")
873 .arg("-f") .arg("-s")
875 .arg("-")
876 .arg(file_path)
877 .run(builder);
878}
879
880#[derive(Debug, Clone, PartialEq, Eq, Hash)]
881pub struct StartupObjects {
882 pub compiler: Compiler,
883 pub target: TargetSelection,
884}
885
886impl Step for StartupObjects {
887 type Output = Vec<(PathBuf, DependencyType)>;
888
889 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
890 run.path("library/rtstartup")
891 }
892
893 fn make_run(run: RunConfig<'_>) {
894 run.builder.ensure(StartupObjects {
895 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
896 target: run.target,
897 });
898 }
899
900 #[cfg_attr(
907 feature = "tracing",
908 instrument(
909 level = "trace",
910 name = "StartupObjects::run",
911 skip_all,
912 fields(compiler = ?self.compiler, target = ?self.target),
913 ),
914 )]
915 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
916 let for_compiler = self.compiler;
917 let target = self.target;
918 if !target.is_windows_gnu() {
919 return vec![];
920 }
921
922 let mut target_deps = vec![];
923
924 let src_dir = &builder.src.join("library").join("rtstartup");
925 let dst_dir = &builder.native_dir(target).join("rtstartup");
926 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
927 t!(fs::create_dir_all(dst_dir));
928
929 for file in &["rsbegin", "rsend"] {
930 let src_file = &src_dir.join(file.to_string() + ".rs");
931 let dst_file = &dst_dir.join(file.to_string() + ".o");
932 if !up_to_date(src_file, dst_file) {
933 let mut cmd = command(&builder.initial_rustc);
934 cmd.env("RUSTC_BOOTSTRAP", "1");
935 if !builder.local_rebuild {
936 cmd.arg("--cfg").arg("bootstrap");
938 }
939 cmd.arg("--target")
940 .arg(target.rustc_target_arg())
941 .arg("--emit=obj")
942 .arg("-o")
943 .arg(dst_file)
944 .arg(src_file)
945 .run(builder);
946 }
947
948 let obj = sysroot_dir.join((*file).to_string() + ".o");
949 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
950 target_deps.push((obj, DependencyType::Target));
951 }
952
953 target_deps
954 }
955}
956
957fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
958 let ci_rustc_dir = builder.config.ci_rustc_dir();
959
960 for file in contents {
961 let src = ci_rustc_dir.join(&file);
962 let dst = sysroot.join(file);
963 if src.is_dir() {
964 t!(fs::create_dir_all(dst));
965 } else {
966 builder.copy_link(&src, &dst, FileType::Regular);
967 }
968 }
969}
970
971#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
978pub struct Rustc {
979 pub target: TargetSelection,
981 pub build_compiler: Compiler,
983 crates: Vec<String>,
989}
990
991impl Rustc {
992 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
993 Self { target, build_compiler, crates: Default::default() }
994 }
995}
996
997impl Step for Rustc {
998 type Output = u32;
1006 const ONLY_HOSTS: bool = true;
1007 const DEFAULT: bool = false;
1008
1009 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1010 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1011 for (i, krate) in crates.iter().enumerate() {
1012 if krate.name == "rustc-main" {
1015 crates.swap_remove(i);
1016 break;
1017 }
1018 }
1019 run.crates(crates)
1020 }
1021
1022 fn make_run(run: RunConfig<'_>) {
1023 if run.builder.paths == vec![PathBuf::from("compiler")] {
1026 return;
1027 }
1028
1029 let crates = run.cargo_crates_in_set();
1030 run.builder.ensure(Rustc {
1031 build_compiler: run
1032 .builder
1033 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1034 target: run.target,
1035 crates,
1036 });
1037 }
1038
1039 #[cfg_attr(
1045 feature = "tracing",
1046 instrument(
1047 level = "debug",
1048 name = "Rustc::run",
1049 skip_all,
1050 fields(previous_compiler = ?self.build_compiler, target = ?self.target),
1051 ),
1052 )]
1053 fn run(self, builder: &Builder<'_>) -> u32 {
1054 let build_compiler = self.build_compiler;
1055 let target = self.target;
1056
1057 if builder.download_rustc() && build_compiler.stage != 0 {
1060 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1061
1062 let sysroot =
1063 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1064 cp_rustc_component_to_ci_sysroot(
1065 builder,
1066 &sysroot,
1067 builder.config.ci_rustc_dev_contents(),
1068 );
1069 return build_compiler.stage;
1070 }
1071
1072 builder.std(build_compiler, target);
1075
1076 if builder.config.keep_stage.contains(&build_compiler.stage) {
1077 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1078
1079 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1080 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1081 builder.ensure(RustcLink::from_rustc(self, build_compiler));
1082
1083 return build_compiler.stage;
1084 }
1085
1086 let compiler_to_use =
1087 builder.compiler_for(build_compiler.stage, build_compiler.host, target);
1088 if compiler_to_use != build_compiler {
1089 builder.ensure(Rustc::new(compiler_to_use, target));
1090 let msg = if compiler_to_use.host == target {
1091 format!(
1092 "Uplifting rustc (stage{} -> stage{})",
1093 compiler_to_use.stage,
1094 build_compiler.stage + 1
1095 )
1096 } else {
1097 format!(
1098 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1099 compiler_to_use.stage,
1100 compiler_to_use.host,
1101 build_compiler.stage + 1,
1102 target
1103 )
1104 };
1105 builder.info(&msg);
1106 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1107 return compiler_to_use.stage;
1108 }
1109
1110 builder.std(
1116 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1117 builder.config.host_target,
1118 );
1119
1120 let mut cargo = builder::Cargo::new(
1121 builder,
1122 build_compiler,
1123 Mode::Rustc,
1124 SourceType::InTree,
1125 target,
1126 Kind::Build,
1127 );
1128
1129 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1130
1131 for krate in &*self.crates {
1135 cargo.arg("-p").arg(krate);
1136 }
1137
1138 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1139 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1141 }
1142
1143 let _guard = builder.msg_sysroot_tool(
1144 Kind::Build,
1145 build_compiler.stage,
1146 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1147 build_compiler.host,
1148 target,
1149 );
1150 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1151 run_cargo(
1152 builder,
1153 cargo,
1154 vec![],
1155 &stamp,
1156 vec![],
1157 false,
1158 true, );
1160
1161 let target_root_dir = stamp.path().parent().unwrap();
1162 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1168 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1169 {
1170 let rustc_driver = target_root_dir.join("librustc_driver.so");
1171 strip_debug(builder, target, &rustc_driver);
1172 }
1173
1174 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1175 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1178 }
1179
1180 builder.ensure(RustcLink::from_rustc(
1181 self,
1182 builder.compiler(build_compiler.stage, builder.config.host_target),
1183 ));
1184
1185 build_compiler.stage
1186 }
1187
1188 fn metadata(&self) -> Option<StepMetadata> {
1189 Some(
1190 StepMetadata::build("rustc", self.target)
1191 .built_by(self.build_compiler)
1192 .stage(self.build_compiler.stage + 1),
1193 )
1194 }
1195}
1196
1197pub fn rustc_cargo(
1198 builder: &Builder<'_>,
1199 cargo: &mut Cargo,
1200 target: TargetSelection,
1201 build_compiler: &Compiler,
1202 crates: &[String],
1203) {
1204 cargo
1205 .arg("--features")
1206 .arg(builder.rustc_features(builder.kind, target, crates))
1207 .arg("--manifest-path")
1208 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1209
1210 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1211
1212 cargo.rustflag("-Zon-broken-pipe=kill");
1226
1227 if builder.config.llvm_enzyme {
1230 let arch = builder.build.host_target;
1231 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1232 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1233
1234 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1235 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1236 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1237 }
1238 }
1239
1240 if builder.build.config.lld_mode.is_used() {
1245 cargo.rustflag("-Zdefault-visibility=protected");
1246 }
1247
1248 if is_lto_stage(build_compiler) {
1249 match builder.config.rust_lto {
1250 RustcLto::Thin | RustcLto::Fat => {
1251 cargo.rustflag("-Zdylib-lto");
1254 let lto_type = match builder.config.rust_lto {
1258 RustcLto::Thin => "thin",
1259 RustcLto::Fat => "fat",
1260 _ => unreachable!(),
1261 };
1262 cargo.rustflag(&format!("-Clto={lto_type}"));
1263 cargo.rustflag("-Cembed-bitcode=yes");
1264 }
1265 RustcLto::ThinLocal => { }
1266 RustcLto::Off => {
1267 cargo.rustflag("-Clto=off");
1268 }
1269 }
1270 } else if builder.config.rust_lto == RustcLto::Off {
1271 cargo.rustflag("-Clto=off");
1272 }
1273
1274 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1282 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1283 }
1284
1285 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1286 panic!("Cannot use and generate PGO profiles at the same time");
1287 }
1288 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1289 if build_compiler.stage == 1 {
1290 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1291 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1294 true
1295 } else {
1296 false
1297 }
1298 } else if let Some(path) = &builder.config.rust_profile_use {
1299 if build_compiler.stage == 1 {
1300 cargo.rustflag(&format!("-Cprofile-use={path}"));
1301 if builder.is_verbose() {
1302 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1303 }
1304 true
1305 } else {
1306 false
1307 }
1308 } else {
1309 false
1310 };
1311 if is_collecting {
1312 cargo.rustflag(&format!(
1314 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1315 builder.config.src.components().count()
1316 ));
1317 }
1318
1319 if let Some(ref ccache) = builder.config.ccache
1324 && build_compiler.stage == 0
1325 && !builder.config.incremental
1326 {
1327 cargo.env("RUSTC_WRAPPER", ccache);
1328 }
1329
1330 rustc_cargo_env(builder, cargo, target, build_compiler.stage);
1331}
1332
1333pub fn rustc_cargo_env(
1334 builder: &Builder<'_>,
1335 cargo: &mut Cargo,
1336 target: TargetSelection,
1337 build_stage: u32,
1338) {
1339 cargo
1342 .env("CFG_RELEASE", builder.rust_release())
1343 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1344 .env("CFG_VERSION", builder.rust_version());
1345
1346 if builder.config.omit_git_hash {
1350 cargo.env("CFG_OMIT_GIT_HASH", "1");
1351 }
1352
1353 if let Some(backend) = builder.config.default_codegen_backend(target) {
1354 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1355 }
1356
1357 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1358 let target_config = builder.config.target_config.get(&target);
1359
1360 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1361
1362 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1363 cargo.env("CFG_VER_DATE", ver_date);
1364 }
1365 if let Some(ref ver_hash) = builder.rust_info().sha() {
1366 cargo.env("CFG_VER_HASH", ver_hash);
1367 }
1368 if !builder.unstable_features() {
1369 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1370 }
1371
1372 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1375 cargo.env("CFG_DEFAULT_LINKER", s);
1376 } else if let Some(ref s) = builder.config.rustc_default_linker {
1377 cargo.env("CFG_DEFAULT_LINKER", s);
1378 }
1379
1380 if builder.config.lld_enabled
1382 && (builder.config.channel == "dev" || builder.config.channel == "nightly")
1383 {
1384 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1385 }
1386
1387 if builder.config.rust_verify_llvm_ir {
1388 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1389 }
1390
1391 if builder.config.llvm_enzyme {
1392 cargo.rustflag("--cfg=llvm_enzyme");
1393 }
1394
1395 if builder.config.llvm_enabled(target) {
1400 let building_is_expensive =
1401 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1402 .should_build();
1403 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == build_stage;
1405 let should_skip_build = building_is_expensive && can_skip_build;
1406 if !should_skip_build {
1407 rustc_llvm_env(builder, cargo, target)
1408 }
1409 }
1410
1411 if builder.config.jemalloc(target)
1414 && target.starts_with("aarch64")
1415 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1416 {
1417 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1418 }
1419}
1420
1421fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1424 if builder.config.is_rust_llvm(target) {
1425 cargo.env("LLVM_RUSTLLVM", "1");
1426 }
1427 if builder.config.llvm_enzyme {
1428 cargo.env("LLVM_ENZYME", "1");
1429 }
1430 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1431 cargo.env("LLVM_CONFIG", &llvm_config);
1432
1433 let mut llvm_linker_flags = String::new();
1443 if builder.config.llvm_profile_generate
1444 && target.is_msvc()
1445 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1446 {
1447 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1449 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1450 }
1451
1452 if let Some(ref s) = builder.config.llvm_ldflags {
1454 if !llvm_linker_flags.is_empty() {
1455 llvm_linker_flags.push(' ');
1456 }
1457 llvm_linker_flags.push_str(s);
1458 }
1459
1460 if !llvm_linker_flags.is_empty() {
1462 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1463 }
1464
1465 if builder.config.llvm_static_stdcpp
1468 && !target.contains("freebsd")
1469 && !target.is_msvc()
1470 && !target.contains("apple")
1471 && !target.contains("solaris")
1472 {
1473 let libstdcxx_name =
1474 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1475 let file = compiler_file(
1476 builder,
1477 &builder.cxx(target).unwrap(),
1478 target,
1479 CLang::Cxx,
1480 libstdcxx_name,
1481 );
1482 cargo.env("LLVM_STATIC_STDCPP", file);
1483 }
1484 if builder.llvm_link_shared() {
1485 cargo.env("LLVM_LINK_SHARED", "1");
1486 }
1487 if builder.config.llvm_use_libcxx {
1488 cargo.env("LLVM_USE_LIBCXX", "1");
1489 }
1490 if builder.config.llvm_assertions {
1491 cargo.env("LLVM_ASSERTIONS", "1");
1492 }
1493}
1494
1495#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1501struct RustcLink {
1502 pub compiler: Compiler,
1504 pub previous_stage_compiler: Compiler,
1506 pub target: TargetSelection,
1507 crates: Vec<String>,
1509}
1510
1511impl RustcLink {
1512 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1513 Self {
1514 compiler: host_compiler,
1515 previous_stage_compiler: rustc.build_compiler,
1516 target: rustc.target,
1517 crates: rustc.crates,
1518 }
1519 }
1520}
1521
1522impl Step for RustcLink {
1523 type Output = ();
1524
1525 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1526 run.never()
1527 }
1528
1529 #[cfg_attr(
1531 feature = "tracing",
1532 instrument(
1533 level = "trace",
1534 name = "RustcLink::run",
1535 skip_all,
1536 fields(
1537 compiler = ?self.compiler,
1538 previous_stage_compiler = ?self.previous_stage_compiler,
1539 target = ?self.target,
1540 ),
1541 ),
1542 )]
1543 fn run(self, builder: &Builder<'_>) {
1544 let compiler = self.compiler;
1545 let previous_stage_compiler = self.previous_stage_compiler;
1546 let target = self.target;
1547 add_to_sysroot(
1548 builder,
1549 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1550 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1551 &build_stamp::librustc_stamp(builder, compiler, target),
1552 );
1553 }
1554}
1555
1556#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1557pub struct CodegenBackend {
1558 pub target: TargetSelection,
1559 pub compiler: Compiler,
1560 pub backend: String,
1561}
1562
1563fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1564 let mut needs_codegen_cfg = false;
1565 for path_set in &run.paths {
1566 needs_codegen_cfg = match path_set {
1567 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1568 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1569 }
1570 }
1571 needs_codegen_cfg
1572}
1573
1574pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1575
1576fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1577 let path = path.path.to_str().unwrap();
1578
1579 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1580 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1581
1582 if path.contains(CODEGEN_BACKEND_PREFIX) {
1583 let mut needs_codegen_backend_config = true;
1584 for backend in run.builder.config.codegen_backends(run.target) {
1585 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1586 needs_codegen_backend_config = false;
1587 }
1588 }
1589 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1590 && needs_codegen_backend_config
1591 {
1592 run.builder.info(
1593 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1594 HELP: add backend to codegen-backends in bootstrap.toml.",
1595 );
1596 return true;
1597 }
1598 }
1599
1600 false
1601}
1602
1603impl Step for CodegenBackend {
1604 type Output = ();
1605 const ONLY_HOSTS: bool = true;
1606 const DEFAULT: bool = true;
1608
1609 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1610 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1611 }
1612
1613 fn make_run(run: RunConfig<'_>) {
1614 if needs_codegen_config(&run) {
1615 return;
1616 }
1617
1618 for backend in run.builder.config.codegen_backends(run.target) {
1619 if backend == "llvm" {
1620 continue; }
1622
1623 run.builder.ensure(CodegenBackend {
1624 target: run.target,
1625 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1626 backend: backend.clone(),
1627 });
1628 }
1629 }
1630
1631 #[cfg_attr(
1632 feature = "tracing",
1633 instrument(
1634 level = "debug",
1635 name = "CodegenBackend::run",
1636 skip_all,
1637 fields(
1638 compiler = ?self.compiler,
1639 target = ?self.target,
1640 backend = ?self.target,
1641 ),
1642 ),
1643 )]
1644 fn run(self, builder: &Builder<'_>) {
1645 let compiler = self.compiler;
1646 let target = self.target;
1647 let backend = self.backend;
1648
1649 builder.ensure(Rustc::new(compiler, target));
1650
1651 if builder.config.keep_stage.contains(&compiler.stage) {
1652 trace!("`keep-stage` requested");
1653 builder.info(
1654 "WARNING: Using a potentially old codegen backend. \
1655 This may not behave well.",
1656 );
1657 return;
1660 }
1661
1662 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1663 if compiler_to_use != compiler {
1664 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1665 return;
1666 }
1667
1668 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1669
1670 let mut cargo = builder::Cargo::new(
1671 builder,
1672 compiler,
1673 Mode::Codegen,
1674 SourceType::InTree,
1675 target,
1676 Kind::Build,
1677 );
1678 cargo
1679 .arg("--manifest-path")
1680 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1681 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1682
1683 if backend == "gcc" {
1687 let gcc = builder.ensure(Gcc { target });
1688 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1689 }
1690
1691 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1692
1693 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1694 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1695 if builder.config.dry_run() {
1696 return;
1697 }
1698 let mut files = files.into_iter().filter(|f| {
1699 let filename = f.file_name().unwrap().to_str().unwrap();
1700 is_dylib(f) && filename.contains("rustc_codegen_")
1701 });
1702 let codegen_backend = match files.next() {
1703 Some(f) => f,
1704 None => panic!("no dylibs built for codegen backend?"),
1705 };
1706 if let Some(f) = files.next() {
1707 panic!(
1708 "codegen backend built two dylibs:\n{}\n{}",
1709 codegen_backend.display(),
1710 f.display()
1711 );
1712 }
1713 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1714 let codegen_backend = codegen_backend.to_str().unwrap();
1715 t!(stamp.add_stamp(codegen_backend).write());
1716 }
1717}
1718
1719fn copy_codegen_backends_to_sysroot(
1726 builder: &Builder<'_>,
1727 compiler: Compiler,
1728 target_compiler: Compiler,
1729) {
1730 let target = target_compiler.host;
1731
1732 let dst = builder.sysroot_codegen_backends(target_compiler);
1741 t!(fs::create_dir_all(&dst), dst);
1742
1743 if builder.config.dry_run() {
1744 return;
1745 }
1746
1747 for backend in builder.config.codegen_backends(target) {
1748 if backend == "llvm" {
1749 continue; }
1751
1752 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1753 let dylib = t!(fs::read_to_string(stamp.path()));
1754 let file = Path::new(&dylib);
1755 let filename = file.file_name().unwrap().to_str().unwrap();
1756 let target_filename = {
1759 let dash = filename.find('-').unwrap();
1760 let dot = filename.find('.').unwrap();
1761 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1762 };
1763 builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
1764 }
1765}
1766
1767pub fn compiler_file(
1768 builder: &Builder<'_>,
1769 compiler: &Path,
1770 target: TargetSelection,
1771 c: CLang,
1772 file: &str,
1773) -> PathBuf {
1774 if builder.config.dry_run() {
1775 return PathBuf::new();
1776 }
1777 let mut cmd = command(compiler);
1778 cmd.args(builder.cc_handled_clags(target, c));
1779 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1780 cmd.arg(format!("-print-file-name={file}"));
1781 let out = cmd.run_capture_stdout(builder).stdout();
1782 PathBuf::from(out.trim())
1783}
1784
1785#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1786pub struct Sysroot {
1787 pub compiler: Compiler,
1788 force_recompile: bool,
1790}
1791
1792impl Sysroot {
1793 pub(crate) fn new(compiler: Compiler) -> Self {
1794 Sysroot { compiler, force_recompile: false }
1795 }
1796}
1797
1798impl Step for Sysroot {
1799 type Output = PathBuf;
1800
1801 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1802 run.never()
1803 }
1804
1805 #[cfg_attr(
1809 feature = "tracing",
1810 instrument(
1811 level = "debug",
1812 name = "Sysroot::run",
1813 skip_all,
1814 fields(compiler = ?self.compiler),
1815 ),
1816 )]
1817 fn run(self, builder: &Builder<'_>) -> PathBuf {
1818 let compiler = self.compiler;
1819 let host_dir = builder.out.join(compiler.host);
1820
1821 let sysroot_dir = |stage| {
1822 if stage == 0 {
1823 host_dir.join("stage0-sysroot")
1824 } else if self.force_recompile && stage == compiler.stage {
1825 host_dir.join(format!("stage{stage}-test-sysroot"))
1826 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1827 host_dir.join("ci-rustc-sysroot")
1828 } else {
1829 host_dir.join(format!("stage{stage}"))
1830 }
1831 };
1832 let sysroot = sysroot_dir(compiler.stage);
1833 trace!(stage = ?compiler.stage, ?sysroot);
1834
1835 builder
1836 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1837 let _ = fs::remove_dir_all(&sysroot);
1838 t!(fs::create_dir_all(&sysroot));
1839
1840 if compiler.stage == 0 {
1847 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1848 }
1849
1850 if builder.download_rustc() && compiler.stage != 0 {
1852 assert_eq!(
1853 builder.config.host_target, compiler.host,
1854 "Cross-compiling is not yet supported with `download-rustc`",
1855 );
1856
1857 for stage in 0..=2 {
1859 if stage != compiler.stage {
1860 let dir = sysroot_dir(stage);
1861 if !dir.ends_with("ci-rustc-sysroot") {
1862 let _ = fs::remove_dir_all(dir);
1863 }
1864 }
1865 }
1866
1867 let mut filtered_files = Vec::new();
1877 let mut add_filtered_files = |suffix, contents| {
1878 for path in contents {
1879 let path = Path::new(&path);
1880 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1881 filtered_files.push(path.file_name().unwrap().to_owned());
1882 }
1883 }
1884 };
1885 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1886 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1887 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1890
1891 let filtered_extensions = [
1892 OsStr::new("rmeta"),
1893 OsStr::new("rlib"),
1894 OsStr::new(std::env::consts::DLL_EXTENSION),
1896 ];
1897 let ci_rustc_dir = builder.config.ci_rustc_dir();
1898 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1899 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1900 return true;
1901 }
1902 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1903 return true;
1904 }
1905 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1906 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1907 false
1908 } else {
1909 true
1910 }
1911 });
1912 }
1913
1914 if compiler.stage != 0 {
1920 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1921 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1922 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1923 if let Err(e) =
1924 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1925 {
1926 eprintln!(
1927 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1928 sysroot_lib_rustlib_src_rust.display(),
1929 builder.src.display(),
1930 e,
1931 );
1932 if builder.config.rust_remap_debuginfo {
1933 eprintln!(
1934 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1935 sysroot_lib_rustlib_src_rust.display(),
1936 );
1937 }
1938 build_helper::exit!(1);
1939 }
1940 }
1941
1942 if !builder.download_rustc() {
1944 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1945 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1946 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1947 if let Err(e) =
1948 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1949 {
1950 eprintln!(
1951 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1952 sysroot_lib_rustlib_rustcsrc_rust.display(),
1953 builder.src.display(),
1954 e,
1955 );
1956 build_helper::exit!(1);
1957 }
1958 }
1959
1960 sysroot
1961 }
1962}
1963
1964#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1965pub struct Assemble {
1966 pub target_compiler: Compiler,
1971}
1972
1973impl Step for Assemble {
1974 type Output = Compiler;
1975 const ONLY_HOSTS: bool = true;
1976
1977 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1978 run.path("compiler/rustc").path("compiler")
1979 }
1980
1981 fn make_run(run: RunConfig<'_>) {
1982 run.builder.ensure(Assemble {
1983 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1984 });
1985 }
1986
1987 #[cfg_attr(
1993 feature = "tracing",
1994 instrument(
1995 level = "debug",
1996 name = "Assemble::run",
1997 skip_all,
1998 fields(target_compiler = ?self.target_compiler),
1999 ),
2000 )]
2001 fn run(self, builder: &Builder<'_>) -> Compiler {
2002 let target_compiler = self.target_compiler;
2003
2004 if target_compiler.stage == 0 {
2005 trace!("stage 0 build compiler is always available, simply returning");
2006 assert_eq!(
2007 builder.config.host_target, target_compiler.host,
2008 "Cannot obtain compiler for non-native build triple at stage 0"
2009 );
2010 return target_compiler;
2012 }
2013
2014 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2017 let libdir_bin = libdir.parent().unwrap().join("bin");
2018 t!(fs::create_dir_all(&libdir_bin));
2019
2020 if builder.config.llvm_enabled(target_compiler.host) {
2021 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2022
2023 let llvm::LlvmResult { llvm_config, .. } =
2024 builder.ensure(llvm::Llvm { target: target_compiler.host });
2025 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2026 trace!("LLVM tools enabled");
2027
2028 let llvm_bin_dir =
2029 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
2030 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
2031
2032 #[cfg(feature = "tracing")]
2039 let _llvm_tools_span =
2040 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2041 .entered();
2042 for tool in LLVM_TOOLS {
2043 trace!("installing `{tool}`");
2044 let tool_exe = exe(tool, target_compiler.host);
2045 let src_path = llvm_bin_dir.join(&tool_exe);
2046
2047 if !src_path.exists() && builder.config.llvm_from_ci {
2049 eprintln!("{} does not exist; skipping copy", src_path.display());
2050 continue;
2051 }
2052
2053 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2060 }
2061 }
2062 }
2063
2064 let maybe_install_llvm_bitcode_linker = |compiler| {
2065 if builder.config.llvm_bitcode_linker_enabled {
2066 trace!("llvm-bitcode-linker enabled, installing");
2067 let llvm_bitcode_linker =
2068 builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
2069 compiler,
2070 target: target_compiler.host,
2071 extra_features: vec![],
2072 });
2073 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2074 builder.copy_link(
2075 &llvm_bitcode_linker.tool_path,
2076 &libdir_bin.join(tool_exe),
2077 FileType::Executable,
2078 );
2079 }
2080 };
2081
2082 if builder.download_rustc() {
2084 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2085
2086 builder.std(target_compiler, target_compiler.host);
2087 let sysroot =
2088 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2089 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2092 if target_compiler.stage == builder.top_stage {
2094 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
2095 }
2096
2097 let mut precompiled_compiler = target_compiler;
2098 precompiled_compiler.forced_compiler(true);
2099 maybe_install_llvm_bitcode_linker(precompiled_compiler);
2100
2101 return target_compiler;
2102 }
2103
2104 debug!(
2118 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2119 target_compiler.stage - 1,
2120 builder.config.host_target,
2121 );
2122 let mut build_compiler =
2123 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2124
2125 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2127 debug!("`llvm_enzyme` requested");
2128 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2129 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2130 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2131 let lib_ext = std::env::consts::DLL_EXTENSION;
2132 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2133 let src_lib =
2134 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2135 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2136 let target_libdir =
2137 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2138 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2139 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2140 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2141 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2142 }
2143 }
2144
2145 debug!(
2151 ?build_compiler,
2152 "target_compiler.host" = ?target_compiler.host,
2153 "building compiler libraries to link to"
2154 );
2155 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2156 debug!(
2159 "(old) build_compiler.stage" = build_compiler.stage,
2160 "(adjusted) build_compiler.stage" = actual_stage,
2161 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2162 );
2163 build_compiler.stage = actual_stage;
2164
2165 #[cfg(feature = "tracing")]
2166 let _codegen_backend_span =
2167 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2168 for backend in builder.config.codegen_backends(target_compiler.host) {
2169 if backend == "llvm" {
2170 debug!("llvm codegen backend is already built as part of rustc");
2171 continue; }
2173
2174 builder.ensure(CodegenBackend {
2175 compiler: build_compiler,
2176 target: target_compiler.host,
2177 backend: backend.clone(),
2178 });
2179 }
2180 #[cfg(feature = "tracing")]
2181 drop(_codegen_backend_span);
2182
2183 let stage = target_compiler.stage;
2184 let host = target_compiler.host;
2185 let (host_info, dir_name) = if build_compiler.host == host {
2186 ("".into(), "host".into())
2187 } else {
2188 (format!(" ({host})"), host.to_string())
2189 };
2190 let msg = format!(
2195 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2196 );
2197 builder.info(&msg);
2198
2199 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2201 let proc_macros = builder
2202 .read_stamp_file(&stamp)
2203 .into_iter()
2204 .filter_map(|(path, dependency_type)| {
2205 if dependency_type == DependencyType::Host {
2206 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2207 } else {
2208 None
2209 }
2210 })
2211 .collect::<HashSet<_>>();
2212
2213 let sysroot = builder.sysroot(target_compiler);
2214 let rustc_libdir = builder.rustc_libdir(target_compiler);
2215 t!(fs::create_dir_all(&rustc_libdir));
2216 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2217 for f in builder.read_dir(&src_libdir) {
2218 let filename = f.file_name().into_string().unwrap();
2219
2220 let is_proc_macro = proc_macros.contains(&filename);
2221 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2222
2223 let can_be_rustc_dynamic_dep = if builder
2227 .link_std_into_rustc_driver(target_compiler.host)
2228 && !target_compiler.host.is_windows()
2229 {
2230 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2231 !is_std
2232 } else {
2233 true
2234 };
2235
2236 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2237 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2238 }
2239 }
2240
2241 debug!("copying codegen backends to sysroot");
2242 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2243
2244 if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) {
2245 builder.ensure(crate::core::build_steps::tool::LldWrapper {
2246 build_compiler,
2247 target_compiler,
2248 });
2249 }
2250
2251 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2252 debug!(
2253 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2254 workaround faulty homebrew `strip`s"
2255 );
2256
2257 let src_exe = exe("llvm-objcopy", target_compiler.host);
2264 let dst_exe = exe("rust-objcopy", target_compiler.host);
2265 builder.copy_link(
2266 &libdir_bin.join(src_exe),
2267 &libdir_bin.join(dst_exe),
2268 FileType::Executable,
2269 );
2270 }
2271
2272 if builder.tool_enabled("wasm-component-ld") {
2278 let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
2279 compiler: build_compiler,
2280 target: target_compiler.host,
2281 });
2282 builder.copy_link(
2283 &wasm_component.tool_path,
2284 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2285 FileType::Executable,
2286 );
2287 }
2288
2289 maybe_install_llvm_bitcode_linker(target_compiler);
2290
2291 debug!(
2294 "target_compiler.host" = ?target_compiler.host,
2295 ?sysroot,
2296 "ensuring availability of `libLLVM.so` in compiler directory"
2297 );
2298 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2299 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2300
2301 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2303 let rustc = out_dir.join(exe("rustc-main", host));
2304 let bindir = sysroot.join("bin");
2305 t!(fs::create_dir_all(bindir));
2306 let compiler = builder.rustc(target_compiler);
2307 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2308 builder.copy_link(&rustc, &compiler, FileType::Executable);
2309
2310 target_compiler
2311 }
2312}
2313
2314pub fn add_to_sysroot(
2319 builder: &Builder<'_>,
2320 sysroot_dst: &Path,
2321 sysroot_host_dst: &Path,
2322 stamp: &BuildStamp,
2323) {
2324 let self_contained_dst = &sysroot_dst.join("self-contained");
2325 t!(fs::create_dir_all(sysroot_dst));
2326 t!(fs::create_dir_all(sysroot_host_dst));
2327 t!(fs::create_dir_all(self_contained_dst));
2328 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2329 let dst = match dependency_type {
2330 DependencyType::Host => sysroot_host_dst,
2331 DependencyType::Target => sysroot_dst,
2332 DependencyType::TargetSelfContained => self_contained_dst,
2333 };
2334 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2335 }
2336}
2337
2338pub fn run_cargo(
2339 builder: &Builder<'_>,
2340 cargo: Cargo,
2341 tail_args: Vec<String>,
2342 stamp: &BuildStamp,
2343 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2344 is_check: bool,
2345 rlib_only_metadata: bool,
2346) -> Vec<PathBuf> {
2347 let target_root_dir = stamp.path().parent().unwrap();
2349 let target_deps_dir = target_root_dir.join("deps");
2351 let host_root_dir = target_root_dir
2353 .parent()
2354 .unwrap() .parent()
2356 .unwrap() .join(target_root_dir.file_name().unwrap());
2358
2359 let mut deps = Vec::new();
2363 let mut toplevel = Vec::new();
2364 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2365 let (filenames, crate_types) = match msg {
2366 CargoMessage::CompilerArtifact {
2367 filenames,
2368 target: CargoTarget { crate_types },
2369 ..
2370 } => (filenames, crate_types),
2371 _ => return,
2372 };
2373 for filename in filenames {
2374 let mut keep = false;
2376 if filename.ends_with(".lib")
2377 || filename.ends_with(".a")
2378 || is_debug_info(&filename)
2379 || is_dylib(Path::new(&*filename))
2380 {
2381 keep = true;
2383 }
2384 if is_check && filename.ends_with(".rmeta") {
2385 keep = true;
2387 } else if rlib_only_metadata {
2388 if filename.contains("jemalloc_sys")
2389 || filename.contains("rustc_smir")
2390 || filename.contains("stable_mir")
2391 {
2392 keep |= filename.ends_with(".rlib");
2395 } else {
2396 keep |= filename.ends_with(".rmeta");
2400 }
2401 } else {
2402 keep |= filename.ends_with(".rlib");
2404 }
2405
2406 if !keep {
2407 continue;
2408 }
2409
2410 let filename = Path::new(&*filename);
2411
2412 if filename.starts_with(&host_root_dir) {
2415 if crate_types.iter().any(|t| t == "proc-macro") {
2417 deps.push((filename.to_path_buf(), DependencyType::Host));
2418 }
2419 continue;
2420 }
2421
2422 if filename.starts_with(&target_deps_dir) {
2425 deps.push((filename.to_path_buf(), DependencyType::Target));
2426 continue;
2427 }
2428
2429 let expected_len = t!(filename.metadata()).len();
2440 let filename = filename.file_name().unwrap().to_str().unwrap();
2441 let mut parts = filename.splitn(2, '.');
2442 let file_stem = parts.next().unwrap().to_owned();
2443 let extension = parts.next().unwrap().to_owned();
2444
2445 toplevel.push((file_stem, extension, expected_len));
2446 }
2447 });
2448
2449 if !ok {
2450 crate::exit!(1);
2451 }
2452
2453 if builder.config.dry_run() {
2454 return Vec::new();
2455 }
2456
2457 let contents = target_deps_dir
2461 .read_dir()
2462 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2463 .map(|e| t!(e))
2464 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2465 .collect::<Vec<_>>();
2466 for (prefix, extension, expected_len) in toplevel {
2467 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2468 meta.len() == expected_len
2469 && filename
2470 .strip_prefix(&prefix[..])
2471 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2472 .unwrap_or(false)
2473 });
2474 let max = candidates.max_by_key(|&(_, _, metadata)| {
2475 metadata.modified().expect("mtime should be available on all relevant OSes")
2476 });
2477 let path_to_add = match max {
2478 Some(triple) => triple.0.to_str().unwrap(),
2479 None => panic!("no output generated for {prefix:?} {extension:?}"),
2480 };
2481 if is_dylib(Path::new(path_to_add)) {
2482 let candidate = format!("{path_to_add}.lib");
2483 let candidate = PathBuf::from(candidate);
2484 if candidate.exists() {
2485 deps.push((candidate, DependencyType::Target));
2486 }
2487 }
2488 deps.push((path_to_add.into(), DependencyType::Target));
2489 }
2490
2491 deps.extend(additional_target_deps);
2492 deps.sort();
2493 let mut new_contents = Vec::new();
2494 for (dep, dependency_type) in deps.iter() {
2495 new_contents.extend(match *dependency_type {
2496 DependencyType::Host => b"h",
2497 DependencyType::Target => b"t",
2498 DependencyType::TargetSelfContained => b"s",
2499 });
2500 new_contents.extend(dep.to_str().unwrap().as_bytes());
2501 new_contents.extend(b"\0");
2502 }
2503 t!(fs::write(stamp.path(), &new_contents));
2504 deps.into_iter().map(|(d, _)| d).collect()
2505}
2506
2507pub fn stream_cargo(
2508 builder: &Builder<'_>,
2509 cargo: Cargo,
2510 tail_args: Vec<String>,
2511 cb: &mut dyn FnMut(CargoMessage<'_>),
2512) -> bool {
2513 let mut cmd = cargo.into_cmd();
2514
2515 #[cfg(feature = "tracing")]
2516 let _run_span = crate::trace_cmd!(cmd);
2517
2518 let cargo = cmd.as_command_mut();
2519 let mut message_format = if builder.config.json_output {
2522 String::from("json")
2523 } else {
2524 String::from("json-render-diagnostics")
2525 };
2526 if let Some(s) = &builder.config.rustc_error_format {
2527 message_format.push_str(",json-diagnostic-");
2528 message_format.push_str(s);
2529 }
2530 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
2531
2532 for arg in tail_args {
2533 cargo.arg(arg);
2534 }
2535
2536 builder.verbose(|| println!("running: {cargo:?}"));
2537
2538 if builder.config.dry_run() {
2539 return true;
2540 }
2541
2542 let mut child = match cargo.spawn() {
2543 Ok(child) => child,
2544 Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"),
2545 };
2546
2547 let stdout = BufReader::new(child.stdout.take().unwrap());
2551 for line in stdout.lines() {
2552 let line = t!(line);
2553 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2554 Ok(msg) => {
2555 if builder.config.json_output {
2556 println!("{line}");
2558 }
2559 cb(msg)
2560 }
2561 Err(_) => println!("{line}"),
2563 }
2564 }
2565
2566 let status = t!(child.wait());
2568 if builder.is_verbose() && !status.success() {
2569 eprintln!(
2570 "command did not execute successfully: {cargo:?}\n\
2571 expected success, got: {status}"
2572 );
2573 }
2574 status.success()
2575}
2576
2577#[derive(Deserialize)]
2578pub struct CargoTarget<'a> {
2579 crate_types: Vec<Cow<'a, str>>,
2580}
2581
2582#[derive(Deserialize)]
2583#[serde(tag = "reason", rename_all = "kebab-case")]
2584pub enum CargoMessage<'a> {
2585 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2586 BuildScriptExecuted,
2587 BuildFinished,
2588}
2589
2590pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2591 if target != "x86_64-unknown-linux-gnu"
2595 || !builder.config.is_host_target(target)
2596 || !path.exists()
2597 {
2598 return;
2599 }
2600
2601 let previous_mtime = t!(t!(path.metadata()).modified());
2602 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2603
2604 let file = t!(fs::File::open(path));
2605
2606 t!(file.set_modified(previous_mtime));
2619}
2620
2621pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2623 build_compiler.stage != 0
2624}