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