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