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", "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.build,
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.build,
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.build,
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.build,
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.build,
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.build,
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.build,
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() {
1685 let exe = tmp.join("exe");
1686 let _ = fs::remove_dir_all(&exe);
1687
1688 let prepare = |name: &str| {
1689 builder.create_dir(&exe.join(name));
1690 let dir = if name == "rust-std" || name == "rust-analysis" {
1691 format!("{}-{}", name, target.triple)
1692 } else if name == "rust-analyzer" {
1693 "rust-analyzer-preview".to_string()
1694 } else if name == "clippy" {
1695 "clippy-preview".to_string()
1696 } else if name == "rustfmt" {
1697 "rustfmt-preview".to_string()
1698 } else if name == "miri" {
1699 "miri-preview".to_string()
1700 } else if name == "rustc-codegen-cranelift" {
1701 unreachable!("cg_clif shouldn't be built for windows");
1704 } else {
1705 name.to_string()
1706 };
1707 builder.cp_link_r(
1708 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1709 &exe.join(name),
1710 );
1711 builder.remove(&exe.join(name).join("manifest.in"));
1712 };
1713 prepare("rustc");
1714 prepare("cargo");
1715 prepare("rust-analysis");
1716 prepare("rust-std");
1717 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1718 if built_tools.contains(tool) {
1719 prepare(tool);
1720 }
1721 }
1722 if target.is_windows_gnu() {
1723 prepare("rust-mingw");
1724 }
1725
1726 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1727
1728 let wix_path = env::var_os("WIX")
1730 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1731 let wix = PathBuf::from(wix_path);
1732 let heat = wix.join("bin/heat.exe");
1733 let candle = wix.join("bin/candle.exe");
1734 let light = wix.join("bin/light.exe");
1735
1736 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1737 command(&heat)
1738 .current_dir(&exe)
1739 .arg("dir")
1740 .arg("rustc")
1741 .args(heat_flags)
1742 .arg("-cg")
1743 .arg("RustcGroup")
1744 .arg("-dr")
1745 .arg("Rustc")
1746 .arg("-var")
1747 .arg("var.RustcDir")
1748 .arg("-out")
1749 .arg(exe.join("RustcGroup.wxs"))
1750 .run(builder);
1751 if built_tools.contains("rust-docs") {
1752 command(&heat)
1753 .current_dir(&exe)
1754 .arg("dir")
1755 .arg("rust-docs")
1756 .args(heat_flags)
1757 .arg("-cg")
1758 .arg("DocsGroup")
1759 .arg("-dr")
1760 .arg("Docs")
1761 .arg("-var")
1762 .arg("var.DocsDir")
1763 .arg("-out")
1764 .arg(exe.join("DocsGroup.wxs"))
1765 .arg("-t")
1766 .arg(etc.join("msi/squash-components.xsl"))
1767 .run(builder);
1768 }
1769 command(&heat)
1770 .current_dir(&exe)
1771 .arg("dir")
1772 .arg("cargo")
1773 .args(heat_flags)
1774 .arg("-cg")
1775 .arg("CargoGroup")
1776 .arg("-dr")
1777 .arg("Cargo")
1778 .arg("-var")
1779 .arg("var.CargoDir")
1780 .arg("-out")
1781 .arg(exe.join("CargoGroup.wxs"))
1782 .arg("-t")
1783 .arg(etc.join("msi/remove-duplicates.xsl"))
1784 .run(builder);
1785 command(&heat)
1786 .current_dir(&exe)
1787 .arg("dir")
1788 .arg("rust-std")
1789 .args(heat_flags)
1790 .arg("-cg")
1791 .arg("StdGroup")
1792 .arg("-dr")
1793 .arg("Std")
1794 .arg("-var")
1795 .arg("var.StdDir")
1796 .arg("-out")
1797 .arg(exe.join("StdGroup.wxs"))
1798 .run(builder);
1799 if built_tools.contains("rust-analyzer") {
1800 command(&heat)
1801 .current_dir(&exe)
1802 .arg("dir")
1803 .arg("rust-analyzer")
1804 .args(heat_flags)
1805 .arg("-cg")
1806 .arg("RustAnalyzerGroup")
1807 .arg("-dr")
1808 .arg("RustAnalyzer")
1809 .arg("-var")
1810 .arg("var.RustAnalyzerDir")
1811 .arg("-out")
1812 .arg(exe.join("RustAnalyzerGroup.wxs"))
1813 .arg("-t")
1814 .arg(etc.join("msi/remove-duplicates.xsl"))
1815 .run(builder);
1816 }
1817 if built_tools.contains("clippy") {
1818 command(&heat)
1819 .current_dir(&exe)
1820 .arg("dir")
1821 .arg("clippy")
1822 .args(heat_flags)
1823 .arg("-cg")
1824 .arg("ClippyGroup")
1825 .arg("-dr")
1826 .arg("Clippy")
1827 .arg("-var")
1828 .arg("var.ClippyDir")
1829 .arg("-out")
1830 .arg(exe.join("ClippyGroup.wxs"))
1831 .arg("-t")
1832 .arg(etc.join("msi/remove-duplicates.xsl"))
1833 .run(builder);
1834 }
1835 if built_tools.contains("rustfmt") {
1836 command(&heat)
1837 .current_dir(&exe)
1838 .arg("dir")
1839 .arg("rustfmt")
1840 .args(heat_flags)
1841 .arg("-cg")
1842 .arg("RustFmtGroup")
1843 .arg("-dr")
1844 .arg("RustFmt")
1845 .arg("-var")
1846 .arg("var.RustFmtDir")
1847 .arg("-out")
1848 .arg(exe.join("RustFmtGroup.wxs"))
1849 .arg("-t")
1850 .arg(etc.join("msi/remove-duplicates.xsl"))
1851 .run(builder);
1852 }
1853 if built_tools.contains("miri") {
1854 command(&heat)
1855 .current_dir(&exe)
1856 .arg("dir")
1857 .arg("miri")
1858 .args(heat_flags)
1859 .arg("-cg")
1860 .arg("MiriGroup")
1861 .arg("-dr")
1862 .arg("Miri")
1863 .arg("-var")
1864 .arg("var.MiriDir")
1865 .arg("-out")
1866 .arg(exe.join("MiriGroup.wxs"))
1867 .arg("-t")
1868 .arg(etc.join("msi/remove-duplicates.xsl"))
1869 .run(builder);
1870 }
1871 command(&heat)
1872 .current_dir(&exe)
1873 .arg("dir")
1874 .arg("rust-analysis")
1875 .args(heat_flags)
1876 .arg("-cg")
1877 .arg("AnalysisGroup")
1878 .arg("-dr")
1879 .arg("Analysis")
1880 .arg("-var")
1881 .arg("var.AnalysisDir")
1882 .arg("-out")
1883 .arg(exe.join("AnalysisGroup.wxs"))
1884 .arg("-t")
1885 .arg(etc.join("msi/remove-duplicates.xsl"))
1886 .run(builder);
1887 if target.is_windows_gnu() {
1888 command(&heat)
1889 .current_dir(&exe)
1890 .arg("dir")
1891 .arg("rust-mingw")
1892 .args(heat_flags)
1893 .arg("-cg")
1894 .arg("GccGroup")
1895 .arg("-dr")
1896 .arg("Gcc")
1897 .arg("-var")
1898 .arg("var.GccDir")
1899 .arg("-out")
1900 .arg(exe.join("GccGroup.wxs"))
1901 .run(builder);
1902 }
1903
1904 let candle = |input: &Path| {
1905 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1906 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1907 let mut cmd = command(&candle);
1908 cmd.current_dir(&exe)
1909 .arg("-nologo")
1910 .arg("-dRustcDir=rustc")
1911 .arg("-dCargoDir=cargo")
1912 .arg("-dStdDir=rust-std")
1913 .arg("-dAnalysisDir=rust-analysis")
1914 .arg("-arch")
1915 .arg(arch)
1916 .arg("-out")
1917 .arg(&output)
1918 .arg(input);
1919 add_env(builder, &mut cmd, target, &built_tools);
1920
1921 if built_tools.contains("clippy") {
1922 cmd.arg("-dClippyDir=clippy");
1923 }
1924 if built_tools.contains("rustfmt") {
1925 cmd.arg("-dRustFmtDir=rustfmt");
1926 }
1927 if built_tools.contains("rust-docs") {
1928 cmd.arg("-dDocsDir=rust-docs");
1929 }
1930 if built_tools.contains("rust-analyzer") {
1931 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1932 }
1933 if built_tools.contains("miri") {
1934 cmd.arg("-dMiriDir=miri");
1935 }
1936 if target.is_windows_gnu() {
1937 cmd.arg("-dGccDir=rust-mingw");
1938 }
1939 cmd.run(builder);
1940 };
1941 candle(&xform(&etc.join("msi/rust.wxs")));
1942 candle(&etc.join("msi/ui.wxs"));
1943 candle(&etc.join("msi/rustwelcomedlg.wxs"));
1944 candle("RustcGroup.wxs".as_ref());
1945 if built_tools.contains("rust-docs") {
1946 candle("DocsGroup.wxs".as_ref());
1947 }
1948 candle("CargoGroup.wxs".as_ref());
1949 candle("StdGroup.wxs".as_ref());
1950 if built_tools.contains("clippy") {
1951 candle("ClippyGroup.wxs".as_ref());
1952 }
1953 if built_tools.contains("rustfmt") {
1954 candle("RustFmtGroup.wxs".as_ref());
1955 }
1956 if built_tools.contains("miri") {
1957 candle("MiriGroup.wxs".as_ref());
1958 }
1959 if built_tools.contains("rust-analyzer") {
1960 candle("RustAnalyzerGroup.wxs".as_ref());
1961 }
1962 candle("AnalysisGroup.wxs".as_ref());
1963
1964 if target.is_windows_gnu() {
1965 candle("GccGroup.wxs".as_ref());
1966 }
1967
1968 builder.create(&exe.join("LICENSE.rtf"), &rtf);
1969 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
1970 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
1971
1972 builder.info(&format!("building `msi` installer with {light:?}"));
1973 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1974 let mut cmd = command(&light);
1975 cmd.arg("-nologo")
1976 .arg("-ext")
1977 .arg("WixUIExtension")
1978 .arg("-ext")
1979 .arg("WixUtilExtension")
1980 .arg("-out")
1981 .arg(exe.join(&filename))
1982 .arg("rust.wixobj")
1983 .arg("ui.wixobj")
1984 .arg("rustwelcomedlg.wixobj")
1985 .arg("RustcGroup.wixobj")
1986 .arg("CargoGroup.wixobj")
1987 .arg("StdGroup.wixobj")
1988 .arg("AnalysisGroup.wixobj")
1989 .current_dir(&exe);
1990
1991 if built_tools.contains("clippy") {
1992 cmd.arg("ClippyGroup.wixobj");
1993 }
1994 if built_tools.contains("rustfmt") {
1995 cmd.arg("RustFmtGroup.wixobj");
1996 }
1997 if built_tools.contains("miri") {
1998 cmd.arg("MiriGroup.wixobj");
1999 }
2000 if built_tools.contains("rust-analyzer") {
2001 cmd.arg("RustAnalyzerGroup.wixobj");
2002 }
2003 if built_tools.contains("rust-docs") {
2004 cmd.arg("DocsGroup.wixobj");
2005 }
2006
2007 if target.is_windows_gnu() {
2008 cmd.arg("GccGroup.wixobj");
2009 }
2010 cmd.arg("-sice:ICE57");
2012
2013 let _time = timeit(builder);
2014 cmd.run(builder);
2015
2016 if !builder.config.dry_run() {
2017 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2018 }
2019 }
2020 }
2021}
2022
2023fn add_env(
2024 builder: &Builder<'_>,
2025 cmd: &mut BootstrapCommand,
2026 target: TargetSelection,
2027 built_tools: &HashSet<&'static str>,
2028) {
2029 let mut parts = builder.version.split('.');
2030 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2031 .env("CFG_RELEASE_NUM", &builder.version)
2032 .env("CFG_RELEASE", builder.rust_release())
2033 .env("CFG_VER_MAJOR", parts.next().unwrap())
2034 .env("CFG_VER_MINOR", parts.next().unwrap())
2035 .env("CFG_VER_PATCH", parts.next().unwrap())
2036 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2038 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2039 .env("CFG_BUILD", target.triple)
2040 .env("CFG_CHANNEL", &builder.config.channel);
2041
2042 if target.contains("windows-gnullvm") {
2043 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2044 } else if target.is_windows_gnu() {
2045 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2046 } else {
2047 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2048 }
2049
2050 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2052 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2053 };
2054 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2055 define_optional_tool("clippy", "CFG_CLIPPY");
2056 define_optional_tool("miri", "CFG_MIRI");
2057 define_optional_tool("rust-analyzer", "CFG_RA");
2058}
2059
2060fn install_llvm_file(
2061 builder: &Builder<'_>,
2062 source: &Path,
2063 destination: &Path,
2064 install_symlink: bool,
2065) {
2066 if builder.config.dry_run() {
2067 return;
2068 }
2069
2070 if source.is_symlink() {
2071 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2074
2075 let full_dest = destination.join(source.file_name().unwrap());
2076 if install_symlink {
2077 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2080 } else {
2081 let link = t!(fs::read_link(source));
2085 let mut linker_script = t!(fs::File::create(full_dest));
2086 t!(write!(linker_script, "INPUT({})\n", link.display()));
2087
2088 let meta = t!(fs::metadata(source));
2091 if let Ok(mtime) = meta.modified() {
2092 t!(linker_script.set_modified(mtime));
2093 }
2094 }
2095 } else {
2096 builder.install(source, destination, FileType::NativeLibrary);
2097 }
2098}
2099
2100#[cfg_attr(
2104 feature = "tracing",
2105 instrument(
2106 level = "trace",
2107 name = "maybe_install_llvm",
2108 skip_all,
2109 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2110 ),
2111)]
2112fn maybe_install_llvm(
2113 builder: &Builder<'_>,
2114 target: TargetSelection,
2115 dst_libdir: &Path,
2116 install_symlink: bool,
2117) -> bool {
2118 if builder.config.is_system_llvm(target) {
2135 trace!("system LLVM requested, no install");
2136 return false;
2137 }
2138
2139 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2145 let src_libdir = builder.llvm_out(target).join("lib");
2146 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2147 if llvm_dylib_path.exists() {
2148 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2149 }
2150 !builder.config.dry_run()
2151 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
2152 llvm::prebuilt_llvm_config(builder, target, true)
2153 {
2154 trace!("LLVM already built, installing LLVM files");
2155 let mut cmd = command(llvm_config);
2156 cmd.arg("--libfiles");
2157 builder.verbose(|| println!("running {cmd:?}"));
2158 let files = cmd.run_capture_stdout(builder).stdout();
2159 let build_llvm_out = &builder.llvm_out(builder.config.build);
2160 let target_llvm_out = &builder.llvm_out(target);
2161 for file in files.trim_end().split(' ') {
2162 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2164 target_llvm_out.join(relative_path)
2165 } else {
2166 PathBuf::from(file)
2167 };
2168 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2169 }
2170 !builder.config.dry_run()
2171 } else {
2172 false
2173 }
2174}
2175
2176#[cfg_attr(
2178 feature = "tracing",
2179 instrument(
2180 level = "trace",
2181 name = "maybe_install_llvm_target",
2182 skip_all,
2183 fields(
2184 llvm_link_shared = ?builder.llvm_link_shared(),
2185 target = ?target,
2186 sysroot = ?sysroot,
2187 ),
2188 ),
2189)]
2190pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2191 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2192 if builder.llvm_link_shared() {
2196 maybe_install_llvm(builder, target, &dst_libdir, false);
2197 }
2198}
2199
2200#[cfg_attr(
2202 feature = "tracing",
2203 instrument(
2204 level = "trace",
2205 name = "maybe_install_llvm_runtime",
2206 skip_all,
2207 fields(
2208 llvm_link_shared = ?builder.llvm_link_shared(),
2209 target = ?target,
2210 sysroot = ?sysroot,
2211 ),
2212 ),
2213)]
2214pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2215 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2216 if builder.llvm_link_shared() {
2220 maybe_install_llvm(builder, target, &dst_libdir, false);
2221 }
2222}
2223
2224#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2225pub struct LlvmTools {
2226 pub target: TargetSelection,
2227}
2228
2229impl Step for LlvmTools {
2230 type Output = Option<GeneratedTarball>;
2231 const ONLY_HOSTS: bool = true;
2232 const DEFAULT: bool = true;
2233
2234 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2235 let default = should_build_extended_tool(run.builder, "llvm-tools");
2236
2237 let mut run = run.alias("llvm-tools");
2238 for tool in LLVM_TOOLS {
2239 run = run.alias(tool);
2240 }
2241
2242 run.default_condition(default)
2243 }
2244
2245 fn make_run(run: RunConfig<'_>) {
2246 run.builder.ensure(LlvmTools { target: run.target });
2247 }
2248
2249 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2250 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2251 let mut tools = vec![];
2252
2253 for path in paths {
2254 let path = path.to_str().unwrap();
2255
2256 if path == "llvm-tools" {
2258 return LLVM_TOOLS.to_owned();
2259 }
2260
2261 for tool in LLVM_TOOLS {
2262 if path == *tool {
2263 tools.push(*tool);
2264 }
2265 }
2266 }
2267
2268 if tools.is_empty() {
2270 tools = LLVM_TOOLS.to_owned();
2271 }
2272
2273 tools
2274 }
2275
2276 let target = self.target;
2277
2278 if let Some(config) = builder.config.target_config.get(&target) {
2280 if !builder.config.llvm_from_ci && config.llvm_config.is_some() {
2281 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2282 return None;
2283 }
2284 }
2285
2286 if !builder.config.dry_run() {
2287 builder.require_submodule("src/llvm-project", None);
2288 }
2289
2290 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2291
2292 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2293 tarball.set_overlay(OverlayKind::Llvm);
2294 tarball.is_preview(true);
2295
2296 if builder.config.llvm_tools_enabled {
2297 let src_bindir = builder.llvm_out(target).join("bin");
2299 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2300 for tool in tools_to_install(&builder.paths) {
2301 let exe = src_bindir.join(exe(tool, target));
2302 if !exe.exists() && builder.config.llvm_from_ci {
2304 eprintln!("{} does not exist; skipping copy", exe.display());
2305 continue;
2306 }
2307
2308 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2309 }
2310 }
2311
2312 maybe_install_llvm_target(builder, target, tarball.image_dir());
2317
2318 Some(tarball.generate())
2319 }
2320}
2321
2322#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
2323pub struct LlvmBitcodeLinker {
2324 pub compiler: Compiler,
2325 pub target: TargetSelection,
2326}
2327
2328impl Step for LlvmBitcodeLinker {
2329 type Output = Option<GeneratedTarball>;
2330 const DEFAULT: bool = true;
2331 const ONLY_HOSTS: bool = true;
2332
2333 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2334 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2335 run.alias("llvm-bitcode-linker").default_condition(default)
2336 }
2337
2338 fn make_run(run: RunConfig<'_>) {
2339 run.builder.ensure(LlvmBitcodeLinker {
2340 compiler: run.builder.compiler_for(
2341 run.builder.top_stage,
2342 run.builder.config.build,
2343 run.target,
2344 ),
2345 target: run.target,
2346 });
2347 }
2348
2349 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2350 let compiler = self.compiler;
2351 let target = self.target;
2352
2353 builder.ensure(compile::Rustc::new(compiler, target));
2354
2355 let llbc_linker =
2356 builder.ensure(tool::LlvmBitcodeLinker { compiler, target, extra_features: vec![] });
2357
2358 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2359
2360 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2362 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2363 tarball.is_preview(true);
2364
2365 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2366
2367 Some(tarball.generate())
2368 }
2369}
2370
2371#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2380pub struct RustDev {
2381 pub target: TargetSelection,
2382}
2383
2384impl Step for RustDev {
2385 type Output = Option<GeneratedTarball>;
2386 const DEFAULT: bool = true;
2387 const ONLY_HOSTS: bool = true;
2388
2389 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2390 run.alias("rust-dev")
2391 }
2392
2393 fn make_run(run: RunConfig<'_>) {
2394 run.builder.ensure(RustDev { target: run.target });
2395 }
2396
2397 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2398 let target = self.target;
2399
2400 if let Some(config) = builder.config.target_config.get(&target) {
2402 if let Some(ref _s) = config.llvm_config {
2403 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2404 return None;
2405 }
2406 }
2407
2408 if !builder.config.dry_run() {
2409 builder.require_submodule("src/llvm-project", None);
2410 }
2411
2412 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2413 tarball.set_overlay(OverlayKind::Llvm);
2414 tarball.permit_symlinks(true);
2416
2417 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2418
2419 let src_bindir = builder.llvm_out(target).join("bin");
2420 if src_bindir.exists() {
2426 for entry in walkdir::WalkDir::new(&src_bindir) {
2427 let entry = t!(entry);
2428 if entry.file_type().is_file() && !entry.path_is_symlink() {
2429 let name = entry.file_name().to_str().unwrap();
2430 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2431 }
2432 }
2433 }
2434
2435 if builder.config.lld_enabled {
2436 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2438
2439 let lld_path = lld_out.join("bin").join(exe("lld", target));
2441 if lld_path.exists() {
2442 tarball.add_file(&lld_path, "bin", FileType::Executable);
2443 }
2444 }
2445
2446 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2447
2448 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2452
2453 let dst_libdir = tarball.image_dir().join("lib");
2458 maybe_install_llvm(builder, target, &dst_libdir, true);
2459 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2460 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2461
2462 copy_src_dirs(
2466 builder,
2467 &builder.src.join("src").join("llvm-project"),
2468 &["compiler-rt"],
2469 &["compiler-rt/test"],
2472 tarball.image_dir(),
2473 );
2474
2475 Some(tarball.generate())
2476 }
2477}
2478
2479#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2483pub struct Bootstrap {
2484 pub target: TargetSelection,
2485}
2486
2487impl Step for Bootstrap {
2488 type Output = Option<GeneratedTarball>;
2489 const DEFAULT: bool = false;
2490 const ONLY_HOSTS: bool = true;
2491
2492 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2493 run.alias("bootstrap")
2494 }
2495
2496 fn make_run(run: RunConfig<'_>) {
2497 run.builder.ensure(Bootstrap { target: run.target });
2498 }
2499
2500 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2501 let target = self.target;
2502
2503 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2504
2505 let bootstrap_outdir = &builder.bootstrap_out;
2506 for file in &["bootstrap", "rustc", "rustdoc"] {
2507 tarball.add_file(
2508 bootstrap_outdir.join(exe(file, target)),
2509 "bootstrap/bin",
2510 FileType::Executable,
2511 );
2512 }
2513
2514 Some(tarball.generate())
2515 }
2516}
2517
2518#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2523pub struct BuildManifest {
2524 pub target: TargetSelection,
2525}
2526
2527impl Step for BuildManifest {
2528 type Output = GeneratedTarball;
2529 const DEFAULT: bool = false;
2530 const ONLY_HOSTS: bool = true;
2531
2532 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2533 run.alias("build-manifest")
2534 }
2535
2536 fn make_run(run: RunConfig<'_>) {
2537 run.builder.ensure(BuildManifest { target: run.target });
2538 }
2539
2540 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2541 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2542
2543 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2544 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2545 tarball.generate()
2546 }
2547}
2548
2549#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2555pub struct ReproducibleArtifacts {
2556 pub target: TargetSelection,
2557}
2558
2559impl Step for ReproducibleArtifacts {
2560 type Output = Option<GeneratedTarball>;
2561 const DEFAULT: bool = true;
2562 const ONLY_HOSTS: bool = true;
2563
2564 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2565 run.alias("reproducible-artifacts")
2566 }
2567
2568 fn make_run(run: RunConfig<'_>) {
2569 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2570 }
2571
2572 fn run(self, builder: &Builder<'_>) -> Self::Output {
2573 let mut added_anything = false;
2574 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2575 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2576 tarball.add_file(path, ".", FileType::Regular);
2577 added_anything = true;
2578 }
2579 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2580 tarball.add_file(path, ".", FileType::Regular);
2581 added_anything = true;
2582 }
2583 for profile in &builder.config.reproducible_artifacts {
2584 tarball.add_file(profile, ".", FileType::Regular);
2585 added_anything = true;
2586 }
2587 if added_anything { Some(tarball.generate()) } else { None }
2588 }
2589}
2590
2591#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2595pub struct Gcc {
2596 pub target: TargetSelection,
2597}
2598
2599impl Step for Gcc {
2600 type Output = GeneratedTarball;
2601
2602 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2603 run.alias("gcc")
2604 }
2605
2606 fn make_run(run: RunConfig<'_>) {
2607 run.builder.ensure(Gcc { target: run.target });
2608 }
2609
2610 fn run(self, builder: &Builder<'_>) -> Self::Output {
2611 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2612 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2613 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2614 tarball.generate()
2615 }
2616}