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
20use crate::core::build_steps::tool::SourceType;
21use crate::core::build_steps::{dist, llvm};
22use crate::core::builder;
23use crate::core::builder::{
24 Builder, Cargo, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath, crate_description,
25};
26use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
27use crate::utils::build_stamp;
28use crate::utils::build_stamp::BuildStamp;
29use crate::utils::exec::command;
30use crate::utils::helpers::{
31 exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
32};
33use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode};
34
35#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub struct Std {
37 pub target: TargetSelection,
38 pub compiler: Compiler,
39 crates: Vec<String>,
43 force_recompile: bool,
46 extra_rust_args: &'static [&'static str],
47 is_for_mir_opt_tests: bool,
48}
49
50impl Std {
51 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
52 Self {
53 target,
54 compiler,
55 crates: Default::default(),
56 force_recompile: false,
57 extra_rust_args: &[],
58 is_for_mir_opt_tests: false,
59 }
60 }
61
62 pub fn force_recompile(mut self, force_recompile: bool) -> Self {
63 self.force_recompile = force_recompile;
64 self
65 }
66
67 #[allow(clippy::wrong_self_convention)]
68 pub fn is_for_mir_opt_tests(mut self, is_for_mir_opt_tests: bool) -> Self {
69 self.is_for_mir_opt_tests = is_for_mir_opt_tests;
70 self
71 }
72
73 pub fn extra_rust_args(mut self, extra_rust_args: &'static [&'static str]) -> Self {
74 self.extra_rust_args = extra_rust_args;
75 self
76 }
77
78 fn copy_extra_objects(
79 &self,
80 builder: &Builder<'_>,
81 compiler: &Compiler,
82 target: TargetSelection,
83 ) -> Vec<(PathBuf, DependencyType)> {
84 let mut deps = Vec::new();
85 if !self.is_for_mir_opt_tests {
86 deps.extend(copy_third_party_objects(builder, compiler, target));
87 deps.extend(copy_self_contained_objects(builder, compiler, target));
88 }
89 deps
90 }
91}
92
93impl Step for Std {
94 type Output = ();
95 const DEFAULT: bool = true;
96
97 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
98 run.crate_or_deps("sysroot").path("library").alias("core")
99 }
100
101 fn make_run(run: RunConfig<'_>) {
102 let crates = std_crates_for_run_make(&run);
103 let builder = run.builder;
104
105 let force_recompile = builder.rust_info().is_managed_git_subrepository()
109 && builder.download_rustc()
110 && builder.config.last_modified_commit(&["library"], "download-rustc", true).is_none();
111
112 run.builder.ensure(Std {
113 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
114 target: run.target,
115 crates,
116 force_recompile,
117 extra_rust_args: &[],
118 is_for_mir_opt_tests: false,
119 });
120 }
121
122 fn run(self, builder: &Builder<'_>) {
128 let target = self.target;
129 let compiler = self.compiler;
130
131 if builder.download_rustc() && target == builder.build.build
134 && compiler.stage != 0
137 && !self.force_recompile
138 {
139 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
140 cp_rustc_component_to_ci_sysroot(
141 builder,
142 &sysroot,
143 builder.config.ci_rust_std_contents(),
144 );
145 return;
146 }
147
148 if builder.config.keep_stage.contains(&compiler.stage)
149 || builder.config.keep_stage_std.contains(&compiler.stage)
150 {
151 builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
152
153 builder.ensure(StartupObjects { compiler, target });
154
155 self.copy_extra_objects(builder, &compiler, target);
156
157 builder.ensure(StdLink::from_std(self, compiler));
158 return;
159 }
160
161 builder.require_submodule("library/stdarch", None);
162
163 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
164
165 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
166 if compiler_to_use != compiler {
167 builder.ensure(Std::new(compiler_to_use, target));
168 let msg = if compiler_to_use.host == target {
169 format!(
170 "Uplifting library (stage{} -> stage{})",
171 compiler_to_use.stage, compiler.stage
172 )
173 } else {
174 format!(
175 "Uplifting library (stage{}:{} -> stage{}:{})",
176 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
177 )
178 };
179 builder.info(&msg);
180
181 self.copy_extra_objects(builder, &compiler, target);
184
185 builder.ensure(StdLink::from_std(self, compiler_to_use));
186 return;
187 }
188
189 target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
190
191 if compiler.stage == 0 && builder.is_builder_target(&compiler.host) {
195 let src_sysroot_bin = builder
197 .rustc_snapshot_sysroot()
198 .join("lib")
199 .join("rustlib")
200 .join(compiler.host)
201 .join("bin");
202 if src_sysroot_bin.exists() {
203 let target_sysroot_bin = builder.sysroot_target_bindir(compiler, target);
204 t!(fs::create_dir_all(&target_sysroot_bin));
205 builder.cp_link_r(&src_sysroot_bin, &target_sysroot_bin);
206 }
207 }
208
209 let mut cargo = if self.is_for_mir_opt_tests {
213 let mut cargo = builder::Cargo::new_for_mir_opt_tests(
214 builder,
215 compiler,
216 Mode::Std,
217 SourceType::InTree,
218 target,
219 Kind::Check,
220 );
221 cargo.rustflag("-Zalways-encode-mir");
222 cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
223 cargo
224 } else {
225 let mut cargo = builder::Cargo::new(
226 builder,
227 compiler,
228 Mode::Std,
229 SourceType::InTree,
230 target,
231 Kind::Build,
232 );
233 std_cargo(builder, target, compiler.stage, &mut cargo);
234 for krate in &*self.crates {
235 cargo.arg("-p").arg(krate);
236 }
237 cargo
238 };
239
240 if target.is_synthetic() {
242 cargo.env("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET", "1");
243 }
244 for rustflag in self.extra_rust_args.iter() {
245 cargo.rustflag(rustflag);
246 }
247
248 let _guard = builder.msg(
249 Kind::Build,
250 compiler.stage,
251 format_args!("library artifacts{}", crate_description(&self.crates)),
252 compiler.host,
253 target,
254 );
255 run_cargo(
256 builder,
257 cargo,
258 vec![],
259 &build_stamp::libstd_stamp(builder, compiler, target),
260 target_deps,
261 self.is_for_mir_opt_tests, false,
263 );
264
265 builder.ensure(StdLink::from_std(
266 self,
267 builder.compiler(compiler.stage, builder.config.build),
268 ));
269 }
270}
271
272fn copy_and_stamp(
273 builder: &Builder<'_>,
274 libdir: &Path,
275 sourcedir: &Path,
276 name: &str,
277 target_deps: &mut Vec<(PathBuf, DependencyType)>,
278 dependency_type: DependencyType,
279) {
280 let target = libdir.join(name);
281 builder.copy_link(&sourcedir.join(name), &target);
282
283 target_deps.push((target, dependency_type));
284}
285
286fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
287 let libunwind_path = builder.ensure(llvm::Libunwind { target });
288 let libunwind_source = libunwind_path.join("libunwind.a");
289 let libunwind_target = libdir.join("libunwind.a");
290 builder.copy_link(&libunwind_source, &libunwind_target);
291 libunwind_target
292}
293
294fn copy_third_party_objects(
296 builder: &Builder<'_>,
297 compiler: &Compiler,
298 target: TargetSelection,
299) -> Vec<(PathBuf, DependencyType)> {
300 let mut target_deps = vec![];
301
302 if builder.config.needs_sanitizer_runtime_built(target) && compiler.stage != 0 {
303 target_deps.extend(
306 copy_sanitizers(builder, compiler, target)
307 .into_iter()
308 .map(|d| (d, DependencyType::Target)),
309 );
310 }
311
312 if target == "x86_64-fortanix-unknown-sgx"
313 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
314 && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
315 {
316 let libunwind_path =
317 copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
318 target_deps.push((libunwind_path, DependencyType::Target));
319 }
320
321 target_deps
322}
323
324fn copy_self_contained_objects(
326 builder: &Builder<'_>,
327 compiler: &Compiler,
328 target: TargetSelection,
329) -> Vec<(PathBuf, DependencyType)> {
330 let libdir_self_contained =
331 builder.sysroot_target_libdir(*compiler, target).join("self-contained");
332 t!(fs::create_dir_all(&libdir_self_contained));
333 let mut target_deps = vec![];
334
335 if target.needs_crt_begin_end() {
343 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
344 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
345 });
346 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
347 copy_and_stamp(
348 builder,
349 &libdir_self_contained,
350 &srcdir,
351 obj,
352 &mut target_deps,
353 DependencyType::TargetSelfContained,
354 );
355 }
356 let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
357 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
358 let src = crt_path.join(obj);
359 let target = libdir_self_contained.join(obj);
360 builder.copy_link(&src, &target);
361 target_deps.push((target, DependencyType::TargetSelfContained));
362 }
363
364 if !target.starts_with("s390x") {
365 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
366 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
367 }
368 } else if target.contains("-wasi") {
369 let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| {
370 panic!(
371 "Target {:?} does not have a \"wasi-root\" key in Config.toml \
372 or `$WASI_SDK_PATH` set",
373 target.triple
374 )
375 });
376 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
377 copy_and_stamp(
378 builder,
379 &libdir_self_contained,
380 &srcdir,
381 obj,
382 &mut target_deps,
383 DependencyType::TargetSelfContained,
384 );
385 }
386 } else if target.is_windows_gnu() {
387 for obj in ["crt2.o", "dllcrt2.o"].iter() {
388 let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
389 let target = libdir_self_contained.join(obj);
390 builder.copy_link(&src, &target);
391 target_deps.push((target, DependencyType::TargetSelfContained));
392 }
393 }
394
395 target_deps
396}
397
398pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
400 if cfg!(test) {
402 return vec![];
403 }
404
405 let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
406 let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
407
408 if target_is_no_std {
410 vec![]
411 }
412 else if has_alias {
414 run.make_run_crates(builder::Alias::Library)
415 } else {
416 run.cargo_crates_in_set()
417 }
418}
419
420fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
426 if builder.config.llvm_from_ci {
428 builder.config.maybe_download_ci_llvm();
430 let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt");
431 if ci_llvm_compiler_rt.exists() {
432 return ci_llvm_compiler_rt;
433 }
434 }
435
436 builder.require_submodule("src/llvm-project", {
438 Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.")
439 });
440 builder.src.join("src/llvm-project/compiler-rt")
441}
442
443pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
446 if target.contains("apple") && !builder.config.dry_run() {
464 let mut cmd = command(builder.rustc(cargo.compiler()));
468 cmd.arg("--target").arg(target.rustc_target_arg());
469 cmd.arg("--print=deployment-target");
470 let output = cmd.run_capture_stdout(builder).stdout();
471
472 let (env_var, value) = output.split_once('=').unwrap();
473 cargo.env(env_var.trim(), value.trim());
476
477 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
487 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
488 }
489 }
490
491 if let Some(path) = builder.config.profiler_path(target) {
493 cargo.env("LLVM_PROFILER_RT_LIB", path);
494 } else if builder.config.profiler_enabled(target) {
495 let compiler_rt = compiler_rt_for_profiler(builder);
496 cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt);
500 }
501
502 let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
516 builder.require_submodule(
524 "src/llvm-project",
525 Some(
526 "The `build.optimized-compiler-builtins` config option \
527 requires `compiler-rt` sources from LLVM.",
528 ),
529 );
530 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
531 assert!(compiler_builtins_root.exists());
532 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
535 " compiler-builtins-c"
536 } else {
537 ""
538 };
539
540 if !builder.unstable_features() {
543 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
544 }
545
546 let mut features = String::new();
547
548 if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
549 {
550 features += "compiler-builtins-no-f16-f128 ";
551 }
552
553 if builder.no_std(target) == Some(true) {
554 features += " compiler-builtins-mem";
555 if !target.starts_with("bpf") {
556 features.push_str(compiler_builtins_c_feature);
557 }
558
559 cargo
561 .args(["-p", "alloc"])
562 .arg("--manifest-path")
563 .arg(builder.src.join("library/alloc/Cargo.toml"))
564 .arg("--features")
565 .arg(features);
566 } else {
567 features += &builder.std_features(target);
568 features.push_str(compiler_builtins_c_feature);
569
570 cargo
571 .arg("--features")
572 .arg(features)
573 .arg("--manifest-path")
574 .arg(builder.src.join("library/sysroot/Cargo.toml"));
575
576 if target.contains("musl") {
579 if let Some(p) = builder.musl_libdir(target) {
580 let root = format!("native={}", p.to_str().unwrap());
581 cargo.rustflag("-L").rustflag(&root);
582 }
583 }
584
585 if target.contains("-wasi") {
586 if let Some(dir) = builder.wasi_libdir(target) {
587 let root = format!("native={}", dir.to_str().unwrap());
588 cargo.rustflag("-L").rustflag(&root);
589 }
590 }
591 }
592
593 if stage >= 1 {
602 cargo.rustflag("-Cembed-bitcode=yes");
603 }
604 if builder.config.rust_lto == RustcLto::Off {
605 cargo.rustflag("-Clto=off");
606 }
607
608 if target.contains("riscv") {
615 cargo.rustflag("-Cforce-unwind-tables=yes");
616 }
617
618 cargo.rustflag("-Cforce-frame-pointers=yes");
621
622 let html_root =
623 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
624 cargo.rustflag(&html_root);
625 cargo.rustdocflag(&html_root);
626
627 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
628}
629
630#[derive(Debug, Clone, PartialEq, Eq, Hash)]
631struct StdLink {
632 pub compiler: Compiler,
633 pub target_compiler: Compiler,
634 pub target: TargetSelection,
635 crates: Vec<String>,
637 force_recompile: bool,
639}
640
641impl StdLink {
642 fn from_std(std: Std, host_compiler: Compiler) -> Self {
643 Self {
644 compiler: host_compiler,
645 target_compiler: std.compiler,
646 target: std.target,
647 crates: std.crates,
648 force_recompile: std.force_recompile,
649 }
650 }
651}
652
653impl Step for StdLink {
654 type Output = ();
655
656 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
657 run.never()
658 }
659
660 fn run(self, builder: &Builder<'_>) {
669 let compiler = self.compiler;
670 let target_compiler = self.target_compiler;
671 let target = self.target;
672
673 let (libdir, hostdir) = if self.force_recompile && builder.download_rustc() {
675 let lib = builder.sysroot_libdir_relative(self.compiler);
677 let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
678 compiler: self.compiler,
679 force_recompile: self.force_recompile,
680 });
681 let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
682 let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
683 (libdir, hostdir)
684 } else {
685 let libdir = builder.sysroot_target_libdir(target_compiler, target);
686 let hostdir = builder.sysroot_target_libdir(target_compiler, compiler.host);
687 (libdir, hostdir)
688 };
689
690 add_to_sysroot(
691 builder,
692 &libdir,
693 &hostdir,
694 &build_stamp::libstd_stamp(builder, compiler, target),
695 );
696
697 if compiler.stage == 0
701 && builder
702 .build
703 .config
704 .initial_rustc
705 .starts_with(builder.out.join(compiler.host).join("stage0/bin"))
706 {
707 let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
709
710 let host = compiler.host;
711 let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
712 let sysroot_bin_dir = sysroot.join("bin");
713 t!(fs::create_dir_all(&sysroot_bin_dir));
714 builder.cp_link_r(&stage0_bin_dir, &sysroot_bin_dir);
715
716 let stage0_lib_dir = builder.out.join(host).join("stage0/lib");
718 if let Ok(files) = fs::read_dir(stage0_lib_dir) {
719 for file in files {
720 let file = t!(file);
721 let path = file.path();
722 if path.is_file() {
723 builder
724 .copy_link(&path, &sysroot.join("lib").join(path.file_name().unwrap()));
725 }
726 }
727 }
728
729 let sysroot_codegen_backends = builder.sysroot_codegen_backends(compiler);
731 t!(fs::create_dir_all(&sysroot_codegen_backends));
732 let stage0_codegen_backends = builder
733 .out
734 .join(host)
735 .join("stage0/lib/rustlib")
736 .join(host)
737 .join("codegen-backends");
738 if stage0_codegen_backends.exists() {
739 builder.cp_link_r(&stage0_codegen_backends, &sysroot_codegen_backends);
740 }
741 }
742 }
743}
744
745fn copy_sanitizers(
747 builder: &Builder<'_>,
748 compiler: &Compiler,
749 target: TargetSelection,
750) -> Vec<PathBuf> {
751 let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
752
753 if builder.config.dry_run() {
754 return Vec::new();
755 }
756
757 let mut target_deps = Vec::new();
758 let libdir = builder.sysroot_target_libdir(*compiler, target);
759
760 for runtime in &runtimes {
761 let dst = libdir.join(&runtime.name);
762 builder.copy_link(&runtime.path, &dst);
763
764 if target == "x86_64-apple-darwin"
768 || target == "aarch64-apple-darwin"
769 || target == "aarch64-apple-ios"
770 || target == "aarch64-apple-ios-sim"
771 || target == "x86_64-apple-ios"
772 {
773 apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", runtime.name));
775 apple_darwin_sign_file(builder, &dst);
778 }
779
780 target_deps.push(dst);
781 }
782
783 target_deps
784}
785
786fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
787 command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
788}
789
790fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
791 command("codesign")
792 .arg("-f") .arg("-s")
794 .arg("-")
795 .arg(file_path)
796 .run(builder);
797}
798
799#[derive(Debug, Clone, PartialEq, Eq, Hash)]
800pub struct StartupObjects {
801 pub compiler: Compiler,
802 pub target: TargetSelection,
803}
804
805impl Step for StartupObjects {
806 type Output = Vec<(PathBuf, DependencyType)>;
807
808 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
809 run.path("library/rtstartup")
810 }
811
812 fn make_run(run: RunConfig<'_>) {
813 run.builder.ensure(StartupObjects {
814 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
815 target: run.target,
816 });
817 }
818
819 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
826 let for_compiler = self.compiler;
827 let target = self.target;
828 if !target.is_windows_gnu() {
829 return vec![];
830 }
831
832 let mut target_deps = vec![];
833
834 let src_dir = &builder.src.join("library").join("rtstartup");
835 let dst_dir = &builder.native_dir(target).join("rtstartup");
836 let sysroot_dir = &builder.sysroot_target_libdir(for_compiler, target);
837 t!(fs::create_dir_all(dst_dir));
838
839 for file in &["rsbegin", "rsend"] {
840 let src_file = &src_dir.join(file.to_string() + ".rs");
841 let dst_file = &dst_dir.join(file.to_string() + ".o");
842 if !up_to_date(src_file, dst_file) {
843 let mut cmd = command(&builder.initial_rustc);
844 cmd.env("RUSTC_BOOTSTRAP", "1");
845 if !builder.local_rebuild {
846 cmd.arg("--cfg").arg("bootstrap");
848 }
849 cmd.arg("--target")
850 .arg(target.rustc_target_arg())
851 .arg("--emit=obj")
852 .arg("-o")
853 .arg(dst_file)
854 .arg(src_file)
855 .run(builder);
856 }
857
858 let target = sysroot_dir.join((*file).to_string() + ".o");
859 builder.copy_link(dst_file, &target);
860 target_deps.push((target, DependencyType::Target));
861 }
862
863 target_deps
864 }
865}
866
867fn cp_rustc_component_to_ci_sysroot(builder: &Builder<'_>, sysroot: &Path, contents: Vec<String>) {
868 let ci_rustc_dir = builder.config.ci_rustc_dir();
869
870 for file in contents {
871 let src = ci_rustc_dir.join(&file);
872 let dst = sysroot.join(file);
873 if src.is_dir() {
874 t!(fs::create_dir_all(dst));
875 } else {
876 builder.copy_link(&src, &dst);
877 }
878 }
879}
880
881#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
882pub struct Rustc {
883 pub target: TargetSelection,
884 pub compiler: Compiler,
886 crates: Vec<String>,
892}
893
894impl Rustc {
895 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
896 Self { target, compiler, crates: Default::default() }
897 }
898}
899
900impl Step for Rustc {
901 type Output = u32;
909 const ONLY_HOSTS: bool = true;
910 const DEFAULT: bool = false;
911
912 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
913 let mut crates = run.builder.in_tree_crates("rustc-main", None);
914 for (i, krate) in crates.iter().enumerate() {
915 if krate.name == "rustc-main" {
918 crates.swap_remove(i);
919 break;
920 }
921 }
922 run.crates(crates)
923 }
924
925 fn make_run(run: RunConfig<'_>) {
926 let crates = run.cargo_crates_in_set();
927 run.builder.ensure(Rustc {
928 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
929 target: run.target,
930 crates,
931 });
932 }
933
934 fn run(self, builder: &Builder<'_>) -> u32 {
940 let compiler = self.compiler;
941 let target = self.target;
942
943 if builder.download_rustc() && compiler.stage != 0 {
946 let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
947 cp_rustc_component_to_ci_sysroot(
948 builder,
949 &sysroot,
950 builder.config.ci_rustc_dev_contents(),
951 );
952 return compiler.stage;
953 }
954
955 builder.ensure(Std::new(compiler, target));
956
957 if builder.config.keep_stage.contains(&compiler.stage) {
958 builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
959 builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
960 builder.ensure(RustcLink::from_rustc(self, compiler));
961
962 return compiler.stage;
963 }
964
965 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
966 if compiler_to_use != compiler {
967 builder.ensure(Rustc::new(compiler_to_use, target));
968 let msg = if compiler_to_use.host == target {
969 format!(
970 "Uplifting rustc (stage{} -> stage{})",
971 compiler_to_use.stage,
972 compiler.stage + 1
973 )
974 } else {
975 format!(
976 "Uplifting rustc (stage{}:{} -> stage{}:{})",
977 compiler_to_use.stage,
978 compiler_to_use.host,
979 compiler.stage + 1,
980 target
981 )
982 };
983 builder.info(&msg);
984 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
985 return compiler_to_use.stage;
986 }
987
988 builder.ensure(Std::new(
990 builder.compiler(self.compiler.stage, builder.config.build),
991 builder.config.build,
992 ));
993
994 let mut cargo = builder::Cargo::new(
995 builder,
996 compiler,
997 Mode::Rustc,
998 SourceType::InTree,
999 target,
1000 Kind::Build,
1001 );
1002
1003 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
1004
1005 for krate in &*self.crates {
1009 cargo.arg("-p").arg(krate);
1010 }
1011
1012 if builder.build.config.enable_bolt_settings && compiler.stage == 1 {
1013 cargo.env("RUSTC_BOLT_LINK_FLAGS", "1");
1015 }
1016
1017 let _guard = builder.msg_sysroot_tool(
1018 Kind::Build,
1019 compiler.stage,
1020 format_args!("compiler artifacts{}", crate_description(&self.crates)),
1021 compiler.host,
1022 target,
1023 );
1024 let stamp = build_stamp::librustc_stamp(builder, compiler, target);
1025 run_cargo(
1026 builder,
1027 cargo,
1028 vec![],
1029 &stamp,
1030 vec![],
1031 false,
1032 true, );
1034
1035 let target_root_dir = stamp.path().parent().unwrap();
1036 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None
1042 && builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None
1043 {
1044 let rustc_driver = target_root_dir.join("librustc_driver.so");
1045 strip_debug(builder, target, &rustc_driver);
1046 }
1047
1048 if builder.config.rust_debuginfo_level_rustc == DebuginfoLevel::None {
1049 strip_debug(builder, target, &target_root_dir.join("rustc-main"));
1052 }
1053
1054 builder.ensure(RustcLink::from_rustc(
1055 self,
1056 builder.compiler(compiler.stage, builder.config.build),
1057 ));
1058
1059 compiler.stage
1060 }
1061}
1062
1063pub fn rustc_cargo(
1064 builder: &Builder<'_>,
1065 cargo: &mut Cargo,
1066 target: TargetSelection,
1067 compiler: &Compiler,
1068 crates: &[String],
1069) {
1070 cargo
1071 .arg("--features")
1072 .arg(builder.rustc_features(builder.kind, target, crates))
1073 .arg("--manifest-path")
1074 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
1075
1076 cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
1077
1078 cargo.rustflag("-Zon-broken-pipe=kill");
1092
1093 if builder.config.llvm_enzyme {
1096 let llvm_config = builder.llvm_config(builder.config.build).unwrap();
1097 let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config);
1098 cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}"));
1099 }
1100
1101 if builder.build.config.lld_mode.is_used() {
1106 cargo.rustflag("-Zdefault-visibility=protected");
1107 }
1108
1109 if is_lto_stage(compiler) {
1110 match builder.config.rust_lto {
1111 RustcLto::Thin | RustcLto::Fat => {
1112 cargo.rustflag("-Zdylib-lto");
1115 let lto_type = match builder.config.rust_lto {
1119 RustcLto::Thin => "thin",
1120 RustcLto::Fat => "fat",
1121 _ => unreachable!(),
1122 };
1123 cargo.rustflag(&format!("-Clto={lto_type}"));
1124 cargo.rustflag("-Cembed-bitcode=yes");
1125 }
1126 RustcLto::ThinLocal => { }
1127 RustcLto::Off => {
1128 cargo.rustflag("-Clto=off");
1129 }
1130 }
1131 } else if builder.config.rust_lto == RustcLto::Off {
1132 cargo.rustflag("-Clto=off");
1133 }
1134
1135 if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
1143 cargo.rustflag("-Clink-args=-Wl,--icf=all");
1144 }
1145
1146 if builder.config.rust_profile_use.is_some() && builder.config.rust_profile_generate.is_some() {
1147 panic!("Cannot use and generate PGO profiles at the same time");
1148 }
1149 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
1150 if compiler.stage == 1 {
1151 cargo.rustflag(&format!("-Cprofile-generate={path}"));
1152 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
1155 true
1156 } else {
1157 false
1158 }
1159 } else if let Some(path) = &builder.config.rust_profile_use {
1160 if compiler.stage == 1 {
1161 cargo.rustflag(&format!("-Cprofile-use={path}"));
1162 if builder.is_verbose() {
1163 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
1164 }
1165 true
1166 } else {
1167 false
1168 }
1169 } else {
1170 false
1171 };
1172 if is_collecting {
1173 cargo.rustflag(&format!(
1175 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
1176 builder.config.src.components().count()
1177 ));
1178 }
1179
1180 rustc_cargo_env(builder, cargo, target, compiler.stage);
1181}
1182
1183pub fn rustc_cargo_env(
1184 builder: &Builder<'_>,
1185 cargo: &mut Cargo,
1186 target: TargetSelection,
1187 stage: u32,
1188) {
1189 cargo
1192 .env("CFG_RELEASE", builder.rust_release())
1193 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1194 .env("CFG_VERSION", builder.rust_version());
1195
1196 if builder.config.omit_git_hash {
1200 cargo.env("CFG_OMIT_GIT_HASH", "1");
1201 }
1202
1203 if let Some(backend) = builder.config.default_codegen_backend(target) {
1204 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
1205 }
1206
1207 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
1208 let target_config = builder.config.target_config.get(&target);
1209
1210 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
1211
1212 if let Some(ref ver_date) = builder.rust_info().commit_date() {
1213 cargo.env("CFG_VER_DATE", ver_date);
1214 }
1215 if let Some(ref ver_hash) = builder.rust_info().sha() {
1216 cargo.env("CFG_VER_HASH", ver_hash);
1217 }
1218 if !builder.unstable_features() {
1219 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
1220 }
1221
1222 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
1225 cargo.env("CFG_DEFAULT_LINKER", s);
1226 } else if let Some(ref s) = builder.config.rustc_default_linker {
1227 cargo.env("CFG_DEFAULT_LINKER", s);
1228 }
1229
1230 if builder.config.lld_enabled
1232 && (builder.config.channel == "dev" || builder.config.channel == "nightly")
1233 {
1234 cargo.env("CFG_USE_SELF_CONTAINED_LINKER", "1");
1235 }
1236
1237 if builder.config.rust_verify_llvm_ir {
1238 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
1239 }
1240
1241 if builder.config.llvm_enzyme {
1242 cargo.rustflag("--cfg=llvm_enzyme");
1243 }
1244
1245 if builder.config.llvm_enabled(target) {
1250 let building_is_expensive =
1251 crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
1252 .should_build();
1253 let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage;
1255 let should_skip_build = building_is_expensive && can_skip_build;
1256 if !should_skip_build {
1257 rustc_llvm_env(builder, cargo, target)
1258 }
1259 }
1260
1261 if builder.config.jemalloc
1264 && target.starts_with("aarch64")
1265 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
1266 {
1267 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
1268 }
1269}
1270
1271fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
1274 if builder.is_rust_llvm(target) {
1275 cargo.env("LLVM_RUSTLLVM", "1");
1276 }
1277 if builder.config.llvm_enzyme {
1278 cargo.env("LLVM_ENZYME", "1");
1279 }
1280 let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
1281 cargo.env("LLVM_CONFIG", &llvm_config);
1282
1283 let mut llvm_linker_flags = String::new();
1293 if builder.config.llvm_profile_generate && target.is_msvc() {
1294 if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
1295 let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
1297 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
1298 }
1299 }
1300
1301 if let Some(ref s) = builder.config.llvm_ldflags {
1303 if !llvm_linker_flags.is_empty() {
1304 llvm_linker_flags.push(' ');
1305 }
1306 llvm_linker_flags.push_str(s);
1307 }
1308
1309 if !llvm_linker_flags.is_empty() {
1311 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
1312 }
1313
1314 if builder.config.llvm_static_stdcpp
1317 && !target.contains("freebsd")
1318 && !target.is_msvc()
1319 && !target.contains("apple")
1320 && !target.contains("solaris")
1321 {
1322 let file = compiler_file(
1323 builder,
1324 &builder.cxx(target).unwrap(),
1325 target,
1326 CLang::Cxx,
1327 "libstdc++.a",
1328 );
1329 cargo.env("LLVM_STATIC_STDCPP", file);
1330 }
1331 if builder.llvm_link_shared() {
1332 cargo.env("LLVM_LINK_SHARED", "1");
1333 }
1334 if builder.config.llvm_use_libcxx {
1335 cargo.env("LLVM_USE_LIBCXX", "1");
1336 }
1337 if builder.config.llvm_assertions {
1338 cargo.env("LLVM_ASSERTIONS", "1");
1339 }
1340}
1341
1342#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1348struct RustcLink {
1349 pub compiler: Compiler,
1351 pub previous_stage_compiler: Compiler,
1353 pub target: TargetSelection,
1354 crates: Vec<String>,
1356}
1357
1358impl RustcLink {
1359 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
1360 Self {
1361 compiler: host_compiler,
1362 previous_stage_compiler: rustc.compiler,
1363 target: rustc.target,
1364 crates: rustc.crates,
1365 }
1366 }
1367}
1368
1369impl Step for RustcLink {
1370 type Output = ();
1371
1372 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1373 run.never()
1374 }
1375
1376 fn run(self, builder: &Builder<'_>) {
1378 let compiler = self.compiler;
1379 let previous_stage_compiler = self.previous_stage_compiler;
1380 let target = self.target;
1381 add_to_sysroot(
1382 builder,
1383 &builder.sysroot_target_libdir(previous_stage_compiler, target),
1384 &builder.sysroot_target_libdir(previous_stage_compiler, compiler.host),
1385 &build_stamp::librustc_stamp(builder, compiler, target),
1386 );
1387 }
1388}
1389
1390#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1391pub struct CodegenBackend {
1392 pub target: TargetSelection,
1393 pub compiler: Compiler,
1394 pub backend: String,
1395}
1396
1397fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
1398 let mut needs_codegen_cfg = false;
1399 for path_set in &run.paths {
1400 needs_codegen_cfg = match path_set {
1401 PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
1402 PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
1403 }
1404 }
1405 needs_codegen_cfg
1406}
1407
1408pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
1409
1410fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
1411 let path = path.path.to_str().unwrap();
1412
1413 let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
1414 let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
1415
1416 if path.contains(CODEGEN_BACKEND_PREFIX) {
1417 let mut needs_codegen_backend_config = true;
1418 for backend in run.builder.config.codegen_backends(run.target) {
1419 if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
1420 needs_codegen_backend_config = false;
1421 }
1422 }
1423 if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
1424 && needs_codegen_backend_config
1425 {
1426 run.builder.info(
1427 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
1428 HELP: add backend to codegen-backends in config.toml.",
1429 );
1430 return true;
1431 }
1432 }
1433
1434 false
1435}
1436
1437impl Step for CodegenBackend {
1438 type Output = ();
1439 const ONLY_HOSTS: bool = true;
1440 const DEFAULT: bool = true;
1442
1443 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1444 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1445 }
1446
1447 fn make_run(run: RunConfig<'_>) {
1448 if needs_codegen_config(&run) {
1449 return;
1450 }
1451
1452 for backend in run.builder.config.codegen_backends(run.target) {
1453 if backend == "llvm" {
1454 continue; }
1456
1457 run.builder.ensure(CodegenBackend {
1458 target: run.target,
1459 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1460 backend: backend.clone(),
1461 });
1462 }
1463 }
1464
1465 fn run(self, builder: &Builder<'_>) {
1466 let compiler = self.compiler;
1467 let target = self.target;
1468 let backend = self.backend;
1469
1470 builder.ensure(Rustc::new(compiler, target));
1471
1472 if builder.config.keep_stage.contains(&compiler.stage) {
1473 builder.info(
1474 "WARNING: Using a potentially old codegen backend. \
1475 This may not behave well.",
1476 );
1477 return;
1480 }
1481
1482 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1483 if compiler_to_use != compiler {
1484 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1485 return;
1486 }
1487
1488 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1489
1490 let mut cargo = builder::Cargo::new(
1491 builder,
1492 compiler,
1493 Mode::Codegen,
1494 SourceType::InTree,
1495 target,
1496 Kind::Build,
1497 );
1498 cargo
1499 .arg("--manifest-path")
1500 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
1501 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
1502
1503 let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
1504
1505 let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
1506 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1507 if builder.config.dry_run() {
1508 return;
1509 }
1510 let mut files = files.into_iter().filter(|f| {
1511 let filename = f.file_name().unwrap().to_str().unwrap();
1512 is_dylib(f) && filename.contains("rustc_codegen_")
1513 });
1514 let codegen_backend = match files.next() {
1515 Some(f) => f,
1516 None => panic!("no dylibs built for codegen backend?"),
1517 };
1518 if let Some(f) = files.next() {
1519 panic!(
1520 "codegen backend built two dylibs:\n{}\n{}",
1521 codegen_backend.display(),
1522 f.display()
1523 );
1524 }
1525 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, &backend);
1526 let codegen_backend = codegen_backend.to_str().unwrap();
1527 t!(stamp.add_stamp(codegen_backend).write());
1528 }
1529}
1530
1531fn copy_codegen_backends_to_sysroot(
1538 builder: &Builder<'_>,
1539 compiler: Compiler,
1540 target_compiler: Compiler,
1541) {
1542 let target = target_compiler.host;
1543
1544 let dst = builder.sysroot_codegen_backends(target_compiler);
1553 t!(fs::create_dir_all(&dst), dst);
1554
1555 if builder.config.dry_run() {
1556 return;
1557 }
1558
1559 for backend in builder.config.codegen_backends(target) {
1560 if backend == "llvm" {
1561 continue; }
1563
1564 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
1565 let dylib = t!(fs::read_to_string(stamp.path()));
1566 let file = Path::new(&dylib);
1567 let filename = file.file_name().unwrap().to_str().unwrap();
1568 let target_filename = {
1571 let dash = filename.find('-').unwrap();
1572 let dot = filename.find('.').unwrap();
1573 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1574 };
1575 builder.copy_link(file, &dst.join(target_filename));
1576 }
1577}
1578
1579pub fn compiler_file(
1580 builder: &Builder<'_>,
1581 compiler: &Path,
1582 target: TargetSelection,
1583 c: CLang,
1584 file: &str,
1585) -> PathBuf {
1586 if builder.config.dry_run() {
1587 return PathBuf::new();
1588 }
1589 let mut cmd = command(compiler);
1590 cmd.args(builder.cc_handled_clags(target, c));
1591 cmd.args(builder.cc_unhandled_cflags(target, GitRepo::Rustc, c));
1592 cmd.arg(format!("-print-file-name={file}"));
1593 let out = cmd.run_capture_stdout(builder).stdout();
1594 PathBuf::from(out.trim())
1595}
1596
1597#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1598pub struct Sysroot {
1599 pub compiler: Compiler,
1600 force_recompile: bool,
1602}
1603
1604impl Sysroot {
1605 pub(crate) fn new(compiler: Compiler) -> Self {
1606 Sysroot { compiler, force_recompile: false }
1607 }
1608}
1609
1610impl Step for Sysroot {
1611 type Output = PathBuf;
1612
1613 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1614 run.never()
1615 }
1616
1617 fn run(self, builder: &Builder<'_>) -> PathBuf {
1621 let compiler = self.compiler;
1622 let host_dir = builder.out.join(compiler.host);
1623
1624 let sysroot_dir = |stage| {
1625 if stage == 0 {
1626 host_dir.join("stage0-sysroot")
1627 } else if self.force_recompile && stage == compiler.stage {
1628 host_dir.join(format!("stage{stage}-test-sysroot"))
1629 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1630 host_dir.join("ci-rustc-sysroot")
1631 } else {
1632 host_dir.join(format!("stage{}", stage))
1633 }
1634 };
1635 let sysroot = sysroot_dir(compiler.stage);
1636
1637 builder
1638 .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
1639 let _ = fs::remove_dir_all(&sysroot);
1640 t!(fs::create_dir_all(&sysroot));
1641
1642 if compiler.stage == 0 {
1649 dist::maybe_install_llvm_target(builder, compiler.host, &sysroot);
1650 }
1651
1652 if builder.download_rustc() && compiler.stage != 0 {
1654 assert_eq!(
1655 builder.config.build, compiler.host,
1656 "Cross-compiling is not yet supported with `download-rustc`",
1657 );
1658
1659 for stage in 0..=2 {
1661 if stage != compiler.stage {
1662 let dir = sysroot_dir(stage);
1663 if !dir.ends_with("ci-rustc-sysroot") {
1664 let _ = fs::remove_dir_all(dir);
1665 }
1666 }
1667 }
1668
1669 let mut filtered_files = Vec::new();
1679 let mut add_filtered_files = |suffix, contents| {
1680 for path in contents {
1681 let path = Path::new(&path);
1682 if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
1683 filtered_files.push(path.file_name().unwrap().to_owned());
1684 }
1685 }
1686 };
1687 let suffix = format!("lib/rustlib/{}/lib", compiler.host);
1688 add_filtered_files(suffix.as_str(), builder.config.ci_rustc_dev_contents());
1689 add_filtered_files("lib", builder.config.ci_rust_std_contents());
1692
1693 let filtered_extensions = [
1694 OsStr::new("rmeta"),
1695 OsStr::new("rlib"),
1696 OsStr::new(std::env::consts::DLL_EXTENSION),
1698 ];
1699 let ci_rustc_dir = builder.config.ci_rustc_dir();
1700 builder.cp_link_filtered(&ci_rustc_dir, &sysroot, &|path| {
1701 if path.extension().is_none_or(|ext| !filtered_extensions.contains(&ext)) {
1702 return true;
1703 }
1704 if !path.parent().is_none_or(|p| p.ends_with(&suffix)) {
1705 return true;
1706 }
1707 if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
1708 builder.verbose_than(1, || println!("ignoring {}", path.display()));
1709 false
1710 } else {
1711 true
1712 }
1713 });
1714 }
1715
1716 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1722 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1723 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1724 if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
1725 eprintln!(
1726 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1727 sysroot_lib_rustlib_src_rust.display(),
1728 builder.src.display(),
1729 e,
1730 );
1731 if builder.config.rust_remap_debuginfo {
1732 eprintln!(
1733 "ERROR: some `tests/ui` tests will fail when lacking `{}`",
1734 sysroot_lib_rustlib_src_rust.display(),
1735 );
1736 }
1737 build_helper::exit!(1);
1738 }
1739
1740 if !builder.download_rustc() {
1742 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1743 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1744 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1745 if let Err(e) =
1746 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1747 {
1748 eprintln!(
1749 "ERROR: creating symbolic link `{}` to `{}` failed with {}",
1750 sysroot_lib_rustlib_rustcsrc_rust.display(),
1751 builder.src.display(),
1752 e,
1753 );
1754 build_helper::exit!(1);
1755 }
1756 }
1757
1758 sysroot
1759 }
1760}
1761
1762#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1763pub struct Assemble {
1764 pub target_compiler: Compiler,
1769}
1770
1771impl Step for Assemble {
1772 type Output = Compiler;
1773 const ONLY_HOSTS: bool = true;
1774
1775 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1776 run.path("compiler/rustc").path("compiler")
1777 }
1778
1779 fn make_run(run: RunConfig<'_>) {
1780 run.builder.ensure(Assemble {
1781 target_compiler: run.builder.compiler(run.builder.top_stage + 1, run.target),
1782 });
1783 }
1784
1785 fn run(self, builder: &Builder<'_>) -> Compiler {
1791 let target_compiler = self.target_compiler;
1792
1793 if target_compiler.stage == 0 {
1794 assert_eq!(
1795 builder.config.build, target_compiler.host,
1796 "Cannot obtain compiler for non-native build triple at stage 0"
1797 );
1798 return target_compiler;
1800 }
1801
1802 let libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host);
1805 let libdir_bin = libdir.parent().unwrap().join("bin");
1806 t!(fs::create_dir_all(&libdir_bin));
1807
1808 if builder.config.llvm_enabled(target_compiler.host) {
1809 let llvm::LlvmResult { llvm_config, .. } =
1810 builder.ensure(llvm::Llvm { target: target_compiler.host });
1811 if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
1812 let llvm_bin_dir =
1813 command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
1814 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
1815
1816 for tool in LLVM_TOOLS {
1822 let tool_exe = exe(tool, target_compiler.host);
1823 let src_path = llvm_bin_dir.join(&tool_exe);
1824 if src_path.exists() {
1827 builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
1834 }
1835 }
1836 }
1837 }
1838
1839 let maybe_install_llvm_bitcode_linker = |compiler| {
1840 if builder.config.llvm_bitcode_linker_enabled {
1841 let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
1842 compiler,
1843 target: target_compiler.host,
1844 extra_features: vec![],
1845 });
1846 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
1847 builder.copy_link(&src_path, &libdir_bin.join(tool_exe));
1848 }
1849 };
1850
1851 if builder.download_rustc() {
1853 builder.ensure(Std::new(target_compiler, target_compiler.host));
1854 let sysroot =
1855 builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
1856 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
1859 if target_compiler.stage == builder.top_stage {
1861 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage=target_compiler.stage));
1862 }
1863
1864 maybe_install_llvm_bitcode_linker(target_compiler);
1865
1866 return target_compiler;
1867 }
1868
1869 let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
1883
1884 let enzyme_install = if builder.config.llvm_enzyme {
1886 Some(builder.ensure(llvm::Enzyme { target: build_compiler.host }))
1887 } else {
1888 None
1889 };
1890
1891 if let Some(enzyme_install) = enzyme_install {
1892 let lib_ext = std::env::consts::DLL_EXTENSION;
1893 let src_lib = enzyme_install.join("build/Enzyme/libEnzyme-19").with_extension(lib_ext);
1894 let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
1895 let target_libdir =
1896 builder.sysroot_target_libdir(target_compiler, target_compiler.host);
1897 let dst_lib = libdir.join("libEnzyme-19").with_extension(lib_ext);
1898 let target_dst_lib = target_libdir.join("libEnzyme-19").with_extension(lib_ext);
1899 builder.copy_link(&src_lib, &dst_lib);
1900 builder.copy_link(&src_lib, &target_dst_lib);
1901 }
1902
1903 let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
1909 build_compiler.stage = actual_stage;
1912
1913 for backend in builder.config.codegen_backends(target_compiler.host) {
1914 if backend == "llvm" {
1915 continue; }
1917
1918 builder.ensure(CodegenBackend {
1919 compiler: build_compiler,
1920 target: target_compiler.host,
1921 backend: backend.clone(),
1922 });
1923 }
1924
1925 let stage = target_compiler.stage;
1926 let host = target_compiler.host;
1927 let (host_info, dir_name) = if build_compiler.host == host {
1928 ("".into(), "host".into())
1929 } else {
1930 (format!(" ({host})"), host.to_string())
1931 };
1932 let msg = format!(
1937 "Creating a sysroot for stage{stage} compiler{host_info} (use `rustup toolchain link 'name' build/{dir_name}/stage{stage}`)"
1938 );
1939 builder.info(&msg);
1940
1941 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target_compiler.host);
1943 let proc_macros = builder
1944 .read_stamp_file(&stamp)
1945 .into_iter()
1946 .filter_map(|(path, dependency_type)| {
1947 if dependency_type == DependencyType::Host {
1948 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
1949 } else {
1950 None
1951 }
1952 })
1953 .collect::<HashSet<_>>();
1954
1955 let sysroot = builder.sysroot(target_compiler);
1956 let rustc_libdir = builder.rustc_libdir(target_compiler);
1957 t!(fs::create_dir_all(&rustc_libdir));
1958 let src_libdir = builder.sysroot_target_libdir(build_compiler, host);
1959 for f in builder.read_dir(&src_libdir) {
1960 let filename = f.file_name().into_string().unwrap();
1961
1962 let is_proc_macro = proc_macros.contains(&filename);
1963 let is_dylib_or_debug = is_dylib(&f.path()) || is_debug_info(&filename);
1964
1965 let can_be_rustc_dynamic_dep = if builder
1969 .link_std_into_rustc_driver(target_compiler.host)
1970 && !target_compiler.host.is_windows()
1971 {
1972 let is_std = filename.starts_with("std-") || filename.starts_with("libstd-");
1973 !is_std
1974 } else {
1975 true
1976 };
1977
1978 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
1979 builder.copy_link(&f.path(), &rustc_libdir.join(&filename));
1980 }
1981 }
1982
1983 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
1984
1985 if builder.config.lld_enabled {
1986 builder.ensure(crate::core::build_steps::tool::LldWrapper {
1987 build_compiler,
1988 target_compiler,
1989 });
1990 }
1991
1992 if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
1993 let src_exe = exe("llvm-objcopy", target_compiler.host);
2000 let dst_exe = exe("rust-objcopy", target_compiler.host);
2001 builder.copy_link(&libdir_bin.join(src_exe), &libdir_bin.join(dst_exe));
2002 }
2003
2004 if builder.tool_enabled("wasm-component-ld") {
2010 let wasm_component_ld_exe =
2011 builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
2012 compiler: build_compiler,
2013 target: target_compiler.host,
2014 });
2015 builder.copy_link(
2016 &wasm_component_ld_exe,
2017 &libdir_bin.join(wasm_component_ld_exe.file_name().unwrap()),
2018 );
2019 }
2020
2021 maybe_install_llvm_bitcode_linker(build_compiler);
2022
2023 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
2026 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
2027
2028 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
2030 let rustc = out_dir.join(exe("rustc-main", host));
2031 let bindir = sysroot.join("bin");
2032 t!(fs::create_dir_all(bindir));
2033 let compiler = builder.rustc(target_compiler);
2034 builder.copy_link(&rustc, &compiler);
2035
2036 target_compiler
2037 }
2038}
2039
2040pub fn add_to_sysroot(
2045 builder: &Builder<'_>,
2046 sysroot_dst: &Path,
2047 sysroot_host_dst: &Path,
2048 stamp: &BuildStamp,
2049) {
2050 let self_contained_dst = &sysroot_dst.join("self-contained");
2051 t!(fs::create_dir_all(sysroot_dst));
2052 t!(fs::create_dir_all(sysroot_host_dst));
2053 t!(fs::create_dir_all(self_contained_dst));
2054 for (path, dependency_type) in builder.read_stamp_file(stamp) {
2055 let dst = match dependency_type {
2056 DependencyType::Host => sysroot_host_dst,
2057 DependencyType::Target => sysroot_dst,
2058 DependencyType::TargetSelfContained => self_contained_dst,
2059 };
2060 builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
2061 }
2062}
2063
2064pub fn run_cargo(
2065 builder: &Builder<'_>,
2066 cargo: Cargo,
2067 tail_args: Vec<String>,
2068 stamp: &BuildStamp,
2069 additional_target_deps: Vec<(PathBuf, DependencyType)>,
2070 is_check: bool,
2071 rlib_only_metadata: bool,
2072) -> Vec<PathBuf> {
2073 let target_root_dir = stamp.path().parent().unwrap();
2075 let target_deps_dir = target_root_dir.join("deps");
2077 let host_root_dir = target_root_dir
2079 .parent()
2080 .unwrap() .parent()
2082 .unwrap() .join(target_root_dir.file_name().unwrap());
2084
2085 let mut deps = Vec::new();
2089 let mut toplevel = Vec::new();
2090 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
2091 let (filenames, crate_types) = match msg {
2092 CargoMessage::CompilerArtifact {
2093 filenames,
2094 target: CargoTarget { crate_types },
2095 ..
2096 } => (filenames, crate_types),
2097 _ => return,
2098 };
2099 for filename in filenames {
2100 let mut keep = false;
2102 if filename.ends_with(".lib")
2103 || filename.ends_with(".a")
2104 || is_debug_info(&filename)
2105 || is_dylib(Path::new(&*filename))
2106 {
2107 keep = true;
2109 }
2110 if is_check && filename.ends_with(".rmeta") {
2111 keep = true;
2113 } else if rlib_only_metadata {
2114 if filename.contains("jemalloc_sys")
2115 || filename.contains("rustc_smir")
2116 || filename.contains("stable_mir")
2117 {
2118 keep |= filename.ends_with(".rlib");
2121 } else {
2122 keep |= filename.ends_with(".rmeta");
2126 }
2127 } else {
2128 keep |= filename.ends_with(".rlib");
2130 }
2131
2132 if !keep {
2133 continue;
2134 }
2135
2136 let filename = Path::new(&*filename);
2137
2138 if filename.starts_with(&host_root_dir) {
2141 if crate_types.iter().any(|t| t == "proc-macro") {
2143 deps.push((filename.to_path_buf(), DependencyType::Host));
2144 }
2145 continue;
2146 }
2147
2148 if filename.starts_with(&target_deps_dir) {
2151 deps.push((filename.to_path_buf(), DependencyType::Target));
2152 continue;
2153 }
2154
2155 let expected_len = t!(filename.metadata()).len();
2166 let filename = filename.file_name().unwrap().to_str().unwrap();
2167 let mut parts = filename.splitn(2, '.');
2168 let file_stem = parts.next().unwrap().to_owned();
2169 let extension = parts.next().unwrap().to_owned();
2170
2171 toplevel.push((file_stem, extension, expected_len));
2172 }
2173 });
2174
2175 if !ok {
2176 crate::exit!(1);
2177 }
2178
2179 if builder.config.dry_run() {
2180 return Vec::new();
2181 }
2182
2183 let contents = t!(target_deps_dir.read_dir())
2187 .map(|e| t!(e))
2188 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
2189 .collect::<Vec<_>>();
2190 for (prefix, extension, expected_len) in toplevel {
2191 let candidates = contents.iter().filter(|&(_, filename, meta)| {
2192 meta.len() == expected_len
2193 && filename
2194 .strip_prefix(&prefix[..])
2195 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
2196 .unwrap_or(false)
2197 });
2198 let max = candidates.max_by_key(|&(_, _, metadata)| {
2199 metadata.modified().expect("mtime should be available on all relevant OSes")
2200 });
2201 let path_to_add = match max {
2202 Some(triple) => triple.0.to_str().unwrap(),
2203 None => panic!("no output generated for {prefix:?} {extension:?}"),
2204 };
2205 if is_dylib(Path::new(path_to_add)) {
2206 let candidate = format!("{path_to_add}.lib");
2207 let candidate = PathBuf::from(candidate);
2208 if candidate.exists() {
2209 deps.push((candidate, DependencyType::Target));
2210 }
2211 }
2212 deps.push((path_to_add.into(), DependencyType::Target));
2213 }
2214
2215 deps.extend(additional_target_deps);
2216 deps.sort();
2217 let mut new_contents = Vec::new();
2218 for (dep, dependency_type) in deps.iter() {
2219 new_contents.extend(match *dependency_type {
2220 DependencyType::Host => b"h",
2221 DependencyType::Target => b"t",
2222 DependencyType::TargetSelfContained => b"s",
2223 });
2224 new_contents.extend(dep.to_str().unwrap().as_bytes());
2225 new_contents.extend(b"\0");
2226 }
2227 t!(fs::write(stamp.path(), &new_contents));
2228 deps.into_iter().map(|(d, _)| d).collect()
2229}
2230
2231pub fn stream_cargo(
2232 builder: &Builder<'_>,
2233 cargo: Cargo,
2234 tail_args: Vec<String>,
2235 cb: &mut dyn FnMut(CargoMessage<'_>),
2236) -> bool {
2237 let mut cmd = cargo.into_cmd();
2238
2239 #[cfg(feature = "tracing")]
2240 let _run_span = crate::trace_cmd!(cmd);
2241
2242 let cargo = cmd.as_command_mut();
2243 let mut message_format = if builder.config.json_output {
2246 String::from("json")
2247 } else {
2248 String::from("json-render-diagnostics")
2249 };
2250 if let Some(s) = &builder.config.rustc_error_format {
2251 message_format.push_str(",json-diagnostic-");
2252 message_format.push_str(s);
2253 }
2254 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
2255
2256 for arg in tail_args {
2257 cargo.arg(arg);
2258 }
2259
2260 builder.verbose(|| println!("running: {cargo:?}"));
2261
2262 if builder.config.dry_run() {
2263 return true;
2264 }
2265
2266 let mut child = match cargo.spawn() {
2267 Ok(child) => child,
2268 Err(e) => panic!("failed to execute command: {cargo:?}\nERROR: {e}"),
2269 };
2270
2271 let stdout = BufReader::new(child.stdout.take().unwrap());
2275 for line in stdout.lines() {
2276 let line = t!(line);
2277 match serde_json::from_str::<CargoMessage<'_>>(&line) {
2278 Ok(msg) => {
2279 if builder.config.json_output {
2280 println!("{line}");
2282 }
2283 cb(msg)
2284 }
2285 Err(_) => println!("{line}"),
2287 }
2288 }
2289
2290 let status = t!(child.wait());
2292 if builder.is_verbose() && !status.success() {
2293 eprintln!(
2294 "command did not execute successfully: {cargo:?}\n\
2295 expected success, got: {status}"
2296 );
2297 }
2298 status.success()
2299}
2300
2301#[derive(Deserialize)]
2302pub struct CargoTarget<'a> {
2303 crate_types: Vec<Cow<'a, str>>,
2304}
2305
2306#[derive(Deserialize)]
2307#[serde(tag = "reason", rename_all = "kebab-case")]
2308pub enum CargoMessage<'a> {
2309 CompilerArtifact { filenames: Vec<Cow<'a, str>>, target: CargoTarget<'a> },
2310 BuildScriptExecuted,
2311 BuildFinished,
2312}
2313
2314pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) {
2315 if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(&target) || !path.exists()
2319 {
2320 return;
2321 }
2322
2323 let previous_mtime = t!(t!(path.metadata()).modified());
2324 command("strip").arg("--strip-debug").arg(path).run_capture(builder);
2325
2326 let file = t!(fs::File::open(path));
2327
2328 t!(file.set_modified(previous_mtime));
2341}
2342
2343pub fn is_lto_stage(build_compiler: &Compiler) -> bool {
2345 build_compiler.stage != 0
2346}