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 RustcDev {
827 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
828 Self {
829 build_compiler: builder.compiler(1, builder.config.host_target),
833 target,
834 }
835 }
836}
837
838impl Step for RustcDev {
839 type Output = Option<GeneratedTarball>;
840 const DEFAULT: bool = true;
841 const IS_HOST: bool = true;
842
843 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
844 run.alias("rustc-dev")
845 }
846
847 fn make_run(run: RunConfig<'_>) {
848 run.builder.ensure(RustcDev::new(run.builder, run.target));
849 }
850
851 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
852 let build_compiler = self.build_compiler;
853 let target = self.target;
854 if skip_host_target_lib(builder, build_compiler) {
855 return None;
856 }
857
858 builder.ensure(compile::Rustc::new(build_compiler, target));
860
861 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
862
863 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
864 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
865
866 let src_files = &["Cargo.lock"];
867 copy_src_dirs(
870 builder,
871 &builder.src,
872 &["compiler", "library/proc_macro"],
874 &[],
875 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
876 );
877 for file in src_files {
878 tarball.add_file(
879 builder.src.join(file),
880 "lib/rustlib/rustc-src/rust",
881 FileType::Regular,
882 );
883 }
884
885 Some(tarball.generate())
886 }
887
888 fn metadata(&self) -> Option<StepMetadata> {
889 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
890 }
891}
892
893#[derive(Debug, Clone, Hash, PartialEq, Eq)]
898pub struct Analysis {
899 build_compiler: Compiler,
900 target: TargetSelection,
901}
902
903impl Step for Analysis {
904 type Output = Option<GeneratedTarball>;
905
906 const DEFAULT: bool = true;
907
908 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
909 let default = should_build_extended_tool(run.builder, "analysis");
910 run.alias("rust-analysis").default_condition(default)
911 }
912
913 fn make_run(run: RunConfig<'_>) {
914 run.builder.ensure(Analysis {
916 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
917 target: run.target,
918 });
919 }
920
921 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
922 let compiler = self.build_compiler;
923 let target = self.target;
924 if skip_host_target_lib(builder, compiler) {
925 return None;
926 }
927
928 let src = builder
929 .stage_out(compiler, Mode::Std)
930 .join(target)
931 .join(builder.cargo_dir())
932 .join("deps")
933 .join("save-analysis");
934
935 t!(std::fs::create_dir_all(&src));
937 let mut removed = src.clone();
938 removed.push("removed.json");
939 let mut f = t!(std::fs::File::create(removed));
940 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
941
942 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
943 tarball.include_target_in_component_name(true);
944 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
945 Some(tarball.generate())
946 }
947
948 fn metadata(&self) -> Option<StepMetadata> {
949 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
950 }
951}
952
953fn copy_src_dirs(
956 builder: &Builder<'_>,
957 base: &Path,
958 src_dirs: &[&str],
959 exclude_dirs: &[&str],
960 dst_dir: &Path,
961) {
962 for src_dir in src_dirs {
965 assert!(Path::new(src_dir).is_relative());
966 }
967
968 if builder.config.dry_run() {
971 return;
972 }
973
974 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
975 let spath = match path.to_str() {
977 Some(path) => path,
978 None => return false,
979 };
980 if spath.ends_with('~') || spath.ends_with(".pyc") {
981 return false;
982 }
983 let spath = spath.replace("\\", "/");
985
986 static LLVM_PROJECTS: &[&str] = &[
987 "llvm-project/clang",
988 "llvm-project/libunwind",
989 "llvm-project/lld",
990 "llvm-project/lldb",
991 "llvm-project/llvm",
992 "llvm-project/compiler-rt",
993 "llvm-project/cmake",
994 "llvm-project/runtimes",
995 "llvm-project/third-party",
996 ];
997 if spath.starts_with("llvm-project") && spath != "llvm-project" {
998 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
999 return false;
1000 }
1001
1002 if spath.starts_with("llvm-project/third-party")
1004 && spath != "llvm-project/third-party"
1005 && !spath.starts_with("llvm-project/third-party/siphash")
1006 {
1007 return false;
1008 }
1009
1010 if spath.starts_with("llvm-project/llvm/test")
1011 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1012 {
1013 return false;
1014 }
1015 }
1016
1017 if spath.starts_with("tools/cargo/tests") {
1019 return true;
1020 }
1021
1022 if !exclude_dirs.is_empty() {
1023 let full_path = Path::new(dir).join(path);
1024 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1025 return false;
1026 }
1027 }
1028
1029 static EXCLUDES: &[&str] = &[
1030 "CVS",
1031 "RCS",
1032 "SCCS",
1033 ".git",
1034 ".gitignore",
1035 ".gitmodules",
1036 ".gitattributes",
1037 ".cvsignore",
1038 ".svn",
1039 ".arch-ids",
1040 "{arch}",
1041 "=RELEASE-ID",
1042 "=meta-update",
1043 "=update",
1044 ".bzr",
1045 ".bzrignore",
1046 ".bzrtags",
1047 ".hg",
1048 ".hgignore",
1049 ".hgrags",
1050 "_darcs",
1051 ];
1052
1053 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1060 !EXCLUDES.contains(&last_component)
1061 }
1062
1063 for item in src_dirs {
1065 let dst = &dst_dir.join(item);
1066 t!(fs::create_dir_all(dst));
1067 builder
1068 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1069 }
1070}
1071
1072#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1073pub struct Src;
1074
1075impl Step for Src {
1076 type Output = GeneratedTarball;
1078 const DEFAULT: bool = true;
1079 const IS_HOST: bool = true;
1080
1081 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1082 run.alias("rust-src")
1083 }
1084
1085 fn make_run(run: RunConfig<'_>) {
1086 run.builder.ensure(Src);
1087 }
1088
1089 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1091 if !builder.config.dry_run() {
1092 builder.require_submodule("src/llvm-project", None);
1093 }
1094
1095 let tarball = Tarball::new_targetless(builder, "rust-src");
1096
1097 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1105
1106 copy_src_dirs(
1109 builder,
1110 &builder.src,
1111 &["library", "src/llvm-project/libunwind"],
1112 &[
1113 "library/backtrace/crates",
1116 "library/stdarch/Cargo.toml",
1119 "library/stdarch/crates/stdarch-verify",
1120 "library/stdarch/crates/intrinsic-test",
1121 ],
1122 &dst_src,
1123 );
1124
1125 tarball.generate()
1126 }
1127
1128 fn metadata(&self) -> Option<StepMetadata> {
1129 Some(StepMetadata::dist("src", TargetSelection::default()))
1130 }
1131}
1132
1133#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1134pub struct PlainSourceTarball;
1135
1136impl Step for PlainSourceTarball {
1137 type Output = GeneratedTarball;
1139 const DEFAULT: bool = true;
1140 const IS_HOST: bool = true;
1141
1142 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1143 let builder = run.builder;
1144 run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
1145 }
1146
1147 fn make_run(run: RunConfig<'_>) {
1148 run.builder.ensure(PlainSourceTarball);
1149 }
1150
1151 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1153 let mut tarball = Tarball::new(builder, "rustc", "src");
1158 tarball.permit_symlinks(true);
1159 let plain_dst_src = tarball.image_dir();
1160
1161 let src_files = [
1163 ".gitmodules",
1165 "CONTRIBUTING.md",
1166 "COPYRIGHT",
1167 "Cargo.lock",
1168 "Cargo.toml",
1169 "LICENSE-APACHE",
1170 "LICENSE-MIT",
1171 "README.md",
1172 "RELEASES.md",
1173 "REUSE.toml",
1174 "bootstrap.example.toml",
1175 "configure",
1176 "license-metadata.json",
1177 "package-lock.json",
1178 "package.json",
1179 "x",
1180 "x.ps1",
1181 "x.py",
1182 ];
1184 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1185
1186 copy_src_dirs(
1187 builder,
1188 &builder.src,
1189 &src_dirs,
1190 &[
1191 "src/gcc",
1195 ],
1196 plain_dst_src,
1197 );
1198 if !builder.config.dry_run() {
1203 builder.create_dir(&plain_dst_src.join("src/gcc"));
1204 t!(std::fs::write(
1205 plain_dst_src.join("src/gcc/notice.txt"),
1206 "The GCC source code is not included due to unclear licensing implications\n"
1207 ));
1208 }
1209
1210 for item in &src_files {
1212 builder.copy_link(
1213 &builder.src.join(item),
1214 &plain_dst_src.join(item),
1215 FileType::Regular,
1216 );
1217 }
1218
1219 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1221
1222 let write_git_info = |info: Option<&Info>, path: &Path| {
1224 if let Some(info) = info {
1225 t!(std::fs::create_dir_all(path));
1226 channel::write_commit_hash_file(path, &info.sha);
1227 channel::write_commit_info_file(path, info);
1228 }
1229 };
1230 write_git_info(builder.rust_info().info(), plain_dst_src);
1231 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1232
1233 if builder.config.dist_vendor {
1234 builder.require_and_update_all_submodules();
1235
1236 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1238 .iter()
1239 .chain(build_helper::RUSTC_PGO_CRATES)
1240 .map(|pkg| {
1241 let mut manifest_path =
1242 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1243 manifest_path.push(pkg);
1244 manifest_path.push("Cargo.toml");
1245 manifest_path
1246 });
1247
1248 let vendor = builder.ensure(Vendor {
1250 sync_args: pkgs_for_pgo_training.collect(),
1251 versioned_dirs: true,
1252 root_dir: plain_dst_src.into(),
1253 output_dir: VENDOR_DIR.into(),
1254 });
1255
1256 let cargo_config_dir = plain_dst_src.join(".cargo");
1257 builder.create_dir(&cargo_config_dir);
1258 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1259 }
1260
1261 for entry in walkdir::WalkDir::new(tarball.image_dir())
1265 .follow_links(true)
1266 .into_iter()
1267 .filter_map(|e| e.ok())
1268 {
1269 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1270 {
1271 t!(fs::remove_dir_all(entry.path()));
1272 }
1273 }
1274
1275 tarball.bare()
1276 }
1277}
1278
1279#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1280pub struct Cargo {
1281 pub build_compiler: Compiler,
1282 pub target: TargetSelection,
1283}
1284
1285impl Step for Cargo {
1286 type Output = Option<GeneratedTarball>;
1287 const DEFAULT: bool = true;
1288 const IS_HOST: bool = true;
1289
1290 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1291 let default = should_build_extended_tool(run.builder, "cargo");
1292 run.alias("cargo").default_condition(default)
1293 }
1294
1295 fn make_run(run: RunConfig<'_>) {
1296 run.builder.ensure(Cargo {
1297 build_compiler: get_tool_target_compiler(
1298 run.builder,
1299 ToolTargetBuildMode::Build(run.target),
1300 ),
1301 target: run.target,
1302 });
1303 }
1304
1305 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1306 let build_compiler = self.build_compiler;
1307 let target = self.target;
1308
1309 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1310 let src = builder.src.join("src/tools/cargo");
1311 let etc = src.join("src/etc");
1312
1313 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1315 tarball.set_overlay(OverlayKind::Cargo);
1316
1317 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1318 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1319 tarball.add_renamed_file(
1320 etc.join("cargo.bashcomp.sh"),
1321 "etc/bash_completion.d",
1322 "cargo",
1323 FileType::Regular,
1324 );
1325 tarball.add_dir(etc.join("man"), "share/man/man1");
1326 tarball.add_legal_and_readme_to("share/doc/cargo");
1327
1328 Some(tarball.generate())
1329 }
1330
1331 fn metadata(&self) -> Option<StepMetadata> {
1332 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1333 }
1334}
1335
1336#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1338pub struct RustAnalyzer {
1339 pub compilers: RustcPrivateCompilers,
1340 pub target: TargetSelection,
1341}
1342
1343impl Step for RustAnalyzer {
1344 type Output = Option<GeneratedTarball>;
1345 const DEFAULT: bool = true;
1346 const IS_HOST: bool = true;
1347
1348 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1349 let default = should_build_extended_tool(run.builder, "rust-analyzer");
1350 run.alias("rust-analyzer").default_condition(default)
1351 }
1352
1353 fn make_run(run: RunConfig<'_>) {
1354 run.builder.ensure(RustAnalyzer {
1355 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1356 target: run.target,
1357 });
1358 }
1359
1360 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1361 let target = self.target;
1362 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1363
1364 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1365 tarball.set_overlay(OverlayKind::RustAnalyzer);
1366 tarball.is_preview(true);
1367 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1368 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1369 Some(tarball.generate())
1370 }
1371
1372 fn metadata(&self) -> Option<StepMetadata> {
1373 Some(
1374 StepMetadata::dist("rust-analyzer", self.target)
1375 .built_by(self.compilers.build_compiler()),
1376 )
1377 }
1378}
1379
1380#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1381pub struct Clippy {
1382 pub compilers: RustcPrivateCompilers,
1383 pub target: TargetSelection,
1384}
1385
1386impl Step for Clippy {
1387 type Output = Option<GeneratedTarball>;
1388 const DEFAULT: bool = true;
1389 const IS_HOST: bool = true;
1390
1391 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1392 let default = should_build_extended_tool(run.builder, "clippy");
1393 run.alias("clippy").default_condition(default)
1394 }
1395
1396 fn make_run(run: RunConfig<'_>) {
1397 run.builder.ensure(Clippy {
1398 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1399 target: run.target,
1400 });
1401 }
1402
1403 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1404 let target = self.target;
1405
1406 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1410 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1411
1412 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1413 tarball.set_overlay(OverlayKind::Clippy);
1414 tarball.is_preview(true);
1415 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1416 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1417 tarball.add_legal_and_readme_to("share/doc/clippy");
1418 Some(tarball.generate())
1419 }
1420
1421 fn metadata(&self) -> Option<StepMetadata> {
1422 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1423 }
1424}
1425
1426#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1427pub struct Miri {
1428 pub compilers: RustcPrivateCompilers,
1429 pub target: TargetSelection,
1430}
1431
1432impl Step for Miri {
1433 type Output = Option<GeneratedTarball>;
1434 const DEFAULT: bool = true;
1435 const IS_HOST: bool = true;
1436
1437 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1438 let default = should_build_extended_tool(run.builder, "miri");
1439 run.alias("miri").default_condition(default)
1440 }
1441
1442 fn make_run(run: RunConfig<'_>) {
1443 run.builder.ensure(Miri {
1444 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1445 target: run.target,
1446 });
1447 }
1448
1449 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1450 if !builder.build.unstable_features() {
1454 return None;
1455 }
1456
1457 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1458 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1459
1460 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1461 tarball.set_overlay(OverlayKind::Miri);
1462 tarball.is_preview(true);
1463 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1464 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1465 tarball.add_legal_and_readme_to("share/doc/miri");
1466 Some(tarball.generate())
1467 }
1468
1469 fn metadata(&self) -> Option<StepMetadata> {
1470 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1471 }
1472}
1473
1474#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1475pub struct CraneliftCodegenBackend {
1476 pub compilers: RustcPrivateCompilers,
1477 pub target: TargetSelection,
1478}
1479
1480impl Step for CraneliftCodegenBackend {
1481 type Output = Option<GeneratedTarball>;
1482 const DEFAULT: bool = true;
1483 const IS_HOST: bool = true;
1484
1485 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1486 let clif_enabled_by_default = run
1491 .builder
1492 .config
1493 .enabled_codegen_backends(run.builder.host_target)
1494 .contains(&CodegenBackendKind::Cranelift);
1495 run.alias("rustc_codegen_cranelift").default_condition(clif_enabled_by_default)
1496 }
1497
1498 fn make_run(run: RunConfig<'_>) {
1499 run.builder.ensure(CraneliftCodegenBackend {
1500 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1501 target: run.target,
1502 });
1503 }
1504
1505 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1506 if !builder.build.unstable_features() {
1510 return None;
1511 }
1512
1513 let target = self.target;
1514 if !target_supports_cranelift_backend(target) {
1515 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1516 return None;
1517 }
1518
1519 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1520 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1521 tarball.is_preview(true);
1522 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1523
1524 let compilers = self.compilers;
1525 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1526
1527 if builder.config.dry_run() {
1528 return None;
1529 }
1530
1531 let backends_dst = builder.sysroot_codegen_backends(compilers.target_compiler());
1533 let backends_rel = backends_dst
1534 .strip_prefix(builder.sysroot(compilers.target_compiler()))
1535 .unwrap()
1536 .strip_prefix(builder.sysroot_libdir_relative(compilers.target_compiler()))
1537 .unwrap();
1538 let backends_dst = PathBuf::from("lib").join(backends_rel);
1540
1541 let codegen_backend_dylib = get_codegen_backend_file(&stamp);
1542 tarball.add_renamed_file(
1543 &codegen_backend_dylib,
1544 &backends_dst,
1545 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1546 FileType::NativeLibrary,
1547 );
1548
1549 Some(tarball.generate())
1550 }
1551
1552 fn metadata(&self) -> Option<StepMetadata> {
1553 Some(
1554 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1555 .built_by(self.compilers.build_compiler()),
1556 )
1557 }
1558}
1559
1560#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1561pub struct Rustfmt {
1562 pub compilers: RustcPrivateCompilers,
1563 pub target: TargetSelection,
1564}
1565
1566impl Step for Rustfmt {
1567 type Output = Option<GeneratedTarball>;
1568 const DEFAULT: bool = true;
1569 const IS_HOST: bool = true;
1570
1571 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1572 let default = should_build_extended_tool(run.builder, "rustfmt");
1573 run.alias("rustfmt").default_condition(default)
1574 }
1575
1576 fn make_run(run: RunConfig<'_>) {
1577 run.builder.ensure(Rustfmt {
1578 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1579 target: run.target,
1580 });
1581 }
1582
1583 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1584 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1585 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1586
1587 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1588 tarball.set_overlay(OverlayKind::Rustfmt);
1589 tarball.is_preview(true);
1590 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1591 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1592 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1593 Some(tarball.generate())
1594 }
1595
1596 fn metadata(&self) -> Option<StepMetadata> {
1597 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1598 }
1599}
1600
1601#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1603pub struct Extended {
1604 build_compiler: Compiler,
1605 target: TargetSelection,
1606}
1607
1608impl Step for Extended {
1609 type Output = ();
1610 const DEFAULT: bool = true;
1611 const IS_HOST: bool = true;
1612
1613 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1614 let builder = run.builder;
1615 run.alias("extended").default_condition(builder.config.extended)
1616 }
1617
1618 fn make_run(run: RunConfig<'_>) {
1619 run.builder.ensure(Extended {
1620 build_compiler: run
1621 .builder
1622 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1623 target: run.target,
1624 });
1625 }
1626
1627 fn run(self, builder: &Builder<'_>) {
1629 let target = self.target;
1630 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1631
1632 let mut tarballs = Vec::new();
1633 let mut built_tools = HashSet::new();
1634 macro_rules! add_component {
1635 ($name:expr => $step:expr) => {
1636 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1637 tarballs.push(tarball);
1638 built_tools.insert($name);
1639 }
1640 };
1641 }
1642
1643 let rustc_private_compilers =
1644 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1645 let build_compiler = rustc_private_compilers.build_compiler();
1646 let target_compiler = rustc_private_compilers.target_compiler();
1647
1648 tarballs.push(builder.ensure(Rustc { target_compiler }));
1653 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1654
1655 if target.is_windows_gnu() {
1656 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1657 }
1658
1659 add_component!("rust-docs" => Docs { host: target });
1660 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1662 add_component!("cargo" => Cargo { build_compiler, target });
1663 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1664 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1665 add_component!("llvm-components" => LlvmTools { target });
1666 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1667 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1668 add_component!("analysis" => Analysis { build_compiler, target });
1669 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1670 compilers: rustc_private_compilers,
1671 target
1672 });
1673 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1674 build_compiler,
1675 target
1676 });
1677
1678 let etc = builder.src.join("src/etc/installer");
1679
1680 if builder.config.dry_run() {
1682 return;
1683 }
1684
1685 let tarball = Tarball::new(builder, "rust", &target.triple);
1686 let generated = tarball.combine(&tarballs);
1687
1688 let tmp = tmpdir(builder).join("combined-tarball");
1689 let work = generated.work_dir();
1690
1691 let mut license = String::new();
1692 license += &builder.read(&builder.src.join("COPYRIGHT"));
1693 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1694 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1695 license.push('\n');
1696 license.push('\n');
1697
1698 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1699 let mut rtf = rtf.to_string();
1700 rtf.push('\n');
1701 for line in license.lines() {
1702 rtf.push_str(line);
1703 rtf.push_str("\\line ");
1704 }
1705 rtf.push('}');
1706
1707 fn filter(contents: &str, marker: &str) -> String {
1708 let start = format!("tool-{marker}-start");
1709 let end = format!("tool-{marker}-end");
1710 let mut lines = Vec::new();
1711 let mut omitted = false;
1712 for line in contents.lines() {
1713 if line.contains(&start) {
1714 omitted = true;
1715 } else if line.contains(&end) {
1716 omitted = false;
1717 } else if !omitted {
1718 lines.push(line);
1719 }
1720 }
1721
1722 lines.join("\n")
1723 }
1724
1725 let xform = |p: &Path| {
1726 let mut contents = t!(fs::read_to_string(p));
1727 for tool in &["miri", "rust-docs"] {
1728 if !built_tools.contains(tool) {
1729 contents = filter(&contents, tool);
1730 }
1731 }
1732 let ret = tmp.join(p.file_name().unwrap());
1733 t!(fs::write(&ret, &contents));
1734 ret
1735 };
1736
1737 if target.contains("apple-darwin") {
1738 builder.info("building pkg installer");
1739 let pkg = tmp.join("pkg");
1740 let _ = fs::remove_dir_all(&pkg);
1741
1742 let pkgbuild = |component: &str| {
1743 let mut cmd = command("pkgbuild");
1744 cmd.arg("--identifier")
1745 .arg(format!("org.rust-lang.{component}"))
1746 .arg("--scripts")
1747 .arg(pkg.join(component))
1748 .arg("--nopayload")
1749 .arg(pkg.join(component).with_extension("pkg"));
1750 cmd.run(builder);
1751 };
1752
1753 let prepare = |name: &str| {
1754 builder.create_dir(&pkg.join(name));
1755 builder.cp_link_r(
1756 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1757 &pkg.join(name),
1758 );
1759 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1760 pkgbuild(name);
1761 };
1762 prepare("rustc");
1763 prepare("cargo");
1764 prepare("rust-std");
1765 prepare("rust-analysis");
1766
1767 for tool in &[
1768 "clippy",
1769 "rustfmt",
1770 "rust-analyzer",
1771 "rust-docs",
1772 "miri",
1773 "rustc-codegen-cranelift",
1774 ] {
1775 if built_tools.contains(tool) {
1776 prepare(tool);
1777 }
1778 }
1779 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1781 pkgbuild("uninstall");
1782
1783 builder.create_dir(&pkg.join("res"));
1784 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1785 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1786 let mut cmd = command("productbuild");
1787 cmd.arg("--distribution")
1788 .arg(xform(&etc.join("pkg/Distribution.xml")))
1789 .arg("--resources")
1790 .arg(pkg.join("res"))
1791 .arg(distdir(builder).join(format!(
1792 "{}-{}.pkg",
1793 pkgname(builder, "rust"),
1794 target.triple
1795 )))
1796 .arg("--package-path")
1797 .arg(&pkg);
1798 let _time = timeit(builder);
1799 cmd.run(builder);
1800 }
1801
1802 if target.is_windows() && !target.contains("gnullvm") {
1804 let exe = tmp.join("exe");
1805 let _ = fs::remove_dir_all(&exe);
1806
1807 let prepare = |name: &str| {
1808 builder.create_dir(&exe.join(name));
1809 let dir = if name == "rust-std" || name == "rust-analysis" {
1810 format!("{}-{}", name, target.triple)
1811 } else if name == "rust-analyzer" {
1812 "rust-analyzer-preview".to_string()
1813 } else if name == "clippy" {
1814 "clippy-preview".to_string()
1815 } else if name == "rustfmt" {
1816 "rustfmt-preview".to_string()
1817 } else if name == "miri" {
1818 "miri-preview".to_string()
1819 } else if name == "rustc-codegen-cranelift" {
1820 unreachable!("cg_clif shouldn't be built for windows");
1823 } else {
1824 name.to_string()
1825 };
1826 builder.cp_link_r(
1827 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1828 &exe.join(name),
1829 );
1830 builder.remove(&exe.join(name).join("manifest.in"));
1831 };
1832 prepare("rustc");
1833 prepare("cargo");
1834 prepare("rust-analysis");
1835 prepare("rust-std");
1836 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1837 if built_tools.contains(tool) {
1838 prepare(tool);
1839 }
1840 }
1841 if target.is_windows_gnu() {
1842 prepare("rust-mingw");
1843 }
1844
1845 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1846
1847 let wix_path = env::var_os("WIX")
1849 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1850 let wix = PathBuf::from(wix_path);
1851 let heat = wix.join("bin/heat.exe");
1852 let candle = wix.join("bin/candle.exe");
1853 let light = wix.join("bin/light.exe");
1854
1855 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1856 command(&heat)
1857 .current_dir(&exe)
1858 .arg("dir")
1859 .arg("rustc")
1860 .args(heat_flags)
1861 .arg("-cg")
1862 .arg("RustcGroup")
1863 .arg("-dr")
1864 .arg("Rustc")
1865 .arg("-var")
1866 .arg("var.RustcDir")
1867 .arg("-out")
1868 .arg(exe.join("RustcGroup.wxs"))
1869 .run(builder);
1870 if built_tools.contains("rust-docs") {
1871 command(&heat)
1872 .current_dir(&exe)
1873 .arg("dir")
1874 .arg("rust-docs")
1875 .args(heat_flags)
1876 .arg("-cg")
1877 .arg("DocsGroup")
1878 .arg("-dr")
1879 .arg("Docs")
1880 .arg("-var")
1881 .arg("var.DocsDir")
1882 .arg("-out")
1883 .arg(exe.join("DocsGroup.wxs"))
1884 .arg("-t")
1885 .arg(etc.join("msi/squash-components.xsl"))
1886 .run(builder);
1887 }
1888 command(&heat)
1889 .current_dir(&exe)
1890 .arg("dir")
1891 .arg("cargo")
1892 .args(heat_flags)
1893 .arg("-cg")
1894 .arg("CargoGroup")
1895 .arg("-dr")
1896 .arg("Cargo")
1897 .arg("-var")
1898 .arg("var.CargoDir")
1899 .arg("-out")
1900 .arg(exe.join("CargoGroup.wxs"))
1901 .arg("-t")
1902 .arg(etc.join("msi/remove-duplicates.xsl"))
1903 .run(builder);
1904 command(&heat)
1905 .current_dir(&exe)
1906 .arg("dir")
1907 .arg("rust-std")
1908 .args(heat_flags)
1909 .arg("-cg")
1910 .arg("StdGroup")
1911 .arg("-dr")
1912 .arg("Std")
1913 .arg("-var")
1914 .arg("var.StdDir")
1915 .arg("-out")
1916 .arg(exe.join("StdGroup.wxs"))
1917 .run(builder);
1918 if built_tools.contains("rust-analyzer") {
1919 command(&heat)
1920 .current_dir(&exe)
1921 .arg("dir")
1922 .arg("rust-analyzer")
1923 .args(heat_flags)
1924 .arg("-cg")
1925 .arg("RustAnalyzerGroup")
1926 .arg("-dr")
1927 .arg("RustAnalyzer")
1928 .arg("-var")
1929 .arg("var.RustAnalyzerDir")
1930 .arg("-out")
1931 .arg(exe.join("RustAnalyzerGroup.wxs"))
1932 .arg("-t")
1933 .arg(etc.join("msi/remove-duplicates.xsl"))
1934 .run(builder);
1935 }
1936 if built_tools.contains("clippy") {
1937 command(&heat)
1938 .current_dir(&exe)
1939 .arg("dir")
1940 .arg("clippy")
1941 .args(heat_flags)
1942 .arg("-cg")
1943 .arg("ClippyGroup")
1944 .arg("-dr")
1945 .arg("Clippy")
1946 .arg("-var")
1947 .arg("var.ClippyDir")
1948 .arg("-out")
1949 .arg(exe.join("ClippyGroup.wxs"))
1950 .arg("-t")
1951 .arg(etc.join("msi/remove-duplicates.xsl"))
1952 .run(builder);
1953 }
1954 if built_tools.contains("rustfmt") {
1955 command(&heat)
1956 .current_dir(&exe)
1957 .arg("dir")
1958 .arg("rustfmt")
1959 .args(heat_flags)
1960 .arg("-cg")
1961 .arg("RustFmtGroup")
1962 .arg("-dr")
1963 .arg("RustFmt")
1964 .arg("-var")
1965 .arg("var.RustFmtDir")
1966 .arg("-out")
1967 .arg(exe.join("RustFmtGroup.wxs"))
1968 .arg("-t")
1969 .arg(etc.join("msi/remove-duplicates.xsl"))
1970 .run(builder);
1971 }
1972 if built_tools.contains("miri") {
1973 command(&heat)
1974 .current_dir(&exe)
1975 .arg("dir")
1976 .arg("miri")
1977 .args(heat_flags)
1978 .arg("-cg")
1979 .arg("MiriGroup")
1980 .arg("-dr")
1981 .arg("Miri")
1982 .arg("-var")
1983 .arg("var.MiriDir")
1984 .arg("-out")
1985 .arg(exe.join("MiriGroup.wxs"))
1986 .arg("-t")
1987 .arg(etc.join("msi/remove-duplicates.xsl"))
1988 .run(builder);
1989 }
1990 command(&heat)
1991 .current_dir(&exe)
1992 .arg("dir")
1993 .arg("rust-analysis")
1994 .args(heat_flags)
1995 .arg("-cg")
1996 .arg("AnalysisGroup")
1997 .arg("-dr")
1998 .arg("Analysis")
1999 .arg("-var")
2000 .arg("var.AnalysisDir")
2001 .arg("-out")
2002 .arg(exe.join("AnalysisGroup.wxs"))
2003 .arg("-t")
2004 .arg(etc.join("msi/remove-duplicates.xsl"))
2005 .run(builder);
2006 if target.is_windows_gnu() {
2007 command(&heat)
2008 .current_dir(&exe)
2009 .arg("dir")
2010 .arg("rust-mingw")
2011 .args(heat_flags)
2012 .arg("-cg")
2013 .arg("GccGroup")
2014 .arg("-dr")
2015 .arg("Gcc")
2016 .arg("-var")
2017 .arg("var.GccDir")
2018 .arg("-out")
2019 .arg(exe.join("GccGroup.wxs"))
2020 .run(builder);
2021 }
2022
2023 let candle = |input: &Path| {
2024 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2025 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2026 let mut cmd = command(&candle);
2027 cmd.current_dir(&exe)
2028 .arg("-nologo")
2029 .arg("-dRustcDir=rustc")
2030 .arg("-dCargoDir=cargo")
2031 .arg("-dStdDir=rust-std")
2032 .arg("-dAnalysisDir=rust-analysis")
2033 .arg("-arch")
2034 .arg(arch)
2035 .arg("-out")
2036 .arg(&output)
2037 .arg(input);
2038 add_env(builder, &mut cmd, target, &built_tools);
2039
2040 if built_tools.contains("clippy") {
2041 cmd.arg("-dClippyDir=clippy");
2042 }
2043 if built_tools.contains("rustfmt") {
2044 cmd.arg("-dRustFmtDir=rustfmt");
2045 }
2046 if built_tools.contains("rust-docs") {
2047 cmd.arg("-dDocsDir=rust-docs");
2048 }
2049 if built_tools.contains("rust-analyzer") {
2050 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2051 }
2052 if built_tools.contains("miri") {
2053 cmd.arg("-dMiriDir=miri");
2054 }
2055 if target.is_windows_gnu() {
2056 cmd.arg("-dGccDir=rust-mingw");
2057 }
2058 cmd.run(builder);
2059 };
2060 candle(&xform(&etc.join("msi/rust.wxs")));
2061 candle(&etc.join("msi/ui.wxs"));
2062 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2063 candle("RustcGroup.wxs".as_ref());
2064 if built_tools.contains("rust-docs") {
2065 candle("DocsGroup.wxs".as_ref());
2066 }
2067 candle("CargoGroup.wxs".as_ref());
2068 candle("StdGroup.wxs".as_ref());
2069 if built_tools.contains("clippy") {
2070 candle("ClippyGroup.wxs".as_ref());
2071 }
2072 if built_tools.contains("rustfmt") {
2073 candle("RustFmtGroup.wxs".as_ref());
2074 }
2075 if built_tools.contains("miri") {
2076 candle("MiriGroup.wxs".as_ref());
2077 }
2078 if built_tools.contains("rust-analyzer") {
2079 candle("RustAnalyzerGroup.wxs".as_ref());
2080 }
2081 candle("AnalysisGroup.wxs".as_ref());
2082
2083 if target.is_windows_gnu() {
2084 candle("GccGroup.wxs".as_ref());
2085 }
2086
2087 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2088 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2089 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2090
2091 builder.info(&format!("building `msi` installer with {light:?}"));
2092 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2093 let mut cmd = command(&light);
2094 cmd.arg("-nologo")
2095 .arg("-ext")
2096 .arg("WixUIExtension")
2097 .arg("-ext")
2098 .arg("WixUtilExtension")
2099 .arg("-out")
2100 .arg(exe.join(&filename))
2101 .arg("rust.wixobj")
2102 .arg("ui.wixobj")
2103 .arg("rustwelcomedlg.wixobj")
2104 .arg("RustcGroup.wixobj")
2105 .arg("CargoGroup.wixobj")
2106 .arg("StdGroup.wixobj")
2107 .arg("AnalysisGroup.wixobj")
2108 .current_dir(&exe);
2109
2110 if built_tools.contains("clippy") {
2111 cmd.arg("ClippyGroup.wixobj");
2112 }
2113 if built_tools.contains("rustfmt") {
2114 cmd.arg("RustFmtGroup.wixobj");
2115 }
2116 if built_tools.contains("miri") {
2117 cmd.arg("MiriGroup.wixobj");
2118 }
2119 if built_tools.contains("rust-analyzer") {
2120 cmd.arg("RustAnalyzerGroup.wixobj");
2121 }
2122 if built_tools.contains("rust-docs") {
2123 cmd.arg("DocsGroup.wixobj");
2124 }
2125
2126 if target.is_windows_gnu() {
2127 cmd.arg("GccGroup.wixobj");
2128 }
2129 cmd.arg("-sice:ICE57");
2131
2132 let _time = timeit(builder);
2133 cmd.run(builder);
2134
2135 if !builder.config.dry_run() {
2136 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2137 }
2138 }
2139 }
2140
2141 fn metadata(&self) -> Option<StepMetadata> {
2142 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2143 }
2144}
2145
2146fn add_env(
2147 builder: &Builder<'_>,
2148 cmd: &mut BootstrapCommand,
2149 target: TargetSelection,
2150 built_tools: &HashSet<&'static str>,
2151) {
2152 let mut parts = builder.version.split('.');
2153 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2154 .env("CFG_RELEASE_NUM", &builder.version)
2155 .env("CFG_RELEASE", builder.rust_release())
2156 .env("CFG_VER_MAJOR", parts.next().unwrap())
2157 .env("CFG_VER_MINOR", parts.next().unwrap())
2158 .env("CFG_VER_PATCH", parts.next().unwrap())
2159 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2161 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2162 .env("CFG_BUILD", target.triple)
2163 .env("CFG_CHANNEL", &builder.config.channel);
2164
2165 if target.contains("windows-gnullvm") {
2166 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2167 } else if target.is_windows_gnu() {
2168 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2169 } else {
2170 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2171 }
2172
2173 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2175 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2176 };
2177 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2178 define_optional_tool("clippy", "CFG_CLIPPY");
2179 define_optional_tool("miri", "CFG_MIRI");
2180 define_optional_tool("rust-analyzer", "CFG_RA");
2181}
2182
2183fn install_llvm_file(
2184 builder: &Builder<'_>,
2185 source: &Path,
2186 destination: &Path,
2187 install_symlink: bool,
2188) {
2189 if builder.config.dry_run() {
2190 return;
2191 }
2192
2193 if source.is_symlink() {
2194 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2197
2198 let full_dest = destination.join(source.file_name().unwrap());
2199 if install_symlink {
2200 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2203 } else {
2204 let link = t!(fs::read_link(source));
2208 let mut linker_script = t!(fs::File::create(full_dest));
2209 t!(write!(linker_script, "INPUT({})\n", link.display()));
2210
2211 let meta = t!(fs::metadata(source));
2214 if let Ok(mtime) = meta.modified() {
2215 t!(linker_script.set_modified(mtime));
2216 }
2217 }
2218 } else {
2219 builder.install(source, destination, FileType::NativeLibrary);
2220 }
2221}
2222
2223#[cfg_attr(
2227 feature = "tracing",
2228 instrument(
2229 level = "trace",
2230 name = "maybe_install_llvm",
2231 skip_all,
2232 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2233 ),
2234)]
2235fn maybe_install_llvm(
2236 builder: &Builder<'_>,
2237 target: TargetSelection,
2238 dst_libdir: &Path,
2239 install_symlink: bool,
2240) -> bool {
2241 if builder.config.is_system_llvm(target) {
2258 trace!("system LLVM requested, no install");
2259 return false;
2260 }
2261
2262 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2268 let src_libdir = builder.llvm_out(target).join("lib");
2269 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2270 if llvm_dylib_path.exists() {
2271 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2272 }
2273 !builder.config.dry_run()
2274 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2275 host_llvm_config, ..
2276 }) = llvm::prebuilt_llvm_config(builder, target, true)
2277 {
2278 trace!("LLVM already built, installing LLVM files");
2279 let mut cmd = command(host_llvm_config);
2280 cmd.cached();
2281 cmd.arg("--libfiles");
2282 builder.verbose(|| println!("running {cmd:?}"));
2283 let files = cmd.run_capture_stdout(builder).stdout();
2284 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2285 let target_llvm_out = &builder.llvm_out(target);
2286 for file in files.trim_end().split(' ') {
2287 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2289 target_llvm_out.join(relative_path)
2290 } else {
2291 PathBuf::from(file)
2292 };
2293 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2294 }
2295 !builder.config.dry_run()
2296 } else {
2297 false
2298 }
2299}
2300
2301#[cfg_attr(
2303 feature = "tracing",
2304 instrument(
2305 level = "trace",
2306 name = "maybe_install_llvm_target",
2307 skip_all,
2308 fields(
2309 llvm_link_shared = ?builder.llvm_link_shared(),
2310 target = ?target,
2311 sysroot = ?sysroot,
2312 ),
2313 ),
2314)]
2315pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2316 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2317 if builder.llvm_link_shared() {
2321 maybe_install_llvm(builder, target, &dst_libdir, false);
2322 }
2323}
2324
2325#[cfg_attr(
2327 feature = "tracing",
2328 instrument(
2329 level = "trace",
2330 name = "maybe_install_llvm_runtime",
2331 skip_all,
2332 fields(
2333 llvm_link_shared = ?builder.llvm_link_shared(),
2334 target = ?target,
2335 sysroot = ?sysroot,
2336 ),
2337 ),
2338)]
2339pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2340 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2341 if builder.llvm_link_shared() {
2345 maybe_install_llvm(builder, target, &dst_libdir, false);
2346 }
2347}
2348
2349#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2350pub struct LlvmTools {
2351 pub target: TargetSelection,
2352}
2353
2354impl Step for LlvmTools {
2355 type Output = Option<GeneratedTarball>;
2356 const IS_HOST: bool = true;
2357 const DEFAULT: bool = true;
2358
2359 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2360 let default = should_build_extended_tool(run.builder, "llvm-tools");
2361
2362 let mut run = run.alias("llvm-tools");
2363 for tool in LLVM_TOOLS {
2364 run = run.alias(tool);
2365 }
2366
2367 run.default_condition(default)
2368 }
2369
2370 fn make_run(run: RunConfig<'_>) {
2371 run.builder.ensure(LlvmTools { target: run.target });
2372 }
2373
2374 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2375 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2376 let mut tools = vec![];
2377
2378 for path in paths {
2379 let path = path.to_str().unwrap();
2380
2381 if path == "llvm-tools" {
2383 return LLVM_TOOLS.to_owned();
2384 }
2385
2386 for tool in LLVM_TOOLS {
2387 if path == *tool {
2388 tools.push(*tool);
2389 }
2390 }
2391 }
2392
2393 if tools.is_empty() {
2395 tools = LLVM_TOOLS.to_owned();
2396 }
2397
2398 tools
2399 }
2400
2401 let target = self.target;
2402
2403 if let Some(config) = builder.config.target_config.get(&target)
2405 && !builder.config.llvm_from_ci
2406 && config.llvm_config.is_some()
2407 {
2408 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2409 return None;
2410 }
2411
2412 if !builder.config.dry_run() {
2413 builder.require_submodule("src/llvm-project", None);
2414 }
2415
2416 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2417
2418 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2419 tarball.set_overlay(OverlayKind::Llvm);
2420 tarball.is_preview(true);
2421
2422 if builder.config.llvm_tools_enabled {
2423 let src_bindir = builder.llvm_out(target).join("bin");
2425 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2426 for tool in tools_to_install(&builder.paths) {
2427 let exe = src_bindir.join(exe(tool, target));
2428 if !exe.exists() && builder.config.llvm_from_ci {
2430 eprintln!("{} does not exist; skipping copy", exe.display());
2431 continue;
2432 }
2433
2434 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2435 }
2436 }
2437
2438 maybe_install_llvm_target(builder, target, tarball.image_dir());
2443
2444 Some(tarball.generate())
2445 }
2446}
2447
2448#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2451pub struct LlvmBitcodeLinker {
2452 pub build_compiler: Compiler,
2454 pub target: TargetSelection,
2456}
2457
2458impl Step for LlvmBitcodeLinker {
2459 type Output = Option<GeneratedTarball>;
2460 const DEFAULT: bool = true;
2461 const IS_HOST: bool = true;
2462
2463 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2464 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2465 run.alias("llvm-bitcode-linker").default_condition(default)
2466 }
2467
2468 fn make_run(run: RunConfig<'_>) {
2469 run.builder.ensure(LlvmBitcodeLinker {
2470 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2471 run.builder,
2472 run.target,
2473 ),
2474 target: run.target,
2475 });
2476 }
2477
2478 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2479 let target = self.target;
2480
2481 let llbc_linker = builder
2482 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2483
2484 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2485
2486 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2488 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2489 tarball.is_preview(true);
2490
2491 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2492
2493 Some(tarball.generate())
2494 }
2495}
2496
2497#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2506pub struct RustDev {
2507 pub target: TargetSelection,
2508}
2509
2510impl Step for RustDev {
2511 type Output = Option<GeneratedTarball>;
2512 const DEFAULT: bool = true;
2513 const IS_HOST: bool = true;
2514
2515 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2516 run.alias("rust-dev")
2517 }
2518
2519 fn make_run(run: RunConfig<'_>) {
2520 run.builder.ensure(RustDev { target: run.target });
2521 }
2522
2523 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2524 let target = self.target;
2525
2526 if let Some(config) = builder.config.target_config.get(&target)
2528 && let Some(ref _s) = config.llvm_config
2529 {
2530 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2531 return None;
2532 }
2533
2534 if !builder.config.dry_run() {
2535 builder.require_submodule("src/llvm-project", None);
2536 }
2537
2538 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2539 tarball.set_overlay(OverlayKind::Llvm);
2540 tarball.permit_symlinks(true);
2542
2543 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2544
2545 let src_bindir = builder.llvm_out(target).join("bin");
2546 if src_bindir.exists() {
2552 for entry in walkdir::WalkDir::new(&src_bindir) {
2553 let entry = t!(entry);
2554 if entry.file_type().is_file() && !entry.path_is_symlink() {
2555 let name = entry.file_name().to_str().unwrap();
2556 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2557 }
2558 }
2559 }
2560
2561 if builder.config.lld_enabled {
2562 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2564
2565 let lld_path = lld_out.join("bin").join(exe("lld", target));
2567 if lld_path.exists() {
2568 tarball.add_file(&lld_path, "bin", FileType::Executable);
2569 }
2570 }
2571
2572 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2573
2574 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2578
2579 let dst_libdir = tarball.image_dir().join("lib");
2584 maybe_install_llvm(builder, target, &dst_libdir, true);
2585 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2586 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2587
2588 copy_src_dirs(
2592 builder,
2593 &builder.src.join("src").join("llvm-project"),
2594 &["compiler-rt"],
2595 &["compiler-rt/test"],
2598 tarball.image_dir(),
2599 );
2600
2601 Some(tarball.generate())
2602 }
2603}
2604
2605#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2611pub struct Bootstrap {
2612 target: TargetSelection,
2613}
2614
2615impl Step for Bootstrap {
2616 type Output = Option<GeneratedTarball>;
2617
2618 const IS_HOST: bool = true;
2619
2620 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2621 run.alias("bootstrap")
2622 }
2623
2624 fn make_run(run: RunConfig<'_>) {
2625 run.builder.ensure(Bootstrap { target: run.target });
2626 }
2627
2628 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2629 let target = self.target;
2630
2631 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2632
2633 let bootstrap_outdir = &builder.bootstrap_out;
2634 for file in &["bootstrap", "rustc", "rustdoc"] {
2635 tarball.add_file(
2636 bootstrap_outdir.join(exe(file, target)),
2637 "bootstrap/bin",
2638 FileType::Executable,
2639 );
2640 }
2641
2642 Some(tarball.generate())
2643 }
2644
2645 fn metadata(&self) -> Option<StepMetadata> {
2646 Some(StepMetadata::dist("bootstrap", self.target))
2647 }
2648}
2649
2650#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2655pub struct BuildManifest {
2656 target: TargetSelection,
2657}
2658
2659impl Step for BuildManifest {
2660 type Output = GeneratedTarball;
2661
2662 const IS_HOST: bool = true;
2663
2664 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2665 run.alias("build-manifest")
2666 }
2667
2668 fn make_run(run: RunConfig<'_>) {
2669 run.builder.ensure(BuildManifest { target: run.target });
2670 }
2671
2672 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2673 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2674
2675 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2676 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2677 tarball.generate()
2678 }
2679
2680 fn metadata(&self) -> Option<StepMetadata> {
2681 Some(StepMetadata::dist("build-manifest", self.target))
2682 }
2683}
2684
2685#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2691pub struct ReproducibleArtifacts {
2692 target: TargetSelection,
2693}
2694
2695impl Step for ReproducibleArtifacts {
2696 type Output = Option<GeneratedTarball>;
2697 const DEFAULT: bool = true;
2698 const IS_HOST: bool = true;
2699
2700 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2701 run.alias("reproducible-artifacts")
2702 }
2703
2704 fn make_run(run: RunConfig<'_>) {
2705 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2706 }
2707
2708 fn run(self, builder: &Builder<'_>) -> Self::Output {
2709 let mut added_anything = false;
2710 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2711 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2712 tarball.add_file(path, ".", FileType::Regular);
2713 added_anything = true;
2714 }
2715 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2716 tarball.add_file(path, ".", FileType::Regular);
2717 added_anything = true;
2718 }
2719 for profile in &builder.config.reproducible_artifacts {
2720 tarball.add_file(profile, ".", FileType::Regular);
2721 added_anything = true;
2722 }
2723 if added_anything { Some(tarball.generate()) } else { None }
2724 }
2725
2726 fn metadata(&self) -> Option<StepMetadata> {
2727 Some(StepMetadata::dist("reproducible-artifacts", self.target))
2728 }
2729}
2730
2731#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2735pub struct Gcc {
2736 target: TargetSelection,
2737}
2738
2739impl Step for Gcc {
2740 type Output = GeneratedTarball;
2741
2742 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2743 run.alias("gcc")
2744 }
2745
2746 fn make_run(run: RunConfig<'_>) {
2747 run.builder.ensure(Gcc { target: run.target });
2748 }
2749
2750 fn run(self, builder: &Builder<'_>) -> Self::Output {
2751 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2752 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2753 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2754 tarball.generate()
2755 }
2756
2757 fn metadata(&self) -> Option<StepMetadata> {
2758 Some(StepMetadata::dist("gcc", self.target))
2759 }
2760}