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