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 { llvm_config, .. }) =
2180 llvm::prebuilt_llvm_config(builder, target, true)
2181 {
2182 trace!("LLVM already built, installing LLVM files");
2183 let mut cmd = command(llvm_config);
2184 cmd.arg("--libfiles");
2185 builder.verbose(|| println!("running {cmd:?}"));
2186 let files = cmd.run_capture_stdout(builder).stdout();
2187 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2188 let target_llvm_out = &builder.llvm_out(target);
2189 for file in files.trim_end().split(' ') {
2190 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2192 target_llvm_out.join(relative_path)
2193 } else {
2194 PathBuf::from(file)
2195 };
2196 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2197 }
2198 !builder.config.dry_run()
2199 } else {
2200 false
2201 }
2202}
2203
2204#[cfg_attr(
2206 feature = "tracing",
2207 instrument(
2208 level = "trace",
2209 name = "maybe_install_llvm_target",
2210 skip_all,
2211 fields(
2212 llvm_link_shared = ?builder.llvm_link_shared(),
2213 target = ?target,
2214 sysroot = ?sysroot,
2215 ),
2216 ),
2217)]
2218pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2219 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2220 if builder.llvm_link_shared() {
2224 maybe_install_llvm(builder, target, &dst_libdir, false);
2225 }
2226}
2227
2228#[cfg_attr(
2230 feature = "tracing",
2231 instrument(
2232 level = "trace",
2233 name = "maybe_install_llvm_runtime",
2234 skip_all,
2235 fields(
2236 llvm_link_shared = ?builder.llvm_link_shared(),
2237 target = ?target,
2238 sysroot = ?sysroot,
2239 ),
2240 ),
2241)]
2242pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2243 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2244 if builder.llvm_link_shared() {
2248 maybe_install_llvm(builder, target, &dst_libdir, false);
2249 }
2250}
2251
2252#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2253pub struct LlvmTools {
2254 pub target: TargetSelection,
2255}
2256
2257impl Step for LlvmTools {
2258 type Output = Option<GeneratedTarball>;
2259 const ONLY_HOSTS: bool = true;
2260 const DEFAULT: bool = true;
2261
2262 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2263 let default = should_build_extended_tool(run.builder, "llvm-tools");
2264
2265 let mut run = run.alias("llvm-tools");
2266 for tool in LLVM_TOOLS {
2267 run = run.alias(tool);
2268 }
2269
2270 run.default_condition(default)
2271 }
2272
2273 fn make_run(run: RunConfig<'_>) {
2274 run.builder.ensure(LlvmTools { target: run.target });
2275 }
2276
2277 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2278 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2279 let mut tools = vec![];
2280
2281 for path in paths {
2282 let path = path.to_str().unwrap();
2283
2284 if path == "llvm-tools" {
2286 return LLVM_TOOLS.to_owned();
2287 }
2288
2289 for tool in LLVM_TOOLS {
2290 if path == *tool {
2291 tools.push(*tool);
2292 }
2293 }
2294 }
2295
2296 if tools.is_empty() {
2298 tools = LLVM_TOOLS.to_owned();
2299 }
2300
2301 tools
2302 }
2303
2304 let target = self.target;
2305
2306 if let Some(config) = builder.config.target_config.get(&target)
2308 && !builder.config.llvm_from_ci
2309 && config.llvm_config.is_some()
2310 {
2311 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2312 return None;
2313 }
2314
2315 if !builder.config.dry_run() {
2316 builder.require_submodule("src/llvm-project", None);
2317 }
2318
2319 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2320
2321 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2322 tarball.set_overlay(OverlayKind::Llvm);
2323 tarball.is_preview(true);
2324
2325 if builder.config.llvm_tools_enabled {
2326 let src_bindir = builder.llvm_out(target).join("bin");
2328 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2329 for tool in tools_to_install(&builder.paths) {
2330 let exe = src_bindir.join(exe(tool, target));
2331 if !exe.exists() && builder.config.llvm_from_ci {
2333 eprintln!("{} does not exist; skipping copy", exe.display());
2334 continue;
2335 }
2336
2337 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2338 }
2339 }
2340
2341 maybe_install_llvm_target(builder, target, tarball.image_dir());
2346
2347 Some(tarball.generate())
2348 }
2349}
2350
2351#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
2354pub struct LlvmBitcodeLinker {
2355 pub build_compiler: Compiler,
2357 pub target: TargetSelection,
2359}
2360
2361impl Step for LlvmBitcodeLinker {
2362 type Output = Option<GeneratedTarball>;
2363 const DEFAULT: bool = true;
2364 const ONLY_HOSTS: bool = true;
2365
2366 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2367 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2368 run.alias("llvm-bitcode-linker").default_condition(default)
2369 }
2370
2371 fn make_run(run: RunConfig<'_>) {
2372 run.builder.ensure(LlvmBitcodeLinker {
2373 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2374 run.builder,
2375 run.target,
2376 ),
2377 target: run.target,
2378 });
2379 }
2380
2381 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2382 let target = self.target;
2383
2384 let llbc_linker = builder
2385 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2386
2387 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2388
2389 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2391 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2392 tarball.is_preview(true);
2393
2394 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2395
2396 Some(tarball.generate())
2397 }
2398}
2399
2400#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2409pub struct RustDev {
2410 pub target: TargetSelection,
2411}
2412
2413impl Step for RustDev {
2414 type Output = Option<GeneratedTarball>;
2415 const DEFAULT: bool = true;
2416 const ONLY_HOSTS: bool = true;
2417
2418 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2419 run.alias("rust-dev")
2420 }
2421
2422 fn make_run(run: RunConfig<'_>) {
2423 run.builder.ensure(RustDev { target: run.target });
2424 }
2425
2426 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2427 let target = self.target;
2428
2429 if let Some(config) = builder.config.target_config.get(&target)
2431 && let Some(ref _s) = config.llvm_config
2432 {
2433 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2434 return None;
2435 }
2436
2437 if !builder.config.dry_run() {
2438 builder.require_submodule("src/llvm-project", None);
2439 }
2440
2441 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2442 tarball.set_overlay(OverlayKind::Llvm);
2443 tarball.permit_symlinks(true);
2445
2446 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2447
2448 let src_bindir = builder.llvm_out(target).join("bin");
2449 if src_bindir.exists() {
2455 for entry in walkdir::WalkDir::new(&src_bindir) {
2456 let entry = t!(entry);
2457 if entry.file_type().is_file() && !entry.path_is_symlink() {
2458 let name = entry.file_name().to_str().unwrap();
2459 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2460 }
2461 }
2462 }
2463
2464 if builder.config.lld_enabled {
2465 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2467
2468 let lld_path = lld_out.join("bin").join(exe("lld", target));
2470 if lld_path.exists() {
2471 tarball.add_file(&lld_path, "bin", FileType::Executable);
2472 }
2473 }
2474
2475 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2476
2477 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2481
2482 let dst_libdir = tarball.image_dir().join("lib");
2487 maybe_install_llvm(builder, target, &dst_libdir, true);
2488 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2489 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2490
2491 copy_src_dirs(
2495 builder,
2496 &builder.src.join("src").join("llvm-project"),
2497 &["compiler-rt"],
2498 &["compiler-rt/test"],
2501 tarball.image_dir(),
2502 );
2503
2504 Some(tarball.generate())
2505 }
2506}
2507
2508#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2512pub struct Bootstrap {
2513 pub target: TargetSelection,
2514}
2515
2516impl Step for Bootstrap {
2517 type Output = Option<GeneratedTarball>;
2518 const DEFAULT: bool = false;
2519 const ONLY_HOSTS: bool = true;
2520
2521 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2522 run.alias("bootstrap")
2523 }
2524
2525 fn make_run(run: RunConfig<'_>) {
2526 run.builder.ensure(Bootstrap { target: run.target });
2527 }
2528
2529 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2530 let target = self.target;
2531
2532 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2533
2534 let bootstrap_outdir = &builder.bootstrap_out;
2535 for file in &["bootstrap", "rustc", "rustdoc"] {
2536 tarball.add_file(
2537 bootstrap_outdir.join(exe(file, target)),
2538 "bootstrap/bin",
2539 FileType::Executable,
2540 );
2541 }
2542
2543 Some(tarball.generate())
2544 }
2545}
2546
2547#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2552pub struct BuildManifest {
2553 pub target: TargetSelection,
2554}
2555
2556impl Step for BuildManifest {
2557 type Output = GeneratedTarball;
2558 const DEFAULT: bool = false;
2559 const ONLY_HOSTS: bool = true;
2560
2561 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2562 run.alias("build-manifest")
2563 }
2564
2565 fn make_run(run: RunConfig<'_>) {
2566 run.builder.ensure(BuildManifest { target: run.target });
2567 }
2568
2569 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2570 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2571
2572 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2573 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2574 tarball.generate()
2575 }
2576}
2577
2578#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2584pub struct ReproducibleArtifacts {
2585 pub target: TargetSelection,
2586}
2587
2588impl Step for ReproducibleArtifacts {
2589 type Output = Option<GeneratedTarball>;
2590 const DEFAULT: bool = true;
2591 const ONLY_HOSTS: bool = true;
2592
2593 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2594 run.alias("reproducible-artifacts")
2595 }
2596
2597 fn make_run(run: RunConfig<'_>) {
2598 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2599 }
2600
2601 fn run(self, builder: &Builder<'_>) -> Self::Output {
2602 let mut added_anything = false;
2603 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2604 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2605 tarball.add_file(path, ".", FileType::Regular);
2606 added_anything = true;
2607 }
2608 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2609 tarball.add_file(path, ".", FileType::Regular);
2610 added_anything = true;
2611 }
2612 for profile in &builder.config.reproducible_artifacts {
2613 tarball.add_file(profile, ".", FileType::Regular);
2614 added_anything = true;
2615 }
2616 if added_anything { Some(tarball.generate()) } else { None }
2617 }
2618}
2619
2620#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2624pub struct Gcc {
2625 pub target: TargetSelection,
2626}
2627
2628impl Step for Gcc {
2629 type Output = GeneratedTarball;
2630
2631 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2632 run.alias("gcc")
2633 }
2634
2635 fn make_run(run: RunConfig<'_>) {
2636 run.builder.ensure(Gcc { target: run.target });
2637 }
2638
2639 fn run(self, builder: &Builder<'_>) -> Self::Output {
2640 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2641 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2642 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2643 tarball.generate()
2644 }
2645}