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