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 builder.require_submodule("library/stdarch", None);
201
202 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
203
204 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
205 trace!(?compiler_to_use);
206
207 if compiler_to_use != compiler
208 && compiler.stage > 1
213 {
214 trace!(?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library");
215
216 builder.ensure(Std::new(compiler_to_use, target));
217 let msg = if compiler_to_use.host == target {
218 format!(
219 "Uplifting library (stage{} -> stage{})",
220 compiler_to_use.stage, compiler.stage
221 )
222 } else {
223 format!(
224 "Uplifting library (stage{}:{} -> stage{}:{})",
225 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
226 )
227 };
228 builder.info(&msg);
229
230 self.copy_extra_objects(builder, &compiler, target);
233
234 builder.ensure(StdLink::from_std(self, compiler_to_use));
235 return;
236 }
237
238 trace!(
239 ?compiler_to_use,
240 ?compiler,
241 "compiler == compiler_to_use, handling not-cross-compile scenario"
242 );
243
244 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
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.host_target),
307 ));
308 }
309
310 fn metadata(&self) -> Option<StepMetadata> {
311 Some(
312 StepMetadata::build("std", self.target)
313 .built_by(self.compiler)
314 .stage(self.compiler.stage),
315 )
316 }
317}
318
319fn copy_and_stamp(
320 builder: &Builder<'_>,
321 libdir: &Path,
322 sourcedir: &Path,
323 name: &str,
324 target_deps: &mut Vec<(PathBuf, DependencyType)>,
325 dependency_type: DependencyType,
326) {
327 let target = libdir.join(name);
328 builder.copy_link(&sourcedir.join(name), &target, FileType::Regular);
329
330 target_deps.push((target, dependency_type));
331}
332
333fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
334 let libunwind_path = builder.ensure(llvm::Libunwind { target });
335 let libunwind_source = libunwind_path.join("libunwind.a");
336 let libunwind_target = libdir.join("libunwind.a");
337 builder.copy_link(&libunwind_source, &libunwind_target, FileType::NativeLibrary);
338 libunwind_target
339}
340
341fn copy_third_party_objects(
343 builder: &Builder<'_>,
344 compiler: &Compiler,
345 target: TargetSelection,
346) -> Vec<(PathBuf, DependencyType)> {
347 let mut target_deps = vec![];
348
349 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
350 target_deps.extend(
353 copy_sanitizers(builder, compiler, target)
354 .into_iter()
355 .map(|d| (d, DependencyType::Target)),
356 );
357 }
358
359 if target == "x86_64-fortanix-unknown-sgx"
360 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
361 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
362 {
363 let libunwind_path =
364 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
365 target_deps.push((libunwind_path, DependencyType::Target));
366 }
367
368 target_deps
369}
370
371fn copy_self_contained_objects(
373 builder: &Builder<'_>,
374 compiler: &Compiler,
375 target: TargetSelection,
376) -> Vec<(PathBuf, DependencyType)> {
377 let libdir_self_contained =
378 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
379 t!(fs::create_dir_all(&libdir_self_contained));
380 let mut target_deps = vec![];
381
382 if target.needs_crt_begin_end() {
390 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
391 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
392 });
393 if !target.starts_with("wasm32") {
394 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
395 copy_and_stamp(
396 builder,
397 &libdir_self_contained,
398 &srcdir,
399 obj,
400 &mut target_deps,
401 DependencyType::TargetSelfContained,
402 );
403 }
404 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
405 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
406 let src = crt_path.join(obj);
407 let target = libdir_self_contained.join(obj);
408 builder.copy_link(&src, &target, FileType::NativeLibrary);
409 target_deps.push((target, DependencyType::TargetSelfContained));
410 }
411 } else {
412 for &obj in &["libc.a", "crt1-command.o"] {
415 copy_and_stamp(
416 builder,
417 &libdir_self_contained,
418 &srcdir,
419 obj,
420 &mut target_deps,
421 DependencyType::TargetSelfContained,
422 );
423 }
424 }
425 if !target.starts_with("s390x") {
426 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
427 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
428 }
429 } else if target.contains("-wasi") {
430 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
431 panic!(
432 "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \
433 or `$WASI_SDK_PATH` set",
434 target.triple
435 )
436 });
437 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
438 copy_and_stamp(
439 builder,
440 &libdir_self_contained,
441 &srcdir,
442 obj,
443 &mut target_deps,
444 DependencyType::TargetSelfContained,
445 );
446 }
447 } else if target.is_windows_gnu() {
448 for obj in ["crt2.o", "dllcrt2.o"].iter() {
449 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
450 let dst = libdir_self_contained.join(obj);
451 builder.copy_link(&src, &dst, FileType::NativeLibrary);
452 target_deps.push((dst, DependencyType::TargetSelfContained));
453 }
454 }
455
456 target_deps
457}
458
459pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
461 if cfg!(test) {
463 return vec![];
464 }
465
466 let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
467 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
468
469 if target_is_no_std {
471 vec![]
472 }
473 else if has_alias {
475 run.make_run_crates(builder::Alias::Library)
476 } else {
477 run.cargo_crates_in_set()
478 }
479}
480
481fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
487 if builder.config.llvm_from_ci {
489 builder.config.maybe_download_ci_llvm();
491 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
492 if ci_llvm_compiler_rt.exists() {
493 return ci_llvm_compiler_rt;
494 }
495 }
496
497 builder.require_submodule("src/llvm-project", {
499 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
500 });
501 builder.src.join("src/llvm-project/compiler-rt")
502}
503
504pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
507 if target.contains("apple") && !builder.config.dry_run() {
525 let mut cmd = command(builder.rustc(cargo.compiler()));
529 cmd.arg("--target").arg(target.rustc_target_arg());
530 cmd.arg("--print=deployment-target");
531 let output = cmd.run_capture_stdout(builder).stdout();
532
533 let (env_var, value) = output.split_once('=').unwrap();
534 cargo.env(env_var.trim(), value.trim());
537
538 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
548 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
549 }
550 }
551
552 if let Some(path) = builder.config.profiler_path(target) {
554 cargo.env("LLVM_PROFILER_RT_LIB", path);
555 } else if builder.config.profiler_enabled(target) {
556 let compiler_rt = compiler_rt_for_profiler(builder);
557 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
561 }
562
563 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
577 builder.require_submodule(
585 "src/llvm-project",
586 Some(
587 "The `build.optimized-compiler-builtins` config option \
588 requires `compiler-rt` sources from LLVM.",
589 ),
590 );
591 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
592 assert!(compiler_builtins_root.exists());
593 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
596 " compiler-builtins-c"
597 } else {
598 ""
599 };
600
601 if !builder.unstable_features() {
604 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
605 }
606
607 let mut features = String::new();
608
609 if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
610 {
611 features += "compiler-builtins-no-f16-f128 ";
612 }
613
614 if builder.no_std(target) == Some(true) {
615 features += " compiler-builtins-mem";
616 if !target.starts_with("bpf") {
617 features.push_str(compiler_builtins_c_feature);
618 }
619
620 cargo
622 .args(["-p", "alloc"])
623 .arg("--manifest-path")
624 .arg(builder.src.join("library/alloc/Cargo.toml"))
625 .arg("--features")
626 .arg(features);
627 } else {
628 features += &builder.std_features(target);
629 features.push_str(compiler_builtins_c_feature);
630
631 cargo
632 .arg("--features")
633 .arg(features)
634 .arg("--manifest-path")
635 .arg(builder.src.join("library/sysroot/Cargo.toml"));
636
637 if target.contains("musl")
640 && let Some(p) = builder.musl_libdir(target)
641 {
642 let root = format!("native={}", p.to_str().unwrap());
643 cargo.rustflag("-L").rustflag(&root);
644 }
645
646 if target.contains("-wasi")
647 && let Some(dir) = builder.wasi_libdir(target)
648 {
649 let root = format!("native={}", dir.to_str().unwrap());
650 cargo.rustflag("-L").rustflag(&root);
651 }
652 }
653
654 if stage >= 1 {
663 cargo.rustflag("-Cembed-bitcode=yes");
664 }
665 if builder.config.rust_lto == RustcLto::Off {
666 cargo.rustflag("-Clto=off");
667 }
668
669 if target.contains("riscv") {
676 cargo.rustflag("-Cforce-unwind-tables=yes");
677 }
678
679 cargo.rustflag("-Zunstable-options");
682 cargo.rustflag("-Cforce-frame-pointers=non-leaf");
683
684 let html_root =
685 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
686 cargo.rustflag(&html_root);
687 cargo.rustdocflag(&html_root);
688
689 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
690}
691
692#[derive(Debug, Clone, PartialEq, Eq, Hash)]
693struct StdLink {
694 pub compiler: Compiler,
695 pub target_compiler: Compiler,
696 pub target: TargetSelection,
697 crates: Vec<String>,
699 force_recompile: bool,
701}
702
703impl StdLink {
704 fn from_std(std: Std, host_compiler: Compiler) -> Self {
705 Self {
706 compiler: host_compiler,
707 target_compiler: std.compiler,
708 target: std.target,
709 crates: std.crates,
710 force_recompile: std.force_recompile,
711 }
712 }
713}
714
715impl Step for StdLink {
716 type Output = ();
717
718 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
719 run.never()
720 }
721
722 #[cfg_attr(
731 feature = "tracing",
732 instrument(
733 level = "trace",
734 name = "StdLink::run",
735 skip_all,
736 fields(
737 compiler = ?self.compiler,
738 target_compiler = ?self.target_compiler,
739 target = ?self.target
740 ),
741 ),
742 )]
743 fn run(self, builder: &Builder<'_>) {
744 let compiler = self.compiler;
745 let target_compiler = self.target_compiler;
746 let target = self.target;
747
748 let (libdir, hostdir) = if !self.force_recompile && builder.download_rustc() {
750 let lib = builder.sysroot_libdir_relative(self.compiler);
752 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
753 compiler: self.compiler,
754 force_recompile: self.force_recompile,
755 });
756 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
757 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
758 (libdir, hostdir)
759 } else {
760 let libdir = builder.sysroot_target_libdir(target_compiler, target);
761 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
762 (libdir, hostdir)
763 };
764
765 let is_downloaded_beta_stage0 = builder
766 .build
767 .config
768 .initial_rustc
769 .starts_with(builder.out.join(compiler.host).join("stage0/bin"));
770
771 if compiler.stage == 0 && is_downloaded_beta_stage0 {
775 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
777
778 let host = compiler.host;
779 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
780 let sysroot_bin_dir = sysroot.join("bin");
781 t!(fs::create_dir_all(&sysroot_bin_dir));
782 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
783
784 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
785 t!(fs::create_dir_all(sysroot.join("lib")));
786 builder.cp_link_r(&stage0_lib_dir, &sysroot.join("lib"));
787
788 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
790 t!(fs::create_dir_all(&sysroot_codegen_backends));
791 let stage0_codegen_backends = builder
792 .out
793 .join(host)
794 .join("stage0/lib/rustlib")
795 .join(host)
796 .join("codegen-backends");
797 if stage0_codegen_backends.exists() {
798 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
799 }
800 } else if compiler.stage == 0 {
801 let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
802
803 if builder.local_rebuild {
804 let _ = fs::remove_dir_all(sysroot.join("lib/rustlib/src/rust"));
808 }
809
810 builder.cp_link_r(&builder.initial_sysroot.join("lib"), &sysroot.join("lib"));
811 } else {
812 if builder.download_rustc() {
813 let _ = fs::remove_dir_all(&libdir);
815 let _ = fs::remove_dir_all(&hostdir);
816 }
817
818 add_to_sysroot(
819 builder,
820 &libdir,
821 &hostdir,
822 &build_stamp::libstd_stamp(builder, compiler, target),
823 );
824 }
825 }
826}
827
828fn copy_sanitizers(
830 builder: &Builder<'_>,
831 compiler: &Compiler,
832 target: TargetSelection,
833) -> Vec<PathBuf> {
834 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
835
836 if builder.config.dry_run() {
837 return Vec::new();
838 }
839
840 let mut target_deps = Vec::new();
841 let libdir = builder.sysroot_target_libdir(*compiler, target);
842
843 for runtime in &runtimes {
844 let dst = libdir.join(&runtime.name);
845 builder.copy_link(&runtime.path, &dst, FileType::NativeLibrary);
846
847 if target == "x86_64-apple-darwin"
851 || target == "aarch64-apple-darwin"
852 || target == "aarch64-apple-ios"
853 || target == "aarch64-apple-ios-sim"
854 || target == "x86_64-apple-ios"
855 {
856 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
858 apple_darwin_sign_file(builder, &dst);
861 }
862
863 target_deps.push(dst);
864 }
865
866 target_deps
867}
868
869fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
870 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
871}
872
873fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
874 command("codesign")
875 .arg("-f") .arg("-s")
877 .arg("-")
878 .arg(file_path)
879 .run(builder);
880}
881
882#[derive(Debug, Clone, PartialEq, Eq, Hash)]
883pub struct StartupObjects {
884 pub compiler: Compiler,
885 pub target: TargetSelection,
886}
887
888impl Step for StartupObjects {
889 type Output = Vec<(PathBuf, DependencyType)>;
890
891 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
892 run.path("library/rtstartup")
893 }
894
895 fn make_run(run: RunConfig<'_>) {
896 run.builder.ensure(StartupObjects {
897 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
898 target: run.target,
899 });
900 }
901
902 #[cfg_attr(
909 feature = "tracing",
910 instrument(
911 level = "trace",
912 name = "StartupObjects::run",
913 skip_all,
914 fields(compiler = ?self.compiler, target = ?self.target),
915 ),
916 )]
917 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
918 let for_compiler = self.compiler;
919 let target = self.target;
920 if !target.is_windows_gnu() {
921 return vec![];
922 }
923
924 let mut target_deps = vec![];
925
926 let src_dir = &builder.src.join("library").join("rtstartup");
927 let dst_dir = &builder.native_dir(target).join("rtstartup");
928 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
929 t!(fs::create_dir_all(dst_dir));
930
931 for file in &["rsbegin", "rsend"] {
932 let src_file = &src_dir.join(file.to_string() + ".rs");
933 let dst_file = &dst_dir.join(file.to_string() + ".o");
934 if !up_to_date(src_file, dst_file) {
935 let mut cmd = command(&builder.initial_rustc);
936 cmd.env("RUSTC_BOOTSTRAP", "1");
937 if !builder.local_rebuild {
938 cmd.arg("--cfg").arg("bootstrap");
940 }
941 cmd.arg("--target")
942 .arg(target.rustc_target_arg())
943 .arg("--emit=obj")
944 .arg("-o")
945 .arg(dst_file)
946 .arg(src_file)
947 .run(builder);
948 }
949
950 let obj = sysroot_dir.join((*file).to_string() + ".o");
951 builder.copy_link(dst_file, &obj, FileType::NativeLibrary);
952 target_deps.push((obj, DependencyType::Target));
953 }
954
955 target_deps
956 }
957}
958
959fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
960 let ci_rustc_dir = builder.config.ci_rustc_dir();
961
962 for file in contents {
963 let src = ci_rustc_dir.join(&file);
964 let dst = sysroot.join(file);
965 if src.is_dir() {
966 t!(fs::create_dir_all(dst));
967 } else {
968 builder.copy_link(&src, &dst, FileType::Regular);
969 }
970 }
971}
972
973#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
980pub struct Rustc {
981 pub target: TargetSelection,
983 pub build_compiler: Compiler,
985 crates: Vec<String>,
991}
992
993impl Rustc {
994 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
995 Self { target, build_compiler, crates: Default::default() }
996 }
997}
998
999impl Step for Rustc {
1000 type Output = u32;
1008 const ONLY_HOSTS: bool = true;
1009 const DEFAULT: bool = false;
1010
1011 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1012 let mut crates = run.builder.in_tree_crates("rustc-main", None);
1013 for (i, krate) in crates.iter().enumerate() {
1014 if krate.name == "rustc-main" {
1017 crates.swap_remove(i);
1018 break;
1019 }
1020 }
1021 run.crates(crates)
1022 }
1023
1024 fn make_run(run: RunConfig<'_>) {
1025 let crates = run.cargo_crates_in_set();
1026 run.builder.ensure(Rustc {
1027 build_compiler: run
1028 .builder
1029 .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
1030 target: run.target,
1031 crates,
1032 });
1033 }
1034
1035 #[cfg_attr(
1041 feature = "tracing",
1042 instrument(
1043 level = "debug",
1044 name = "Rustc::run",
1045 skip_all,
1046 fields(previous_compiler = ?self.build_compiler, target = ?self.target),
1047 ),
1048 )]
1049 fn run(self, builder: &Builder<'_>) -> u32 {
1050 let build_compiler = self.build_compiler;
1051 let target = self.target;
1052
1053 if builder.download_rustc() && build_compiler.stage != 0 {
1056 trace!(stage = build_compiler.stage, "`download_rustc` requested");
1057
1058 let sysroot =
1059 builder.ensure(Sysroot { compiler: build_compiler, force_recompile: false });
1060 cp_rustc_component_to_ci_sysroot(
1061 builder,
1062 &sysroot,
1063 builder.config.ci_rustc_dev_contents(),
1064 );
1065 return build_compiler.stage;
1066 }
1067
1068 builder.ensure(Std::new(build_compiler, target));
1071
1072 if builder.config.keep_stage.contains(&build_compiler.stage) {
1073 trace!(stage = build_compiler.stage, "`keep-stage` requested");
1074
1075 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
1076 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
1077 builder.ensure(RustcLink::from_rustc(self, build_compiler));
1078
1079 return build_compiler.stage;
1080 }
1081
1082 let compiler_to_use =
1083 builder.compiler_for(build_compiler.stage, build_compiler.host, target);
1084 if compiler_to_use != build_compiler {
1085 builder.ensure(Rustc::new(compiler_to_use, target));
1086 let msg = if compiler_to_use.host == target {
1087 format!(
1088 "Uplifting rustc (stage{} -> stage{})",
1089 compiler_to_use.stage,
1090 build_compiler.stage + 1
1091 )
1092 } else {
1093 format!(
1094 "Uplifting rustc (stage{}:{} -> stage{}:{})",
1095 compiler_to_use.stage,
1096 compiler_to_use.host,
1097 build_compiler.stage + 1,
1098 target
1099 )
1100 };
1101 builder.info(&msg);
1102 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
1103 return compiler_to_use.stage;
1104 }
1105
1106 builder.ensure(Std::new(
1112 builder.compiler(self.build_compiler.stage, builder.config.host_target),
1113 builder.config.host_target,
1114 ));
1115
1116 let mut cargo = builder::Cargo::new(
1117 builder,
1118 build_compiler,
1119 Mode::Rustc,
1120 SourceType::InTree,
1121 target,
1122 Kind::Build,
1123 );
1124
1125 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
1126
1127 for krate in &*self.crates {
1131 cargo.arg("-p").arg(krate);
1132 }
1133
1134 if builder.build.config.enable_bolt_settings && build_compiler.stage == 1 {
1135 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1137 }
1138
1139 let _guard = builder.msg_sysroot_tool(
1140 Kind::Build,
1141 build_compiler.stage,
1142 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1143 build_compiler.host,
1144 target,
1145 );
1146 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
1147 run_cargo(
1148 builder,
1149 cargo,
1150 vec![],
1151 &stamp,
1152 vec![],
1153 false,
1154 true, );
1156
1157 let target_root_dir = stamp.path().parent().unwrap();
1158 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1164 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1165 {
1166 let rustc_driver = target_root_dir.join("librustc_driver.so");
1167 strip_debug(builder, target, &rustc_driver);
1168 }
1169
1170 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1171 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1174 }
1175
1176 builder.ensure(RustcLink::from_rustc(
1177 self,
1178 builder.compiler(build_compiler.stage, builder.config.host_target),
1179 ));
1180
1181 build_compiler.stage
1182 }
1183
1184 fn metadata(&self) -> Option<StepMetadata> {
1185 Some(
1186 StepMetadata::build("rustc", self.target)
1187 .built_by(self.build_compiler)
1188 .stage(self.build_compiler.stage + 1),
1189 )
1190 }
1191}
1192
1193pub fn rustc_cargo(
1194 builder: &Builder<'_>,
1195 cargo: &mut Cargo,
1196 target: TargetSelection,
1197 build_compiler: &Compiler,
1198 crates: &[String],
1199) {
1200 cargo
1201 .arg("--features")
1202 .arg(builder.rustc_features(builder.kind, target, crates))
1203 .arg("--manifest-path")
1204 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1205
1206 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1207
1208 cargo.rustflag("-Zon-broken-pipe=kill");
1222
1223 if builder.config.llvm_enzyme {
1226 let arch = builder.build.host_target;
1227 let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib");
1228 cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path"));
1229
1230 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
1231 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1232 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1233 }
1234 }
1235
1236 if builder.build.config.lld_mode.is_used() {
1241 cargo.rustflag("-Zdefault-visibility=protected");
1242 }
1243
1244 if is_lto_stage(build_compiler) {
1245 match builder.config.rust_lto {
1246 RustcLto::Thin | RustcLto::Fat => {
1247 cargo.rustflag("-Zdylib-lto");
1250 let lto_type = match builder.config.rust_lto {
1254 RustcLto::Thin => "thin",
1255 RustcLto::Fat => "fat",
1256 _ => unreachable!(),
1257 };
1258 cargo.rustflag(&format!("-Clto={lto_type}"));
1259 cargo.rustflag("-Cembed-bitcode=yes");
1260 }
1261 RustcLto::ThinLocal => { }
1262 RustcLto::Off => {
1263 cargo.rustflag("-Clto=off");
1264 }
1265 }
1266 } else if builder.config.rust_lto == RustcLto::Off {
1267 cargo.rustflag("-Clto=off");
1268 }
1269
1270 if builder.config.lld_mode.is_used() && !build_compiler.host.is_msvc() {
1278 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1279 }
1280
1281 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1282 panic!("Cannot use and generate PGO profiles at the same time");
1283 }
1284 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1285 if build_compiler.stage == 1 {
1286 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1287 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1290 true
1291 } else {
1292 false
1293 }
1294 } else if let Some(path) = &builder.config.rust_profile_use {
1295 if build_compiler.stage == 1 {
1296 cargo.rustflag(&format!("-Cprofile-use={path}"));
1297 if builder.is_verbose() {
1298 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1299 }
1300 true
1301 } else {
1302 false
1303 }
1304 } else {
1305 false
1306 };
1307 if is_collecting {
1308 cargo.rustflag(&format!(
1310 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1311 builder.config.src.components().count()
1312 ));
1313 }
1314
1315 if let Some(ref ccache) = builder.config.ccache
1320 && build_compiler.stage == 0
1321 && !builder.config.incremental
1322 {
1323 cargo.env("RUSTC_WRAPPER", ccache);
1324 }
1325
1326 rustc_cargo_env(builder, cargo, target, build_compiler.stage);
1327}
1328
1329pub fn rustc_cargo_env(
1330 builder: &Builder<'_>,
1331 cargo: &mut Cargo,
1332 target: TargetSelection,
1333 build_stage: u32,
1334) {
1335 cargo
1338 .env("CFG_RELEASE", builder.rust_release())
1339 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1340 .env("CFG_VERSION", builder.rust_version());
1341
1342 if builder.config.omit_git_hash {
1346 cargo.env("CFG_OMIT_GIT_HASH", "1");
1347 }
1348
1349 if let Some(backend) = builder.config.default_codegen_backend(target) {
1350 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1351 }
1352
1353 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1354 let target_config = builder.config.target_config.get(&target);
1355
1356 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1357
1358 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1359 cargo.env("CFG_VER_DATE", ver_date);
1360 }
1361 if let Some(ref ver_hash) = builder.rust_info().sha() {
1362 cargo.env("CFG_VER_HASH", ver_hash);
1363 }
1364 if !builder.unstable_features() {
1365 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1366 }
1367
1368 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1371 cargo.env("CFG_DEFAULT_LINKER", s);
1372 } else if let Some(ref s) = builder.config.rustc_default_linker {
1373 cargo.env("CFG_DEFAULT_LINKER", s);
1374 }
1375
1376 if builder.config.lld_enabled
1378 && (builder.config.channel == "dev" || builder.config.channel == "nightly")
1379 {
1380 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1381 }
1382
1383 if builder.config.rust_verify_llvm_ir {
1384 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1385 }
1386
1387 if builder.config.llvm_enzyme {
1388 cargo.rustflag("--cfg=llvm_enzyme");
1389 }
1390
1391 if builder.config.llvm_enabled(target) {
1396 let building_is_expensive =
1397 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1398 .should_build();
1399 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == build_stage;
1401 let should_skip_build = building_is_expensive && can_skip_build;
1402 if !should_skip_build {
1403 rustc_llvm_env(builder, cargo, target)
1404 }
1405 }
1406
1407 if builder.config.jemalloc(target)
1410 && target.starts_with("aarch64")
1411 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1412 {
1413 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1414 }
1415}
1416
1417fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1420 if builder.config.is_rust_llvm(target) {
1421 cargo.env("LLVM_RUSTLLVM", "1");
1422 }
1423 if builder.config.llvm_enzyme {
1424 cargo.env("LLVM_ENZYME", "1");
1425 }
1426 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1427 cargo.env("LLVM_CONFIG", &llvm_config);
1428
1429 let mut llvm_linker_flags = String::new();
1439 if builder.config.llvm_profile_generate
1440 && target.is_msvc()
1441 && let Some(ref clang_cl_path) = builder.config.llvm_clang_cl
1442 {
1443 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1445 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1446 }
1447
1448 if let Some(ref s) = builder.config.llvm_ldflags {
1450 if !llvm_linker_flags.is_empty() {
1451 llvm_linker_flags.push(' ');
1452 }
1453 llvm_linker_flags.push_str(s);
1454 }
1455
1456 if !llvm_linker_flags.is_empty() {
1458 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1459 }
1460
1461 if builder.config.llvm_static_stdcpp
1464 && !target.contains("freebsd")
1465 && !target.is_msvc()
1466 && !target.contains("apple")
1467 && !target.contains("solaris")
1468 {
1469 let libstdcxx_name =
1470 if target.contains("windows-gnullvm") { "libc++.a" } else { "libstdc++.a" };
1471 let file = compiler_file(
1472 builder,
1473 &builder.cxx(target).unwrap(),
1474 target,
1475 CLang::Cxx,
1476 libstdcxx_name,
1477 );
1478 cargo.env("LLVM_STATIC_STDCPP", file);
1479 }
1480 if builder.llvm_link_shared() {
1481 cargo.env("LLVM_LINK_SHARED", "1");
1482 }
1483 if builder.config.llvm_use_libcxx {
1484 cargo.env("LLVM_USE_LIBCXX", "1");
1485 }
1486 if builder.config.llvm_assertions {
1487 cargo.env("LLVM_ASSERTIONS", "1");
1488 }
1489}
1490
1491#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1497struct RustcLink {
1498 pub compiler: Compiler,
1500 pub previous_stage_compiler: Compiler,
1502 pub target: TargetSelection,
1503 crates: Vec<String>,
1505}
1506
1507impl RustcLink {
1508 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1509 Self {
1510 compiler: host_compiler,
1511 previous_stage_compiler: rustc.build_compiler,
1512 target: rustc.target,
1513 crates: rustc.crates,
1514 }
1515 }
1516}
1517
1518impl Step for RustcLink {
1519 type Output = ();
1520
1521 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1522 run.never()
1523 }
1524
1525 #[cfg_attr(
1527 feature = "tracing",
1528 instrument(
1529 level = "trace",
1530 name = "RustcLink::run",
1531 skip_all,
1532 fields(
1533 compiler = ?self.compiler,
1534 previous_stage_compiler = ?self.previous_stage_compiler,
1535 target = ?self.target,
1536 ),
1537 ),
1538 )]
1539 fn run(self, builder: &Builder<'_>) {
1540 let compiler = self.compiler;
1541 let previous_stage_compiler = self.previous_stage_compiler;
1542 let target = self.target;
1543 add_to_sysroot(
1544 builder,
1545 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1546 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1547 &build_stamp::librustc_stamp(builder, compiler, target),
1548 );
1549 }
1550}
1551
1552#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1553pub struct CodegenBackend {
1554 pub target: TargetSelection,
1555 pub compiler: Compiler,
1556 pub backend: String,
1557}
1558
1559fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1560 let mut needs_codegen_cfg = false;
1561 for path_set in &run.paths {
1562 needs_codegen_cfg = match path_set {
1563 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1564 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1565 }
1566 }
1567 needs_codegen_cfg
1568}
1569
1570pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1571
1572fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1573 let path = path.path.to_str().unwrap();
1574
1575 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1576 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1577
1578 if path.contains(CODEGEN_BACKEND_PREFIX) {
1579 let mut needs_codegen_backend_config = true;
1580 for backend in run.builder.config.codegen_backends(run.target) {
1581 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1582 needs_codegen_backend_config = false;
1583 }
1584 }
1585 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1586 && needs_codegen_backend_config
1587 {
1588 run.builder.info(
1589 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1590 HELP: add backend to codegen-backends in bootstrap.toml.",
1591 );
1592 return true;
1593 }
1594 }
1595
1596 false
1597}
1598
1599impl Step for CodegenBackend {
1600 type Output = ();
1601 const ONLY_HOSTS: bool = true;
1602 const DEFAULT: bool = true;
1604
1605 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1606 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1607 }
1608
1609 fn make_run(run: RunConfig<'_>) {
1610 if needs_codegen_config(&run) {
1611 return;
1612 }
1613
1614 for backend in run.builder.config.codegen_backends(run.target) {
1615 if backend == "llvm" {
1616 continue; }
1618
1619 run.builder.ensure(CodegenBackend {
1620 target: run.target,
1621 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1622 backend: backend.clone(),
1623 });
1624 }
1625 }
1626
1627 #[cfg_attr(
1628 feature = "tracing",
1629 instrument(
1630 level = "debug",
1631 name = "CodegenBackend::run",
1632 skip_all,
1633 fields(
1634 compiler = ?self.compiler,
1635 target = ?self.target,
1636 backend = ?self.target,
1637 ),
1638 ),
1639 )]
1640 fn run(self, builder: &Builder<'_>) {
1641 let compiler = self.compiler;
1642 let target = self.target;
1643 let backend = self.backend;
1644
1645 builder.ensure(Rustc::new(compiler, target));
1646
1647 if builder.config.keep_stage.contains(&compiler.stage) {
1648 trace!("`keep-stage` requested");
1649 builder.info(
1650 "WARNING: Using a potentially old codegen backend. \
1651 This may not behave well.",
1652 );
1653 return;
1656 }
1657
1658 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1659 if compiler_to_use != compiler {
1660 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1661 return;
1662 }
1663
1664 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1665
1666 let mut cargo = builder::Cargo::new(
1667 builder,
1668 compiler,
1669 Mode::Codegen,
1670 SourceType::InTree,
1671 target,
1672 Kind::Build,
1673 );
1674 cargo
1675 .arg("--manifest-path")
1676 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1677 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1678
1679 if backend == "gcc" {
1683 let gcc = builder.ensure(Gcc { target });
1684 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
1685 }
1686
1687 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1688
1689 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1690 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1691 if builder.config.dry_run() {
1692 return;
1693 }
1694 let mut files = files.into_iter().filter(|f| {
1695 let filename = f.file_name().unwrap().to_str().unwrap();
1696 is_dylib(f) && filename.contains("rustc_codegen_")
1697 });
1698 let codegen_backend = match files.next() {
1699 Some(f) => f,
1700 None => panic!("no dylibs built for codegen backend?"),
1701 };
1702 if let Some(f) = files.next() {
1703 panic!(
1704 "codegen backend built two dylibs:\n{}\n{}",
1705 codegen_backend.display(),
1706 f.display()
1707 );
1708 }
1709 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1710 let codegen_backend = codegen_backend.to_str().unwrap();
1711 t!(stamp.add_stamp(codegen_backend).write());
1712 }
1713}
1714
1715fn copy_codegen_backends_to_sysroot(
1722 builder: &Builder<'_>,
1723 compiler: Compiler,
1724 target_compiler: Compiler,
1725) {
1726 let target = target_compiler.host;
1727
1728 let dst = builder.sysroot_codegen_backends(target_compiler);
1737 t!(fs::create_dir_all(&dst), dst);
1738
1739 if builder.config.dry_run() {
1740 return;
1741 }
1742
1743 for backend in builder.config.codegen_backends(target) {
1744 if backend == "llvm" {
1745 continue; }
1747
1748 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1749 let dylib = t!(fs::read_to_string(stamp.path()));
1750 let file = Path::new(&dylib);
1751 let filename = file.file_name().unwrap().to_str().unwrap();
1752 let target_filename = {
1755 let dash = filename.find('-').unwrap();
1756 let dot = filename.find('.').unwrap();
1757 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1758 };
1759 builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
1760 }
1761}
1762
1763pub fn compiler_file(
1764 builder: &Builder<'_>,
1765 compiler: &Path,
1766 target: TargetSelection,
1767 c: CLang,
1768 file: &str,
1769) -> PathBuf {
1770 if builder.config.dry_run() {
1771 return PathBuf::new();
1772 }
1773 let mut cmd = command(compiler);
1774 cmd.args(builder.cc_handled_clags(target, c));
1775 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1776 cmd.arg(format!("-print-file-name={file}"));
1777 let out = cmd.run_capture_stdout(builder).stdout();
1778 PathBuf::from(out.trim())
1779}
1780
1781#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1782pub struct Sysroot {
1783 pub compiler: Compiler,
1784 force_recompile: bool,
1786}
1787
1788impl Sysroot {
1789 pub(crate) fn new(compiler: Compiler) -> Self {
1790 Sysroot { compiler, force_recompile: false }
1791 }
1792}
1793
1794impl Step for Sysroot {
1795 type Output = PathBuf;
1796
1797 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1798 run.never()
1799 }
1800
1801 #[cfg_attr(
1805 feature = "tracing",
1806 instrument(
1807 level = "debug",
1808 name = "Sysroot::run",
1809 skip_all,
1810 fields(compiler = ?self.compiler),
1811 ),
1812 )]
1813 fn run(self, builder: &Builder<'_>) -> PathBuf {
1814 let compiler = self.compiler;
1815 let host_dir = builder.out.join(compiler.host);
1816
1817 let sysroot_dir = |stage| {
1818 if stage == 0 {
1819 host_dir.join("stage0-sysroot")
1820 } else if self.force_recompile && stage == compiler.stage {
1821 host_dir.join(format!("stage{stage}-test-sysroot"))
1822 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1823 host_dir.join("ci-rustc-sysroot")
1824 } else {
1825 host_dir.join(format!("stage{stage}"))
1826 }
1827 };
1828 let sysroot = sysroot_dir(compiler.stage);
1829 trace!(stage = ?compiler.stage, ?sysroot);
1830
1831 builder
1832 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1833 let _ = fs::remove_dir_all(&sysroot);
1834 t!(fs::create_dir_all(&sysroot));
1835
1836 if compiler.stage == 0 {
1843 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1844 }
1845
1846 if builder.download_rustc() && compiler.stage != 0 {
1848 assert_eq!(
1849 builder.config.host_target, compiler.host,
1850 "Cross-compiling is not yet supported with `download-rustc`",
1851 );
1852
1853 for stage in 0..=2 {
1855 if stage != compiler.stage {
1856 let dir = sysroot_dir(stage);
1857 if !dir.ends_with("ci-rustc-sysroot") {
1858 let _ = fs::remove_dir_all(dir);
1859 }
1860 }
1861 }
1862
1863 let mut filtered_files = Vec::new();
1873 let mut add_filtered_files = |suffix, contents| {
1874 for path in contents {
1875 let path = Path::new(&path);
1876 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1877 filtered_files.push(path.file_name().unwrap().to_owned());
1878 }
1879 }
1880 };
1881 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1882 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1883 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1886
1887 let filtered_extensions = [
1888 OsStr::new("rmeta"),
1889 OsStr::new("rlib"),
1890 OsStr::new(std::env::consts::DLL_EXTENSION),
1892 ];
1893 let ci_rustc_dir = builder.config.ci_rustc_dir();
1894 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1895 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1896 return true;
1897 }
1898 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1899 return true;
1900 }
1901 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1902 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1903 false
1904 } else {
1905 true
1906 }
1907 });
1908 }
1909
1910 if compiler.stage != 0 {
1916 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1917 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1918 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1919 if let Err(e) =
1920 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust)
1921 {
1922 eprintln!(
1923 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1924 sysroot_lib_rustlib_src_rust.display(),
1925 builder.src.display(),
1926 e,
1927 );
1928 if builder.config.rust_remap_debuginfo {
1929 eprintln!(
1930 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1931 sysroot_lib_rustlib_src_rust.display(),
1932 );
1933 }
1934 build_helper::exit!(1);
1935 }
1936 }
1937
1938 if !builder.download_rustc() {
1940 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1941 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1942 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1943 if let Err(e) =
1944 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1945 {
1946 eprintln!(
1947 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1948 sysroot_lib_rustlib_rustcsrc_rust.display(),
1949 builder.src.display(),
1950 e,
1951 );
1952 build_helper::exit!(1);
1953 }
1954 }
1955
1956 sysroot
1957 }
1958}
1959
1960#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1961pub struct Assemble {
1962 pub target_compiler: Compiler,
1967}
1968
1969impl Step for Assemble {
1970 type Output = Compiler;
1971 const ONLY_HOSTS: bool = true;
1972
1973 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1974 run.path("compiler/rustc").path("compiler")
1975 }
1976
1977 fn make_run(run: RunConfig<'_>) {
1978 run.builder.ensure(Assemble {
1979 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
1980 });
1981 }
1982
1983 #[cfg_attr(
1989 feature = "tracing",
1990 instrument(
1991 level = "debug",
1992 name = "Assemble::run",
1993 skip_all,
1994 fields(target_compiler = ?self.target_compiler),
1995 ),
1996 )]
1997 fn run(self, builder: &Builder<'_>) -> Compiler {
1998 let target_compiler = self.target_compiler;
1999
2000 if target_compiler.stage == 0 {
2001 trace!("stage 0 build compiler is always available, simply returning");
2002 assert_eq!(
2003 builder.config.host_target, target_compiler.host,
2004 "Cannot obtain compiler for non-native build triple at stage 0"
2005 );
2006 return target_compiler;
2008 }
2009
2010 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2013 let libdir_bin = libdir.parent().unwrap().join("bin");
2014 t!(fs::create_dir_all(&libdir_bin));
2015
2016 if builder.config.llvm_enabled(target_compiler.host) {
2017 trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
2018
2019 let llvm::LlvmResult { llvm_config, .. } =
2020 builder.ensure(llvm::Llvm { target: target_compiler.host });
2021 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
2022 trace!("LLVM tools enabled");
2023
2024 let llvm_bin_dir =
2025 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
2026 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
2027
2028 #[cfg(feature = "tracing")]
2035 let _llvm_tools_span =
2036 span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
2037 .entered();
2038 for tool in LLVM_TOOLS {
2039 trace!("installing `{tool}`");
2040 let tool_exe = exe(tool, target_compiler.host);
2041 let src_path = llvm_bin_dir.join(&tool_exe);
2042
2043 if !src_path.exists() && builder.config.llvm_from_ci {
2045 eprintln!("{} does not exist; skipping copy", src_path.display());
2046 continue;
2047 }
2048
2049 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
2056 }
2057 }
2058 }
2059
2060 let maybe_install_llvm_bitcode_linker = |compiler| {
2061 if builder.config.llvm_bitcode_linker_enabled {
2062 trace!("llvm-bitcode-linker enabled, installing");
2063 let llvm_bitcode_linker =
2064 builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
2065 compiler,
2066 target: target_compiler.host,
2067 extra_features: vec![],
2068 });
2069 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
2070 builder.copy_link(
2071 &llvm_bitcode_linker.tool_path,
2072 &libdir_bin.join(tool_exe),
2073 FileType::Executable,
2074 );
2075 }
2076 };
2077
2078 if builder.download_rustc() {
2080 trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
2081
2082 builder.ensure(Std::new(target_compiler, target_compiler.host));
2083 let sysroot =
2084 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
2085 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2088 if target_compiler.stage == builder.top_stage {
2090 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage=target_compiler.stage));
2091 }
2092
2093 let mut precompiled_compiler = target_compiler;
2094 precompiled_compiler.forced_compiler(true);
2095 maybe_install_llvm_bitcode_linker(precompiled_compiler);
2096
2097 return target_compiler;
2098 }
2099
2100 debug!(
2114 "ensuring build compiler is available: compiler(stage = {}, host = {:?})",
2115 target_compiler.stage - 1,
2116 builder.config.host_target,
2117 );
2118 let mut build_compiler =
2119 builder.compiler(target_compiler.stage - 1, builder.config.host_target);
2120
2121 if builder.config.llvm_enzyme && !builder.config.dry_run() {
2123 debug!("`llvm_enzyme` requested");
2124 let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
2125 if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) {
2126 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
2127 let lib_ext = std::env::consts::DLL_EXTENSION;
2128 let libenzyme = format!("libEnzyme-{llvm_version_major}");
2129 let src_lib =
2130 enzyme_install.join("build/Enzyme").join(&libenzyme).with_extension(lib_ext);
2131 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
2132 let target_libdir =
2133 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
2134 let dst_lib = libdir.join(&libenzyme).with_extension(lib_ext);
2135 let target_dst_lib = target_libdir.join(&libenzyme).with_extension(lib_ext);
2136 builder.copy_link(&src_lib, &dst_lib, FileType::NativeLibrary);
2137 builder.copy_link(&src_lib, &target_dst_lib, FileType::NativeLibrary);
2138 }
2139 }
2140
2141 debug!(
2147 ?build_compiler,
2148 "target_compiler.host" = ?target_compiler.host,
2149 "building compiler libraries to link to"
2150 );
2151 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
2152 debug!(
2155 "(old) build_compiler.stage" = build_compiler.stage,
2156 "(adjusted) build_compiler.stage" = actual_stage,
2157 "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2158 );
2159 build_compiler.stage = actual_stage;
2160
2161 #[cfg(feature = "tracing")]
2162 let _codegen_backend_span =
2163 span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
2164 for backend in builder.config.codegen_backends(target_compiler.host) {
2165 if backend == "llvm" {
2166 debug!("llvm codegen backend is already built as part of rustc");
2167 continue; }
2169
2170 builder.ensure(CodegenBackend {
2171 compiler: build_compiler,
2172 target: target_compiler.host,
2173 backend: backend.clone(),
2174 });
2175 }
2176 #[cfg(feature = "tracing")]
2177 drop(_codegen_backend_span);
2178
2179 let stage = target_compiler.stage;
2180 let host = target_compiler.host;
2181 let (host_info, dir_name) = if build_compiler.host == host {
2182 ("".into(), "host".into())
2183 } else {
2184 (format!(" ({host})"), host.to_string())
2185 };
2186 let msg = format!(
2191 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
2192 );
2193 builder.info(&msg);
2194
2195 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
2197 let proc_macros = builder
2198 .read_stamp_file(&stamp)
2199 .into_iter()
2200 .filter_map(|(path, dependency_type)| {
2201 if dependency_type == DependencyType::Host {
2202 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
2203 } else {
2204 None
2205 }
2206 })
2207 .collect::<HashSet<_>>();
2208
2209 let sysroot = builder.sysroot(target_compiler);
2210 let rustc_libdir = builder.rustc_libdir(target_compiler);
2211 t!(fs::create_dir_all(&rustc_libdir));
2212 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
2213 for f in builder.read_dir(&src_libdir) {
2214 let filename = f.file_name().into_string().unwrap();
2215
2216 let is_proc_macro = proc_macros.contains(&filename);
2217 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
2218
2219 let can_be_rustc_dynamic_dep = if builder
2223 .link_std_into_rustc_driver(target_compiler.host)
2224 && !target_compiler.host.is_windows()
2225 {
2226 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
2227 !is_std
2228 } else {
2229 true
2230 };
2231
2232 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
2233 builder.copy_link(&f.path(), &rustc_libdir.join(&filename), FileType::Regular);
2234 }
2235 }
2236
2237 debug!("copying codegen backends to sysroot");
2238 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
2239
2240 if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) {
2241 builder.ensure(crate::core::build_steps::tool::LldWrapper {
2242 build_compiler,
2243 target_compiler,
2244 });
2245 }
2246
2247 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
2248 debug!(
2249 "llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
2250 workaround faulty homebrew `strip`s"
2251 );
2252
2253 let src_exe = exe("llvm-objcopy", target_compiler.host);
2260 let dst_exe = exe("rust-objcopy", target_compiler.host);
2261 builder.copy_link(
2262 &libdir_bin.join(src_exe),
2263 &libdir_bin.join(dst_exe),
2264 FileType::Executable,
2265 );
2266 }
2267
2268 if builder.tool_enabled("wasm-component-ld") {
2274 let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
2275 compiler: build_compiler,
2276 target: target_compiler.host,
2277 });
2278 builder.copy_link(
2279 &wasm_component.tool_path,
2280 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
2281 FileType::Executable,
2282 );
2283 }
2284
2285 maybe_install_llvm_bitcode_linker(target_compiler);
2286
2287 debug!(
2290 "target_compiler.host" = ?target_compiler.host,
2291 ?sysroot,
2292 "ensuring availability of `libLLVM.so` in compiler directory"
2293 );
2294 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2295 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2296
2297 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2299 let rustc = out_dir.join(exe("rustc-main", host));
2300 let bindir = sysroot.join("bin");
2301 t!(fs::create_dir_all(bindir));
2302 let compiler = builder.rustc(target_compiler);
2303 debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
2304 builder.copy_link(&rustc, &compiler, FileType::Executable);
2305
2306 target_compiler
2307 }
2308}
2309
2310pub fn add_to_sysroot(
2315 builder: &Builder<'_>,
2316 sysroot_dst: &Path,
2317 sysroot_host_dst: &Path,
2318 stamp: &BuildStamp,
2319) {
2320 let self_contained_dst = &sysroot_dst.join("self-contained");
2321 t!(fs::create_dir_all(sysroot_dst));
2322 t!(fs::create_dir_all(sysroot_host_dst));
2323 t!(fs::create_dir_all(self_contained_dst));
2324 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2325 let dst = match dependency_type {
2326 DependencyType::Host => sysroot_host_dst,
2327 DependencyType::Target => sysroot_dst,
2328 DependencyType::TargetSelfContained => self_contained_dst,
2329 };
2330 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
2331 }
2332}
2333
2334pub fn run_cargo(
2335 builder: &Builder<'_>,
2336 cargo: Cargo,
2337 tail_args: Vec<String>,
2338 stamp: &BuildStamp,
2339 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2340 is_check: bool,
2341 rlib_only_metadata: bool,
2342) -> Vec<PathBuf> {
2343 let target_root_dir = stamp.path().parent().unwrap();
2345 let target_deps_dir = target_root_dir.join("deps");
2347 let host_root_dir = target_root_dir
2349 .parent()
2350 .unwrap() .parent()
2352 .unwrap() .join(target_root_dir.file_name().unwrap());
2354
2355 let mut deps = Vec::new();
2359 let mut toplevel = Vec::new();
2360 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2361 let (filenames, crate_types) = match msg {
2362 CargoMessage::CompilerArtifact {
2363 filenames,
2364 target: CargoTarget { crate_types },
2365 ..
2366 } => (filenames, crate_types),
2367 _ => return,
2368 };
2369 for filename in filenames {
2370 let mut keep = false;
2372 if filename.ends_with(".lib")
2373 || filename.ends_with(".a")
2374 || is_debug_info(&filename)
2375 || is_dylib(Path::new(&*filename))
2376 {
2377 keep = true;
2379 }
2380 if is_check && filename.ends_with(".rmeta") {
2381 keep = true;
2383 } else if rlib_only_metadata {
2384 if filename.contains("jemalloc_sys")
2385 || filename.contains("rustc_smir")
2386 || filename.contains("stable_mir")
2387 {
2388 keep |= filename.ends_with(".rlib");
2391 } else {
2392 keep |= filename.ends_with(".rmeta");
2396 }
2397 } else {
2398 keep |= filename.ends_with(".rlib");
2400 }
2401
2402 if !keep {
2403 continue;
2404 }
2405
2406 let filename = Path::new(&*filename);
2407
2408 if filename.starts_with(&host_root_dir) {
2411 if crate_types.iter().any(|t| t == "proc-macro") {
2413 deps.push((filename.to_path_buf(), DependencyType::Host));
2414 }
2415 continue;
2416 }
2417
2418 if filename.starts_with(&target_deps_dir) {
2421 deps.push((filename.to_path_buf(), DependencyType::Target));
2422 continue;
2423 }
2424
2425 let expected_len = t!(filename.metadata()).len();
2436 let filename = filename.file_name().unwrap().to_str().unwrap();
2437 let mut parts = filename.splitn(2, '.');
2438 let file_stem = parts.next().unwrap().to_owned();
2439 let extension = parts.next().unwrap().to_owned();
2440
2441 toplevel.push((file_stem, extension, expected_len));
2442 }
2443 });
2444
2445 if !ok {
2446 crate::exit!(1);
2447 }
2448
2449 if builder.config.dry_run() {
2450 return Vec::new();
2451 }
2452
2453 let contents = target_deps_dir
2457 .read_dir()
2458 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e))
2459 .map(|e| t!(e))
2460 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2461 .collect::<Vec<_>>();
2462 for (prefix, extension, expected_len) in toplevel {
2463 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2464 meta.len() == expected_len
2465 && filename
2466 .strip_prefix(&prefix[..])
2467 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2468 .unwrap_or(false)
2469 });
2470 let max = candidates.max_by_key(|&(_, _, metadata)| {
2471 metadata.modified().expect("mtime should be available on all relevant OSes")
2472 });
2473 let path_to_add = match max {
2474 Some(triple) => triple.0.to_str().unwrap(),
2475 None => panic!("no output generated for {prefix:?} {extension:?}"),
2476 };
2477 if is_dylib(Path::new(path_to_add)) {
2478 let candidate = format!("{path_to_add}.lib");
2479 let candidate = PathBuf::from(candidate);
2480 if candidate.exists() {
2481 deps.push((candidate, DependencyType::Target));
2482 }
2483 }
2484 deps.push((path_to_add.into(), DependencyType::Target));
2485 }
2486
2487 deps.extend(additional_target_deps);
2488 deps.sort();
2489 let mut new_contents = Vec::new();
2490 for (dep, dependency_type) in deps.iter() {
2491 new_contents.extend(match *dependency_type {
2492 DependencyType::Host => b"h",
2493 DependencyType::Target => b"t",
2494 DependencyType::TargetSelfContained => b"s",
2495 });
2496 new_contents.extend(dep.to_str().unwrap().as_bytes());
2497 new_contents.extend(b"\0");
2498 }
2499 t!(fs::write(stamp.path(), &new_contents));
2500 deps.into_iter().map(|(d, _)| d).collect()
2501}
2502
2503pub fn stream_cargo(
2504 builder: &Builder<'_>,
2505 cargo: Cargo,
2506 tail_args: Vec<String>,
2507 cb: &mut dyn FnMut(CargoMessage<'_>),
2508) -> bool {
2509 let mut cmd = cargo.into_cmd();
2510
2511 #[cfg(feature = "tracing")]
2512 let _run_span = crate::trace_cmd!(cmd);
2513
2514 let cargo = cmd.as_command_mut();
2515 let mut message_format = if builder.config.json_output {
2518 String::from("json")
2519 } else {
2520 String::from("json-render-diagnostics")
2521 };
2522 if let Some(s) = &builder.config.rustc_error_format {
2523 message_format.push_str(",json-diagnostic-");
2524 message_format.push_str(s);
2525 }
2526 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
2527
2528 for arg in tail_args {
2529 cargo.arg(arg);
2530 }
2531
2532 builder.verbose(|| println!("running: {cargo:?}"));
2533
2534 if builder.config.dry_run() {
2535 return true;
2536 }
2537
2538 let mut child = match cargo.spawn() {
2539 Ok(child) => child,
2540 Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"),
2541 };
2542
2543 let stdout = BufReader::new(child.stdout.take().unwrap());
2547 for line in stdout.lines() {
2548 let line = t!(line);
2549 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2550 Ok(msg) => {
2551 if builder.config.json_output {
2552 println!("{line}");
2554 }
2555 cb(msg)
2556 }
2557 Err(_) => println!("{line}"),
2559 }
2560 }
2561
2562 let status = t!(child.wait());
2564 if builder.is_verbose() && !status.success() {
2565 eprintln!(
2566 "command did not execute successfully: {cargo:?}\n\
2567 expected success, got: {status}"
2568 );
2569 }
2570 status.success()
2571}
2572
2573#[derive(Deserialize)]
2574pub struct CargoTarget<'a> {
2575 crate_types: Vec<Cow<'a, str>>,
2576}
2577
2578#[derive(Deserialize)]
2579#[serde(tag = "reason", rename_all = "kebab-case")]
2580pub enum CargoMessage<'a> {
2581 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2582 BuildScriptExecuted,
2583 BuildFinished,
2584}
2585
2586pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2587 if target != "x86_64-unknown-linux-gnu"
2591 || !builder.config.is_host_target(target)
2592 || !path.exists()
2593 {
2594 return;
2595 }
2596
2597 let previous_mtime = t!(t!(path.metadata()).modified());
2598 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2599
2600 let file = t!(fs::File::open(path));
2601
2602 t!(file.set_modified(previous_mtime));
2615}
2616
2617pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2619 build_compiler.stage != 0
2620}