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