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 let ra_proc_macro_srv_compiler =
425 builder.compiler_for(compiler.stage, builder.config.host_target, compiler.host);
426 builder.ensure(compile::Rustc::new(ra_proc_macro_srv_compiler, compiler.host));
427
428 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
429 tool::RustAnalyzerProcMacroSrv {
430 compiler: ra_proc_macro_srv_compiler,
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.config.is_host_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.config.is_host_target(target)
675 {
676 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
677 }
678 }
679}
680
681#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
682pub struct Std {
683 pub compiler: Compiler,
684 pub target: TargetSelection,
685}
686
687impl Step for Std {
688 type Output = Option<GeneratedTarball>;
689 const DEFAULT: bool = true;
690
691 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
692 run.alias("rust-std")
693 }
694
695 fn make_run(run: RunConfig<'_>) {
696 run.builder.ensure(Std {
697 compiler: run.builder.compiler_for(
698 run.builder.top_stage,
699 run.builder.config.host_target,
700 run.target,
701 ),
702 target: run.target,
703 });
704 }
705
706 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
707 let compiler = self.compiler;
708 let target = self.target;
709
710 if skip_host_target_lib(builder, compiler) {
711 return None;
712 }
713
714 builder.ensure(compile::Std::new(compiler, target));
715
716 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
717 tarball.include_target_in_component_name(true);
718
719 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
720 let stamp = build_stamp::libstd_stamp(builder, compiler_to_use, target);
721 verify_uefi_rlib_format(builder, target, &stamp);
722 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
723
724 Some(tarball.generate())
725 }
726}
727
728#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
733pub struct RustcDev {
734 pub compiler: Compiler,
735 pub target: TargetSelection,
736}
737
738impl Step for RustcDev {
739 type Output = Option<GeneratedTarball>;
740 const DEFAULT: bool = true;
741 const ONLY_HOSTS: bool = true;
742
743 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
744 run.alias("rustc-dev")
745 }
746
747 fn make_run(run: RunConfig<'_>) {
748 run.builder.ensure(RustcDev {
749 compiler: run.builder.compiler_for(
750 run.builder.top_stage,
751 run.builder.config.host_target,
752 run.target,
753 ),
754 target: run.target,
755 });
756 }
757
758 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
759 let compiler = self.compiler;
760 let target = self.target;
761 if skip_host_target_lib(builder, compiler) {
762 return None;
763 }
764
765 builder.ensure(compile::Rustc::new(compiler, target));
766
767 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
768
769 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
770 let stamp = build_stamp::librustc_stamp(builder, compiler_to_use, target);
771 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
772
773 let src_files = &["Cargo.lock"];
774 copy_src_dirs(
777 builder,
778 &builder.src,
779 &["compiler", "library/proc_macro"],
781 &[],
782 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
783 );
784 for file in src_files {
785 tarball.add_file(
786 builder.src.join(file),
787 "lib/rustlib/rustc-src/rust",
788 FileType::Regular,
789 );
790 }
791
792 Some(tarball.generate())
793 }
794}
795
796#[derive(Debug, Clone, Hash, PartialEq, Eq)]
797pub struct Analysis {
798 pub compiler: Compiler,
799 pub target: TargetSelection,
800}
801
802impl Step for Analysis {
803 type Output = Option<GeneratedTarball>;
804 const DEFAULT: bool = true;
805
806 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
807 let default = should_build_extended_tool(run.builder, "analysis");
808 run.alias("rust-analysis").default_condition(default)
809 }
810
811 fn make_run(run: RunConfig<'_>) {
812 run.builder.ensure(Analysis {
813 compiler: run.builder.compiler_for(
817 run.builder.top_stage,
818 run.builder.config.host_target,
819 run.target,
820 ),
821 target: run.target,
822 });
823 }
824
825 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
827 let compiler = self.compiler;
828 let target = self.target;
829 if !builder.config.is_host_target(compiler.host) {
830 return None;
831 }
832
833 let src = builder
834 .stage_out(compiler, Mode::Std)
835 .join(target)
836 .join(builder.cargo_dir())
837 .join("deps")
838 .join("save-analysis");
839
840 t!(std::fs::create_dir_all(&src));
842 let mut removed = src.clone();
843 removed.push("removed.json");
844 let mut f = t!(std::fs::File::create(removed));
845 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
846
847 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
848 tarball.include_target_in_component_name(true);
849 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
850 Some(tarball.generate())
851 }
852}
853
854fn copy_src_dirs(
857 builder: &Builder<'_>,
858 base: &Path,
859 src_dirs: &[&str],
860 exclude_dirs: &[&str],
861 dst_dir: &Path,
862) {
863 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
864 let spath = match path.to_str() {
865 Some(path) => path,
866 None => return false,
867 };
868 if spath.ends_with('~') || spath.ends_with(".pyc") {
869 return false;
870 }
871
872 const LLVM_PROJECTS: &[&str] = &[
873 "llvm-project/clang",
874 "llvm-project\\clang",
875 "llvm-project/libunwind",
876 "llvm-project\\libunwind",
877 "llvm-project/lld",
878 "llvm-project\\lld",
879 "llvm-project/lldb",
880 "llvm-project\\lldb",
881 "llvm-project/llvm",
882 "llvm-project\\llvm",
883 "llvm-project/compiler-rt",
884 "llvm-project\\compiler-rt",
885 "llvm-project/cmake",
886 "llvm-project\\cmake",
887 "llvm-project/runtimes",
888 "llvm-project\\runtimes",
889 ];
890 if spath.contains("llvm-project")
891 && !spath.ends_with("llvm-project")
892 && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
893 {
894 return false;
895 }
896
897 const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
898 if LLVM_TEST.iter().any(|path| spath.contains(path))
899 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
900 {
901 return false;
902 }
903
904 const CARGO_TESTS: &[&str] = &["tools/cargo/tests", "tools\\cargo\\tests"];
906 if CARGO_TESTS.iter().any(|path| spath.contains(path)) {
907 return true;
908 }
909
910 let full_path = Path::new(dir).join(path);
911 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
912 return false;
913 }
914
915 let excludes = [
916 "CVS",
917 "RCS",
918 "SCCS",
919 ".git",
920 ".gitignore",
921 ".gitmodules",
922 ".gitattributes",
923 ".cvsignore",
924 ".svn",
925 ".arch-ids",
926 "{arch}",
927 "=RELEASE-ID",
928 "=meta-update",
929 "=update",
930 ".bzr",
931 ".bzrignore",
932 ".bzrtags",
933 ".hg",
934 ".hgignore",
935 ".hgrags",
936 "_darcs",
937 ];
938 !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
939 }
940
941 for item in src_dirs {
943 let dst = &dst_dir.join(item);
944 t!(fs::create_dir_all(dst));
945 builder
946 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
947 }
948}
949
950#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
951pub struct Src;
952
953impl Step for Src {
954 type Output = GeneratedTarball;
956 const DEFAULT: bool = true;
957 const ONLY_HOSTS: bool = true;
958
959 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
960 run.alias("rust-src")
961 }
962
963 fn make_run(run: RunConfig<'_>) {
964 run.builder.ensure(Src);
965 }
966
967 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
969 if !builder.config.dry_run() {
970 builder.require_submodule("src/llvm-project", None);
971 }
972
973 let tarball = Tarball::new_targetless(builder, "rust-src");
974
975 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
983
984 copy_src_dirs(
987 builder,
988 &builder.src,
989 &["library", "src/llvm-project/libunwind"],
990 &[
991 "library/backtrace/crates",
994 "library/stdarch/Cargo.toml",
997 "library/stdarch/crates/stdarch-verify",
998 "library/stdarch/crates/intrinsic-test",
999 ],
1000 &dst_src,
1001 );
1002
1003 tarball.generate()
1004 }
1005}
1006
1007#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1008pub struct PlainSourceTarball;
1009
1010impl Step for PlainSourceTarball {
1011 type Output = GeneratedTarball;
1013 const DEFAULT: bool = true;
1014 const ONLY_HOSTS: bool = true;
1015
1016 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1017 let builder = run.builder;
1018 run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
1019 }
1020
1021 fn make_run(run: RunConfig<'_>) {
1022 run.builder.ensure(PlainSourceTarball);
1023 }
1024
1025 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1027 let mut tarball = Tarball::new(builder, "rustc", "src");
1032 tarball.permit_symlinks(true);
1033 let plain_dst_src = tarball.image_dir();
1034
1035 let src_files = [
1037 ".gitmodules",
1039 "bootstrap.example.toml",
1040 "Cargo.lock",
1041 "Cargo.toml",
1042 "configure",
1043 "CONTRIBUTING.md",
1044 "COPYRIGHT",
1045 "LICENSE-APACHE",
1046 "license-metadata.json",
1047 "LICENSE-MIT",
1048 "README.md",
1049 "RELEASES.md",
1050 "REUSE.toml",
1051 "x",
1052 "x.ps1",
1053 "x.py",
1054 ];
1056 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1057
1058 copy_src_dirs(
1059 builder,
1060 &builder.src,
1061 &src_dirs,
1062 &[
1063 "src/gcc",
1067 ],
1068 plain_dst_src,
1069 );
1070 if !builder.config.dry_run() {
1075 builder.create_dir(&plain_dst_src.join("src/gcc"));
1076 t!(std::fs::write(
1077 plain_dst_src.join("src/gcc/notice.txt"),
1078 "The GCC source code is not included due to unclear licensing implications\n"
1079 ));
1080 }
1081
1082 for item in &src_files {
1084 builder.copy_link(
1085 &builder.src.join(item),
1086 &plain_dst_src.join(item),
1087 FileType::Regular,
1088 );
1089 }
1090
1091 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1093
1094 let write_git_info = |info: Option<&Info>, path: &Path| {
1096 if let Some(info) = info {
1097 t!(std::fs::create_dir_all(path));
1098 channel::write_commit_hash_file(path, &info.sha);
1099 channel::write_commit_info_file(path, info);
1100 }
1101 };
1102 write_git_info(builder.rust_info().info(), plain_dst_src);
1103 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1104
1105 if builder.config.dist_vendor {
1106 builder.require_and_update_all_submodules();
1107
1108 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1110 .iter()
1111 .chain(build_helper::RUSTC_PGO_CRATES)
1112 .map(|pkg| {
1113 let mut manifest_path =
1114 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1115 manifest_path.push(pkg);
1116 manifest_path.push("Cargo.toml");
1117 manifest_path
1118 });
1119
1120 let vendor = builder.ensure(Vendor {
1122 sync_args: pkgs_for_pgo_training.collect(),
1123 versioned_dirs: true,
1124 root_dir: plain_dst_src.into(),
1125 output_dir: VENDOR_DIR.into(),
1126 });
1127
1128 let cargo_config_dir = plain_dst_src.join(".cargo");
1129 builder.create_dir(&cargo_config_dir);
1130 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1131 }
1132
1133 for entry in walkdir::WalkDir::new(tarball.image_dir())
1137 .follow_links(true)
1138 .into_iter()
1139 .filter_map(|e| e.ok())
1140 {
1141 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1142 {
1143 t!(fs::remove_dir_all(entry.path()));
1144 }
1145 }
1146
1147 tarball.bare()
1148 }
1149}
1150
1151#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1152pub struct Cargo {
1153 pub compiler: Compiler,
1154 pub target: TargetSelection,
1155}
1156
1157impl Step for Cargo {
1158 type Output = Option<GeneratedTarball>;
1159 const DEFAULT: bool = true;
1160 const ONLY_HOSTS: bool = true;
1161
1162 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1163 let default = should_build_extended_tool(run.builder, "cargo");
1164 run.alias("cargo").default_condition(default)
1165 }
1166
1167 fn make_run(run: RunConfig<'_>) {
1168 run.builder.ensure(Cargo {
1169 compiler: run.builder.compiler_for(
1170 run.builder.top_stage,
1171 run.builder.config.host_target,
1172 run.target,
1173 ),
1174 target: run.target,
1175 });
1176 }
1177
1178 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1179 let compiler = self.compiler;
1180 let target = self.target;
1181
1182 builder.ensure(compile::Rustc::new(compiler, target));
1183
1184 let cargo = builder.ensure(tool::Cargo { compiler, target });
1185 let src = builder.src.join("src/tools/cargo");
1186 let etc = src.join("src/etc");
1187
1188 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1190 tarball.set_overlay(OverlayKind::Cargo);
1191
1192 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1193 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1194 tarball.add_renamed_file(
1195 etc.join("cargo.bashcomp.sh"),
1196 "etc/bash_completion.d",
1197 "cargo",
1198 FileType::Regular,
1199 );
1200 tarball.add_dir(etc.join("man"), "share/man/man1");
1201 tarball.add_legal_and_readme_to("share/doc/cargo");
1202
1203 Some(tarball.generate())
1204 }
1205}
1206
1207#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1208pub struct RustAnalyzer {
1209 pub compiler: Compiler,
1210 pub target: TargetSelection,
1211}
1212
1213impl Step for RustAnalyzer {
1214 type Output = Option<GeneratedTarball>;
1215 const DEFAULT: bool = true;
1216 const ONLY_HOSTS: bool = true;
1217
1218 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1219 let default = should_build_extended_tool(run.builder, "rust-analyzer");
1220 run.alias("rust-analyzer").default_condition(default)
1221 }
1222
1223 fn make_run(run: RunConfig<'_>) {
1224 run.builder.ensure(RustAnalyzer {
1225 compiler: run.builder.compiler_for(
1226 run.builder.top_stage,
1227 run.builder.config.host_target,
1228 run.target,
1229 ),
1230 target: run.target,
1231 });
1232 }
1233
1234 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1235 let compiler = self.compiler;
1236 let target = self.target;
1237
1238 builder.ensure(compile::Rustc::new(compiler, target));
1239
1240 let rust_analyzer = builder.ensure(tool::RustAnalyzer { compiler, target });
1241
1242 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1243 tarball.set_overlay(OverlayKind::RustAnalyzer);
1244 tarball.is_preview(true);
1245 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1246 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1247 Some(tarball.generate())
1248 }
1249}
1250
1251#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1252pub struct Clippy {
1253 pub compiler: Compiler,
1254 pub target: TargetSelection,
1255}
1256
1257impl Step for Clippy {
1258 type Output = Option<GeneratedTarball>;
1259 const DEFAULT: bool = true;
1260 const ONLY_HOSTS: bool = true;
1261
1262 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1263 let default = should_build_extended_tool(run.builder, "clippy");
1264 run.alias("clippy").default_condition(default)
1265 }
1266
1267 fn make_run(run: RunConfig<'_>) {
1268 run.builder.ensure(Clippy {
1269 compiler: run.builder.compiler_for(
1270 run.builder.top_stage,
1271 run.builder.config.host_target,
1272 run.target,
1273 ),
1274 target: run.target,
1275 });
1276 }
1277
1278 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1279 let compiler = self.compiler;
1280 let target = self.target;
1281
1282 builder.ensure(compile::Rustc::new(compiler, target));
1283
1284 let clippy = builder.ensure(tool::Clippy { compiler, target });
1288 let cargoclippy = builder.ensure(tool::CargoClippy { compiler, target });
1289
1290 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1291 tarball.set_overlay(OverlayKind::Clippy);
1292 tarball.is_preview(true);
1293 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1294 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1295 tarball.add_legal_and_readme_to("share/doc/clippy");
1296 Some(tarball.generate())
1297 }
1298}
1299
1300#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1301pub struct Miri {
1302 pub compiler: Compiler,
1303 pub target: TargetSelection,
1304}
1305
1306impl Step for Miri {
1307 type Output = Option<GeneratedTarball>;
1308 const DEFAULT: bool = true;
1309 const ONLY_HOSTS: bool = true;
1310
1311 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1312 let default = should_build_extended_tool(run.builder, "miri");
1313 run.alias("miri").default_condition(default)
1314 }
1315
1316 fn make_run(run: RunConfig<'_>) {
1317 run.builder.ensure(Miri {
1318 compiler: run.builder.compiler_for(
1319 run.builder.top_stage,
1320 run.builder.config.host_target,
1321 run.target,
1322 ),
1323 target: run.target,
1324 });
1325 }
1326
1327 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1328 if !builder.build.unstable_features() {
1332 return None;
1333 }
1334
1335 let compiler = self.compiler;
1336 let target = self.target;
1337
1338 builder.ensure(compile::Rustc::new(compiler, target));
1339
1340 let miri = builder.ensure(tool::Miri { compiler, target });
1341 let cargomiri = builder.ensure(tool::CargoMiri { compiler, target });
1342
1343 let mut tarball = Tarball::new(builder, "miri", &target.triple);
1344 tarball.set_overlay(OverlayKind::Miri);
1345 tarball.is_preview(true);
1346 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1347 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1348 tarball.add_legal_and_readme_to("share/doc/miri");
1349 Some(tarball.generate())
1350 }
1351}
1352
1353#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1354pub struct CodegenBackend {
1355 pub compiler: Compiler,
1356 pub backend: String,
1357}
1358
1359impl Step for CodegenBackend {
1360 type Output = Option<GeneratedTarball>;
1361 const DEFAULT: bool = true;
1362 const ONLY_HOSTS: bool = true;
1363
1364 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1365 run.path("compiler/rustc_codegen_cranelift")
1366 }
1367
1368 fn make_run(run: RunConfig<'_>) {
1369 for backend in run.builder.config.codegen_backends(run.target) {
1370 if backend == "llvm" {
1371 continue; }
1373
1374 run.builder.ensure(CodegenBackend {
1375 compiler: run.builder.compiler(run.builder.top_stage, run.target),
1376 backend: backend.clone(),
1377 });
1378 }
1379 }
1380
1381 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1382 if builder.config.dry_run() {
1383 return None;
1384 }
1385
1386 if !builder.build.unstable_features() {
1390 return None;
1391 }
1392
1393 if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend.to_string())
1394 {
1395 return None;
1396 }
1397
1398 if self.backend == "cranelift" && !target_supports_cranelift_backend(self.compiler.host) {
1399 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1400 return None;
1401 }
1402
1403 let compiler = self.compiler;
1404 let backend = self.backend;
1405
1406 let mut tarball =
1407 Tarball::new(builder, &format!("rustc-codegen-{backend}"), &compiler.host.triple);
1408 if backend == "cranelift" {
1409 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1410 } else {
1411 panic!("Unknown backend rustc_codegen_{backend}");
1412 }
1413 tarball.is_preview(true);
1414 tarball.add_legal_and_readme_to(format!("share/doc/rustc_codegen_{backend}"));
1415
1416 let src = builder.sysroot(compiler);
1417 let backends_src = builder.sysroot_codegen_backends(compiler);
1418 let backends_rel = backends_src
1419 .strip_prefix(src)
1420 .unwrap()
1421 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1422 .unwrap();
1423 let backends_dst = PathBuf::from("lib").join(backends_rel);
1425
1426 let backend_name = format!("rustc_codegen_{backend}");
1427 let mut found_backend = false;
1428 for backend in fs::read_dir(&backends_src).unwrap() {
1429 let file_name = backend.unwrap().file_name();
1430 if file_name.to_str().unwrap().contains(&backend_name) {
1431 tarball.add_file(
1432 backends_src.join(file_name),
1433 &backends_dst,
1434 FileType::NativeLibrary,
1435 );
1436 found_backend = true;
1437 }
1438 }
1439 assert!(found_backend);
1440
1441 Some(tarball.generate())
1442 }
1443}
1444
1445#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1446pub struct Rustfmt {
1447 pub compiler: Compiler,
1448 pub target: TargetSelection,
1449}
1450
1451impl Step for Rustfmt {
1452 type Output = Option<GeneratedTarball>;
1453 const DEFAULT: bool = true;
1454 const ONLY_HOSTS: bool = true;
1455
1456 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1457 let default = should_build_extended_tool(run.builder, "rustfmt");
1458 run.alias("rustfmt").default_condition(default)
1459 }
1460
1461 fn make_run(run: RunConfig<'_>) {
1462 run.builder.ensure(Rustfmt {
1463 compiler: run.builder.compiler_for(
1464 run.builder.top_stage,
1465 run.builder.config.host_target,
1466 run.target,
1467 ),
1468 target: run.target,
1469 });
1470 }
1471
1472 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1473 let compiler = self.compiler;
1474 let target = self.target;
1475
1476 builder.ensure(compile::Rustc::new(compiler, target));
1477
1478 let rustfmt = builder.ensure(tool::Rustfmt { compiler, target });
1479 let cargofmt = builder.ensure(tool::Cargofmt { compiler, target });
1480 let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
1481 tarball.set_overlay(OverlayKind::Rustfmt);
1482 tarball.is_preview(true);
1483 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1484 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1485 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1486 Some(tarball.generate())
1487 }
1488}
1489
1490#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1491pub struct Extended {
1492 stage: u32,
1493 host: TargetSelection,
1494 target: TargetSelection,
1495}
1496
1497impl Step for Extended {
1498 type Output = ();
1499 const DEFAULT: bool = true;
1500 const ONLY_HOSTS: bool = true;
1501
1502 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1503 let builder = run.builder;
1504 run.alias("extended").default_condition(builder.config.extended)
1505 }
1506
1507 fn make_run(run: RunConfig<'_>) {
1508 run.builder.ensure(Extended {
1509 stage: run.builder.top_stage,
1510 host: run.builder.config.host_target,
1511 target: run.target,
1512 });
1513 }
1514
1515 fn run(self, builder: &Builder<'_>) {
1517 let target = self.target;
1518 let stage = self.stage;
1519 let compiler = builder.compiler_for(self.stage, self.host, self.target);
1520
1521 builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1522
1523 let mut tarballs = Vec::new();
1524 let mut built_tools = HashSet::new();
1525 macro_rules! add_component {
1526 ($name:expr => $step:expr) => {
1527 if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) {
1528 tarballs.push(tarball);
1529 built_tools.insert($name);
1530 }
1531 };
1532 }
1533
1534 tarballs.push(builder.ensure(Rustc { compiler: builder.compiler(stage, target) }));
1539 tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
1540
1541 if target.is_windows_gnu() {
1542 tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
1543 }
1544
1545 add_component!("rust-docs" => Docs { host: target });
1546 add_component!("rust-json-docs" => JsonDocs { host: target });
1547 add_component!("cargo" => Cargo { compiler, target });
1548 add_component!("rustfmt" => Rustfmt { compiler, target });
1549 add_component!("rust-analyzer" => RustAnalyzer { compiler, target });
1550 add_component!("llvm-components" => LlvmTools { target });
1551 add_component!("clippy" => Clippy { compiler, target });
1552 add_component!("miri" => Miri { compiler, target });
1553 add_component!("analysis" => Analysis { compiler, target });
1554 add_component!("rustc-codegen-cranelift" => CodegenBackend {
1555 compiler: builder.compiler(stage, target),
1556 backend: "cranelift".to_string(),
1557 });
1558 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {compiler, target});
1559
1560 let etc = builder.src.join("src/etc/installer");
1561
1562 if builder.config.dry_run() {
1564 return;
1565 }
1566
1567 let tarball = Tarball::new(builder, "rust", &target.triple);
1568 let generated = tarball.combine(&tarballs);
1569
1570 let tmp = tmpdir(builder).join("combined-tarball");
1571 let work = generated.work_dir();
1572
1573 let mut license = String::new();
1574 license += &builder.read(&builder.src.join("COPYRIGHT"));
1575 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1576 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1577 license.push('\n');
1578 license.push('\n');
1579
1580 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1581 let mut rtf = rtf.to_string();
1582 rtf.push('\n');
1583 for line in license.lines() {
1584 rtf.push_str(line);
1585 rtf.push_str("\\line ");
1586 }
1587 rtf.push('}');
1588
1589 fn filter(contents: &str, marker: &str) -> String {
1590 let start = format!("tool-{marker}-start");
1591 let end = format!("tool-{marker}-end");
1592 let mut lines = Vec::new();
1593 let mut omitted = false;
1594 for line in contents.lines() {
1595 if line.contains(&start) {
1596 omitted = true;
1597 } else if line.contains(&end) {
1598 omitted = false;
1599 } else if !omitted {
1600 lines.push(line);
1601 }
1602 }
1603
1604 lines.join("\n")
1605 }
1606
1607 let xform = |p: &Path| {
1608 let mut contents = t!(fs::read_to_string(p));
1609 for tool in &["miri", "rust-docs"] {
1610 if !built_tools.contains(tool) {
1611 contents = filter(&contents, tool);
1612 }
1613 }
1614 let ret = tmp.join(p.file_name().unwrap());
1615 t!(fs::write(&ret, &contents));
1616 ret
1617 };
1618
1619 if target.contains("apple-darwin") {
1620 builder.info("building pkg installer");
1621 let pkg = tmp.join("pkg");
1622 let _ = fs::remove_dir_all(&pkg);
1623
1624 let pkgbuild = |component: &str| {
1625 let mut cmd = command("pkgbuild");
1626 cmd.arg("--identifier")
1627 .arg(format!("org.rust-lang.{component}"))
1628 .arg("--scripts")
1629 .arg(pkg.join(component))
1630 .arg("--nopayload")
1631 .arg(pkg.join(component).with_extension("pkg"));
1632 cmd.run(builder);
1633 };
1634
1635 let prepare = |name: &str| {
1636 builder.create_dir(&pkg.join(name));
1637 builder.cp_link_r(
1638 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1639 &pkg.join(name),
1640 );
1641 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1642 pkgbuild(name);
1643 };
1644 prepare("rustc");
1645 prepare("cargo");
1646 prepare("rust-std");
1647 prepare("rust-analysis");
1648
1649 for tool in &[
1650 "clippy",
1651 "rustfmt",
1652 "rust-analyzer",
1653 "rust-docs",
1654 "miri",
1655 "rustc-codegen-cranelift",
1656 ] {
1657 if built_tools.contains(tool) {
1658 prepare(tool);
1659 }
1660 }
1661 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1663 pkgbuild("uninstall");
1664
1665 builder.create_dir(&pkg.join("res"));
1666 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1667 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1668 let mut cmd = command("productbuild");
1669 cmd.arg("--distribution")
1670 .arg(xform(&etc.join("pkg/Distribution.xml")))
1671 .arg("--resources")
1672 .arg(pkg.join("res"))
1673 .arg(distdir(builder).join(format!(
1674 "{}-{}.pkg",
1675 pkgname(builder, "rust"),
1676 target.triple
1677 )))
1678 .arg("--package-path")
1679 .arg(&pkg);
1680 let _time = timeit(builder);
1681 cmd.run(builder);
1682 }
1683
1684 if target.is_windows() && !target.contains("gnullvm") {
1686 let exe = tmp.join("exe");
1687 let _ = fs::remove_dir_all(&exe);
1688
1689 let prepare = |name: &str| {
1690 builder.create_dir(&exe.join(name));
1691 let dir = if name == "rust-std" || name == "rust-analysis" {
1692 format!("{}-{}", name, target.triple)
1693 } else if name == "rust-analyzer" {
1694 "rust-analyzer-preview".to_string()
1695 } else if name == "clippy" {
1696 "clippy-preview".to_string()
1697 } else if name == "rustfmt" {
1698 "rustfmt-preview".to_string()
1699 } else if name == "miri" {
1700 "miri-preview".to_string()
1701 } else if name == "rustc-codegen-cranelift" {
1702 unreachable!("cg_clif shouldn't be built for windows");
1705 } else {
1706 name.to_string()
1707 };
1708 builder.cp_link_r(
1709 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1710 &exe.join(name),
1711 );
1712 builder.remove(&exe.join(name).join("manifest.in"));
1713 };
1714 prepare("rustc");
1715 prepare("cargo");
1716 prepare("rust-analysis");
1717 prepare("rust-std");
1718 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1719 if built_tools.contains(tool) {
1720 prepare(tool);
1721 }
1722 }
1723 if target.is_windows_gnu() {
1724 prepare("rust-mingw");
1725 }
1726
1727 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1728
1729 let wix_path = env::var_os("WIX")
1731 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1732 let wix = PathBuf::from(wix_path);
1733 let heat = wix.join("bin/heat.exe");
1734 let candle = wix.join("bin/candle.exe");
1735 let light = wix.join("bin/light.exe");
1736
1737 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1738 command(&heat)
1739 .current_dir(&exe)
1740 .arg("dir")
1741 .arg("rustc")
1742 .args(heat_flags)
1743 .arg("-cg")
1744 .arg("RustcGroup")
1745 .arg("-dr")
1746 .arg("Rustc")
1747 .arg("-var")
1748 .arg("var.RustcDir")
1749 .arg("-out")
1750 .arg(exe.join("RustcGroup.wxs"))
1751 .run(builder);
1752 if built_tools.contains("rust-docs") {
1753 command(&heat)
1754 .current_dir(&exe)
1755 .arg("dir")
1756 .arg("rust-docs")
1757 .args(heat_flags)
1758 .arg("-cg")
1759 .arg("DocsGroup")
1760 .arg("-dr")
1761 .arg("Docs")
1762 .arg("-var")
1763 .arg("var.DocsDir")
1764 .arg("-out")
1765 .arg(exe.join("DocsGroup.wxs"))
1766 .arg("-t")
1767 .arg(etc.join("msi/squash-components.xsl"))
1768 .run(builder);
1769 }
1770 command(&heat)
1771 .current_dir(&exe)
1772 .arg("dir")
1773 .arg("cargo")
1774 .args(heat_flags)
1775 .arg("-cg")
1776 .arg("CargoGroup")
1777 .arg("-dr")
1778 .arg("Cargo")
1779 .arg("-var")
1780 .arg("var.CargoDir")
1781 .arg("-out")
1782 .arg(exe.join("CargoGroup.wxs"))
1783 .arg("-t")
1784 .arg(etc.join("msi/remove-duplicates.xsl"))
1785 .run(builder);
1786 command(&heat)
1787 .current_dir(&exe)
1788 .arg("dir")
1789 .arg("rust-std")
1790 .args(heat_flags)
1791 .arg("-cg")
1792 .arg("StdGroup")
1793 .arg("-dr")
1794 .arg("Std")
1795 .arg("-var")
1796 .arg("var.StdDir")
1797 .arg("-out")
1798 .arg(exe.join("StdGroup.wxs"))
1799 .run(builder);
1800 if built_tools.contains("rust-analyzer") {
1801 command(&heat)
1802 .current_dir(&exe)
1803 .arg("dir")
1804 .arg("rust-analyzer")
1805 .args(heat_flags)
1806 .arg("-cg")
1807 .arg("RustAnalyzerGroup")
1808 .arg("-dr")
1809 .arg("RustAnalyzer")
1810 .arg("-var")
1811 .arg("var.RustAnalyzerDir")
1812 .arg("-out")
1813 .arg(exe.join("RustAnalyzerGroup.wxs"))
1814 .arg("-t")
1815 .arg(etc.join("msi/remove-duplicates.xsl"))
1816 .run(builder);
1817 }
1818 if built_tools.contains("clippy") {
1819 command(&heat)
1820 .current_dir(&exe)
1821 .arg("dir")
1822 .arg("clippy")
1823 .args(heat_flags)
1824 .arg("-cg")
1825 .arg("ClippyGroup")
1826 .arg("-dr")
1827 .arg("Clippy")
1828 .arg("-var")
1829 .arg("var.ClippyDir")
1830 .arg("-out")
1831 .arg(exe.join("ClippyGroup.wxs"))
1832 .arg("-t")
1833 .arg(etc.join("msi/remove-duplicates.xsl"))
1834 .run(builder);
1835 }
1836 if built_tools.contains("rustfmt") {
1837 command(&heat)
1838 .current_dir(&exe)
1839 .arg("dir")
1840 .arg("rustfmt")
1841 .args(heat_flags)
1842 .arg("-cg")
1843 .arg("RustFmtGroup")
1844 .arg("-dr")
1845 .arg("RustFmt")
1846 .arg("-var")
1847 .arg("var.RustFmtDir")
1848 .arg("-out")
1849 .arg(exe.join("RustFmtGroup.wxs"))
1850 .arg("-t")
1851 .arg(etc.join("msi/remove-duplicates.xsl"))
1852 .run(builder);
1853 }
1854 if built_tools.contains("miri") {
1855 command(&heat)
1856 .current_dir(&exe)
1857 .arg("dir")
1858 .arg("miri")
1859 .args(heat_flags)
1860 .arg("-cg")
1861 .arg("MiriGroup")
1862 .arg("-dr")
1863 .arg("Miri")
1864 .arg("-var")
1865 .arg("var.MiriDir")
1866 .arg("-out")
1867 .arg(exe.join("MiriGroup.wxs"))
1868 .arg("-t")
1869 .arg(etc.join("msi/remove-duplicates.xsl"))
1870 .run(builder);
1871 }
1872 command(&heat)
1873 .current_dir(&exe)
1874 .arg("dir")
1875 .arg("rust-analysis")
1876 .args(heat_flags)
1877 .arg("-cg")
1878 .arg("AnalysisGroup")
1879 .arg("-dr")
1880 .arg("Analysis")
1881 .arg("-var")
1882 .arg("var.AnalysisDir")
1883 .arg("-out")
1884 .arg(exe.join("AnalysisGroup.wxs"))
1885 .arg("-t")
1886 .arg(etc.join("msi/remove-duplicates.xsl"))
1887 .run(builder);
1888 if target.is_windows_gnu() {
1889 command(&heat)
1890 .current_dir(&exe)
1891 .arg("dir")
1892 .arg("rust-mingw")
1893 .args(heat_flags)
1894 .arg("-cg")
1895 .arg("GccGroup")
1896 .arg("-dr")
1897 .arg("Gcc")
1898 .arg("-var")
1899 .arg("var.GccDir")
1900 .arg("-out")
1901 .arg(exe.join("GccGroup.wxs"))
1902 .run(builder);
1903 }
1904
1905 let candle = |input: &Path| {
1906 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1907 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1908 let mut cmd = command(&candle);
1909 cmd.current_dir(&exe)
1910 .arg("-nologo")
1911 .arg("-dRustcDir=rustc")
1912 .arg("-dCargoDir=cargo")
1913 .arg("-dStdDir=rust-std")
1914 .arg("-dAnalysisDir=rust-analysis")
1915 .arg("-arch")
1916 .arg(arch)
1917 .arg("-out")
1918 .arg(&output)
1919 .arg(input);
1920 add_env(builder, &mut cmd, target, &built_tools);
1921
1922 if built_tools.contains("clippy") {
1923 cmd.arg("-dClippyDir=clippy");
1924 }
1925 if built_tools.contains("rustfmt") {
1926 cmd.arg("-dRustFmtDir=rustfmt");
1927 }
1928 if built_tools.contains("rust-docs") {
1929 cmd.arg("-dDocsDir=rust-docs");
1930 }
1931 if built_tools.contains("rust-analyzer") {
1932 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1933 }
1934 if built_tools.contains("miri") {
1935 cmd.arg("-dMiriDir=miri");
1936 }
1937 if target.is_windows_gnu() {
1938 cmd.arg("-dGccDir=rust-mingw");
1939 }
1940 cmd.run(builder);
1941 };
1942 candle(&xform(&etc.join("msi/rust.wxs")));
1943 candle(&etc.join("msi/ui.wxs"));
1944 candle(&etc.join("msi/rustwelcomedlg.wxs"));
1945 candle("RustcGroup.wxs".as_ref());
1946 if built_tools.contains("rust-docs") {
1947 candle("DocsGroup.wxs".as_ref());
1948 }
1949 candle("CargoGroup.wxs".as_ref());
1950 candle("StdGroup.wxs".as_ref());
1951 if built_tools.contains("clippy") {
1952 candle("ClippyGroup.wxs".as_ref());
1953 }
1954 if built_tools.contains("rustfmt") {
1955 candle("RustFmtGroup.wxs".as_ref());
1956 }
1957 if built_tools.contains("miri") {
1958 candle("MiriGroup.wxs".as_ref());
1959 }
1960 if built_tools.contains("rust-analyzer") {
1961 candle("RustAnalyzerGroup.wxs".as_ref());
1962 }
1963 candle("AnalysisGroup.wxs".as_ref());
1964
1965 if target.is_windows_gnu() {
1966 candle("GccGroup.wxs".as_ref());
1967 }
1968
1969 builder.create(&exe.join("LICENSE.rtf"), &rtf);
1970 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
1971 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
1972
1973 builder.info(&format!("building `msi` installer with {light:?}"));
1974 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1975 let mut cmd = command(&light);
1976 cmd.arg("-nologo")
1977 .arg("-ext")
1978 .arg("WixUIExtension")
1979 .arg("-ext")
1980 .arg("WixUtilExtension")
1981 .arg("-out")
1982 .arg(exe.join(&filename))
1983 .arg("rust.wixobj")
1984 .arg("ui.wixobj")
1985 .arg("rustwelcomedlg.wixobj")
1986 .arg("RustcGroup.wixobj")
1987 .arg("CargoGroup.wixobj")
1988 .arg("StdGroup.wixobj")
1989 .arg("AnalysisGroup.wixobj")
1990 .current_dir(&exe);
1991
1992 if built_tools.contains("clippy") {
1993 cmd.arg("ClippyGroup.wixobj");
1994 }
1995 if built_tools.contains("rustfmt") {
1996 cmd.arg("RustFmtGroup.wixobj");
1997 }
1998 if built_tools.contains("miri") {
1999 cmd.arg("MiriGroup.wixobj");
2000 }
2001 if built_tools.contains("rust-analyzer") {
2002 cmd.arg("RustAnalyzerGroup.wixobj");
2003 }
2004 if built_tools.contains("rust-docs") {
2005 cmd.arg("DocsGroup.wixobj");
2006 }
2007
2008 if target.is_windows_gnu() {
2009 cmd.arg("GccGroup.wixobj");
2010 }
2011 cmd.arg("-sice:ICE57");
2013
2014 let _time = timeit(builder);
2015 cmd.run(builder);
2016
2017 if !builder.config.dry_run() {
2018 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2019 }
2020 }
2021 }
2022}
2023
2024fn add_env(
2025 builder: &Builder<'_>,
2026 cmd: &mut BootstrapCommand,
2027 target: TargetSelection,
2028 built_tools: &HashSet<&'static str>,
2029) {
2030 let mut parts = builder.version.split('.');
2031 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2032 .env("CFG_RELEASE_NUM", &builder.version)
2033 .env("CFG_RELEASE", builder.rust_release())
2034 .env("CFG_VER_MAJOR", parts.next().unwrap())
2035 .env("CFG_VER_MINOR", parts.next().unwrap())
2036 .env("CFG_VER_PATCH", parts.next().unwrap())
2037 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2039 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2040 .env("CFG_BUILD", target.triple)
2041 .env("CFG_CHANNEL", &builder.config.channel);
2042
2043 if target.contains("windows-gnullvm") {
2044 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2045 } else if target.is_windows_gnu() {
2046 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2047 } else {
2048 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2049 }
2050
2051 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2053 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2054 };
2055 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2056 define_optional_tool("clippy", "CFG_CLIPPY");
2057 define_optional_tool("miri", "CFG_MIRI");
2058 define_optional_tool("rust-analyzer", "CFG_RA");
2059}
2060
2061fn install_llvm_file(
2062 builder: &Builder<'_>,
2063 source: &Path,
2064 destination: &Path,
2065 install_symlink: bool,
2066) {
2067 if builder.config.dry_run() {
2068 return;
2069 }
2070
2071 if source.is_symlink() {
2072 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2075
2076 let full_dest = destination.join(source.file_name().unwrap());
2077 if install_symlink {
2078 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2081 } else {
2082 let link = t!(fs::read_link(source));
2086 let mut linker_script = t!(fs::File::create(full_dest));
2087 t!(write!(linker_script, "INPUT({})\n", link.display()));
2088
2089 let meta = t!(fs::metadata(source));
2092 if let Ok(mtime) = meta.modified() {
2093 t!(linker_script.set_modified(mtime));
2094 }
2095 }
2096 } else {
2097 builder.install(source, destination, FileType::NativeLibrary);
2098 }
2099}
2100
2101#[cfg_attr(
2105 feature = "tracing",
2106 instrument(
2107 level = "trace",
2108 name = "maybe_install_llvm",
2109 skip_all,
2110 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2111 ),
2112)]
2113fn maybe_install_llvm(
2114 builder: &Builder<'_>,
2115 target: TargetSelection,
2116 dst_libdir: &Path,
2117 install_symlink: bool,
2118) -> bool {
2119 if builder.config.is_system_llvm(target) {
2136 trace!("system LLVM requested, no install");
2137 return false;
2138 }
2139
2140 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2146 let src_libdir = builder.llvm_out(target).join("lib");
2147 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2148 if llvm_dylib_path.exists() {
2149 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2150 }
2151 !builder.config.dry_run()
2152 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
2153 llvm::prebuilt_llvm_config(builder, target, true)
2154 {
2155 trace!("LLVM already built, installing LLVM files");
2156 let mut cmd = command(llvm_config);
2157 cmd.arg("--libfiles");
2158 builder.verbose(|| println!("running {cmd:?}"));
2159 let files = cmd.run_capture_stdout(builder).stdout();
2160 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2161 let target_llvm_out = &builder.llvm_out(target);
2162 for file in files.trim_end().split(' ') {
2163 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2165 target_llvm_out.join(relative_path)
2166 } else {
2167 PathBuf::from(file)
2168 };
2169 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2170 }
2171 !builder.config.dry_run()
2172 } else {
2173 false
2174 }
2175}
2176
2177#[cfg_attr(
2179 feature = "tracing",
2180 instrument(
2181 level = "trace",
2182 name = "maybe_install_llvm_target",
2183 skip_all,
2184 fields(
2185 llvm_link_shared = ?builder.llvm_link_shared(),
2186 target = ?target,
2187 sysroot = ?sysroot,
2188 ),
2189 ),
2190)]
2191pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2192 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2193 if builder.llvm_link_shared() {
2197 maybe_install_llvm(builder, target, &dst_libdir, false);
2198 }
2199}
2200
2201#[cfg_attr(
2203 feature = "tracing",
2204 instrument(
2205 level = "trace",
2206 name = "maybe_install_llvm_runtime",
2207 skip_all,
2208 fields(
2209 llvm_link_shared = ?builder.llvm_link_shared(),
2210 target = ?target,
2211 sysroot = ?sysroot,
2212 ),
2213 ),
2214)]
2215pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2216 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2217 if builder.llvm_link_shared() {
2221 maybe_install_llvm(builder, target, &dst_libdir, false);
2222 }
2223}
2224
2225#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2226pub struct LlvmTools {
2227 pub target: TargetSelection,
2228}
2229
2230impl Step for LlvmTools {
2231 type Output = Option<GeneratedTarball>;
2232 const ONLY_HOSTS: bool = true;
2233 const DEFAULT: bool = true;
2234
2235 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2236 let default = should_build_extended_tool(run.builder, "llvm-tools");
2237
2238 let mut run = run.alias("llvm-tools");
2239 for tool in LLVM_TOOLS {
2240 run = run.alias(tool);
2241 }
2242
2243 run.default_condition(default)
2244 }
2245
2246 fn make_run(run: RunConfig<'_>) {
2247 run.builder.ensure(LlvmTools { target: run.target });
2248 }
2249
2250 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2251 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2252 let mut tools = vec![];
2253
2254 for path in paths {
2255 let path = path.to_str().unwrap();
2256
2257 if path == "llvm-tools" {
2259 return LLVM_TOOLS.to_owned();
2260 }
2261
2262 for tool in LLVM_TOOLS {
2263 if path == *tool {
2264 tools.push(*tool);
2265 }
2266 }
2267 }
2268
2269 if tools.is_empty() {
2271 tools = LLVM_TOOLS.to_owned();
2272 }
2273
2274 tools
2275 }
2276
2277 let target = self.target;
2278
2279 if let Some(config) = builder.config.target_config.get(&target)
2281 && !builder.config.llvm_from_ci
2282 && config.llvm_config.is_some()
2283 {
2284 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2285 return None;
2286 }
2287
2288 if !builder.config.dry_run() {
2289 builder.require_submodule("src/llvm-project", None);
2290 }
2291
2292 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2293
2294 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2295 tarball.set_overlay(OverlayKind::Llvm);
2296 tarball.is_preview(true);
2297
2298 if builder.config.llvm_tools_enabled {
2299 let src_bindir = builder.llvm_out(target).join("bin");
2301 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2302 for tool in tools_to_install(&builder.paths) {
2303 let exe = src_bindir.join(exe(tool, target));
2304 if !exe.exists() && builder.config.llvm_from_ci {
2306 eprintln!("{} does not exist; skipping copy", exe.display());
2307 continue;
2308 }
2309
2310 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2311 }
2312 }
2313
2314 maybe_install_llvm_target(builder, target, tarball.image_dir());
2319
2320 Some(tarball.generate())
2321 }
2322}
2323
2324#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
2325pub struct LlvmBitcodeLinker {
2326 pub compiler: Compiler,
2327 pub target: TargetSelection,
2328}
2329
2330impl Step for LlvmBitcodeLinker {
2331 type Output = Option<GeneratedTarball>;
2332 const DEFAULT: bool = true;
2333 const ONLY_HOSTS: bool = true;
2334
2335 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2336 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2337 run.alias("llvm-bitcode-linker").default_condition(default)
2338 }
2339
2340 fn make_run(run: RunConfig<'_>) {
2341 run.builder.ensure(LlvmBitcodeLinker {
2342 compiler: run.builder.compiler_for(
2343 run.builder.top_stage,
2344 run.builder.config.host_target,
2345 run.target,
2346 ),
2347 target: run.target,
2348 });
2349 }
2350
2351 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2352 let compiler = self.compiler;
2353 let target = self.target;
2354
2355 builder.ensure(compile::Rustc::new(compiler, target));
2356
2357 let llbc_linker =
2358 builder.ensure(tool::LlvmBitcodeLinker { compiler, target, extra_features: vec![] });
2359
2360 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2361
2362 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2364 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2365 tarball.is_preview(true);
2366
2367 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2368
2369 Some(tarball.generate())
2370 }
2371}
2372
2373#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2382pub struct RustDev {
2383 pub target: TargetSelection,
2384}
2385
2386impl Step for RustDev {
2387 type Output = Option<GeneratedTarball>;
2388 const DEFAULT: bool = true;
2389 const ONLY_HOSTS: bool = true;
2390
2391 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2392 run.alias("rust-dev")
2393 }
2394
2395 fn make_run(run: RunConfig<'_>) {
2396 run.builder.ensure(RustDev { target: run.target });
2397 }
2398
2399 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2400 let target = self.target;
2401
2402 if let Some(config) = builder.config.target_config.get(&target)
2404 && let Some(ref _s) = config.llvm_config
2405 {
2406 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2407 return None;
2408 }
2409
2410 if !builder.config.dry_run() {
2411 builder.require_submodule("src/llvm-project", None);
2412 }
2413
2414 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2415 tarball.set_overlay(OverlayKind::Llvm);
2416 tarball.permit_symlinks(true);
2418
2419 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2420
2421 let src_bindir = builder.llvm_out(target).join("bin");
2422 if src_bindir.exists() {
2428 for entry in walkdir::WalkDir::new(&src_bindir) {
2429 let entry = t!(entry);
2430 if entry.file_type().is_file() && !entry.path_is_symlink() {
2431 let name = entry.file_name().to_str().unwrap();
2432 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2433 }
2434 }
2435 }
2436
2437 if builder.config.lld_enabled {
2438 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2440
2441 let lld_path = lld_out.join("bin").join(exe("lld", target));
2443 if lld_path.exists() {
2444 tarball.add_file(&lld_path, "bin", FileType::Executable);
2445 }
2446 }
2447
2448 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2449
2450 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2454
2455 let dst_libdir = tarball.image_dir().join("lib");
2460 maybe_install_llvm(builder, target, &dst_libdir, true);
2461 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2462 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2463
2464 copy_src_dirs(
2468 builder,
2469 &builder.src.join("src").join("llvm-project"),
2470 &["compiler-rt"],
2471 &["compiler-rt/test"],
2474 tarball.image_dir(),
2475 );
2476
2477 Some(tarball.generate())
2478 }
2479}
2480
2481#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2485pub struct Bootstrap {
2486 pub target: TargetSelection,
2487}
2488
2489impl Step for Bootstrap {
2490 type Output = Option<GeneratedTarball>;
2491 const DEFAULT: bool = false;
2492 const ONLY_HOSTS: bool = true;
2493
2494 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2495 run.alias("bootstrap")
2496 }
2497
2498 fn make_run(run: RunConfig<'_>) {
2499 run.builder.ensure(Bootstrap { target: run.target });
2500 }
2501
2502 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2503 let target = self.target;
2504
2505 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2506
2507 let bootstrap_outdir = &builder.bootstrap_out;
2508 for file in &["bootstrap", "rustc", "rustdoc"] {
2509 tarball.add_file(
2510 bootstrap_outdir.join(exe(file, target)),
2511 "bootstrap/bin",
2512 FileType::Executable,
2513 );
2514 }
2515
2516 Some(tarball.generate())
2517 }
2518}
2519
2520#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2525pub struct BuildManifest {
2526 pub target: TargetSelection,
2527}
2528
2529impl Step for BuildManifest {
2530 type Output = GeneratedTarball;
2531 const DEFAULT: bool = false;
2532 const ONLY_HOSTS: bool = true;
2533
2534 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2535 run.alias("build-manifest")
2536 }
2537
2538 fn make_run(run: RunConfig<'_>) {
2539 run.builder.ensure(BuildManifest { target: run.target });
2540 }
2541
2542 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2543 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2544
2545 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2546 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2547 tarball.generate()
2548 }
2549}
2550
2551#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2557pub struct ReproducibleArtifacts {
2558 pub target: TargetSelection,
2559}
2560
2561impl Step for ReproducibleArtifacts {
2562 type Output = Option<GeneratedTarball>;
2563 const DEFAULT: bool = true;
2564 const ONLY_HOSTS: bool = true;
2565
2566 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2567 run.alias("reproducible-artifacts")
2568 }
2569
2570 fn make_run(run: RunConfig<'_>) {
2571 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2572 }
2573
2574 fn run(self, builder: &Builder<'_>) -> Self::Output {
2575 let mut added_anything = false;
2576 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2577 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2578 tarball.add_file(path, ".", FileType::Regular);
2579 added_anything = true;
2580 }
2581 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2582 tarball.add_file(path, ".", FileType::Regular);
2583 added_anything = true;
2584 }
2585 for profile in &builder.config.reproducible_artifacts {
2586 tarball.add_file(profile, ".", FileType::Regular);
2587 added_anything = true;
2588 }
2589 if added_anything { Some(tarball.generate()) } else { None }
2590 }
2591}
2592
2593#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2597pub struct Gcc {
2598 pub target: TargetSelection,
2599}
2600
2601impl Step for Gcc {
2602 type Output = GeneratedTarball;
2603
2604 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2605 run.alias("gcc")
2606 }
2607
2608 fn make_run(run: RunConfig<'_>) {
2609 run.builder.ensure(Gcc { target: run.target });
2610 }
2611
2612 fn run(self, builder: &Builder<'_>) -> Self::Output {
2613 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2614 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2615 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2616 tarball.generate()
2617 }
2618}