1use std::collections::HashSet;
12use std::ffi::OsStr;
13use std::io::Write;
14use std::path::{Path, PathBuf};
15use std::{env, fs};
16
17use object::BinaryFormat;
18use object::read::archive::ArchiveFile;
19#[cfg(feature = "tracing")]
20use tracing::instrument;
21
22use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
23use crate::core::build_steps::doc::DocumentationFormat;
24use crate::core::build_steps::tool::{
25 self, RustcPrivateCompilers, Tool, ToolTargetBuildMode, get_tool_target_compiler,
26};
27use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
28use crate::core::build_steps::{compile, llvm};
29use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
30use crate::core::config::TargetSelection;
31use crate::utils::build_stamp::{self, BuildStamp};
32use crate::utils::channel::{self, Info};
33use crate::utils::exec::{BootstrapCommand, command};
34use crate::utils::helpers::{
35 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
36};
37use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
38use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
39
40pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
41 format!("{}-{}", component, builder.rust_package_vers())
42}
43
44pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
45 builder.out.join("dist")
46}
47
48pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
49 builder.out.join("tmp/dist")
50}
51
52fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
53 if !builder.config.extended {
54 return false;
55 }
56 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
57}
58
59#[derive(Debug, Clone, Hash, PartialEq, Eq)]
60pub struct Docs {
61 pub host: TargetSelection,
62}
63
64impl Step for Docs {
65 type Output = Option<GeneratedTarball>;
66 const DEFAULT: bool = true;
67
68 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
69 let default = run.builder.config.docs;
70 run.alias("rust-docs").default_condition(default)
71 }
72
73 fn make_run(run: RunConfig<'_>) {
74 run.builder.ensure(Docs { host: run.target });
75 }
76
77 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
79 let host = self.host;
80 builder.run_default_doc_steps();
84
85 let dest = "share/doc/rust/html";
86
87 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
88 tarball.set_product_name("Rust Documentation");
89 tarball.add_bulk_dir(builder.doc_out(host), dest);
90 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
91 Some(tarball.generate())
92 }
93
94 fn metadata(&self) -> Option<StepMetadata> {
95 Some(StepMetadata::dist("docs", self.host))
96 }
97}
98
99#[derive(Debug, Clone, Hash, PartialEq, Eq)]
100pub struct JsonDocs {
101 build_compiler: Compiler,
102 target: TargetSelection,
103}
104
105impl Step for JsonDocs {
106 type Output = Option<GeneratedTarball>;
107 const DEFAULT: bool = true;
108
109 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
110 let default = run.builder.config.docs;
111 run.alias("rust-docs-json").default_condition(default)
112 }
113
114 fn make_run(run: RunConfig<'_>) {
115 run.builder.ensure(JsonDocs {
116 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
117 target: run.target,
118 });
119 }
120
121 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
123 let target = self.target;
124 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
125 self.build_compiler,
126 target,
127 DocumentationFormat::Json,
128 ));
129
130 let dest = "share/doc/rust/json";
131
132 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
133 tarball.set_product_name("Rust Documentation In JSON Format");
134 tarball.is_preview(true);
135 tarball.add_bulk_dir(directory, dest);
136 Some(tarball.generate())
137 }
138}
139
140#[derive(Debug, Clone, Hash, PartialEq, Eq)]
147pub struct RustcDocs {
148 target: TargetSelection,
149}
150
151impl Step for RustcDocs {
152 type Output = GeneratedTarball;
153
154 const DEFAULT: bool = true;
155 const IS_HOST: bool = true;
156
157 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
158 let builder = run.builder;
159 run.alias("rustc-docs").default_condition(builder.config.compiler_docs)
160 }
161
162 fn make_run(run: RunConfig<'_>) {
163 run.builder.ensure(RustcDocs { target: run.target });
164 }
165
166 fn run(self, builder: &Builder<'_>) -> Self::Output {
167 let target = self.target;
168 builder.run_default_doc_steps();
169
170 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
171 tarball.set_product_name("Rustc Documentation");
172 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc");
173 tarball.generate()
174 }
175}
176
177fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
178 let mut found = Vec::with_capacity(files.len());
179
180 for file in files {
181 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
182
183 if let Some(file_path) = file_path {
184 found.push(file_path);
185 } else {
186 panic!("Could not find '{file}' in {path:?}");
187 }
188 }
189
190 found
191}
192
193fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
194 if builder.config.dry_run() {
195 return;
196 }
197
198 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
199
200 let compiler = if target == "i686-pc-windows-gnu" {
201 "i686-w64-mingw32-gcc.exe"
202 } else if target == "x86_64-pc-windows-gnu" {
203 "x86_64-w64-mingw32-gcc.exe"
204 } else {
205 "gcc.exe"
206 };
207 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
208
209 let target_libs = [
212 "libgcc.a",
214 "libgcc_eh.a",
215 "libgcc_s.a",
216 "libm.a",
217 "libmingw32.a",
218 "libmingwex.a",
219 "libstdc++.a",
220 "libiconv.a",
221 "libmoldname.a",
222 "libpthread.a",
223 "libadvapi32.a",
228 "libbcrypt.a",
229 "libcomctl32.a",
230 "libcomdlg32.a",
231 "libcredui.a",
232 "libcrypt32.a",
233 "libdbghelp.a",
234 "libgdi32.a",
235 "libimagehlp.a",
236 "libiphlpapi.a",
237 "libkernel32.a",
238 "libmsimg32.a",
239 "libmsvcrt.a",
240 "libntdll.a",
241 "libodbc32.a",
242 "libole32.a",
243 "liboleaut32.a",
244 "libopengl32.a",
245 "libpsapi.a",
246 "librpcrt4.a",
247 "libsecur32.a",
248 "libsetupapi.a",
249 "libshell32.a",
250 "libsynchronization.a",
251 "libuser32.a",
252 "libuserenv.a",
253 "libuuid.a",
254 "libwinhttp.a",
255 "libwinmm.a",
256 "libwinspool.a",
257 "libws2_32.a",
258 "libwsock32.a",
259 ];
260
261 let target_tools = find_files(&target_tools, &bin_path);
263 let target_libs = find_files(&target_libs, &lib_path);
264
265 let plat_target_bin_self_contained_dir =
267 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
268 fs::create_dir_all(&plat_target_bin_self_contained_dir)
269 .expect("creating plat_target_bin_self_contained_dir failed");
270 for src in target_tools {
271 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
272 }
273
274 builder.create(
276 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
277 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
278 used as a linker. In order to be able to compile projects containing C code use \
279 the GCC provided by MinGW or Cygwin.",
280 );
281
282 let plat_target_lib_self_contained_dir =
284 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
285 fs::create_dir_all(&plat_target_lib_self_contained_dir)
286 .expect("creating plat_target_lib_self_contained_dir failed");
287 for src in target_libs {
288 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
289 }
290}
291
292fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
293 if builder.config.dry_run() {
294 return;
295 }
296
297 let (bin_path, libs_path) = get_cc_search_dirs(target, builder);
298
299 let mut rustc_dlls = vec![];
300 if target.ends_with("windows-gnu") {
302 rustc_dlls.push("libwinpthread-1.dll");
303 if target.starts_with("i686-") {
304 rustc_dlls.push("libgcc_s_dw2-1.dll");
305 } else {
306 rustc_dlls.push("libgcc_s_seh-1.dll");
307 }
308 } else if target.ends_with("windows-gnullvm") {
309 rustc_dlls.push("libunwind.dll");
310 } else {
311 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
312 }
313 let bin_path = if target.ends_with("windows-gnullvm") && builder.host_target != target {
315 bin_path
316 .into_iter()
317 .chain(libs_path.iter().map(|path| path.with_file_name("bin")))
318 .collect()
319 } else {
320 bin_path
321 };
322 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
323
324 let rust_bin_dir = rust_root.join("bin/");
326 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
327 for src in &rustc_dlls {
328 builder.copy_link_to_folder(src, &rust_bin_dir);
329 }
330
331 if builder.config.lld_enabled {
332 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
334 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
335 for src in &rustc_dlls {
336 builder.copy_link_to_folder(src, &rust_target_bin_dir);
337 }
338 }
339}
340
341fn get_cc_search_dirs(
342 target: TargetSelection,
343 builder: &Builder<'_>,
344) -> (Vec<PathBuf>, Vec<PathBuf>) {
345 let mut cmd = command(builder.cc(target));
347 cmd.arg("-print-search-dirs");
348 let gcc_out = cmd.run_capture_stdout(builder).stdout();
349
350 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
351 let mut lib_path = Vec::new();
352
353 for line in gcc_out.lines() {
354 let idx = line.find(':').unwrap();
355 let key = &line[..idx];
356 let trim_chars: &[_] = &[' ', '='];
357 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
358
359 if key == "programs" {
360 bin_path.extend(value);
361 } else if key == "libraries" {
362 lib_path.extend(value);
363 }
364 }
365 (bin_path, lib_path)
366}
367
368#[derive(Debug, Clone, Hash, PartialEq, Eq)]
373pub struct Mingw {
374 target: TargetSelection,
375}
376
377impl Step for Mingw {
378 type Output = Option<GeneratedTarball>;
379 const DEFAULT: bool = true;
380
381 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
382 run.alias("rust-mingw")
383 }
384
385 fn make_run(run: RunConfig<'_>) {
386 run.builder.ensure(Mingw { target: run.target });
387 }
388
389 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
390 let target = self.target;
391 if !target.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
392 return None;
393 }
394
395 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
396 tarball.set_product_name("Rust MinGW");
397
398 make_win_dist(tarball.image_dir(), target, builder);
399
400 Some(tarball.generate())
401 }
402
403 fn metadata(&self) -> Option<StepMetadata> {
404 Some(StepMetadata::dist("mingw", self.target))
405 }
406}
407
408#[derive(Debug, Clone, Hash, PartialEq, Eq)]
418pub struct Rustc {
419 pub target_compiler: Compiler,
421}
422
423impl Step for Rustc {
424 type Output = GeneratedTarball;
425
426 const DEFAULT: bool = true;
427 const IS_HOST: bool = true;
428
429 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
430 run.alias("rustc")
431 }
432
433 fn make_run(run: RunConfig<'_>) {
434 run.builder.ensure(Rustc {
435 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
436 });
437 }
438
439 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
440 let target_compiler = self.target_compiler;
441 let target = self.target_compiler.host;
442
443 let tarball = Tarball::new(builder, "rustc", &target.triple);
444
445 prepare_image(builder, target_compiler, tarball.image_dir());
447
448 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
456 runtime_dll_dist(tarball.image_dir(), target, builder);
457 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
458 }
459
460 return tarball.generate();
461
462 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
463 let target = target_compiler.host;
464 let src = builder.sysroot(target_compiler);
465
466 t!(fs::create_dir_all(image.join("bin")));
468 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
469
470 if builder
472 .config
473 .tools
474 .as_ref()
475 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
476 {
477 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
478 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
479 }
480
481 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
482
483 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
484 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
485 builder.kind,
486 ) {
487 let dst = image.join("libexec");
488 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
489 }
490
491 let libdir_relative = builder.libdir_relative(target_compiler);
492
493 if libdir_relative.to_str() != Some("bin") {
495 let libdir = builder.rustc_libdir(target_compiler);
496 for entry in builder.read_dir(&libdir) {
497 if is_dylib(&entry.path())
503 && !entry
504 .path()
505 .file_name()
506 .and_then(|n| n.to_str())
507 .map(|n| n.contains("libgccjit"))
508 .unwrap_or(false)
509 {
510 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
513 }
514 }
515 }
516
517 maybe_install_llvm_runtime(builder, target, image);
523
524 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
525 t!(fs::create_dir_all(&dst_dir));
526
527 if builder.config.lld_enabled {
529 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
530 let rust_lld = exe("rust-lld", target_compiler.host);
531 builder.copy_link(
532 &src_dir.join(&rust_lld),
533 &dst_dir.join(&rust_lld),
534 FileType::Executable,
535 );
536 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
537 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
538 t!(fs::create_dir(&self_contained_lld_dst_dir));
539 for name in crate::LLD_FILE_NAMES {
540 let exe_name = exe(name, target_compiler.host);
541 builder.copy_link(
542 &self_contained_lld_src_dir.join(&exe_name),
543 &self_contained_lld_dst_dir.join(&exe_name),
544 FileType::Executable,
545 );
546 }
547 }
548
549 if builder.config.llvm_enabled(target_compiler.host)
550 && builder.config.llvm_tools_enabled
551 {
552 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
553 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
554 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
555 builder.copy_link(
556 &src_dir.join(&llvm_objcopy),
557 &dst_dir.join(&rust_objcopy),
558 FileType::Executable,
559 );
560 }
561
562 if builder.tool_enabled("wasm-component-ld") {
563 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
564 let ld = exe("wasm-component-ld", target_compiler.host);
565 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
566 }
567
568 t!(fs::create_dir_all(image.join("share/man/man1")));
570 let man_src = builder.src.join("src/doc/man");
571 let man_dst = image.join("share/man/man1");
572
573 for file_entry in builder.read_dir(&man_src) {
576 let page_src = file_entry.path();
577 let page_dst = man_dst.join(file_entry.file_name());
578 let src_text = t!(std::fs::read_to_string(&page_src));
579 let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version);
580 t!(std::fs::write(&page_dst, &new_text));
581 t!(fs::copy(&page_src, &page_dst));
582 }
583
584 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
586
587 let file_list = builder.ensure(super::run::GenerateCopyright);
589 for file in file_list {
590 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
591 }
592
593 builder.install(
595 &builder.src.join("README.md"),
596 &image.join("share/doc/rust"),
597 FileType::Regular,
598 );
599
600 let license = |path: &Path| {
602 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
603 };
604 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
605 license(&entry.path());
606 }
607 }
608 }
609
610 fn metadata(&self) -> Option<StepMetadata> {
611 Some(StepMetadata::dist("rustc", self.target_compiler.host))
612 }
613}
614
615#[derive(Debug, Clone, Hash, PartialEq, Eq)]
617pub struct DebuggerScripts {
618 pub sysroot: PathBuf,
620 pub target: TargetSelection,
621}
622
623impl Step for DebuggerScripts {
624 type Output = ();
625
626 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
627 run.never()
628 }
629
630 fn run(self, builder: &Builder<'_>) {
631 let target = self.target;
632 let sysroot = self.sysroot;
633 let dst = sysroot.join("lib/rustlib/etc");
634 t!(fs::create_dir_all(&dst));
635 let cp_debugger_script = |file: &str| {
636 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
637 };
638 if target.contains("windows-msvc") {
639 builder.install(
641 &builder.src.join("src/etc/rust-windbg.cmd"),
642 &sysroot.join("bin"),
643 FileType::Script,
644 );
645
646 cp_debugger_script("natvis/intrinsic.natvis");
647 cp_debugger_script("natvis/liballoc.natvis");
648 cp_debugger_script("natvis/libcore.natvis");
649 cp_debugger_script("natvis/libstd.natvis");
650 }
651
652 cp_debugger_script("rust_types.py");
653
654 builder.install(
656 &builder.src.join("src/etc/rust-gdb"),
657 &sysroot.join("bin"),
658 FileType::Script,
659 );
660 builder.install(
661 &builder.src.join("src/etc/rust-gdbgui"),
662 &sysroot.join("bin"),
663 FileType::Script,
664 );
665
666 cp_debugger_script("gdb_load_rust_pretty_printers.py");
667 cp_debugger_script("gdb_lookup.py");
668 cp_debugger_script("gdb_providers.py");
669
670 builder.install(
672 &builder.src.join("src/etc/rust-lldb"),
673 &sysroot.join("bin"),
674 FileType::Script,
675 );
676
677 cp_debugger_script("lldb_lookup.py");
678 cp_debugger_script("lldb_providers.py");
679 cp_debugger_script("lldb_commands")
680 }
681}
682
683fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
684 if !builder.config.is_host_target(compiler.host) {
687 builder.info("\tskipping, not a build host");
688 true
689 } else {
690 false
691 }
692}
693
694fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
698 if !target.ends_with("-uefi") {
699 return;
700 }
701
702 for (path, _) in builder.read_stamp_file(stamp) {
703 if path.extension() != Some(OsStr::new("rlib")) {
704 continue;
705 }
706
707 let data = t!(fs::read(&path));
708 let data = data.as_slice();
709 let archive = t!(ArchiveFile::parse(data));
710 for member in archive.members() {
711 let member = t!(member);
712 let member_data = t!(member.data(data));
713
714 let is_coff = match object::File::parse(member_data) {
715 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
716 Err(_) => false,
717 };
718
719 if !is_coff {
720 let member_name = String::from_utf8_lossy(member.name());
721 panic!("member {} in {} is not COFF", member_name, path.display());
722 }
723 }
724 }
725}
726
727fn copy_target_libs(
729 builder: &Builder<'_>,
730 target: TargetSelection,
731 image: &Path,
732 stamp: &BuildStamp,
733) {
734 let dst = image.join("lib/rustlib").join(target).join("lib");
735 let self_contained_dst = dst.join("self-contained");
736 t!(fs::create_dir_all(&dst));
737 t!(fs::create_dir_all(&self_contained_dst));
738 for (path, dependency_type) in builder.read_stamp_file(stamp) {
739 if dependency_type == DependencyType::TargetSelfContained {
740 builder.copy_link(
741 &path,
742 &self_contained_dst.join(path.file_name().unwrap()),
743 FileType::NativeLibrary,
744 );
745 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
746 {
747 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
748 }
749 }
750}
751
752#[derive(Debug, Clone, Hash, PartialEq, Eq)]
759pub struct Std {
760 pub build_compiler: Compiler,
762 pub target: TargetSelection,
763}
764
765impl Std {
766 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
767 let build_compiler =
777 if compile::Std::should_be_uplifted_from_stage_1(builder, builder.top_stage, target) {
778 builder.compiler(1, builder.host_target)
779 } else {
780 builder.compiler(builder.top_stage, builder.host_target)
781 };
782 Std { build_compiler, target }
783 }
784}
785
786impl Step for Std {
787 type Output = Option<GeneratedTarball>;
788 const DEFAULT: bool = true;
789
790 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
791 run.alias("rust-std")
792 }
793
794 fn make_run(run: RunConfig<'_>) {
795 run.builder.ensure(Std::new(run.builder, run.target));
796 }
797
798 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
799 let build_compiler = self.build_compiler;
800 let target = self.target;
801
802 if skip_host_target_lib(builder, build_compiler) {
803 return None;
804 }
805
806 let stamp =
809 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
810
811 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
812 tarball.include_target_in_component_name(true);
813
814 verify_uefi_rlib_format(builder, target, &stamp);
815 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
816
817 Some(tarball.generate())
818 }
819
820 fn metadata(&self) -> Option<StepMetadata> {
821 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
822 }
823}
824
825#[derive(Debug, Clone, Hash, PartialEq, Eq)]
830pub struct RustcDev {
831 build_compiler: Compiler,
833 target: TargetSelection,
834}
835
836impl Step for RustcDev {
837 type Output = Option<GeneratedTarball>;
838 const DEFAULT: bool = true;
839 const IS_HOST: bool = true;
840
841 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
842 run.alias("rustc-dev")
843 }
844
845 fn make_run(run: RunConfig<'_>) {
846 run.builder.ensure(RustcDev {
847 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
851 target: run.target,
852 });
853 }
854
855 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
856 let build_compiler = self.build_compiler;
857 let target = self.target;
858 if skip_host_target_lib(builder, build_compiler) {
859 return None;
860 }
861
862 builder.ensure(compile::Rustc::new(build_compiler, target));
864
865 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
866
867 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
868 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
869
870 let src_files = &["Cargo.lock"];
871 copy_src_dirs(
874 builder,
875 &builder.src,
876 &["compiler", "library/proc_macro"],
878 &[],
879 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
880 );
881 for file in src_files {
882 tarball.add_file(
883 builder.src.join(file),
884 "lib/rustlib/rustc-src/rust",
885 FileType::Regular,
886 );
887 }
888
889 Some(tarball.generate())
890 }
891
892 fn metadata(&self) -> Option<StepMetadata> {
893 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
894 }
895}
896
897#[derive(Debug, Clone, Hash, PartialEq, Eq)]
902pub struct Analysis {
903 build_compiler: Compiler,
904 target: TargetSelection,
905}
906
907impl Step for Analysis {
908 type Output = Option<GeneratedTarball>;
909
910 const DEFAULT: bool = true;
911
912 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
913 let default = should_build_extended_tool(run.builder, "analysis");
914 run.alias("rust-analysis").default_condition(default)
915 }
916
917 fn make_run(run: RunConfig<'_>) {
918 run.builder.ensure(Analysis {
920 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
921 target: run.target,
922 });
923 }
924
925 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
926 let compiler = self.build_compiler;
927 let target = self.target;
928 if skip_host_target_lib(builder, compiler) {
929 return None;
930 }
931
932 let src = builder
933 .stage_out(compiler, Mode::Std)
934 .join(target)
935 .join(builder.cargo_dir())
936 .join("deps")
937 .join("save-analysis");
938
939 t!(std::fs::create_dir_all(&src));
941 let mut removed = src.clone();
942 removed.push("removed.json");
943 let mut f = t!(std::fs::File::create(removed));
944 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
945
946 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
947 tarball.include_target_in_component_name(true);
948 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
949 Some(tarball.generate())
950 }
951
952 fn metadata(&self) -> Option<StepMetadata> {
953 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
954 }
955}
956
957fn copy_src_dirs(
960 builder: &Builder<'_>,
961 base: &Path,
962 src_dirs: &[&str],
963 exclude_dirs: &[&str],
964 dst_dir: &Path,
965) {
966 for src_dir in src_dirs {
969 assert!(Path::new(src_dir).is_relative());
970 }
971
972 if builder.config.dry_run() {
975 return;
976 }
977
978 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
979 let spath = match path.to_str() {
981 Some(path) => path,
982 None => return false,
983 };
984 if spath.ends_with('~') || spath.ends_with(".pyc") {
985 return false;
986 }
987 let spath = spath.replace("\\", "/");
989
990 static LLVM_PROJECTS: &[&str] = &[
991 "llvm-project/clang",
992 "llvm-project/libunwind",
993 "llvm-project/lld",
994 "llvm-project/lldb",
995 "llvm-project/llvm",
996 "llvm-project/compiler-rt",
997 "llvm-project/cmake",
998 "llvm-project/runtimes",
999 "llvm-project/third-party",
1000 ];
1001 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1002 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1003 return false;
1004 }
1005
1006 if spath.starts_with("llvm-project/third-party")
1008 && spath != "llvm-project/third-party"
1009 && !spath.starts_with("llvm-project/third-party/siphash")
1010 {
1011 return false;
1012 }
1013
1014 if spath.starts_with("llvm-project/llvm/test")
1015 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1016 {
1017 return false;
1018 }
1019 }
1020
1021 if spath.starts_with("tools/cargo/tests") {
1023 return true;
1024 }
1025
1026 if !exclude_dirs.is_empty() {
1027 let full_path = Path::new(dir).join(path);
1028 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1029 return false;
1030 }
1031 }
1032
1033 static EXCLUDES: &[&str] = &[
1034 "CVS",
1035 "RCS",
1036 "SCCS",
1037 ".git",
1038 ".gitignore",
1039 ".gitmodules",
1040 ".gitattributes",
1041 ".cvsignore",
1042 ".svn",
1043 ".arch-ids",
1044 "{arch}",
1045 "=RELEASE-ID",
1046 "=meta-update",
1047 "=update",
1048 ".bzr",
1049 ".bzrignore",
1050 ".bzrtags",
1051 ".hg",
1052 ".hgignore",
1053 ".hgrags",
1054 "_darcs",
1055 ];
1056
1057 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1064 !EXCLUDES.contains(&last_component)
1065 }
1066
1067 for item in src_dirs {
1069 let dst = &dst_dir.join(item);
1070 t!(fs::create_dir_all(dst));
1071 builder
1072 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1073 }
1074}
1075
1076#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1077pub struct Src;
1078
1079impl Step for Src {
1080 type Output = GeneratedTarball;
1082 const DEFAULT: bool = true;
1083 const IS_HOST: bool = true;
1084
1085 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1086 run.alias("rust-src")
1087 }
1088
1089 fn make_run(run: RunConfig<'_>) {
1090 run.builder.ensure(Src);
1091 }
1092
1093 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1095 if !builder.config.dry_run() {
1096 builder.require_submodule("src/llvm-project", None);
1097 }
1098
1099 let tarball = Tarball::new_targetless(builder, "rust-src");
1100
1101 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1109
1110 copy_src_dirs(
1113 builder,
1114 &builder.src,
1115 &["library", "src/llvm-project/libunwind"],
1116 &[
1117 "library/backtrace/crates",
1120 "library/stdarch/Cargo.toml",
1123 "library/stdarch/crates/stdarch-verify",
1124 "library/stdarch/crates/intrinsic-test",
1125 ],
1126 &dst_src,
1127 );
1128
1129 tarball.generate()
1130 }
1131
1132 fn metadata(&self) -> Option<StepMetadata> {
1133 Some(StepMetadata::dist("src", TargetSelection::default()))
1134 }
1135}
1136
1137#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1138pub struct PlainSourceTarball;
1139
1140impl Step for PlainSourceTarball {
1141 type Output = GeneratedTarball;
1143 const DEFAULT: bool = true;
1144 const IS_HOST: bool = true;
1145
1146 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1147 let builder = run.builder;
1148 run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
1149 }
1150
1151 fn make_run(run: RunConfig<'_>) {
1152 run.builder.ensure(PlainSourceTarball);
1153 }
1154
1155 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1157 let mut tarball = Tarball::new(builder, "rustc", "src");
1162 tarball.permit_symlinks(true);
1163 let plain_dst_src = tarball.image_dir();
1164
1165 let src_files = [
1167 ".gitmodules",
1169 "CONTRIBUTING.md",
1170 "COPYRIGHT",
1171 "Cargo.lock",
1172 "Cargo.toml",
1173 "LICENSE-APACHE",
1174 "LICENSE-MIT",
1175 "README.md",
1176 "RELEASES.md",
1177 "REUSE.toml",
1178 "bootstrap.example.toml",
1179 "configure",
1180 "license-metadata.json",
1181 "package-lock.json",
1182 "package.json",
1183 "x",
1184 "x.ps1",
1185 "x.py",
1186 ];
1188 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1189
1190 copy_src_dirs(
1191 builder,
1192 &builder.src,
1193 &src_dirs,
1194 &[
1195 "src/gcc",
1199 ],
1200 plain_dst_src,
1201 );
1202 if !builder.config.dry_run() {
1207 builder.create_dir(&plain_dst_src.join("src/gcc"));
1208 t!(std::fs::write(
1209 plain_dst_src.join("src/gcc/notice.txt"),
1210 "The GCC source code is not included due to unclear licensing implications\n"
1211 ));
1212 }
1213
1214 for item in &src_files {
1216 builder.copy_link(
1217 &builder.src.join(item),
1218 &plain_dst_src.join(item),
1219 FileType::Regular,
1220 );
1221 }
1222
1223 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1225
1226 let write_git_info = |info: Option<&Info>, path: &Path| {
1228 if let Some(info) = info {
1229 t!(std::fs::create_dir_all(path));
1230 channel::write_commit_hash_file(path, &info.sha);
1231 channel::write_commit_info_file(path, info);
1232 }
1233 };
1234 write_git_info(builder.rust_info().info(), plain_dst_src);
1235 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1236
1237 if builder.config.dist_vendor {
1238 builder.require_and_update_all_submodules();
1239
1240 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1242 .iter()
1243 .chain(build_helper::RUSTC_PGO_CRATES)
1244 .map(|pkg| {
1245 let mut manifest_path =
1246 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1247 manifest_path.push(pkg);
1248 manifest_path.push("Cargo.toml");
1249 manifest_path
1250 });
1251
1252 let vendor = builder.ensure(Vendor {
1254 sync_args: pkgs_for_pgo_training.collect(),
1255 versioned_dirs: true,
1256 root_dir: plain_dst_src.into(),
1257 output_dir: VENDOR_DIR.into(),
1258 });
1259
1260 let cargo_config_dir = plain_dst_src.join(".cargo");
1261 builder.create_dir(&cargo_config_dir);
1262 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1263 }
1264
1265 for entry in walkdir::WalkDir::new(tarball.image_dir())
1269 .follow_links(true)
1270 .into_iter()
1271 .filter_map(|e| e.ok())
1272 {
1273 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1274 {
1275 t!(fs::remove_dir_all(entry.path()));
1276 }
1277 }
1278
1279 tarball.bare()
1280 }
1281}
1282
1283#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1284pub struct Cargo {
1285 pub build_compiler: Compiler,
1286 pub target: TargetSelection,
1287}
1288
1289impl Step for Cargo {
1290 type Output = Option<GeneratedTarball>;
1291 const DEFAULT: bool = true;
1292 const IS_HOST: bool = true;
1293
1294 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1295 let default = should_build_extended_tool(run.builder, "cargo");
1296 run.alias("cargo").default_condition(default)
1297 }
1298
1299 fn make_run(run: RunConfig<'_>) {
1300 run.builder.ensure(Cargo {
1301 build_compiler: get_tool_target_compiler(
1302 run.builder,
1303 ToolTargetBuildMode::Build(run.target),
1304 ),
1305 target: run.target,
1306 });
1307 }
1308
1309 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1310 let build_compiler = self.build_compiler;
1311 let target = self.target;
1312
1313 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1314 let src = builder.src.join("src/tools/cargo");
1315 let etc = src.join("src/etc");
1316
1317 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1319 tarball.set_overlay(OverlayKind::Cargo);
1320
1321 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1322 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1323 tarball.add_renamed_file(
1324 etc.join("cargo.bashcomp.sh"),
1325 "etc/bash_completion.d",
1326 "cargo",
1327 FileType::Regular,
1328 );
1329 tarball.add_dir(etc.join("man"), "share/man/man1");
1330 tarball.add_legal_and_readme_to("share/doc/cargo");
1331
1332 Some(tarball.generate())
1333 }
1334
1335 fn metadata(&self) -> Option<StepMetadata> {
1336 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1337 }
1338}
1339
1340#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1342pub struct RustAnalyzer {
1343 pub compilers: RustcPrivateCompilers,
1344 pub target: TargetSelection,
1345}
1346
1347impl Step for RustAnalyzer {
1348 type Output = Option<GeneratedTarball>;
1349 const DEFAULT: bool = true;
1350 const IS_HOST: bool = true;
1351
1352 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1353 let default = should_build_extended_tool(run.builder, "rust-analyzer");
1354 run.alias("rust-analyzer").default_condition(default)
1355 }
1356
1357 fn make_run(run: RunConfig<'_>) {
1358 run.builder.ensure(RustAnalyzer {
1359 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1360 target: run.target,
1361 });
1362 }
1363
1364 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1365 let target = self.target;
1366 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1367
1368 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1369 tarball.set_overlay(OverlayKind::RustAnalyzer);
1370 tarball.is_preview(true);
1371 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1372 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1373 Some(tarball.generate())
1374 }
1375
1376 fn metadata(&self) -> Option<StepMetadata> {
1377 Some(
1378 StepMetadata::dist("rust-analyzer", self.target)
1379 .built_by(self.compilers.build_compiler()),
1380 )
1381 }
1382}
1383
1384#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1385pub struct Clippy {
1386 pub compilers: RustcPrivateCompilers,
1387 pub target: TargetSelection,
1388}
1389
1390impl Step for Clippy {
1391 type Output = Option<GeneratedTarball>;
1392 const DEFAULT: bool = true;
1393 const IS_HOST: bool = true;
1394
1395 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1396 let default = should_build_extended_tool(run.builder, "clippy");
1397 run.alias("clippy").default_condition(default)
1398 }
1399
1400 fn make_run(run: RunConfig<'_>) {
1401 run.builder.ensure(Clippy {
1402 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1403 target: run.target,
1404 });
1405 }
1406
1407 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1408 let target = self.target;
1409
1410 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1414 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1415
1416 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1417 tarball.set_overlay(OverlayKind::Clippy);
1418 tarball.is_preview(true);
1419 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1420 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1421 tarball.add_legal_and_readme_to("share/doc/clippy");
1422 Some(tarball.generate())
1423 }
1424
1425 fn metadata(&self) -> Option<StepMetadata> {
1426 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1427 }
1428}
1429
1430#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1431pub struct Miri {
1432 pub compilers: RustcPrivateCompilers,
1433 pub target: TargetSelection,
1434}
1435
1436impl Step for Miri {
1437 type Output = Option<GeneratedTarball>;
1438 const DEFAULT: bool = true;
1439 const IS_HOST: bool = true;
1440
1441 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1442 let default = should_build_extended_tool(run.builder, "miri");
1443 run.alias("miri").default_condition(default)
1444 }
1445
1446 fn make_run(run: RunConfig<'_>) {
1447 run.builder.ensure(Miri {
1448 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1449 target: run.target,
1450 });
1451 }
1452
1453 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1454 if !builder.build.unstable_features() {
1458 return None;
1459 }
1460
1461 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1462 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1463
1464 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1465 tarball.set_overlay(OverlayKind::Miri);
1466 tarball.is_preview(true);
1467 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1468 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1469 tarball.add_legal_and_readme_to("share/doc/miri");
1470 Some(tarball.generate())
1471 }
1472
1473 fn metadata(&self) -> Option<StepMetadata> {
1474 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1475 }
1476}
1477
1478#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1479pub struct CraneliftCodegenBackend {
1480 pub compilers: RustcPrivateCompilers,
1481 pub target: TargetSelection,
1482}
1483
1484impl Step for CraneliftCodegenBackend {
1485 type Output = Option<GeneratedTarball>;
1486 const DEFAULT: bool = true;
1487 const IS_HOST: bool = true;
1488
1489 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1490 let clif_enabled_by_default = run
1495 .builder
1496 .config
1497 .enabled_codegen_backends(run.builder.host_target)
1498 .contains(&CodegenBackendKind::Cranelift);
1499 run.alias("rustc_codegen_cranelift").default_condition(clif_enabled_by_default)
1500 }
1501
1502 fn make_run(run: RunConfig<'_>) {
1503 run.builder.ensure(CraneliftCodegenBackend {
1504 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1505 target: run.target,
1506 });
1507 }
1508
1509 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1510 if !builder.build.unstable_features() {
1514 return None;
1515 }
1516
1517 let target = self.target;
1518 if !target_supports_cranelift_backend(target) {
1519 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1520 return None;
1521 }
1522
1523 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1524 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1525 tarball.is_preview(true);
1526 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1527
1528 let compilers = self.compilers;
1529 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1530
1531 if builder.config.dry_run() {
1532 return None;
1533 }
1534
1535 let backends_dst = builder.sysroot_codegen_backends(compilers.target_compiler());
1537 let backends_rel = backends_dst
1538 .strip_prefix(builder.sysroot(compilers.target_compiler()))
1539 .unwrap()
1540 .strip_prefix(builder.sysroot_libdir_relative(compilers.target_compiler()))
1541 .unwrap();
1542 let backends_dst = PathBuf::from("lib").join(backends_rel);
1544
1545 let codegen_backend_dylib = get_codegen_backend_file(&stamp);
1546 tarball.add_renamed_file(
1547 &codegen_backend_dylib,
1548 &backends_dst,
1549 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1550 FileType::NativeLibrary,
1551 );
1552
1553 Some(tarball.generate())
1554 }
1555
1556 fn metadata(&self) -> Option<StepMetadata> {
1557 Some(
1558 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1559 .built_by(self.compilers.build_compiler()),
1560 )
1561 }
1562}
1563
1564#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1565pub struct Rustfmt {
1566 pub compilers: RustcPrivateCompilers,
1567 pub target: TargetSelection,
1568}
1569
1570impl Step for Rustfmt {
1571 type Output = Option<GeneratedTarball>;
1572 const DEFAULT: bool = true;
1573 const IS_HOST: bool = true;
1574
1575 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1576 let default = should_build_extended_tool(run.builder, "rustfmt");
1577 run.alias("rustfmt").default_condition(default)
1578 }
1579
1580 fn make_run(run: RunConfig<'_>) {
1581 run.builder.ensure(Rustfmt {
1582 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1583 target: run.target,
1584 });
1585 }
1586
1587 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1588 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1589 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1590
1591 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1592 tarball.set_overlay(OverlayKind::Rustfmt);
1593 tarball.is_preview(true);
1594 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1595 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1596 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1597 Some(tarball.generate())
1598 }
1599
1600 fn metadata(&self) -> Option<StepMetadata> {
1601 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1602 }
1603}
1604
1605#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1607pub struct Extended {
1608 build_compiler: Compiler,
1609 target: TargetSelection,
1610}
1611
1612impl Step for Extended {
1613 type Output = ();
1614 const DEFAULT: bool = true;
1615 const IS_HOST: bool = true;
1616
1617 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1618 let builder = run.builder;
1619 run.alias("extended").default_condition(builder.config.extended)
1620 }
1621
1622 fn make_run(run: RunConfig<'_>) {
1623 run.builder.ensure(Extended {
1624 build_compiler: run
1625 .builder
1626 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1627 target: run.target,
1628 });
1629 }
1630
1631 fn run(self, builder: &Builder<'_>) {
1633 let target = self.target;
1634 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1635
1636 let mut tarballs = Vec::new();
1637 let mut built_tools = HashSet::new();
1638 macro_rules! add_component {
1639 ($name:expr => $step:expr) => {
1640 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1641 tarballs.push(tarball);
1642 built_tools.insert($name);
1643 }
1644 };
1645 }
1646
1647 let rustc_private_compilers =
1648 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1649 let build_compiler = rustc_private_compilers.build_compiler();
1650 let target_compiler = rustc_private_compilers.target_compiler();
1651
1652 tarballs.push(builder.ensure(Rustc { target_compiler }));
1657 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1658
1659 if target.is_windows_gnu() {
1660 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1661 }
1662
1663 add_component!("rust-docs" => Docs { host: target });
1664 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1666 add_component!("cargo" => Cargo { build_compiler, target });
1667 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1668 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1669 add_component!("llvm-components" => LlvmTools { target });
1670 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1671 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1672 add_component!("analysis" => Analysis { build_compiler, target });
1673 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1674 compilers: rustc_private_compilers,
1675 target
1676 });
1677 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1678 build_compiler,
1679 target
1680 });
1681
1682 let etc = builder.src.join("src/etc/installer");
1683
1684 if builder.config.dry_run() {
1686 return;
1687 }
1688
1689 let tarball = Tarball::new(builder, "rust", &target.triple);
1690 let generated = tarball.combine(&tarballs);
1691
1692 let tmp = tmpdir(builder).join("combined-tarball");
1693 let work = generated.work_dir();
1694
1695 let mut license = String::new();
1696 license += &builder.read(&builder.src.join("COPYRIGHT"));
1697 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1698 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1699 license.push('\n');
1700 license.push('\n');
1701
1702 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1703 let mut rtf = rtf.to_string();
1704 rtf.push('\n');
1705 for line in license.lines() {
1706 rtf.push_str(line);
1707 rtf.push_str("\\line ");
1708 }
1709 rtf.push('}');
1710
1711 fn filter(contents: &str, marker: &str) -> String {
1712 let start = format!("tool-{marker}-start");
1713 let end = format!("tool-{marker}-end");
1714 let mut lines = Vec::new();
1715 let mut omitted = false;
1716 for line in contents.lines() {
1717 if line.contains(&start) {
1718 omitted = true;
1719 } else if line.contains(&end) {
1720 omitted = false;
1721 } else if !omitted {
1722 lines.push(line);
1723 }
1724 }
1725
1726 lines.join("\n")
1727 }
1728
1729 let xform = |p: &Path| {
1730 let mut contents = t!(fs::read_to_string(p));
1731 for tool in &["miri", "rust-docs"] {
1732 if !built_tools.contains(tool) {
1733 contents = filter(&contents, tool);
1734 }
1735 }
1736 let ret = tmp.join(p.file_name().unwrap());
1737 t!(fs::write(&ret, &contents));
1738 ret
1739 };
1740
1741 if target.contains("apple-darwin") {
1742 builder.info("building pkg installer");
1743 let pkg = tmp.join("pkg");
1744 let _ = fs::remove_dir_all(&pkg);
1745
1746 let pkgbuild = |component: &str| {
1747 let mut cmd = command("pkgbuild");
1748 cmd.arg("--identifier")
1749 .arg(format!("org.rust-lang.{component}"))
1750 .arg("--scripts")
1751 .arg(pkg.join(component))
1752 .arg("--nopayload")
1753 .arg(pkg.join(component).with_extension("pkg"));
1754 cmd.run(builder);
1755 };
1756
1757 let prepare = |name: &str| {
1758 builder.create_dir(&pkg.join(name));
1759 builder.cp_link_r(
1760 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1761 &pkg.join(name),
1762 );
1763 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1764 pkgbuild(name);
1765 };
1766 prepare("rustc");
1767 prepare("cargo");
1768 prepare("rust-std");
1769 prepare("rust-analysis");
1770
1771 for tool in &[
1772 "clippy",
1773 "rustfmt",
1774 "rust-analyzer",
1775 "rust-docs",
1776 "miri",
1777 "rustc-codegen-cranelift",
1778 ] {
1779 if built_tools.contains(tool) {
1780 prepare(tool);
1781 }
1782 }
1783 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1785 pkgbuild("uninstall");
1786
1787 builder.create_dir(&pkg.join("res"));
1788 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1789 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1790 let mut cmd = command("productbuild");
1791 cmd.arg("--distribution")
1792 .arg(xform(&etc.join("pkg/Distribution.xml")))
1793 .arg("--resources")
1794 .arg(pkg.join("res"))
1795 .arg(distdir(builder).join(format!(
1796 "{}-{}.pkg",
1797 pkgname(builder, "rust"),
1798 target.triple
1799 )))
1800 .arg("--package-path")
1801 .arg(&pkg);
1802 let _time = timeit(builder);
1803 cmd.run(builder);
1804 }
1805
1806 if target.is_windows() && !target.contains("gnullvm") {
1808 let exe = tmp.join("exe");
1809 let _ = fs::remove_dir_all(&exe);
1810
1811 let prepare = |name: &str| {
1812 builder.create_dir(&exe.join(name));
1813 let dir = if name == "rust-std" || name == "rust-analysis" {
1814 format!("{}-{}", name, target.triple)
1815 } else if name == "rust-analyzer" {
1816 "rust-analyzer-preview".to_string()
1817 } else if name == "clippy" {
1818 "clippy-preview".to_string()
1819 } else if name == "rustfmt" {
1820 "rustfmt-preview".to_string()
1821 } else if name == "miri" {
1822 "miri-preview".to_string()
1823 } else if name == "rustc-codegen-cranelift" {
1824 unreachable!("cg_clif shouldn't be built for windows");
1827 } else {
1828 name.to_string()
1829 };
1830 builder.cp_link_r(
1831 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1832 &exe.join(name),
1833 );
1834 builder.remove(&exe.join(name).join("manifest.in"));
1835 };
1836 prepare("rustc");
1837 prepare("cargo");
1838 prepare("rust-analysis");
1839 prepare("rust-std");
1840 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1841 if built_tools.contains(tool) {
1842 prepare(tool);
1843 }
1844 }
1845 if target.is_windows_gnu() {
1846 prepare("rust-mingw");
1847 }
1848
1849 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1850
1851 let wix_path = env::var_os("WIX")
1853 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1854 let wix = PathBuf::from(wix_path);
1855 let heat = wix.join("bin/heat.exe");
1856 let candle = wix.join("bin/candle.exe");
1857 let light = wix.join("bin/light.exe");
1858
1859 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1860 command(&heat)
1861 .current_dir(&exe)
1862 .arg("dir")
1863 .arg("rustc")
1864 .args(heat_flags)
1865 .arg("-cg")
1866 .arg("RustcGroup")
1867 .arg("-dr")
1868 .arg("Rustc")
1869 .arg("-var")
1870 .arg("var.RustcDir")
1871 .arg("-out")
1872 .arg(exe.join("RustcGroup.wxs"))
1873 .run(builder);
1874 if built_tools.contains("rust-docs") {
1875 command(&heat)
1876 .current_dir(&exe)
1877 .arg("dir")
1878 .arg("rust-docs")
1879 .args(heat_flags)
1880 .arg("-cg")
1881 .arg("DocsGroup")
1882 .arg("-dr")
1883 .arg("Docs")
1884 .arg("-var")
1885 .arg("var.DocsDir")
1886 .arg("-out")
1887 .arg(exe.join("DocsGroup.wxs"))
1888 .arg("-t")
1889 .arg(etc.join("msi/squash-components.xsl"))
1890 .run(builder);
1891 }
1892 command(&heat)
1893 .current_dir(&exe)
1894 .arg("dir")
1895 .arg("cargo")
1896 .args(heat_flags)
1897 .arg("-cg")
1898 .arg("CargoGroup")
1899 .arg("-dr")
1900 .arg("Cargo")
1901 .arg("-var")
1902 .arg("var.CargoDir")
1903 .arg("-out")
1904 .arg(exe.join("CargoGroup.wxs"))
1905 .arg("-t")
1906 .arg(etc.join("msi/remove-duplicates.xsl"))
1907 .run(builder);
1908 command(&heat)
1909 .current_dir(&exe)
1910 .arg("dir")
1911 .arg("rust-std")
1912 .args(heat_flags)
1913 .arg("-cg")
1914 .arg("StdGroup")
1915 .arg("-dr")
1916 .arg("Std")
1917 .arg("-var")
1918 .arg("var.StdDir")
1919 .arg("-out")
1920 .arg(exe.join("StdGroup.wxs"))
1921 .run(builder);
1922 if built_tools.contains("rust-analyzer") {
1923 command(&heat)
1924 .current_dir(&exe)
1925 .arg("dir")
1926 .arg("rust-analyzer")
1927 .args(heat_flags)
1928 .arg("-cg")
1929 .arg("RustAnalyzerGroup")
1930 .arg("-dr")
1931 .arg("RustAnalyzer")
1932 .arg("-var")
1933 .arg("var.RustAnalyzerDir")
1934 .arg("-out")
1935 .arg(exe.join("RustAnalyzerGroup.wxs"))
1936 .arg("-t")
1937 .arg(etc.join("msi/remove-duplicates.xsl"))
1938 .run(builder);
1939 }
1940 if built_tools.contains("clippy") {
1941 command(&heat)
1942 .current_dir(&exe)
1943 .arg("dir")
1944 .arg("clippy")
1945 .args(heat_flags)
1946 .arg("-cg")
1947 .arg("ClippyGroup")
1948 .arg("-dr")
1949 .arg("Clippy")
1950 .arg("-var")
1951 .arg("var.ClippyDir")
1952 .arg("-out")
1953 .arg(exe.join("ClippyGroup.wxs"))
1954 .arg("-t")
1955 .arg(etc.join("msi/remove-duplicates.xsl"))
1956 .run(builder);
1957 }
1958 if built_tools.contains("rustfmt") {
1959 command(&heat)
1960 .current_dir(&exe)
1961 .arg("dir")
1962 .arg("rustfmt")
1963 .args(heat_flags)
1964 .arg("-cg")
1965 .arg("RustFmtGroup")
1966 .arg("-dr")
1967 .arg("RustFmt")
1968 .arg("-var")
1969 .arg("var.RustFmtDir")
1970 .arg("-out")
1971 .arg(exe.join("RustFmtGroup.wxs"))
1972 .arg("-t")
1973 .arg(etc.join("msi/remove-duplicates.xsl"))
1974 .run(builder);
1975 }
1976 if built_tools.contains("miri") {
1977 command(&heat)
1978 .current_dir(&exe)
1979 .arg("dir")
1980 .arg("miri")
1981 .args(heat_flags)
1982 .arg("-cg")
1983 .arg("MiriGroup")
1984 .arg("-dr")
1985 .arg("Miri")
1986 .arg("-var")
1987 .arg("var.MiriDir")
1988 .arg("-out")
1989 .arg(exe.join("MiriGroup.wxs"))
1990 .arg("-t")
1991 .arg(etc.join("msi/remove-duplicates.xsl"))
1992 .run(builder);
1993 }
1994 command(&heat)
1995 .current_dir(&exe)
1996 .arg("dir")
1997 .arg("rust-analysis")
1998 .args(heat_flags)
1999 .arg("-cg")
2000 .arg("AnalysisGroup")
2001 .arg("-dr")
2002 .arg("Analysis")
2003 .arg("-var")
2004 .arg("var.AnalysisDir")
2005 .arg("-out")
2006 .arg(exe.join("AnalysisGroup.wxs"))
2007 .arg("-t")
2008 .arg(etc.join("msi/remove-duplicates.xsl"))
2009 .run(builder);
2010 if target.is_windows_gnu() {
2011 command(&heat)
2012 .current_dir(&exe)
2013 .arg("dir")
2014 .arg("rust-mingw")
2015 .args(heat_flags)
2016 .arg("-cg")
2017 .arg("GccGroup")
2018 .arg("-dr")
2019 .arg("Gcc")
2020 .arg("-var")
2021 .arg("var.GccDir")
2022 .arg("-out")
2023 .arg(exe.join("GccGroup.wxs"))
2024 .run(builder);
2025 }
2026
2027 let candle = |input: &Path| {
2028 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2029 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2030 let mut cmd = command(&candle);
2031 cmd.current_dir(&exe)
2032 .arg("-nologo")
2033 .arg("-dRustcDir=rustc")
2034 .arg("-dCargoDir=cargo")
2035 .arg("-dStdDir=rust-std")
2036 .arg("-dAnalysisDir=rust-analysis")
2037 .arg("-arch")
2038 .arg(arch)
2039 .arg("-out")
2040 .arg(&output)
2041 .arg(input);
2042 add_env(builder, &mut cmd, target, &built_tools);
2043
2044 if built_tools.contains("clippy") {
2045 cmd.arg("-dClippyDir=clippy");
2046 }
2047 if built_tools.contains("rustfmt") {
2048 cmd.arg("-dRustFmtDir=rustfmt");
2049 }
2050 if built_tools.contains("rust-docs") {
2051 cmd.arg("-dDocsDir=rust-docs");
2052 }
2053 if built_tools.contains("rust-analyzer") {
2054 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2055 }
2056 if built_tools.contains("miri") {
2057 cmd.arg("-dMiriDir=miri");
2058 }
2059 if target.is_windows_gnu() {
2060 cmd.arg("-dGccDir=rust-mingw");
2061 }
2062 cmd.run(builder);
2063 };
2064 candle(&xform(&etc.join("msi/rust.wxs")));
2065 candle(&etc.join("msi/ui.wxs"));
2066 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2067 candle("RustcGroup.wxs".as_ref());
2068 if built_tools.contains("rust-docs") {
2069 candle("DocsGroup.wxs".as_ref());
2070 }
2071 candle("CargoGroup.wxs".as_ref());
2072 candle("StdGroup.wxs".as_ref());
2073 if built_tools.contains("clippy") {
2074 candle("ClippyGroup.wxs".as_ref());
2075 }
2076 if built_tools.contains("rustfmt") {
2077 candle("RustFmtGroup.wxs".as_ref());
2078 }
2079 if built_tools.contains("miri") {
2080 candle("MiriGroup.wxs".as_ref());
2081 }
2082 if built_tools.contains("rust-analyzer") {
2083 candle("RustAnalyzerGroup.wxs".as_ref());
2084 }
2085 candle("AnalysisGroup.wxs".as_ref());
2086
2087 if target.is_windows_gnu() {
2088 candle("GccGroup.wxs".as_ref());
2089 }
2090
2091 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2092 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2093 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2094
2095 builder.info(&format!("building `msi` installer with {light:?}"));
2096 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2097 let mut cmd = command(&light);
2098 cmd.arg("-nologo")
2099 .arg("-ext")
2100 .arg("WixUIExtension")
2101 .arg("-ext")
2102 .arg("WixUtilExtension")
2103 .arg("-out")
2104 .arg(exe.join(&filename))
2105 .arg("rust.wixobj")
2106 .arg("ui.wixobj")
2107 .arg("rustwelcomedlg.wixobj")
2108 .arg("RustcGroup.wixobj")
2109 .arg("CargoGroup.wixobj")
2110 .arg("StdGroup.wixobj")
2111 .arg("AnalysisGroup.wixobj")
2112 .current_dir(&exe);
2113
2114 if built_tools.contains("clippy") {
2115 cmd.arg("ClippyGroup.wixobj");
2116 }
2117 if built_tools.contains("rustfmt") {
2118 cmd.arg("RustFmtGroup.wixobj");
2119 }
2120 if built_tools.contains("miri") {
2121 cmd.arg("MiriGroup.wixobj");
2122 }
2123 if built_tools.contains("rust-analyzer") {
2124 cmd.arg("RustAnalyzerGroup.wixobj");
2125 }
2126 if built_tools.contains("rust-docs") {
2127 cmd.arg("DocsGroup.wixobj");
2128 }
2129
2130 if target.is_windows_gnu() {
2131 cmd.arg("GccGroup.wixobj");
2132 }
2133 cmd.arg("-sice:ICE57");
2135
2136 let _time = timeit(builder);
2137 cmd.run(builder);
2138
2139 if !builder.config.dry_run() {
2140 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2141 }
2142 }
2143 }
2144
2145 fn metadata(&self) -> Option<StepMetadata> {
2146 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2147 }
2148}
2149
2150fn add_env(
2151 builder: &Builder<'_>,
2152 cmd: &mut BootstrapCommand,
2153 target: TargetSelection,
2154 built_tools: &HashSet<&'static str>,
2155) {
2156 let mut parts = builder.version.split('.');
2157 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2158 .env("CFG_RELEASE_NUM", &builder.version)
2159 .env("CFG_RELEASE", builder.rust_release())
2160 .env("CFG_VER_MAJOR", parts.next().unwrap())
2161 .env("CFG_VER_MINOR", parts.next().unwrap())
2162 .env("CFG_VER_PATCH", parts.next().unwrap())
2163 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2165 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2166 .env("CFG_BUILD", target.triple)
2167 .env("CFG_CHANNEL", &builder.config.channel);
2168
2169 if target.contains("windows-gnullvm") {
2170 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2171 } else if target.is_windows_gnu() {
2172 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2173 } else {
2174 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2175 }
2176
2177 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2179 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2180 };
2181 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2182 define_optional_tool("clippy", "CFG_CLIPPY");
2183 define_optional_tool("miri", "CFG_MIRI");
2184 define_optional_tool("rust-analyzer", "CFG_RA");
2185}
2186
2187fn install_llvm_file(
2188 builder: &Builder<'_>,
2189 source: &Path,
2190 destination: &Path,
2191 install_symlink: bool,
2192) {
2193 if builder.config.dry_run() {
2194 return;
2195 }
2196
2197 if source.is_symlink() {
2198 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2201
2202 let full_dest = destination.join(source.file_name().unwrap());
2203 if install_symlink {
2204 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2207 } else {
2208 let link = t!(fs::read_link(source));
2212 let mut linker_script = t!(fs::File::create(full_dest));
2213 t!(write!(linker_script, "INPUT({})\n", link.display()));
2214
2215 let meta = t!(fs::metadata(source));
2218 if let Ok(mtime) = meta.modified() {
2219 t!(linker_script.set_modified(mtime));
2220 }
2221 }
2222 } else {
2223 builder.install(source, destination, FileType::NativeLibrary);
2224 }
2225}
2226
2227#[cfg_attr(
2231 feature = "tracing",
2232 instrument(
2233 level = "trace",
2234 name = "maybe_install_llvm",
2235 skip_all,
2236 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2237 ),
2238)]
2239fn maybe_install_llvm(
2240 builder: &Builder<'_>,
2241 target: TargetSelection,
2242 dst_libdir: &Path,
2243 install_symlink: bool,
2244) -> bool {
2245 if builder.config.is_system_llvm(target) {
2262 trace!("system LLVM requested, no install");
2263 return false;
2264 }
2265
2266 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2272 let src_libdir = builder.llvm_out(target).join("lib");
2273 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2274 if llvm_dylib_path.exists() {
2275 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2276 }
2277 !builder.config.dry_run()
2278 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2279 host_llvm_config, ..
2280 }) = llvm::prebuilt_llvm_config(builder, target, true)
2281 {
2282 trace!("LLVM already built, installing LLVM files");
2283 let mut cmd = command(host_llvm_config);
2284 cmd.cached();
2285 cmd.arg("--libfiles");
2286 builder.verbose(|| println!("running {cmd:?}"));
2287 let files = cmd.run_capture_stdout(builder).stdout();
2288 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2289 let target_llvm_out = &builder.llvm_out(target);
2290 for file in files.trim_end().split(' ') {
2291 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2293 target_llvm_out.join(relative_path)
2294 } else {
2295 PathBuf::from(file)
2296 };
2297 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2298 }
2299 !builder.config.dry_run()
2300 } else {
2301 false
2302 }
2303}
2304
2305#[cfg_attr(
2307 feature = "tracing",
2308 instrument(
2309 level = "trace",
2310 name = "maybe_install_llvm_target",
2311 skip_all,
2312 fields(
2313 llvm_link_shared = ?builder.llvm_link_shared(),
2314 target = ?target,
2315 sysroot = ?sysroot,
2316 ),
2317 ),
2318)]
2319pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2320 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2321 if builder.llvm_link_shared() {
2325 maybe_install_llvm(builder, target, &dst_libdir, false);
2326 }
2327}
2328
2329#[cfg_attr(
2331 feature = "tracing",
2332 instrument(
2333 level = "trace",
2334 name = "maybe_install_llvm_runtime",
2335 skip_all,
2336 fields(
2337 llvm_link_shared = ?builder.llvm_link_shared(),
2338 target = ?target,
2339 sysroot = ?sysroot,
2340 ),
2341 ),
2342)]
2343pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2344 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2345 if builder.llvm_link_shared() {
2349 maybe_install_llvm(builder, target, &dst_libdir, false);
2350 }
2351}
2352
2353#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2354pub struct LlvmTools {
2355 pub target: TargetSelection,
2356}
2357
2358impl Step for LlvmTools {
2359 type Output = Option<GeneratedTarball>;
2360 const IS_HOST: bool = true;
2361 const DEFAULT: bool = true;
2362
2363 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2364 let default = should_build_extended_tool(run.builder, "llvm-tools");
2365
2366 let mut run = run.alias("llvm-tools");
2367 for tool in LLVM_TOOLS {
2368 run = run.alias(tool);
2369 }
2370
2371 run.default_condition(default)
2372 }
2373
2374 fn make_run(run: RunConfig<'_>) {
2375 run.builder.ensure(LlvmTools { target: run.target });
2376 }
2377
2378 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2379 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2380 let mut tools = vec![];
2381
2382 for path in paths {
2383 let path = path.to_str().unwrap();
2384
2385 if path == "llvm-tools" {
2387 return LLVM_TOOLS.to_owned();
2388 }
2389
2390 for tool in LLVM_TOOLS {
2391 if path == *tool {
2392 tools.push(*tool);
2393 }
2394 }
2395 }
2396
2397 if tools.is_empty() {
2399 tools = LLVM_TOOLS.to_owned();
2400 }
2401
2402 tools
2403 }
2404
2405 let target = self.target;
2406
2407 if let Some(config) = builder.config.target_config.get(&target)
2409 && !builder.config.llvm_from_ci
2410 && config.llvm_config.is_some()
2411 {
2412 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2413 return None;
2414 }
2415
2416 if !builder.config.dry_run() {
2417 builder.require_submodule("src/llvm-project", None);
2418 }
2419
2420 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2421
2422 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2423 tarball.set_overlay(OverlayKind::Llvm);
2424 tarball.is_preview(true);
2425
2426 if builder.config.llvm_tools_enabled {
2427 let src_bindir = builder.llvm_out(target).join("bin");
2429 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2430 for tool in tools_to_install(&builder.paths) {
2431 let exe = src_bindir.join(exe(tool, target));
2432 if !exe.exists() && builder.config.llvm_from_ci {
2434 eprintln!("{} does not exist; skipping copy", exe.display());
2435 continue;
2436 }
2437
2438 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2439 }
2440 }
2441
2442 maybe_install_llvm_target(builder, target, tarball.image_dir());
2447
2448 Some(tarball.generate())
2449 }
2450}
2451
2452#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2455pub struct LlvmBitcodeLinker {
2456 pub build_compiler: Compiler,
2458 pub target: TargetSelection,
2460}
2461
2462impl Step for LlvmBitcodeLinker {
2463 type Output = Option<GeneratedTarball>;
2464 const DEFAULT: bool = true;
2465 const IS_HOST: bool = true;
2466
2467 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2468 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2469 run.alias("llvm-bitcode-linker").default_condition(default)
2470 }
2471
2472 fn make_run(run: RunConfig<'_>) {
2473 run.builder.ensure(LlvmBitcodeLinker {
2474 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2475 run.builder,
2476 run.target,
2477 ),
2478 target: run.target,
2479 });
2480 }
2481
2482 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2483 let target = self.target;
2484
2485 let llbc_linker = builder
2486 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2487
2488 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2489
2490 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2492 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2493 tarball.is_preview(true);
2494
2495 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2496
2497 Some(tarball.generate())
2498 }
2499}
2500
2501#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2510pub struct RustDev {
2511 pub target: TargetSelection,
2512}
2513
2514impl Step for RustDev {
2515 type Output = Option<GeneratedTarball>;
2516 const DEFAULT: bool = true;
2517 const IS_HOST: bool = true;
2518
2519 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2520 run.alias("rust-dev")
2521 }
2522
2523 fn make_run(run: RunConfig<'_>) {
2524 run.builder.ensure(RustDev { target: run.target });
2525 }
2526
2527 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2528 let target = self.target;
2529
2530 if let Some(config) = builder.config.target_config.get(&target)
2532 && let Some(ref _s) = config.llvm_config
2533 {
2534 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2535 return None;
2536 }
2537
2538 if !builder.config.dry_run() {
2539 builder.require_submodule("src/llvm-project", None);
2540 }
2541
2542 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2543 tarball.set_overlay(OverlayKind::Llvm);
2544 tarball.permit_symlinks(true);
2546
2547 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2548
2549 let src_bindir = builder.llvm_out(target).join("bin");
2550 if src_bindir.exists() {
2556 for entry in walkdir::WalkDir::new(&src_bindir) {
2557 let entry = t!(entry);
2558 if entry.file_type().is_file() && !entry.path_is_symlink() {
2559 let name = entry.file_name().to_str().unwrap();
2560 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2561 }
2562 }
2563 }
2564
2565 if builder.config.lld_enabled {
2566 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2568
2569 let lld_path = lld_out.join("bin").join(exe("lld", target));
2571 if lld_path.exists() {
2572 tarball.add_file(&lld_path, "bin", FileType::Executable);
2573 }
2574 }
2575
2576 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2577
2578 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2582
2583 let dst_libdir = tarball.image_dir().join("lib");
2588 maybe_install_llvm(builder, target, &dst_libdir, true);
2589 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2590 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2591
2592 copy_src_dirs(
2596 builder,
2597 &builder.src.join("src").join("llvm-project"),
2598 &["compiler-rt"],
2599 &["compiler-rt/test"],
2602 tarball.image_dir(),
2603 );
2604
2605 Some(tarball.generate())
2606 }
2607}
2608
2609#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2615pub struct Bootstrap {
2616 target: TargetSelection,
2617}
2618
2619impl Step for Bootstrap {
2620 type Output = Option<GeneratedTarball>;
2621
2622 const IS_HOST: bool = true;
2623
2624 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2625 run.alias("bootstrap")
2626 }
2627
2628 fn make_run(run: RunConfig<'_>) {
2629 run.builder.ensure(Bootstrap { target: run.target });
2630 }
2631
2632 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2633 let target = self.target;
2634
2635 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2636
2637 let bootstrap_outdir = &builder.bootstrap_out;
2638 for file in &["bootstrap", "rustc", "rustdoc"] {
2639 tarball.add_file(
2640 bootstrap_outdir.join(exe(file, target)),
2641 "bootstrap/bin",
2642 FileType::Executable,
2643 );
2644 }
2645
2646 Some(tarball.generate())
2647 }
2648
2649 fn metadata(&self) -> Option<StepMetadata> {
2650 Some(StepMetadata::dist("bootstrap", self.target))
2651 }
2652}
2653
2654#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2659pub struct BuildManifest {
2660 target: TargetSelection,
2661}
2662
2663impl Step for BuildManifest {
2664 type Output = GeneratedTarball;
2665
2666 const IS_HOST: bool = true;
2667
2668 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2669 run.alias("build-manifest")
2670 }
2671
2672 fn make_run(run: RunConfig<'_>) {
2673 run.builder.ensure(BuildManifest { target: run.target });
2674 }
2675
2676 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2677 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2678
2679 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2680 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2681 tarball.generate()
2682 }
2683
2684 fn metadata(&self) -> Option<StepMetadata> {
2685 Some(StepMetadata::dist("build-manifest", self.target))
2686 }
2687}
2688
2689#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2695pub struct ReproducibleArtifacts {
2696 target: TargetSelection,
2697}
2698
2699impl Step for ReproducibleArtifacts {
2700 type Output = Option<GeneratedTarball>;
2701 const DEFAULT: bool = true;
2702 const IS_HOST: bool = true;
2703
2704 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2705 run.alias("reproducible-artifacts")
2706 }
2707
2708 fn make_run(run: RunConfig<'_>) {
2709 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2710 }
2711
2712 fn run(self, builder: &Builder<'_>) -> Self::Output {
2713 let mut added_anything = false;
2714 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2715 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2716 tarball.add_file(path, ".", FileType::Regular);
2717 added_anything = true;
2718 }
2719 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2720 tarball.add_file(path, ".", FileType::Regular);
2721 added_anything = true;
2722 }
2723 for profile in &builder.config.reproducible_artifacts {
2724 tarball.add_file(profile, ".", FileType::Regular);
2725 added_anything = true;
2726 }
2727 if added_anything { Some(tarball.generate()) } else { None }
2728 }
2729
2730 fn metadata(&self) -> Option<StepMetadata> {
2731 Some(StepMetadata::dist("reproducible-artifacts", self.target))
2732 }
2733}
2734
2735#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2739pub struct Gcc {
2740 target: TargetSelection,
2741}
2742
2743impl Step for Gcc {
2744 type Output = GeneratedTarball;
2745
2746 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2747 run.alias("gcc")
2748 }
2749
2750 fn make_run(run: RunConfig<'_>) {
2751 run.builder.ensure(Gcc { target: run.target });
2752 }
2753
2754 fn run(self, builder: &Builder<'_>) -> Self::Output {
2755 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2756 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2757 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2758 tarball.generate()
2759 }
2760
2761 fn metadata(&self) -> Option<StepMetadata> {
2762 Some(StepMetadata::dist("gcc", self.target))
2763 }
2764}