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 {compiler, target});
1579
1580 let etc = builder.src.join("src/etc/installer");
1581
1582 if builder.config.dry_run() {
1584 return;
1585 }
1586
1587 let tarball = Tarball::new(builder, "rust", &target.triple);
1588 let generated = tarball.combine(&tarballs);
1589
1590 let tmp = tmpdir(builder).join("combined-tarball");
1591 let work = generated.work_dir();
1592
1593 let mut license = String::new();
1594 license += &builder.read(&builder.src.join("COPYRIGHT"));
1595 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1596 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1597 license.push('\n');
1598 license.push('\n');
1599
1600 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1601 let mut rtf = rtf.to_string();
1602 rtf.push('\n');
1603 for line in license.lines() {
1604 rtf.push_str(line);
1605 rtf.push_str("\\line ");
1606 }
1607 rtf.push('}');
1608
1609 fn filter(contents: &str, marker: &str) -> String {
1610 let start = format!("tool-{marker}-start");
1611 let end = format!("tool-{marker}-end");
1612 let mut lines = Vec::new();
1613 let mut omitted = false;
1614 for line in contents.lines() {
1615 if line.contains(&start) {
1616 omitted = true;
1617 } else if line.contains(&end) {
1618 omitted = false;
1619 } else if !omitted {
1620 lines.push(line);
1621 }
1622 }
1623
1624 lines.join("\n")
1625 }
1626
1627 let xform = |p: &Path| {
1628 let mut contents = t!(fs::read_to_string(p));
1629 for tool in &["miri", "rust-docs"] {
1630 if !built_tools.contains(tool) {
1631 contents = filter(&contents, tool);
1632 }
1633 }
1634 let ret = tmp.join(p.file_name().unwrap());
1635 t!(fs::write(&ret, &contents));
1636 ret
1637 };
1638
1639 if target.contains("apple-darwin") {
1640 builder.info("building pkg installer");
1641 let pkg = tmp.join("pkg");
1642 let _ = fs::remove_dir_all(&pkg);
1643
1644 let pkgbuild = |component: &str| {
1645 let mut cmd = command("pkgbuild");
1646 cmd.arg("--identifier")
1647 .arg(format!("org.rust-lang.{component}"))
1648 .arg("--scripts")
1649 .arg(pkg.join(component))
1650 .arg("--nopayload")
1651 .arg(pkg.join(component).with_extension("pkg"));
1652 cmd.run(builder);
1653 };
1654
1655 let prepare = |name: &str| {
1656 builder.create_dir(&pkg.join(name));
1657 builder.cp_link_r(
1658 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1659 &pkg.join(name),
1660 );
1661 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1662 pkgbuild(name);
1663 };
1664 prepare("rustc");
1665 prepare("cargo");
1666 prepare("rust-std");
1667 prepare("rust-analysis");
1668
1669 for tool in &[
1670 "clippy",
1671 "rustfmt",
1672 "rust-analyzer",
1673 "rust-docs",
1674 "miri",
1675 "rustc-codegen-cranelift",
1676 ] {
1677 if built_tools.contains(tool) {
1678 prepare(tool);
1679 }
1680 }
1681 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1683 pkgbuild("uninstall");
1684
1685 builder.create_dir(&pkg.join("res"));
1686 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1687 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1688 let mut cmd = command("productbuild");
1689 cmd.arg("--distribution")
1690 .arg(xform(&etc.join("pkg/Distribution.xml")))
1691 .arg("--resources")
1692 .arg(pkg.join("res"))
1693 .arg(distdir(builder).join(format!(
1694 "{}-{}.pkg",
1695 pkgname(builder, "rust"),
1696 target.triple
1697 )))
1698 .arg("--package-path")
1699 .arg(&pkg);
1700 let _time = timeit(builder);
1701 cmd.run(builder);
1702 }
1703
1704 if target.is_windows() && !target.contains("gnullvm") {
1706 let exe = tmp.join("exe");
1707 let _ = fs::remove_dir_all(&exe);
1708
1709 let prepare = |name: &str| {
1710 builder.create_dir(&exe.join(name));
1711 let dir = if name == "rust-std" || name == "rust-analysis" {
1712 format!("{}-{}", name, target.triple)
1713 } else if name == "rust-analyzer" {
1714 "rust-analyzer-preview".to_string()
1715 } else if name == "clippy" {
1716 "clippy-preview".to_string()
1717 } else if name == "rustfmt" {
1718 "rustfmt-preview".to_string()
1719 } else if name == "miri" {
1720 "miri-preview".to_string()
1721 } else if name == "rustc-codegen-cranelift" {
1722 unreachable!("cg_clif shouldn't be built for windows");
1725 } else {
1726 name.to_string()
1727 };
1728 builder.cp_link_r(
1729 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1730 &exe.join(name),
1731 );
1732 builder.remove(&exe.join(name).join("manifest.in"));
1733 };
1734 prepare("rustc");
1735 prepare("cargo");
1736 prepare("rust-analysis");
1737 prepare("rust-std");
1738 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1739 if built_tools.contains(tool) {
1740 prepare(tool);
1741 }
1742 }
1743 if target.is_windows_gnu() {
1744 prepare("rust-mingw");
1745 }
1746
1747 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1748
1749 let wix_path = env::var_os("WIX")
1751 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1752 let wix = PathBuf::from(wix_path);
1753 let heat = wix.join("bin/heat.exe");
1754 let candle = wix.join("bin/candle.exe");
1755 let light = wix.join("bin/light.exe");
1756
1757 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1758 command(&heat)
1759 .current_dir(&exe)
1760 .arg("dir")
1761 .arg("rustc")
1762 .args(heat_flags)
1763 .arg("-cg")
1764 .arg("RustcGroup")
1765 .arg("-dr")
1766 .arg("Rustc")
1767 .arg("-var")
1768 .arg("var.RustcDir")
1769 .arg("-out")
1770 .arg(exe.join("RustcGroup.wxs"))
1771 .run(builder);
1772 if built_tools.contains("rust-docs") {
1773 command(&heat)
1774 .current_dir(&exe)
1775 .arg("dir")
1776 .arg("rust-docs")
1777 .args(heat_flags)
1778 .arg("-cg")
1779 .arg("DocsGroup")
1780 .arg("-dr")
1781 .arg("Docs")
1782 .arg("-var")
1783 .arg("var.DocsDir")
1784 .arg("-out")
1785 .arg(exe.join("DocsGroup.wxs"))
1786 .arg("-t")
1787 .arg(etc.join("msi/squash-components.xsl"))
1788 .run(builder);
1789 }
1790 command(&heat)
1791 .current_dir(&exe)
1792 .arg("dir")
1793 .arg("cargo")
1794 .args(heat_flags)
1795 .arg("-cg")
1796 .arg("CargoGroup")
1797 .arg("-dr")
1798 .arg("Cargo")
1799 .arg("-var")
1800 .arg("var.CargoDir")
1801 .arg("-out")
1802 .arg(exe.join("CargoGroup.wxs"))
1803 .arg("-t")
1804 .arg(etc.join("msi/remove-duplicates.xsl"))
1805 .run(builder);
1806 command(&heat)
1807 .current_dir(&exe)
1808 .arg("dir")
1809 .arg("rust-std")
1810 .args(heat_flags)
1811 .arg("-cg")
1812 .arg("StdGroup")
1813 .arg("-dr")
1814 .arg("Std")
1815 .arg("-var")
1816 .arg("var.StdDir")
1817 .arg("-out")
1818 .arg(exe.join("StdGroup.wxs"))
1819 .run(builder);
1820 if built_tools.contains("rust-analyzer") {
1821 command(&heat)
1822 .current_dir(&exe)
1823 .arg("dir")
1824 .arg("rust-analyzer")
1825 .args(heat_flags)
1826 .arg("-cg")
1827 .arg("RustAnalyzerGroup")
1828 .arg("-dr")
1829 .arg("RustAnalyzer")
1830 .arg("-var")
1831 .arg("var.RustAnalyzerDir")
1832 .arg("-out")
1833 .arg(exe.join("RustAnalyzerGroup.wxs"))
1834 .arg("-t")
1835 .arg(etc.join("msi/remove-duplicates.xsl"))
1836 .run(builder);
1837 }
1838 if built_tools.contains("clippy") {
1839 command(&heat)
1840 .current_dir(&exe)
1841 .arg("dir")
1842 .arg("clippy")
1843 .args(heat_flags)
1844 .arg("-cg")
1845 .arg("ClippyGroup")
1846 .arg("-dr")
1847 .arg("Clippy")
1848 .arg("-var")
1849 .arg("var.ClippyDir")
1850 .arg("-out")
1851 .arg(exe.join("ClippyGroup.wxs"))
1852 .arg("-t")
1853 .arg(etc.join("msi/remove-duplicates.xsl"))
1854 .run(builder);
1855 }
1856 if built_tools.contains("rustfmt") {
1857 command(&heat)
1858 .current_dir(&exe)
1859 .arg("dir")
1860 .arg("rustfmt")
1861 .args(heat_flags)
1862 .arg("-cg")
1863 .arg("RustFmtGroup")
1864 .arg("-dr")
1865 .arg("RustFmt")
1866 .arg("-var")
1867 .arg("var.RustFmtDir")
1868 .arg("-out")
1869 .arg(exe.join("RustFmtGroup.wxs"))
1870 .arg("-t")
1871 .arg(etc.join("msi/remove-duplicates.xsl"))
1872 .run(builder);
1873 }
1874 if built_tools.contains("miri") {
1875 command(&heat)
1876 .current_dir(&exe)
1877 .arg("dir")
1878 .arg("miri")
1879 .args(heat_flags)
1880 .arg("-cg")
1881 .arg("MiriGroup")
1882 .arg("-dr")
1883 .arg("Miri")
1884 .arg("-var")
1885 .arg("var.MiriDir")
1886 .arg("-out")
1887 .arg(exe.join("MiriGroup.wxs"))
1888 .arg("-t")
1889 .arg(etc.join("msi/remove-duplicates.xsl"))
1890 .run(builder);
1891 }
1892 command(&heat)
1893 .current_dir(&exe)
1894 .arg("dir")
1895 .arg("rust-analysis")
1896 .args(heat_flags)
1897 .arg("-cg")
1898 .arg("AnalysisGroup")
1899 .arg("-dr")
1900 .arg("Analysis")
1901 .arg("-var")
1902 .arg("var.AnalysisDir")
1903 .arg("-out")
1904 .arg(exe.join("AnalysisGroup.wxs"))
1905 .arg("-t")
1906 .arg(etc.join("msi/remove-duplicates.xsl"))
1907 .run(builder);
1908 if target.is_windows_gnu() {
1909 command(&heat)
1910 .current_dir(&exe)
1911 .arg("dir")
1912 .arg("rust-mingw")
1913 .args(heat_flags)
1914 .arg("-cg")
1915 .arg("GccGroup")
1916 .arg("-dr")
1917 .arg("Gcc")
1918 .arg("-var")
1919 .arg("var.GccDir")
1920 .arg("-out")
1921 .arg(exe.join("GccGroup.wxs"))
1922 .run(builder);
1923 }
1924
1925 let candle = |input: &Path| {
1926 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1927 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1928 let mut cmd = command(&candle);
1929 cmd.current_dir(&exe)
1930 .arg("-nologo")
1931 .arg("-dRustcDir=rustc")
1932 .arg("-dCargoDir=cargo")
1933 .arg("-dStdDir=rust-std")
1934 .arg("-dAnalysisDir=rust-analysis")
1935 .arg("-arch")
1936 .arg(arch)
1937 .arg("-out")
1938 .arg(&output)
1939 .arg(input);
1940 add_env(builder, &mut cmd, target, &built_tools);
1941
1942 if built_tools.contains("clippy") {
1943 cmd.arg("-dClippyDir=clippy");
1944 }
1945 if built_tools.contains("rustfmt") {
1946 cmd.arg("-dRustFmtDir=rustfmt");
1947 }
1948 if built_tools.contains("rust-docs") {
1949 cmd.arg("-dDocsDir=rust-docs");
1950 }
1951 if built_tools.contains("rust-analyzer") {
1952 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1953 }
1954 if built_tools.contains("miri") {
1955 cmd.arg("-dMiriDir=miri");
1956 }
1957 if target.is_windows_gnu() {
1958 cmd.arg("-dGccDir=rust-mingw");
1959 }
1960 cmd.run(builder);
1961 };
1962 candle(&xform(&etc.join("msi/rust.wxs")));
1963 candle(&etc.join("msi/ui.wxs"));
1964 candle(&etc.join("msi/rustwelcomedlg.wxs"));
1965 candle("RustcGroup.wxs".as_ref());
1966 if built_tools.contains("rust-docs") {
1967 candle("DocsGroup.wxs".as_ref());
1968 }
1969 candle("CargoGroup.wxs".as_ref());
1970 candle("StdGroup.wxs".as_ref());
1971 if built_tools.contains("clippy") {
1972 candle("ClippyGroup.wxs".as_ref());
1973 }
1974 if built_tools.contains("rustfmt") {
1975 candle("RustFmtGroup.wxs".as_ref());
1976 }
1977 if built_tools.contains("miri") {
1978 candle("MiriGroup.wxs".as_ref());
1979 }
1980 if built_tools.contains("rust-analyzer") {
1981 candle("RustAnalyzerGroup.wxs".as_ref());
1982 }
1983 candle("AnalysisGroup.wxs".as_ref());
1984
1985 if target.is_windows_gnu() {
1986 candle("GccGroup.wxs".as_ref());
1987 }
1988
1989 builder.create(&exe.join("LICENSE.rtf"), &rtf);
1990 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
1991 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
1992
1993 builder.info(&format!("building `msi` installer with {light:?}"));
1994 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1995 let mut cmd = command(&light);
1996 cmd.arg("-nologo")
1997 .arg("-ext")
1998 .arg("WixUIExtension")
1999 .arg("-ext")
2000 .arg("WixUtilExtension")
2001 .arg("-out")
2002 .arg(exe.join(&filename))
2003 .arg("rust.wixobj")
2004 .arg("ui.wixobj")
2005 .arg("rustwelcomedlg.wixobj")
2006 .arg("RustcGroup.wixobj")
2007 .arg("CargoGroup.wixobj")
2008 .arg("StdGroup.wixobj")
2009 .arg("AnalysisGroup.wixobj")
2010 .current_dir(&exe);
2011
2012 if built_tools.contains("clippy") {
2013 cmd.arg("ClippyGroup.wixobj");
2014 }
2015 if built_tools.contains("rustfmt") {
2016 cmd.arg("RustFmtGroup.wixobj");
2017 }
2018 if built_tools.contains("miri") {
2019 cmd.arg("MiriGroup.wixobj");
2020 }
2021 if built_tools.contains("rust-analyzer") {
2022 cmd.arg("RustAnalyzerGroup.wixobj");
2023 }
2024 if built_tools.contains("rust-docs") {
2025 cmd.arg("DocsGroup.wixobj");
2026 }
2027
2028 if target.is_windows_gnu() {
2029 cmd.arg("GccGroup.wixobj");
2030 }
2031 cmd.arg("-sice:ICE57");
2033
2034 let _time = timeit(builder);
2035 cmd.run(builder);
2036
2037 if !builder.config.dry_run() {
2038 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2039 }
2040 }
2041 }
2042}
2043
2044fn add_env(
2045 builder: &Builder<'_>,
2046 cmd: &mut BootstrapCommand,
2047 target: TargetSelection,
2048 built_tools: &HashSet<&'static str>,
2049) {
2050 let mut parts = builder.version.split('.');
2051 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2052 .env("CFG_RELEASE_NUM", &builder.version)
2053 .env("CFG_RELEASE", builder.rust_release())
2054 .env("CFG_VER_MAJOR", parts.next().unwrap())
2055 .env("CFG_VER_MINOR", parts.next().unwrap())
2056 .env("CFG_VER_PATCH", parts.next().unwrap())
2057 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2059 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2060 .env("CFG_BUILD", target.triple)
2061 .env("CFG_CHANNEL", &builder.config.channel);
2062
2063 if target.contains("windows-gnullvm") {
2064 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2065 } else if target.is_windows_gnu() {
2066 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2067 } else {
2068 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2069 }
2070
2071 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2073 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2074 };
2075 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2076 define_optional_tool("clippy", "CFG_CLIPPY");
2077 define_optional_tool("miri", "CFG_MIRI");
2078 define_optional_tool("rust-analyzer", "CFG_RA");
2079}
2080
2081fn install_llvm_file(
2082 builder: &Builder<'_>,
2083 source: &Path,
2084 destination: &Path,
2085 install_symlink: bool,
2086) {
2087 if builder.config.dry_run() {
2088 return;
2089 }
2090
2091 if source.is_symlink() {
2092 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2095
2096 let full_dest = destination.join(source.file_name().unwrap());
2097 if install_symlink {
2098 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2101 } else {
2102 let link = t!(fs::read_link(source));
2106 let mut linker_script = t!(fs::File::create(full_dest));
2107 t!(write!(linker_script, "INPUT({})\n", link.display()));
2108
2109 let meta = t!(fs::metadata(source));
2112 if let Ok(mtime) = meta.modified() {
2113 t!(linker_script.set_modified(mtime));
2114 }
2115 }
2116 } else {
2117 builder.install(source, destination, FileType::NativeLibrary);
2118 }
2119}
2120
2121#[cfg_attr(
2125 feature = "tracing",
2126 instrument(
2127 level = "trace",
2128 name = "maybe_install_llvm",
2129 skip_all,
2130 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2131 ),
2132)]
2133fn maybe_install_llvm(
2134 builder: &Builder<'_>,
2135 target: TargetSelection,
2136 dst_libdir: &Path,
2137 install_symlink: bool,
2138) -> bool {
2139 if builder.config.is_system_llvm(target) {
2156 trace!("system LLVM requested, no install");
2157 return false;
2158 }
2159
2160 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2166 let src_libdir = builder.llvm_out(target).join("lib");
2167 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2168 if llvm_dylib_path.exists() {
2169 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2170 }
2171 !builder.config.dry_run()
2172 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
2173 llvm::prebuilt_llvm_config(builder, target, true)
2174 {
2175 trace!("LLVM already built, installing LLVM files");
2176 let mut cmd = command(llvm_config);
2177 cmd.arg("--libfiles");
2178 builder.verbose(|| println!("running {cmd:?}"));
2179 let files = cmd.run_capture_stdout(builder).stdout();
2180 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2181 let target_llvm_out = &builder.llvm_out(target);
2182 for file in files.trim_end().split(' ') {
2183 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2185 target_llvm_out.join(relative_path)
2186 } else {
2187 PathBuf::from(file)
2188 };
2189 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2190 }
2191 !builder.config.dry_run()
2192 } else {
2193 false
2194 }
2195}
2196
2197#[cfg_attr(
2199 feature = "tracing",
2200 instrument(
2201 level = "trace",
2202 name = "maybe_install_llvm_target",
2203 skip_all,
2204 fields(
2205 llvm_link_shared = ?builder.llvm_link_shared(),
2206 target = ?target,
2207 sysroot = ?sysroot,
2208 ),
2209 ),
2210)]
2211pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2212 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2213 if builder.llvm_link_shared() {
2217 maybe_install_llvm(builder, target, &dst_libdir, false);
2218 }
2219}
2220
2221#[cfg_attr(
2223 feature = "tracing",
2224 instrument(
2225 level = "trace",
2226 name = "maybe_install_llvm_runtime",
2227 skip_all,
2228 fields(
2229 llvm_link_shared = ?builder.llvm_link_shared(),
2230 target = ?target,
2231 sysroot = ?sysroot,
2232 ),
2233 ),
2234)]
2235pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2236 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2237 if builder.llvm_link_shared() {
2241 maybe_install_llvm(builder, target, &dst_libdir, false);
2242 }
2243}
2244
2245#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2246pub struct LlvmTools {
2247 pub target: TargetSelection,
2248}
2249
2250impl Step for LlvmTools {
2251 type Output = Option<GeneratedTarball>;
2252 const ONLY_HOSTS: bool = true;
2253 const DEFAULT: bool = true;
2254
2255 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2256 let default = should_build_extended_tool(run.builder, "llvm-tools");
2257
2258 let mut run = run.alias("llvm-tools");
2259 for tool in LLVM_TOOLS {
2260 run = run.alias(tool);
2261 }
2262
2263 run.default_condition(default)
2264 }
2265
2266 fn make_run(run: RunConfig<'_>) {
2267 run.builder.ensure(LlvmTools { target: run.target });
2268 }
2269
2270 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2271 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2272 let mut tools = vec![];
2273
2274 for path in paths {
2275 let path = path.to_str().unwrap();
2276
2277 if path == "llvm-tools" {
2279 return LLVM_TOOLS.to_owned();
2280 }
2281
2282 for tool in LLVM_TOOLS {
2283 if path == *tool {
2284 tools.push(*tool);
2285 }
2286 }
2287 }
2288
2289 if tools.is_empty() {
2291 tools = LLVM_TOOLS.to_owned();
2292 }
2293
2294 tools
2295 }
2296
2297 let target = self.target;
2298
2299 if let Some(config) = builder.config.target_config.get(&target)
2301 && !builder.config.llvm_from_ci
2302 && config.llvm_config.is_some()
2303 {
2304 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2305 return None;
2306 }
2307
2308 if !builder.config.dry_run() {
2309 builder.require_submodule("src/llvm-project", None);
2310 }
2311
2312 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2313
2314 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2315 tarball.set_overlay(OverlayKind::Llvm);
2316 tarball.is_preview(true);
2317
2318 if builder.config.llvm_tools_enabled {
2319 let src_bindir = builder.llvm_out(target).join("bin");
2321 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2322 for tool in tools_to_install(&builder.paths) {
2323 let exe = src_bindir.join(exe(tool, target));
2324 if !exe.exists() && builder.config.llvm_from_ci {
2326 eprintln!("{} does not exist; skipping copy", exe.display());
2327 continue;
2328 }
2329
2330 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2331 }
2332 }
2333
2334 maybe_install_llvm_target(builder, target, tarball.image_dir());
2339
2340 Some(tarball.generate())
2341 }
2342}
2343
2344#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
2345pub struct LlvmBitcodeLinker {
2346 pub compiler: Compiler,
2347 pub target: TargetSelection,
2348}
2349
2350impl Step for LlvmBitcodeLinker {
2351 type Output = Option<GeneratedTarball>;
2352 const DEFAULT: bool = true;
2353 const ONLY_HOSTS: bool = true;
2354
2355 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2356 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2357 run.alias("llvm-bitcode-linker").default_condition(default)
2358 }
2359
2360 fn make_run(run: RunConfig<'_>) {
2361 run.builder.ensure(LlvmBitcodeLinker {
2362 compiler: run.builder.compiler_for(
2363 run.builder.top_stage,
2364 run.builder.config.host_target,
2365 run.target,
2366 ),
2367 target: run.target,
2368 });
2369 }
2370
2371 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2372 let compiler = self.compiler;
2373 let target = self.target;
2374
2375 builder.ensure(compile::Rustc::new(compiler, target));
2376
2377 let llbc_linker =
2378 builder.ensure(tool::LlvmBitcodeLinker { compiler, target, extra_features: vec![] });
2379
2380 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2381
2382 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2384 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2385 tarball.is_preview(true);
2386
2387 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2388
2389 Some(tarball.generate())
2390 }
2391}
2392
2393#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2402pub struct RustDev {
2403 pub target: TargetSelection,
2404}
2405
2406impl Step for RustDev {
2407 type Output = Option<GeneratedTarball>;
2408 const DEFAULT: bool = true;
2409 const ONLY_HOSTS: bool = true;
2410
2411 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2412 run.alias("rust-dev")
2413 }
2414
2415 fn make_run(run: RunConfig<'_>) {
2416 run.builder.ensure(RustDev { target: run.target });
2417 }
2418
2419 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2420 let target = self.target;
2421
2422 if let Some(config) = builder.config.target_config.get(&target)
2424 && let Some(ref _s) = config.llvm_config
2425 {
2426 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2427 return None;
2428 }
2429
2430 if !builder.config.dry_run() {
2431 builder.require_submodule("src/llvm-project", None);
2432 }
2433
2434 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2435 tarball.set_overlay(OverlayKind::Llvm);
2436 tarball.permit_symlinks(true);
2438
2439 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2440
2441 let src_bindir = builder.llvm_out(target).join("bin");
2442 if src_bindir.exists() {
2448 for entry in walkdir::WalkDir::new(&src_bindir) {
2449 let entry = t!(entry);
2450 if entry.file_type().is_file() && !entry.path_is_symlink() {
2451 let name = entry.file_name().to_str().unwrap();
2452 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2453 }
2454 }
2455 }
2456
2457 if builder.config.lld_enabled {
2458 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2460
2461 let lld_path = lld_out.join("bin").join(exe("lld", target));
2463 if lld_path.exists() {
2464 tarball.add_file(&lld_path, "bin", FileType::Executable);
2465 }
2466 }
2467
2468 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2469
2470 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2474
2475 let dst_libdir = tarball.image_dir().join("lib");
2480 maybe_install_llvm(builder, target, &dst_libdir, true);
2481 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2482 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2483
2484 copy_src_dirs(
2488 builder,
2489 &builder.src.join("src").join("llvm-project"),
2490 &["compiler-rt"],
2491 &["compiler-rt/test"],
2494 tarball.image_dir(),
2495 );
2496
2497 Some(tarball.generate())
2498 }
2499}
2500
2501#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2505pub struct Bootstrap {
2506 pub target: TargetSelection,
2507}
2508
2509impl Step for Bootstrap {
2510 type Output = Option<GeneratedTarball>;
2511 const DEFAULT: bool = false;
2512 const ONLY_HOSTS: bool = true;
2513
2514 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2515 run.alias("bootstrap")
2516 }
2517
2518 fn make_run(run: RunConfig<'_>) {
2519 run.builder.ensure(Bootstrap { target: run.target });
2520 }
2521
2522 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2523 let target = self.target;
2524
2525 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2526
2527 let bootstrap_outdir = &builder.bootstrap_out;
2528 for file in &["bootstrap", "rustc", "rustdoc"] {
2529 tarball.add_file(
2530 bootstrap_outdir.join(exe(file, target)),
2531 "bootstrap/bin",
2532 FileType::Executable,
2533 );
2534 }
2535
2536 Some(tarball.generate())
2537 }
2538}
2539
2540#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2545pub struct BuildManifest {
2546 pub target: TargetSelection,
2547}
2548
2549impl Step for BuildManifest {
2550 type Output = GeneratedTarball;
2551 const DEFAULT: bool = false;
2552 const ONLY_HOSTS: bool = true;
2553
2554 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2555 run.alias("build-manifest")
2556 }
2557
2558 fn make_run(run: RunConfig<'_>) {
2559 run.builder.ensure(BuildManifest { target: run.target });
2560 }
2561
2562 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2563 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2564
2565 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2566 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2567 tarball.generate()
2568 }
2569}
2570
2571#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2577pub struct ReproducibleArtifacts {
2578 pub target: TargetSelection,
2579}
2580
2581impl Step for ReproducibleArtifacts {
2582 type Output = Option<GeneratedTarball>;
2583 const DEFAULT: bool = true;
2584 const ONLY_HOSTS: bool = true;
2585
2586 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2587 run.alias("reproducible-artifacts")
2588 }
2589
2590 fn make_run(run: RunConfig<'_>) {
2591 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2592 }
2593
2594 fn run(self, builder: &Builder<'_>) -> Self::Output {
2595 let mut added_anything = false;
2596 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2597 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2598 tarball.add_file(path, ".", FileType::Regular);
2599 added_anything = true;
2600 }
2601 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2602 tarball.add_file(path, ".", FileType::Regular);
2603 added_anything = true;
2604 }
2605 for profile in &builder.config.reproducible_artifacts {
2606 tarball.add_file(profile, ".", FileType::Regular);
2607 added_anything = true;
2608 }
2609 if added_anything { Some(tarball.generate()) } else { None }
2610 }
2611}
2612
2613#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2617pub struct Gcc {
2618 pub target: TargetSelection,
2619}
2620
2621impl Step for Gcc {
2622 type Output = GeneratedTarball;
2623
2624 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2625 run.alias("gcc")
2626 }
2627
2628 fn make_run(run: RunConfig<'_>) {
2629 run.builder.ensure(Gcc { target: run.target });
2630 }
2631
2632 fn run(self, builder: &Builder<'_>) -> Self::Output {
2633 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2634 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2635 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2636 tarball.generate()
2637 }
2638}