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::{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 "x",
1072 "x.ps1",
1073 "x.py",
1074 ];
1076 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1077
1078 copy_src_dirs(
1079 builder,
1080 &builder.src,
1081 &src_dirs,
1082 &[
1083 "src/gcc",
1087 ],
1088 plain_dst_src,
1089 );
1090 if !builder.config.dry_run() {
1095 builder.create_dir(&plain_dst_src.join("src/gcc"));
1096 t!(std::fs::write(
1097 plain_dst_src.join("src/gcc/notice.txt"),
1098 "The GCC source code is not included due to unclear licensing implications\n"
1099 ));
1100 }
1101
1102 for item in &src_files {
1104 builder.copy_link(
1105 &builder.src.join(item),
1106 &plain_dst_src.join(item),
1107 FileType::Regular,
1108 );
1109 }
1110
1111 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1113
1114 let write_git_info = |info: Option<&Info>, path: &Path| {
1116 if let Some(info) = info {
1117 t!(std::fs::create_dir_all(path));
1118 channel::write_commit_hash_file(path, &info.sha);
1119 channel::write_commit_info_file(path, info);
1120 }
1121 };
1122 write_git_info(builder.rust_info().info(), plain_dst_src);
1123 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1124
1125 if builder.config.dist_vendor {
1126 builder.require_and_update_all_submodules();
1127
1128 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1130 .iter()
1131 .chain(build_helper::RUSTC_PGO_CRATES)
1132 .map(|pkg| {
1133 let mut manifest_path =
1134 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1135 manifest_path.push(pkg);
1136 manifest_path.push("Cargo.toml");
1137 manifest_path
1138 });
1139
1140 let vendor = builder.ensure(Vendor {
1142 sync_args: pkgs_for_pgo_training.collect(),
1143 versioned_dirs: true,
1144 root_dir: plain_dst_src.into(),
1145 output_dir: VENDOR_DIR.into(),
1146 });
1147
1148 let cargo_config_dir = plain_dst_src.join(".cargo");
1149 builder.create_dir(&cargo_config_dir);
1150 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1151 }
1152
1153 for entry in walkdir::WalkDir::new(tarball.image_dir())
1157 .follow_links(true)
1158 .into_iter()
1159 .filter_map(|e| e.ok())
1160 {
1161 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1162 {
1163 t!(fs::remove_dir_all(entry.path()));
1164 }
1165 }
1166
1167 tarball.bare()
1168 }
1169}
1170
1171#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1172pub struct Cargo {
1173 pub compiler: Compiler,
1174 pub target: TargetSelection,
1175}
1176
1177impl Step for Cargo {
1178 type Output = Option<GeneratedTarball>;
1179 const DEFAULT: bool = true;
1180 const ONLY_HOSTS: bool = true;
1181
1182 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1183 let default = should_build_extended_tool(run.builder, "cargo");
1184 run.alias("cargo").default_condition(default)
1185 }
1186
1187 fn make_run(run: RunConfig<'_>) {
1188 run.builder.ensure(Cargo {
1189 compiler: run.builder.compiler_for(
1190 run.builder.top_stage,
1191 run.builder.config.host_target,
1192 run.target,
1193 ),
1194 target: run.target,
1195 });
1196 }
1197
1198 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1199 let compiler = self.compiler;
1200 let target = self.target;
1201
1202 builder.ensure(compile::Rustc::new(compiler, target));
1203
1204 let cargo = builder.ensure(tool::Cargo { compiler, target });
1205 let src = builder.src.join("src/tools/cargo");
1206 let etc = src.join("src/etc");
1207
1208 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1210 tarball.set_overlay(OverlayKind::Cargo);
1211
1212 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1213 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1214 tarball.add_renamed_file(
1215 etc.join("cargo.bashcomp.sh"),
1216 "etc/bash_completion.d",
1217 "cargo",
1218 FileType::Regular,
1219 );
1220 tarball.add_dir(etc.join("man"), "share/man/man1");
1221 tarball.add_legal_and_readme_to("share/doc/cargo");
1222
1223 Some(tarball.generate())
1224 }
1225}
1226
1227#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1228pub struct RustAnalyzer {
1229 pub compiler: Compiler,
1230 pub target: TargetSelection,
1231}
1232
1233impl Step for RustAnalyzer {
1234 type Output = Option<GeneratedTarball>;
1235 const DEFAULT: bool = true;
1236 const ONLY_HOSTS: bool = true;
1237
1238 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1239 let default = should_build_extended_tool(run.builder, "rust-analyzer");
1240 run.alias("rust-analyzer").default_condition(default)
1241 }
1242
1243 fn make_run(run: RunConfig<'_>) {
1244 run.builder.ensure(RustAnalyzer {
1245 compiler: run.builder.compiler_for(
1246 run.builder.top_stage,
1247 run.builder.config.host_target,
1248 run.target,
1249 ),
1250 target: run.target,
1251 });
1252 }
1253
1254 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1255 let compiler = self.compiler;
1256 let target = self.target;
1257
1258 builder.ensure(compile::Rustc::new(compiler, target));
1259
1260 let rust_analyzer = builder.ensure(tool::RustAnalyzer { compiler, target });
1261
1262 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1263 tarball.set_overlay(OverlayKind::RustAnalyzer);
1264 tarball.is_preview(true);
1265 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1266 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1267 Some(tarball.generate())
1268 }
1269}
1270
1271#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1272pub struct Clippy {
1273 pub compiler: Compiler,
1274 pub target: TargetSelection,
1275}
1276
1277impl Step for Clippy {
1278 type Output = Option<GeneratedTarball>;
1279 const DEFAULT: bool = true;
1280 const ONLY_HOSTS: bool = true;
1281
1282 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1283 let default = should_build_extended_tool(run.builder, "clippy");
1284 run.alias("clippy").default_condition(default)
1285 }
1286
1287 fn make_run(run: RunConfig<'_>) {
1288 run.builder.ensure(Clippy {
1289 compiler: run.builder.compiler_for(
1290 run.builder.top_stage,
1291 run.builder.config.host_target,
1292 run.target,
1293 ),
1294 target: run.target,
1295 });
1296 }
1297
1298 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1299 let compiler = self.compiler;
1300 let target = self.target;
1301
1302 builder.ensure(compile::Rustc::new(compiler, target));
1303
1304 let clippy = builder.ensure(tool::Clippy { compiler, target });
1308 let cargoclippy = builder.ensure(tool::CargoClippy { compiler, target });
1309
1310 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1311 tarball.set_overlay(OverlayKind::Clippy);
1312 tarball.is_preview(true);
1313 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1314 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1315 tarball.add_legal_and_readme_to("share/doc/clippy");
1316 Some(tarball.generate())
1317 }
1318}
1319
1320#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1321pub struct Miri {
1322 pub compiler: Compiler,
1323 pub target: TargetSelection,
1324}
1325
1326impl Step for Miri {
1327 type Output = Option<GeneratedTarball>;
1328 const DEFAULT: bool = true;
1329 const ONLY_HOSTS: bool = true;
1330
1331 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1332 let default = should_build_extended_tool(run.builder, "miri");
1333 run.alias("miri").default_condition(default)
1334 }
1335
1336 fn make_run(run: RunConfig<'_>) {
1337 run.builder.ensure(Miri {
1338 compiler: run.builder.compiler_for(
1339 run.builder.top_stage,
1340 run.builder.config.host_target,
1341 run.target,
1342 ),
1343 target: run.target,
1344 });
1345 }
1346
1347 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1348 if !builder.build.unstable_features() {
1352 return None;
1353 }
1354
1355 let compiler = self.compiler;
1356 let target = self.target;
1357
1358 builder.ensure(compile::Rustc::new(compiler, target));
1359
1360 let miri = builder.ensure(tool::Miri { compiler, target });
1361 let cargomiri = builder.ensure(tool::CargoMiri { compiler, target });
1362
1363 let mut tarball = Tarball::new(builder, "miri", &target.triple);
1364 tarball.set_overlay(OverlayKind::Miri);
1365 tarball.is_preview(true);
1366 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1367 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1368 tarball.add_legal_and_readme_to("share/doc/miri");
1369 Some(tarball.generate())
1370 }
1371}
1372
1373#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1374pub struct CodegenBackend {
1375 pub compiler: Compiler,
1376 pub backend: String,
1377}
1378
1379impl Step for CodegenBackend {
1380 type Output = Option<GeneratedTarball>;
1381 const DEFAULT: bool = true;
1382 const ONLY_HOSTS: bool = true;
1383
1384 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1385 run.path("compiler/rustc_codegen_cranelift")
1386 }
1387
1388 fn make_run(run: RunConfig<'_>) {
1389 for backend in run.builder.config.codegen_backends(run.target) {
1390 if backend == "llvm" {
1391 continue; }
1393
1394 run.builder.ensure(CodegenBackend {
1395 compiler: run.builder.compiler(run.builder.top_stage, run.target),
1396 backend: backend.clone(),
1397 });
1398 }
1399 }
1400
1401 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1402 if builder.config.dry_run() {
1403 return None;
1404 }
1405
1406 if !builder.build.unstable_features() {
1410 return None;
1411 }
1412
1413 if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend.to_string())
1414 {
1415 return None;
1416 }
1417
1418 if self.backend == "cranelift" && !target_supports_cranelift_backend(self.compiler.host) {
1419 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1420 return None;
1421 }
1422
1423 let compiler = self.compiler;
1424 let backend = self.backend;
1425
1426 let mut tarball =
1427 Tarball::new(builder, &format!("rustc-codegen-{backend}"), &compiler.host.triple);
1428 if backend == "cranelift" {
1429 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1430 } else {
1431 panic!("Unknown backend rustc_codegen_{backend}");
1432 }
1433 tarball.is_preview(true);
1434 tarball.add_legal_and_readme_to(format!("share/doc/rustc_codegen_{backend}"));
1435
1436 let src = builder.sysroot(compiler);
1437 let backends_src = builder.sysroot_codegen_backends(compiler);
1438 let backends_rel = backends_src
1439 .strip_prefix(src)
1440 .unwrap()
1441 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1442 .unwrap();
1443 let backends_dst = PathBuf::from("lib").join(backends_rel);
1445
1446 let backend_name = format!("rustc_codegen_{backend}");
1447 let mut found_backend = false;
1448 for backend in fs::read_dir(&backends_src).unwrap() {
1449 let file_name = backend.unwrap().file_name();
1450 if file_name.to_str().unwrap().contains(&backend_name) {
1451 tarball.add_file(
1452 backends_src.join(file_name),
1453 &backends_dst,
1454 FileType::NativeLibrary,
1455 );
1456 found_backend = true;
1457 }
1458 }
1459 assert!(found_backend);
1460
1461 Some(tarball.generate())
1462 }
1463}
1464
1465#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1466pub struct Rustfmt {
1467 pub compiler: Compiler,
1468 pub target: TargetSelection,
1469}
1470
1471impl Step for Rustfmt {
1472 type Output = Option<GeneratedTarball>;
1473 const DEFAULT: bool = true;
1474 const ONLY_HOSTS: bool = true;
1475
1476 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1477 let default = should_build_extended_tool(run.builder, "rustfmt");
1478 run.alias("rustfmt").default_condition(default)
1479 }
1480
1481 fn make_run(run: RunConfig<'_>) {
1482 run.builder.ensure(Rustfmt {
1483 compiler: run.builder.compiler_for(
1484 run.builder.top_stage,
1485 run.builder.config.host_target,
1486 run.target,
1487 ),
1488 target: run.target,
1489 });
1490 }
1491
1492 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1493 let compiler = self.compiler;
1494 let target = self.target;
1495
1496 builder.ensure(compile::Rustc::new(compiler, target));
1497
1498 let rustfmt = builder.ensure(tool::Rustfmt { compiler, target });
1499 let cargofmt = builder.ensure(tool::Cargofmt { compiler, target });
1500 let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
1501 tarball.set_overlay(OverlayKind::Rustfmt);
1502 tarball.is_preview(true);
1503 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1504 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1505 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1506 Some(tarball.generate())
1507 }
1508}
1509
1510#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1511pub struct Extended {
1512 stage: u32,
1513 host: TargetSelection,
1514 target: TargetSelection,
1515}
1516
1517impl Step for Extended {
1518 type Output = ();
1519 const DEFAULT: bool = true;
1520 const ONLY_HOSTS: bool = true;
1521
1522 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1523 let builder = run.builder;
1524 run.alias("extended").default_condition(builder.config.extended)
1525 }
1526
1527 fn make_run(run: RunConfig<'_>) {
1528 run.builder.ensure(Extended {
1529 stage: run.builder.top_stage,
1530 host: run.builder.config.host_target,
1531 target: run.target,
1532 });
1533 }
1534
1535 fn run(self, builder: &Builder<'_>) {
1537 let target = self.target;
1538 let stage = self.stage;
1539 let compiler = builder.compiler_for(self.stage, self.host, self.target);
1540
1541 builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1542
1543 let mut tarballs = Vec::new();
1544 let mut built_tools = HashSet::new();
1545 macro_rules! add_component {
1546 ($name:expr => $step:expr) => {
1547 if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) {
1548 tarballs.push(tarball);
1549 built_tools.insert($name);
1550 }
1551 };
1552 }
1553
1554 tarballs.push(builder.ensure(Rustc { compiler: builder.compiler(stage, target) }));
1559 tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
1560
1561 if target.is_windows_gnu() {
1562 tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
1563 }
1564
1565 add_component!("rust-docs" => Docs { host: target });
1566 add_component!("rust-json-docs" => JsonDocs { host: target });
1567 add_component!("cargo" => Cargo { compiler, target });
1568 add_component!("rustfmt" => Rustfmt { compiler, target });
1569 add_component!("rust-analyzer" => RustAnalyzer { compiler, target });
1570 add_component!("llvm-components" => LlvmTools { target });
1571 add_component!("clippy" => Clippy { compiler, target });
1572 add_component!("miri" => Miri { compiler, target });
1573 add_component!("analysis" => Analysis { compiler, target });
1574 add_component!("rustc-codegen-cranelift" => CodegenBackend {
1575 compiler: builder.compiler(stage, target),
1576 backend: "cranelift".to_string(),
1577 });
1578 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1579 build_compiler: compiler,
1580 target
1581 });
1582
1583 let etc = builder.src.join("src/etc/installer");
1584
1585 if builder.config.dry_run() {
1587 return;
1588 }
1589
1590 let tarball = Tarball::new(builder, "rust", &target.triple);
1591 let generated = tarball.combine(&tarballs);
1592
1593 let tmp = tmpdir(builder).join("combined-tarball");
1594 let work = generated.work_dir();
1595
1596 let mut license = String::new();
1597 license += &builder.read(&builder.src.join("COPYRIGHT"));
1598 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1599 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1600 license.push('\n');
1601 license.push('\n');
1602
1603 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1604 let mut rtf = rtf.to_string();
1605 rtf.push('\n');
1606 for line in license.lines() {
1607 rtf.push_str(line);
1608 rtf.push_str("\\line ");
1609 }
1610 rtf.push('}');
1611
1612 fn filter(contents: &str, marker: &str) -> String {
1613 let start = format!("tool-{marker}-start");
1614 let end = format!("tool-{marker}-end");
1615 let mut lines = Vec::new();
1616 let mut omitted = false;
1617 for line in contents.lines() {
1618 if line.contains(&start) {
1619 omitted = true;
1620 } else if line.contains(&end) {
1621 omitted = false;
1622 } else if !omitted {
1623 lines.push(line);
1624 }
1625 }
1626
1627 lines.join("\n")
1628 }
1629
1630 let xform = |p: &Path| {
1631 let mut contents = t!(fs::read_to_string(p));
1632 for tool in &["miri", "rust-docs"] {
1633 if !built_tools.contains(tool) {
1634 contents = filter(&contents, tool);
1635 }
1636 }
1637 let ret = tmp.join(p.file_name().unwrap());
1638 t!(fs::write(&ret, &contents));
1639 ret
1640 };
1641
1642 if target.contains("apple-darwin") {
1643 builder.info("building pkg installer");
1644 let pkg = tmp.join("pkg");
1645 let _ = fs::remove_dir_all(&pkg);
1646
1647 let pkgbuild = |component: &str| {
1648 let mut cmd = command("pkgbuild");
1649 cmd.arg("--identifier")
1650 .arg(format!("org.rust-lang.{component}"))
1651 .arg("--scripts")
1652 .arg(pkg.join(component))
1653 .arg("--nopayload")
1654 .arg(pkg.join(component).with_extension("pkg"));
1655 cmd.run(builder);
1656 };
1657
1658 let prepare = |name: &str| {
1659 builder.create_dir(&pkg.join(name));
1660 builder.cp_link_r(
1661 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1662 &pkg.join(name),
1663 );
1664 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1665 pkgbuild(name);
1666 };
1667 prepare("rustc");
1668 prepare("cargo");
1669 prepare("rust-std");
1670 prepare("rust-analysis");
1671
1672 for tool in &[
1673 "clippy",
1674 "rustfmt",
1675 "rust-analyzer",
1676 "rust-docs",
1677 "miri",
1678 "rustc-codegen-cranelift",
1679 ] {
1680 if built_tools.contains(tool) {
1681 prepare(tool);
1682 }
1683 }
1684 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1686 pkgbuild("uninstall");
1687
1688 builder.create_dir(&pkg.join("res"));
1689 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1690 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1691 let mut cmd = command("productbuild");
1692 cmd.arg("--distribution")
1693 .arg(xform(&etc.join("pkg/Distribution.xml")))
1694 .arg("--resources")
1695 .arg(pkg.join("res"))
1696 .arg(distdir(builder).join(format!(
1697 "{}-{}.pkg",
1698 pkgname(builder, "rust"),
1699 target.triple
1700 )))
1701 .arg("--package-path")
1702 .arg(&pkg);
1703 let _time = timeit(builder);
1704 cmd.run(builder);
1705 }
1706
1707 if target.is_windows() && !target.contains("gnullvm") {
1709 let exe = tmp.join("exe");
1710 let _ = fs::remove_dir_all(&exe);
1711
1712 let prepare = |name: &str| {
1713 builder.create_dir(&exe.join(name));
1714 let dir = if name == "rust-std" || name == "rust-analysis" {
1715 format!("{}-{}", name, target.triple)
1716 } else if name == "rust-analyzer" {
1717 "rust-analyzer-preview".to_string()
1718 } else if name == "clippy" {
1719 "clippy-preview".to_string()
1720 } else if name == "rustfmt" {
1721 "rustfmt-preview".to_string()
1722 } else if name == "miri" {
1723 "miri-preview".to_string()
1724 } else if name == "rustc-codegen-cranelift" {
1725 unreachable!("cg_clif shouldn't be built for windows");
1728 } else {
1729 name.to_string()
1730 };
1731 builder.cp_link_r(
1732 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1733 &exe.join(name),
1734 );
1735 builder.remove(&exe.join(name).join("manifest.in"));
1736 };
1737 prepare("rustc");
1738 prepare("cargo");
1739 prepare("rust-analysis");
1740 prepare("rust-std");
1741 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1742 if built_tools.contains(tool) {
1743 prepare(tool);
1744 }
1745 }
1746 if target.is_windows_gnu() {
1747 prepare("rust-mingw");
1748 }
1749
1750 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1751
1752 let wix_path = env::var_os("WIX")
1754 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1755 let wix = PathBuf::from(wix_path);
1756 let heat = wix.join("bin/heat.exe");
1757 let candle = wix.join("bin/candle.exe");
1758 let light = wix.join("bin/light.exe");
1759
1760 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1761 command(&heat)
1762 .current_dir(&exe)
1763 .arg("dir")
1764 .arg("rustc")
1765 .args(heat_flags)
1766 .arg("-cg")
1767 .arg("RustcGroup")
1768 .arg("-dr")
1769 .arg("Rustc")
1770 .arg("-var")
1771 .arg("var.RustcDir")
1772 .arg("-out")
1773 .arg(exe.join("RustcGroup.wxs"))
1774 .run(builder);
1775 if built_tools.contains("rust-docs") {
1776 command(&heat)
1777 .current_dir(&exe)
1778 .arg("dir")
1779 .arg("rust-docs")
1780 .args(heat_flags)
1781 .arg("-cg")
1782 .arg("DocsGroup")
1783 .arg("-dr")
1784 .arg("Docs")
1785 .arg("-var")
1786 .arg("var.DocsDir")
1787 .arg("-out")
1788 .arg(exe.join("DocsGroup.wxs"))
1789 .arg("-t")
1790 .arg(etc.join("msi/squash-components.xsl"))
1791 .run(builder);
1792 }
1793 command(&heat)
1794 .current_dir(&exe)
1795 .arg("dir")
1796 .arg("cargo")
1797 .args(heat_flags)
1798 .arg("-cg")
1799 .arg("CargoGroup")
1800 .arg("-dr")
1801 .arg("Cargo")
1802 .arg("-var")
1803 .arg("var.CargoDir")
1804 .arg("-out")
1805 .arg(exe.join("CargoGroup.wxs"))
1806 .arg("-t")
1807 .arg(etc.join("msi/remove-duplicates.xsl"))
1808 .run(builder);
1809 command(&heat)
1810 .current_dir(&exe)
1811 .arg("dir")
1812 .arg("rust-std")
1813 .args(heat_flags)
1814 .arg("-cg")
1815 .arg("StdGroup")
1816 .arg("-dr")
1817 .arg("Std")
1818 .arg("-var")
1819 .arg("var.StdDir")
1820 .arg("-out")
1821 .arg(exe.join("StdGroup.wxs"))
1822 .run(builder);
1823 if built_tools.contains("rust-analyzer") {
1824 command(&heat)
1825 .current_dir(&exe)
1826 .arg("dir")
1827 .arg("rust-analyzer")
1828 .args(heat_flags)
1829 .arg("-cg")
1830 .arg("RustAnalyzerGroup")
1831 .arg("-dr")
1832 .arg("RustAnalyzer")
1833 .arg("-var")
1834 .arg("var.RustAnalyzerDir")
1835 .arg("-out")
1836 .arg(exe.join("RustAnalyzerGroup.wxs"))
1837 .arg("-t")
1838 .arg(etc.join("msi/remove-duplicates.xsl"))
1839 .run(builder);
1840 }
1841 if built_tools.contains("clippy") {
1842 command(&heat)
1843 .current_dir(&exe)
1844 .arg("dir")
1845 .arg("clippy")
1846 .args(heat_flags)
1847 .arg("-cg")
1848 .arg("ClippyGroup")
1849 .arg("-dr")
1850 .arg("Clippy")
1851 .arg("-var")
1852 .arg("var.ClippyDir")
1853 .arg("-out")
1854 .arg(exe.join("ClippyGroup.wxs"))
1855 .arg("-t")
1856 .arg(etc.join("msi/remove-duplicates.xsl"))
1857 .run(builder);
1858 }
1859 if built_tools.contains("rustfmt") {
1860 command(&heat)
1861 .current_dir(&exe)
1862 .arg("dir")
1863 .arg("rustfmt")
1864 .args(heat_flags)
1865 .arg("-cg")
1866 .arg("RustFmtGroup")
1867 .arg("-dr")
1868 .arg("RustFmt")
1869 .arg("-var")
1870 .arg("var.RustFmtDir")
1871 .arg("-out")
1872 .arg(exe.join("RustFmtGroup.wxs"))
1873 .arg("-t")
1874 .arg(etc.join("msi/remove-duplicates.xsl"))
1875 .run(builder);
1876 }
1877 if built_tools.contains("miri") {
1878 command(&heat)
1879 .current_dir(&exe)
1880 .arg("dir")
1881 .arg("miri")
1882 .args(heat_flags)
1883 .arg("-cg")
1884 .arg("MiriGroup")
1885 .arg("-dr")
1886 .arg("Miri")
1887 .arg("-var")
1888 .arg("var.MiriDir")
1889 .arg("-out")
1890 .arg(exe.join("MiriGroup.wxs"))
1891 .arg("-t")
1892 .arg(etc.join("msi/remove-duplicates.xsl"))
1893 .run(builder);
1894 }
1895 command(&heat)
1896 .current_dir(&exe)
1897 .arg("dir")
1898 .arg("rust-analysis")
1899 .args(heat_flags)
1900 .arg("-cg")
1901 .arg("AnalysisGroup")
1902 .arg("-dr")
1903 .arg("Analysis")
1904 .arg("-var")
1905 .arg("var.AnalysisDir")
1906 .arg("-out")
1907 .arg(exe.join("AnalysisGroup.wxs"))
1908 .arg("-t")
1909 .arg(etc.join("msi/remove-duplicates.xsl"))
1910 .run(builder);
1911 if target.is_windows_gnu() {
1912 command(&heat)
1913 .current_dir(&exe)
1914 .arg("dir")
1915 .arg("rust-mingw")
1916 .args(heat_flags)
1917 .arg("-cg")
1918 .arg("GccGroup")
1919 .arg("-dr")
1920 .arg("Gcc")
1921 .arg("-var")
1922 .arg("var.GccDir")
1923 .arg("-out")
1924 .arg(exe.join("GccGroup.wxs"))
1925 .run(builder);
1926 }
1927
1928 let candle = |input: &Path| {
1929 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1930 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1931 let mut cmd = command(&candle);
1932 cmd.current_dir(&exe)
1933 .arg("-nologo")
1934 .arg("-dRustcDir=rustc")
1935 .arg("-dCargoDir=cargo")
1936 .arg("-dStdDir=rust-std")
1937 .arg("-dAnalysisDir=rust-analysis")
1938 .arg("-arch")
1939 .arg(arch)
1940 .arg("-out")
1941 .arg(&output)
1942 .arg(input);
1943 add_env(builder, &mut cmd, target, &built_tools);
1944
1945 if built_tools.contains("clippy") {
1946 cmd.arg("-dClippyDir=clippy");
1947 }
1948 if built_tools.contains("rustfmt") {
1949 cmd.arg("-dRustFmtDir=rustfmt");
1950 }
1951 if built_tools.contains("rust-docs") {
1952 cmd.arg("-dDocsDir=rust-docs");
1953 }
1954 if built_tools.contains("rust-analyzer") {
1955 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1956 }
1957 if built_tools.contains("miri") {
1958 cmd.arg("-dMiriDir=miri");
1959 }
1960 if target.is_windows_gnu() {
1961 cmd.arg("-dGccDir=rust-mingw");
1962 }
1963 cmd.run(builder);
1964 };
1965 candle(&xform(&etc.join("msi/rust.wxs")));
1966 candle(&etc.join("msi/ui.wxs"));
1967 candle(&etc.join("msi/rustwelcomedlg.wxs"));
1968 candle("RustcGroup.wxs".as_ref());
1969 if built_tools.contains("rust-docs") {
1970 candle("DocsGroup.wxs".as_ref());
1971 }
1972 candle("CargoGroup.wxs".as_ref());
1973 candle("StdGroup.wxs".as_ref());
1974 if built_tools.contains("clippy") {
1975 candle("ClippyGroup.wxs".as_ref());
1976 }
1977 if built_tools.contains("rustfmt") {
1978 candle("RustFmtGroup.wxs".as_ref());
1979 }
1980 if built_tools.contains("miri") {
1981 candle("MiriGroup.wxs".as_ref());
1982 }
1983 if built_tools.contains("rust-analyzer") {
1984 candle("RustAnalyzerGroup.wxs".as_ref());
1985 }
1986 candle("AnalysisGroup.wxs".as_ref());
1987
1988 if target.is_windows_gnu() {
1989 candle("GccGroup.wxs".as_ref());
1990 }
1991
1992 builder.create(&exe.join("LICENSE.rtf"), &rtf);
1993 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
1994 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
1995
1996 builder.info(&format!("building `msi` installer with {light:?}"));
1997 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1998 let mut cmd = command(&light);
1999 cmd.arg("-nologo")
2000 .arg("-ext")
2001 .arg("WixUIExtension")
2002 .arg("-ext")
2003 .arg("WixUtilExtension")
2004 .arg("-out")
2005 .arg(exe.join(&filename))
2006 .arg("rust.wixobj")
2007 .arg("ui.wixobj")
2008 .arg("rustwelcomedlg.wixobj")
2009 .arg("RustcGroup.wixobj")
2010 .arg("CargoGroup.wixobj")
2011 .arg("StdGroup.wixobj")
2012 .arg("AnalysisGroup.wixobj")
2013 .current_dir(&exe);
2014
2015 if built_tools.contains("clippy") {
2016 cmd.arg("ClippyGroup.wixobj");
2017 }
2018 if built_tools.contains("rustfmt") {
2019 cmd.arg("RustFmtGroup.wixobj");
2020 }
2021 if built_tools.contains("miri") {
2022 cmd.arg("MiriGroup.wixobj");
2023 }
2024 if built_tools.contains("rust-analyzer") {
2025 cmd.arg("RustAnalyzerGroup.wixobj");
2026 }
2027 if built_tools.contains("rust-docs") {
2028 cmd.arg("DocsGroup.wixobj");
2029 }
2030
2031 if target.is_windows_gnu() {
2032 cmd.arg("GccGroup.wixobj");
2033 }
2034 cmd.arg("-sice:ICE57");
2036
2037 let _time = timeit(builder);
2038 cmd.run(builder);
2039
2040 if !builder.config.dry_run() {
2041 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2042 }
2043 }
2044 }
2045}
2046
2047fn add_env(
2048 builder: &Builder<'_>,
2049 cmd: &mut BootstrapCommand,
2050 target: TargetSelection,
2051 built_tools: &HashSet<&'static str>,
2052) {
2053 let mut parts = builder.version.split('.');
2054 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2055 .env("CFG_RELEASE_NUM", &builder.version)
2056 .env("CFG_RELEASE", builder.rust_release())
2057 .env("CFG_VER_MAJOR", parts.next().unwrap())
2058 .env("CFG_VER_MINOR", parts.next().unwrap())
2059 .env("CFG_VER_PATCH", parts.next().unwrap())
2060 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2062 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2063 .env("CFG_BUILD", target.triple)
2064 .env("CFG_CHANNEL", &builder.config.channel);
2065
2066 if target.contains("windows-gnullvm") {
2067 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2068 } else if target.is_windows_gnu() {
2069 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2070 } else {
2071 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2072 }
2073
2074 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2076 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2077 };
2078 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2079 define_optional_tool("clippy", "CFG_CLIPPY");
2080 define_optional_tool("miri", "CFG_MIRI");
2081 define_optional_tool("rust-analyzer", "CFG_RA");
2082}
2083
2084fn install_llvm_file(
2085 builder: &Builder<'_>,
2086 source: &Path,
2087 destination: &Path,
2088 install_symlink: bool,
2089) {
2090 if builder.config.dry_run() {
2091 return;
2092 }
2093
2094 if source.is_symlink() {
2095 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2098
2099 let full_dest = destination.join(source.file_name().unwrap());
2100 if install_symlink {
2101 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2104 } else {
2105 let link = t!(fs::read_link(source));
2109 let mut linker_script = t!(fs::File::create(full_dest));
2110 t!(write!(linker_script, "INPUT({})\n", link.display()));
2111
2112 let meta = t!(fs::metadata(source));
2115 if let Ok(mtime) = meta.modified() {
2116 t!(linker_script.set_modified(mtime));
2117 }
2118 }
2119 } else {
2120 builder.install(source, destination, FileType::NativeLibrary);
2121 }
2122}
2123
2124#[cfg_attr(
2128 feature = "tracing",
2129 instrument(
2130 level = "trace",
2131 name = "maybe_install_llvm",
2132 skip_all,
2133 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2134 ),
2135)]
2136fn maybe_install_llvm(
2137 builder: &Builder<'_>,
2138 target: TargetSelection,
2139 dst_libdir: &Path,
2140 install_symlink: bool,
2141) -> bool {
2142 if builder.config.is_system_llvm(target) {
2159 trace!("system LLVM requested, no install");
2160 return false;
2161 }
2162
2163 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2169 let src_libdir = builder.llvm_out(target).join("lib");
2170 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2171 if llvm_dylib_path.exists() {
2172 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2173 }
2174 !builder.config.dry_run()
2175 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
2176 llvm::prebuilt_llvm_config(builder, target, true)
2177 {
2178 trace!("LLVM already built, installing LLVM files");
2179 let mut cmd = command(llvm_config);
2180 cmd.arg("--libfiles");
2181 builder.verbose(|| println!("running {cmd:?}"));
2182 let files = cmd.run_capture_stdout(builder).stdout();
2183 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2184 let target_llvm_out = &builder.llvm_out(target);
2185 for file in files.trim_end().split(' ') {
2186 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2188 target_llvm_out.join(relative_path)
2189 } else {
2190 PathBuf::from(file)
2191 };
2192 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2193 }
2194 !builder.config.dry_run()
2195 } else {
2196 false
2197 }
2198}
2199
2200#[cfg_attr(
2202 feature = "tracing",
2203 instrument(
2204 level = "trace",
2205 name = "maybe_install_llvm_target",
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_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2215 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2216 if builder.llvm_link_shared() {
2220 maybe_install_llvm(builder, target, &dst_libdir, false);
2221 }
2222}
2223
2224#[cfg_attr(
2226 feature = "tracing",
2227 instrument(
2228 level = "trace",
2229 name = "maybe_install_llvm_runtime",
2230 skip_all,
2231 fields(
2232 llvm_link_shared = ?builder.llvm_link_shared(),
2233 target = ?target,
2234 sysroot = ?sysroot,
2235 ),
2236 ),
2237)]
2238pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2239 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2240 if builder.llvm_link_shared() {
2244 maybe_install_llvm(builder, target, &dst_libdir, false);
2245 }
2246}
2247
2248#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2249pub struct LlvmTools {
2250 pub target: TargetSelection,
2251}
2252
2253impl Step for LlvmTools {
2254 type Output = Option<GeneratedTarball>;
2255 const ONLY_HOSTS: bool = true;
2256 const DEFAULT: bool = true;
2257
2258 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2259 let default = should_build_extended_tool(run.builder, "llvm-tools");
2260
2261 let mut run = run.alias("llvm-tools");
2262 for tool in LLVM_TOOLS {
2263 run = run.alias(tool);
2264 }
2265
2266 run.default_condition(default)
2267 }
2268
2269 fn make_run(run: RunConfig<'_>) {
2270 run.builder.ensure(LlvmTools { target: run.target });
2271 }
2272
2273 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2274 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2275 let mut tools = vec![];
2276
2277 for path in paths {
2278 let path = path.to_str().unwrap();
2279
2280 if path == "llvm-tools" {
2282 return LLVM_TOOLS.to_owned();
2283 }
2284
2285 for tool in LLVM_TOOLS {
2286 if path == *tool {
2287 tools.push(*tool);
2288 }
2289 }
2290 }
2291
2292 if tools.is_empty() {
2294 tools = LLVM_TOOLS.to_owned();
2295 }
2296
2297 tools
2298 }
2299
2300 let target = self.target;
2301
2302 if let Some(config) = builder.config.target_config.get(&target)
2304 && !builder.config.llvm_from_ci
2305 && config.llvm_config.is_some()
2306 {
2307 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2308 return None;
2309 }
2310
2311 if !builder.config.dry_run() {
2312 builder.require_submodule("src/llvm-project", None);
2313 }
2314
2315 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2316
2317 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2318 tarball.set_overlay(OverlayKind::Llvm);
2319 tarball.is_preview(true);
2320
2321 if builder.config.llvm_tools_enabled {
2322 let src_bindir = builder.llvm_out(target).join("bin");
2324 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2325 for tool in tools_to_install(&builder.paths) {
2326 let exe = src_bindir.join(exe(tool, target));
2327 if !exe.exists() && builder.config.llvm_from_ci {
2329 eprintln!("{} does not exist; skipping copy", exe.display());
2330 continue;
2331 }
2332
2333 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2334 }
2335 }
2336
2337 maybe_install_llvm_target(builder, target, tarball.image_dir());
2342
2343 Some(tarball.generate())
2344 }
2345}
2346
2347#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
2350pub struct LlvmBitcodeLinker {
2351 pub build_compiler: Compiler,
2353 pub target: TargetSelection,
2355}
2356
2357impl Step for LlvmBitcodeLinker {
2358 type Output = Option<GeneratedTarball>;
2359 const DEFAULT: bool = true;
2360 const ONLY_HOSTS: bool = true;
2361
2362 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2363 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2364 run.alias("llvm-bitcode-linker").default_condition(default)
2365 }
2366
2367 fn make_run(run: RunConfig<'_>) {
2368 run.builder.ensure(LlvmBitcodeLinker {
2369 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2370 run.builder,
2371 run.target,
2372 ),
2373 target: run.target,
2374 });
2375 }
2376
2377 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2378 let target = self.target;
2379
2380 let llbc_linker = builder
2381 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2382
2383 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2384
2385 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2387 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2388 tarball.is_preview(true);
2389
2390 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2391
2392 Some(tarball.generate())
2393 }
2394}
2395
2396#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2405pub struct RustDev {
2406 pub target: TargetSelection,
2407}
2408
2409impl Step for RustDev {
2410 type Output = Option<GeneratedTarball>;
2411 const DEFAULT: bool = true;
2412 const ONLY_HOSTS: bool = true;
2413
2414 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2415 run.alias("rust-dev")
2416 }
2417
2418 fn make_run(run: RunConfig<'_>) {
2419 run.builder.ensure(RustDev { target: run.target });
2420 }
2421
2422 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2423 let target = self.target;
2424
2425 if let Some(config) = builder.config.target_config.get(&target)
2427 && let Some(ref _s) = config.llvm_config
2428 {
2429 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2430 return None;
2431 }
2432
2433 if !builder.config.dry_run() {
2434 builder.require_submodule("src/llvm-project", None);
2435 }
2436
2437 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2438 tarball.set_overlay(OverlayKind::Llvm);
2439 tarball.permit_symlinks(true);
2441
2442 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2443
2444 let src_bindir = builder.llvm_out(target).join("bin");
2445 if src_bindir.exists() {
2451 for entry in walkdir::WalkDir::new(&src_bindir) {
2452 let entry = t!(entry);
2453 if entry.file_type().is_file() && !entry.path_is_symlink() {
2454 let name = entry.file_name().to_str().unwrap();
2455 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2456 }
2457 }
2458 }
2459
2460 if builder.config.lld_enabled {
2461 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2463
2464 let lld_path = lld_out.join("bin").join(exe("lld", target));
2466 if lld_path.exists() {
2467 tarball.add_file(&lld_path, "bin", FileType::Executable);
2468 }
2469 }
2470
2471 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2472
2473 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2477
2478 let dst_libdir = tarball.image_dir().join("lib");
2483 maybe_install_llvm(builder, target, &dst_libdir, true);
2484 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2485 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2486
2487 copy_src_dirs(
2491 builder,
2492 &builder.src.join("src").join("llvm-project"),
2493 &["compiler-rt"],
2494 &["compiler-rt/test"],
2497 tarball.image_dir(),
2498 );
2499
2500 Some(tarball.generate())
2501 }
2502}
2503
2504#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2508pub struct Bootstrap {
2509 pub target: TargetSelection,
2510}
2511
2512impl Step for Bootstrap {
2513 type Output = Option<GeneratedTarball>;
2514 const DEFAULT: bool = false;
2515 const ONLY_HOSTS: bool = true;
2516
2517 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2518 run.alias("bootstrap")
2519 }
2520
2521 fn make_run(run: RunConfig<'_>) {
2522 run.builder.ensure(Bootstrap { target: run.target });
2523 }
2524
2525 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2526 let target = self.target;
2527
2528 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2529
2530 let bootstrap_outdir = &builder.bootstrap_out;
2531 for file in &["bootstrap", "rustc", "rustdoc"] {
2532 tarball.add_file(
2533 bootstrap_outdir.join(exe(file, target)),
2534 "bootstrap/bin",
2535 FileType::Executable,
2536 );
2537 }
2538
2539 Some(tarball.generate())
2540 }
2541}
2542
2543#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2548pub struct BuildManifest {
2549 pub target: TargetSelection,
2550}
2551
2552impl Step for BuildManifest {
2553 type Output = GeneratedTarball;
2554 const DEFAULT: bool = false;
2555 const ONLY_HOSTS: bool = true;
2556
2557 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2558 run.alias("build-manifest")
2559 }
2560
2561 fn make_run(run: RunConfig<'_>) {
2562 run.builder.ensure(BuildManifest { target: run.target });
2563 }
2564
2565 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2566 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2567
2568 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2569 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2570 tarball.generate()
2571 }
2572}
2573
2574#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2580pub struct ReproducibleArtifacts {
2581 pub target: TargetSelection,
2582}
2583
2584impl Step for ReproducibleArtifacts {
2585 type Output = Option<GeneratedTarball>;
2586 const DEFAULT: bool = true;
2587 const ONLY_HOSTS: bool = true;
2588
2589 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2590 run.alias("reproducible-artifacts")
2591 }
2592
2593 fn make_run(run: RunConfig<'_>) {
2594 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2595 }
2596
2597 fn run(self, builder: &Builder<'_>) -> Self::Output {
2598 let mut added_anything = false;
2599 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2600 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2601 tarball.add_file(path, ".", FileType::Regular);
2602 added_anything = true;
2603 }
2604 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2605 tarball.add_file(path, ".", FileType::Regular);
2606 added_anything = true;
2607 }
2608 for profile in &builder.config.reproducible_artifacts {
2609 tarball.add_file(profile, ".", FileType::Regular);
2610 added_anything = true;
2611 }
2612 if added_anything { Some(tarball.generate()) } else { None }
2613 }
2614}
2615
2616#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2620pub struct Gcc {
2621 pub target: TargetSelection,
2622}
2623
2624impl Step for Gcc {
2625 type Output = GeneratedTarball;
2626
2627 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2628 run.alias("gcc")
2629 }
2630
2631 fn make_run(run: RunConfig<'_>) {
2632 run.builder.ensure(Gcc { target: run.target });
2633 }
2634
2635 fn run(self, builder: &Builder<'_>) -> Self::Output {
2636 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2637 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2638 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2639 tarball.generate()
2640 }
2641}