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::backend::CodegenBackendKind;
23use crate::core::build_steps::compile::{
24 get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name,
25};
26use crate::core::build_steps::doc::DocumentationFormat;
27use crate::core::build_steps::gcc::GccTargetPair;
28use crate::core::build_steps::llvm::{
29 LLVM_CI_LINK_TYPE_PATH, LlvmBuildStatus, get_llvm_build_status,
30};
31use crate::core::build_steps::tool::{
32 self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
33};
34use crate::core::build_steps::vendor::Vendor;
35use crate::core::build_steps::{compile, llvm};
36use crate::core::builder::{
37 Builder, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata,
38};
39use crate::core::compiler::Compiler;
40use crate::core::config::{GccCiMode, TargetSelection};
41use crate::core::session::{DependencyType, FileType, Mode};
42use crate::trace;
43use crate::utils::build_stamp::{self, BuildStamp};
44use crate::utils::channel::{self, Info};
45use crate::utils::exec::{BootstrapCommand, command};
46use crate::utils::helpers::{
47 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
48};
49use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
50
51pub(crate) const LLVM_TOOLS: &[&str] = &[
52 "llvm-cov", "llvm-nm", "llvm-objcopy", "llvm-objdump", "llvm-profdata", "llvm-readobj", "llvm-size", "llvm-strip", "llvm-ar", "llvm-as", "llvm-dis", "llvm-link", "llc", "opt", "llubi", ];
68
69pub(crate) const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
71
72pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
73 format!("{}-{}", component, builder.rust_package_vers())
74}
75
76pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
77 builder.out.join("dist")
78}
79
80pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
81 builder.out.join("tmp/dist")
82}
83
84fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
85 if !builder.config.extended {
86 return false;
87 }
88 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
89}
90
91#[derive(Debug, Clone, Hash, PartialEq, Eq)]
92pub struct Docs {
93 pub host: TargetSelection,
94}
95
96impl CommandLineStep for Docs {
97 type Output = Option<GeneratedTarball>;
98
99 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
100 run.alias("rust-docs")
101 }
102
103 fn is_default_step(builder: &Builder<'_>) -> bool {
104 builder.config.docs
105 }
106
107 fn make_run(run: RunConfig<'_>) {
108 run.builder.ensure(Docs { host: run.target });
109 }
110
111 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
113 let host = self.host;
114 builder.run_default_doc_steps();
118
119 if !builder.config.dry_run() {
122 t!(fs::create_dir_all(builder.doc_out(host)));
123 }
124
125 let dest = "share/doc/rust/html";
126
127 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
128 tarball.set_product_name("Rust Documentation");
129 tarball.add_bulk_dir(builder.doc_out(host), dest);
130 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
131 tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular);
132 Some(tarball.generate())
133 }
134
135 fn metadata(&self) -> Option<StepMetadata> {
136 Some(StepMetadata::dist("docs", self.host))
137 }
138}
139
140#[derive(Debug, Clone, Hash, PartialEq, Eq)]
143pub struct JsonDocs {
144 build_compiler: Compiler,
145 target: TargetSelection,
146}
147
148impl CommandLineStep for JsonDocs {
149 type Output = Option<GeneratedTarball>;
150
151 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
152 run.alias("rust-docs-json")
153 }
154
155 fn is_default_step(builder: &Builder<'_>) -> bool {
156 builder.config.docs
157 }
158
159 fn make_run(run: RunConfig<'_>) {
160 run.builder.ensure(JsonDocs {
161 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
162 target: run.target,
163 });
164 }
165
166 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
167 let target = self.target;
168 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
169 self.build_compiler,
170 target,
171 DocumentationFormat::Json,
172 ));
173
174 let dest = "share/doc/rust/json";
175
176 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
177 tarball.set_product_name("Rust Documentation In JSON Format");
178 tarball.is_preview(true);
179 tarball.add_bulk_dir(directory, dest);
180 Some(tarball.generate())
181 }
182
183 fn metadata(&self) -> Option<StepMetadata> {
184 Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
185 }
186}
187
188#[derive(Debug, Clone, Hash, PartialEq, Eq)]
195pub struct RustcDocs {
196 target: TargetSelection,
197}
198
199impl CommandLineStep for RustcDocs {
200 type Output = GeneratedTarball;
201 const IS_HOST: bool = true;
202
203 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
204 run.alias("rustc-docs")
205 }
206
207 fn is_default_step(builder: &Builder<'_>) -> bool {
208 builder.config.compiler_docs
209 }
210
211 fn make_run(run: RunConfig<'_>) {
212 run.builder.ensure(RustcDocs { target: run.target });
213 }
214
215 fn run(self, builder: &Builder<'_>) -> Self::Output {
216 let target = self.target;
217 builder.run_default_doc_steps();
218
219 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
220 tarball.set_product_name("Rustc Documentation");
221 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc-docs");
222 tarball.generate()
223 }
224}
225
226fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
227 let mut found = Vec::with_capacity(files.len());
228
229 for file in files {
230 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
231
232 if let Some(file_path) = file_path {
233 found.push(file_path);
234 } else {
235 panic!("Could not find '{file}' in {path:?}");
236 }
237 }
238
239 found
240}
241
242fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
243 if builder.config.dry_run() {
244 return;
245 }
246
247 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
248
249 let compiler = if target == "i686-pc-windows-gnu" {
250 "i686-w64-mingw32-gcc.exe"
251 } else if target == "x86_64-pc-windows-gnu" {
252 "x86_64-w64-mingw32-gcc.exe"
253 } else {
254 "gcc.exe"
255 };
256 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
257
258 let target_libs = [
261 "libgcc.a",
263 "libgcc_eh.a",
264 "libgcc_s.a",
265 "libm.a",
266 "libmingw32.a",
267 "libmingwex.a",
268 "libstdc++.a",
269 "libiconv.a",
270 "libmoldname.a",
271 "libpthread.a",
272 "libadvapi32.a",
277 "libbcrypt.a",
278 "libcomctl32.a",
279 "libcomdlg32.a",
280 "libcredui.a",
281 "libcrypt32.a",
282 "libdbghelp.a",
283 "libgdi32.a",
284 "libimagehlp.a",
285 "libiphlpapi.a",
286 "libkernel32.a",
287 "libmsimg32.a",
288 "libmsvcrt.a",
289 "libntdll.a",
290 "libodbc32.a",
291 "libole32.a",
292 "liboleaut32.a",
293 "libopengl32.a",
294 "libpsapi.a",
295 "librpcrt4.a",
296 "libsecur32.a",
297 "libsetupapi.a",
298 "libshell32.a",
299 "libsynchronization.a",
300 "libuser32.a",
301 "libuserenv.a",
302 "libuuid.a",
303 "libwinhttp.a",
304 "libwinmm.a",
305 "libwinspool.a",
306 "libws2_32.a",
307 "libwsock32.a",
308 ];
309
310 let target_tools = find_files(&target_tools, &bin_path);
312 let target_libs = find_files(&target_libs, &lib_path);
313
314 let plat_target_bin_self_contained_dir =
316 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
317 fs::create_dir_all(&plat_target_bin_self_contained_dir)
318 .expect("creating plat_target_bin_self_contained_dir failed");
319 for src in target_tools {
320 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
321 }
322
323 builder.create(
325 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
326 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
327 used as a linker. In order to be able to compile projects containing C code use \
328 the GCC provided by MinGW or Cygwin.",
329 );
330
331 let plat_target_lib_self_contained_dir =
333 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
334 fs::create_dir_all(&plat_target_lib_self_contained_dir)
335 .expect("creating plat_target_lib_self_contained_dir failed");
336 for src in target_libs {
337 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
338 }
339}
340
341fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
342 if builder.config.dry_run() {
343 return;
344 }
345
346 let (_, lib_path) = get_cc_search_dirs(target, builder);
347
348 let target_libs = [
351 "libunwind.a",
353 "libunwind.dll.a",
354 "libmingw32.a",
355 "libmingwex.a",
356 "libmsvcrt.a",
357 "libkernel32.a",
359 "libuser32.a",
360 "libntdll.a",
361 "libuserenv.a",
362 "libws2_32.a",
363 "libdbghelp.a",
364 ];
365
366 let target_libs = find_files(&target_libs, &lib_path);
368
369 let plat_target_lib_self_contained_dir =
371 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
372 fs::create_dir_all(&plat_target_lib_self_contained_dir)
373 .expect("creating plat_target_lib_self_contained_dir failed");
374 for src in target_libs {
375 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
376 }
377}
378
379fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
380 if builder.config.dry_run() {
381 return;
382 }
383
384 let (bin_path, _) = get_cc_search_dirs(target, builder);
385
386 let mut rustc_dlls = vec![];
387 if target.is_windows_gnu() {
389 rustc_dlls.push("libwinpthread-1.dll");
390 if target.starts_with("i686-") {
391 rustc_dlls.push("libgcc_s_dw2-1.dll");
392 } else {
393 rustc_dlls.push("libgcc_s_seh-1.dll");
394 }
395 } else if target.is_windows_gnullvm() {
396 rustc_dlls.push("libunwind.dll");
397 } else {
398 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
399 }
400 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
401
402 let rust_bin_dir = rust_root.join("bin/");
404 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
405 for src in &rustc_dlls {
406 builder.copy_link_to_folder(src, &rust_bin_dir);
407 }
408
409 if builder.config.lld_enabled {
410 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
412 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
413 for src in &rustc_dlls {
414 builder.copy_link_to_folder(src, &rust_target_bin_dir);
415 }
416 }
417}
418
419fn get_cc_search_dirs(
420 target: TargetSelection,
421 builder: &Builder<'_>,
422) -> (Vec<PathBuf>, Vec<PathBuf>) {
423 let mut cmd = command(builder.cc(target));
425 cmd.arg("-print-search-dirs");
426 let gcc_out = cmd.run_capture_stdout(builder).stdout();
427
428 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
429 let mut lib_path = Vec::new();
430
431 for line in gcc_out.lines() {
432 let idx = line.find(':').unwrap();
433 let key = &line[..idx];
434 let trim_chars: &[_] = &[' ', '='];
435 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
436
437 if key == "programs" {
438 bin_path.extend(value);
439 } else if key == "libraries" {
440 lib_path.extend(value);
441 }
442 }
443 (bin_path, lib_path)
444}
445
446#[derive(Debug, Clone, Hash, PartialEq, Eq)]
451pub struct Mingw {
452 target: TargetSelection,
453}
454
455impl CommandLineStep for Mingw {
456 type Output = Option<GeneratedTarball>;
457
458 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
459 run.alias("rust-mingw")
460 }
461
462 fn is_default_step(_builder: &Builder<'_>) -> bool {
463 true
464 }
465
466 fn make_run(run: RunConfig<'_>) {
467 run.builder.ensure(Mingw { target: run.target });
468 }
469
470 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
471 let target = self.target;
472 if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
473 return None;
474 }
475
476 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
477 tarball.set_product_name("Rust MinGW");
478
479 if target.ends_with("pc-windows-gnu") {
480 make_win_dist(tarball.image_dir(), target, builder);
481 } else if target.ends_with("pc-windows-gnullvm") {
482 make_win_llvm_dist(tarball.image_dir(), target, builder);
483 } else {
484 unreachable!();
485 }
486
487 Some(tarball.generate())
488 }
489
490 fn metadata(&self) -> Option<StepMetadata> {
491 Some(StepMetadata::dist("mingw", self.target))
492 }
493}
494
495#[derive(Debug, Clone, Hash, PartialEq, Eq)]
505pub struct Rustc {
506 pub target_compiler: Compiler,
508}
509
510impl CommandLineStep for Rustc {
511 type Output = GeneratedTarball;
512 const IS_HOST: bool = true;
513
514 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
515 run.alias("rustc")
516 }
517
518 fn is_default_step(_builder: &Builder<'_>) -> bool {
519 true
520 }
521
522 fn make_run(run: RunConfig<'_>) {
523 run.builder.ensure(Rustc {
524 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
525 });
526 }
527
528 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
529 let target_compiler = self.target_compiler;
530 let target = self.target_compiler.host;
531
532 let tarball = Tarball::new(builder, "rustc", &target.triple);
533
534 prepare_image(builder, target_compiler, tarball.image_dir());
536
537 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
545 runtime_dll_dist(tarball.image_dir(), target, builder);
546 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
547 }
548
549 return tarball.generate();
550
551 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
552 let target = target_compiler.host;
553 let src = builder.sysroot(target_compiler);
554
555 t!(fs::create_dir_all(image.join("bin")));
557 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
558
559 if builder
561 .config
562 .tools
563 .as_ref()
564 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
565 {
566 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
567 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
568 }
569
570 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
571
572 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
573 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
574 builder.kind,
575 ) {
576 let dst = image.join("libexec");
577 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
578 }
579
580 let libdir_relative = builder.libdir_relative(target_compiler);
581
582 if libdir_relative.to_str() != Some("bin") {
584 let libdir = builder.rustc_libdir(target_compiler);
585 for entry in builder.read_dir(&libdir) {
586 if is_dylib(&entry.path())
592 && !entry
593 .path()
594 .file_name()
595 .and_then(|n| n.to_str())
596 .map(|n| n.contains("libgccjit"))
597 .unwrap_or(false)
598 {
599 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
602 }
603 }
604 }
605
606 maybe_install_llvm_runtime(builder, target, image);
612
613 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
614 t!(fs::create_dir_all(&dst_dir));
615
616 if builder.config.lld_enabled {
618 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
619 let rust_lld = exe("rust-lld", target_compiler.host);
620 builder.copy_link(
621 &src_dir.join(&rust_lld),
622 &dst_dir.join(&rust_lld),
623 FileType::Executable,
624 );
625 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
626 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
627 t!(fs::create_dir(&self_contained_lld_dst_dir));
628 for name in LLD_FILE_NAMES {
629 let exe_name = exe(name, target_compiler.host);
630 builder.copy_link(
631 &self_contained_lld_src_dir.join(&exe_name),
632 &self_contained_lld_dst_dir.join(&exe_name),
633 FileType::Executable,
634 );
635 }
636 }
637
638 if builder.config.llvm_enabled(target_compiler.host)
639 && builder.config.llvm_tools_enabled
640 {
641 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
642 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
643 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
644 builder.copy_link(
645 &src_dir.join(&llvm_objcopy),
646 &dst_dir.join(&rust_objcopy),
647 FileType::Executable,
648 );
649 }
650
651 if builder.tool_enabled("wasm-component-ld") {
652 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
653 let ld = exe("wasm-component-ld", target_compiler.host);
654 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
655 }
656
657 t!(fs::create_dir_all(image.join("share/man/man1")));
659 let man_src = builder.src.join("src/doc/man");
660 let man_dst = image.join("share/man/man1");
661
662 for file_entry in builder.read_dir(&man_src) {
665 let page_src = file_entry.path();
666 let page_dst = man_dst.join(file_entry.file_name());
667 let src_text = t!(std::fs::read_to_string(&page_src));
668 let version = builder.rust_info().version(builder.sess, &builder.version);
669 let new_text = src_text.replace("<INSERT VERSION HERE>", &version);
670 t!(std::fs::write(&page_dst, &new_text));
671 }
672
673 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
675
676 generate_target_spec_json_schema(builder, image);
677
678 let file_list = builder.ensure(super::run::GenerateCopyright);
680 for file in file_list {
681 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
682 }
683
684 builder.install(
686 &builder.src.join("README.md"),
687 &image.join("share/doc/rust"),
688 FileType::Regular,
689 );
690
691 let license = |path: &Path| {
693 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
694 };
695 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
696 license(&entry.path());
697 }
698 }
699 }
700
701 fn metadata(&self) -> Option<StepMetadata> {
702 Some(StepMetadata::dist("rustc", self.target_compiler.host))
703 }
704}
705
706fn generate_target_spec_json_schema(builder: &Builder<'_>, sysroot: &Path) {
707 let stage1_host = builder.compiler(1, builder.host_target);
711 let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
712 rustc
713 .env("RUSTC_BOOTSTRAP", "1")
714 .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
715 let schema = rustc.run_capture(builder).stdout();
716
717 let schema_dir = tmpdir(builder);
718 t!(fs::create_dir_all(&schema_dir));
719 let schema_file = schema_dir.join("target-spec-json-schema.json");
720 t!(std::fs::write(&schema_file, schema));
721
722 let dst = sysroot.join("etc");
723 t!(fs::create_dir_all(&dst));
724
725 builder.install(&schema_file, &dst, FileType::Regular);
726}
727
728#[derive(Debug, Clone, Hash, PartialEq, Eq)]
730pub struct DebuggerScripts {
731 pub sysroot: PathBuf,
733 pub target: TargetSelection,
734}
735
736impl Step for DebuggerScripts {
737 type Output = ();
738
739 fn run(self, builder: &Builder<'_>) {
740 let target = self.target;
741 let sysroot = self.sysroot;
742 let dst = sysroot.join("lib/rustlib/etc");
743 t!(fs::create_dir_all(&dst));
744 let cp_debugger_script = |file: &str| {
745 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
746 };
747 if target.contains("windows-msvc") {
748 builder.install(
750 &builder.src.join("src/etc/rust-windbg.cmd"),
751 &sysroot.join("bin"),
752 FileType::Script,
753 );
754
755 cp_debugger_script("natvis/intrinsic.natvis");
756 cp_debugger_script("natvis/liballoc.natvis");
757 cp_debugger_script("natvis/libcore.natvis");
758 cp_debugger_script("natvis/libstd.natvis");
759 }
760
761 cp_debugger_script("rust_types.py");
762
763 builder.install(
765 &builder.src.join("src/etc/rust-gdb"),
766 &sysroot.join("bin"),
767 FileType::Script,
768 );
769 builder.install(
770 &builder.src.join("src/etc/rust-gdbgui"),
771 &sysroot.join("bin"),
772 FileType::Script,
773 );
774
775 cp_debugger_script("gdb_load_rust_pretty_printers.py");
776 cp_debugger_script("gdb_lookup.py");
777 cp_debugger_script("gdb_providers.py");
778 if builder.sess.unstable_features() {
779 cp_debugger_script("gdb_trim_paths.py");
780 }
781
782 builder.install(
784 &builder.src.join("src/etc/rust-lldb"),
785 &sysroot.join("bin"),
786 FileType::Script,
787 );
788
789 cp_debugger_script("lldb_lookup.py");
790 cp_debugger_script("lldb_providers.py");
791 if builder.sess.unstable_features() {
792 cp_debugger_script("lldb_trim_paths.py");
793 }
794 }
795}
796
797fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
798 if !builder.config.is_host_target(compiler.host) {
801 builder.info("\tskipping, not a build host");
802 true
803 } else {
804 false
805 }
806}
807
808fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
812 if !target.ends_with("-uefi") {
813 return;
814 }
815
816 for (path, _) in builder.read_stamp_file(stamp) {
817 if path.extension() != Some(OsStr::new("rlib")) {
818 continue;
819 }
820
821 let data = t!(fs::read(&path));
822 let data = data.as_slice();
823 let archive = t!(ArchiveFile::parse(data));
824 for member in archive.members() {
825 let member = t!(member);
826 let member_data = t!(member.data(data));
827
828 let is_coff = match object::File::parse(member_data) {
829 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
830 Err(_) => false,
831 };
832
833 if !is_coff {
834 let member_name = String::from_utf8_lossy(member.name());
835 panic!("member {} in {} is not COFF", member_name, path.display());
836 }
837 }
838 }
839}
840
841fn copy_target_libs(
843 builder: &Builder<'_>,
844 target: TargetSelection,
845 image: &Path,
846 stamp: &BuildStamp,
847) {
848 let dst = image.join("lib/rustlib").join(target).join("lib");
849 let self_contained_dst = dst.join("self-contained");
850 t!(fs::create_dir_all(&dst));
851 t!(fs::create_dir_all(&self_contained_dst));
852 for (path, dependency_type) in builder.read_stamp_file(stamp) {
853 if dependency_type == DependencyType::TargetSelfContained {
854 builder.copy_link(
855 &path,
856 &self_contained_dst.join(path.file_name().unwrap()),
857 FileType::NativeLibrary,
858 );
859 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
860 {
861 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
862 }
863 }
864}
865
866#[derive(Debug, Clone, Hash, PartialEq, Eq)]
873pub struct Std {
874 pub build_compiler: Compiler,
876 pub target: TargetSelection,
877}
878
879impl Std {
880 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
881 Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
882 }
883}
884
885impl CommandLineStep for Std {
886 type Output = Option<GeneratedTarball>;
887
888 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
889 run.alias("rust-std")
890 }
891
892 fn is_default_step(_builder: &Builder<'_>) -> bool {
893 true
894 }
895
896 fn make_run(run: RunConfig<'_>) {
897 run.builder.ensure(Std::new(run.builder, run.target));
898 }
899
900 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
901 let build_compiler = self.build_compiler;
902 let target = self.target;
903
904 if skip_host_target_lib(builder, build_compiler) {
905 return None;
906 }
907
908 let stamp =
911 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
912
913 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
914 tarball.include_target_in_component_name(true);
915
916 verify_uefi_rlib_format(builder, target, &stamp);
917 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
918
919 Some(tarball.generate())
920 }
921
922 fn metadata(&self) -> Option<StepMetadata> {
923 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
924 }
925}
926
927#[derive(Debug, Clone, Hash, PartialEq, Eq)]
932pub struct RustcDev {
933 pub build_compiler: Compiler,
935 pub target: TargetSelection,
936}
937
938impl RustcDev {
939 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
940 Self {
941 build_compiler: builder.compiler(1, builder.config.host_target),
945 target,
946 }
947 }
948}
949
950impl CommandLineStep for RustcDev {
951 type Output = Option<GeneratedTarball>;
952 const IS_HOST: bool = true;
953
954 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
955 run.alias("rustc-dev")
956 }
957
958 fn is_default_step(_builder: &Builder<'_>) -> bool {
959 true
960 }
961
962 fn make_run(run: RunConfig<'_>) {
963 run.builder.ensure(RustcDev::new(run.builder, run.target));
964 }
965
966 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
967 let build_compiler = self.build_compiler;
968 let target = self.target;
969 if skip_host_target_lib(builder, build_compiler) {
970 return None;
971 }
972
973 builder.ensure(compile::Rustc::new(build_compiler, target));
975
976 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
977
978 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
979 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
980
981 let src_files = &["Cargo.lock"];
982 copy_src_dirs(
985 builder,
986 &builder.src,
987 &["compiler", "library/proc_macro"],
989 &[],
990 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
991 );
992 for file in src_files {
993 tarball.add_file(
994 builder.src.join(file),
995 "lib/rustlib/rustc-src/rust",
996 FileType::Regular,
997 );
998 }
999
1000 Some(tarball.generate())
1001 }
1002
1003 fn metadata(&self) -> Option<StepMetadata> {
1004 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
1005 }
1006}
1007
1008#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1013pub struct Analysis {
1014 build_compiler: Compiler,
1015 target: TargetSelection,
1016}
1017
1018impl CommandLineStep for Analysis {
1019 type Output = Option<GeneratedTarball>;
1020
1021 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1022 run.alias("rust-analysis")
1023 }
1024
1025 fn is_default_step(builder: &Builder<'_>) -> bool {
1026 should_build_extended_tool(builder, "analysis")
1027 }
1028
1029 fn make_run(run: RunConfig<'_>) {
1030 run.builder.ensure(Analysis {
1032 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
1033 target: run.target,
1034 });
1035 }
1036
1037 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1038 let compiler = self.build_compiler;
1039 let target = self.target;
1040 if skip_host_target_lib(builder, compiler) {
1041 return None;
1042 }
1043
1044 let src = builder
1045 .stage_out(compiler, Mode::Std)
1046 .join(target)
1047 .join(builder.cargo_dir(Mode::Std))
1048 .join("deps")
1049 .join("save-analysis");
1050
1051 t!(std::fs::create_dir_all(&src));
1053 let mut removed = src.clone();
1054 removed.push("removed.json");
1055 let mut f = t!(std::fs::File::create(removed));
1056 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
1057
1058 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
1059 tarball.include_target_in_component_name(true);
1060 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
1061 Some(tarball.generate())
1062 }
1063
1064 fn metadata(&self) -> Option<StepMetadata> {
1065 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
1066 }
1067}
1068
1069fn copy_src_dirs(
1072 builder: &Builder<'_>,
1073 base: &Path,
1074 src_dirs: &[&str],
1075 exclude_dirs: &[&str],
1076 dst_dir: &Path,
1077) {
1078 for src_dir in src_dirs {
1081 assert!(Path::new(src_dir).is_relative());
1082 }
1083
1084 if builder.config.dry_run() {
1087 return;
1088 }
1089
1090 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
1091 let spath = match path.to_str() {
1093 Some(path) => path,
1094 None => return false,
1095 };
1096 if spath.ends_with('~') || spath.ends_with(".pyc") {
1097 return false;
1098 }
1099 let spath = spath.replace("\\", "/");
1101
1102 static LLVM_PROJECTS: &[&str] = &[
1103 "llvm-project/clang",
1104 "llvm-project/libc",
1105 "llvm-project/libunwind",
1106 "llvm-project/lld",
1107 "llvm-project/lldb",
1108 "llvm-project/llvm",
1109 "llvm-project/compiler-rt",
1110 "llvm-project/cmake",
1111 "llvm-project/runtimes",
1112 "llvm-project/third-party",
1113 ];
1114 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1115 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1116 return false;
1117 }
1118
1119 if spath.starts_with("llvm-project/third-party")
1121 && spath != "llvm-project/third-party"
1122 && !spath.starts_with("llvm-project/third-party/siphash")
1123 {
1124 return false;
1125 }
1126
1127 if spath.starts_with("llvm-project/llvm/test")
1128 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1129 {
1130 return false;
1131 }
1132 }
1133
1134 if spath.starts_with("tools/cargo/tests") {
1136 return true;
1137 }
1138
1139 if !exclude_dirs.is_empty() {
1140 let full_path = Path::new(dir).join(path);
1141 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1142 return false;
1143 }
1144 }
1145
1146 static EXCLUDES: &[&str] = &[
1147 "CVS",
1148 "RCS",
1149 "SCCS",
1150 ".git",
1151 ".gitignore",
1152 ".gitmodules",
1153 ".gitattributes",
1154 ".cvsignore",
1155 ".svn",
1156 ".arch-ids",
1157 "{arch}",
1158 "=RELEASE-ID",
1159 "=meta-update",
1160 "=update",
1161 ".bzr",
1162 ".bzrignore",
1163 ".bzrtags",
1164 ".hg",
1165 ".hgignore",
1166 ".hgrags",
1167 "_darcs",
1168 ];
1169
1170 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1177 !EXCLUDES.contains(&last_component)
1178 }
1179
1180 for item in src_dirs {
1182 let dst = &dst_dir.join(item);
1183 t!(fs::create_dir_all(dst));
1184 builder
1185 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1186 }
1187}
1188
1189#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1190pub struct Src;
1191
1192impl CommandLineStep for Src {
1193 type Output = GeneratedTarball;
1195 const IS_HOST: bool = true;
1196
1197 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1198 run.alias("rust-src")
1199 }
1200
1201 fn is_default_step(_builder: &Builder<'_>) -> bool {
1202 true
1203 }
1204
1205 fn make_run(run: RunConfig<'_>) {
1206 run.builder.ensure(Src);
1207 }
1208
1209 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1211 if !builder.config.dry_run() {
1212 builder.require_submodule("src/llvm-project", None);
1213 }
1214
1215 let tarball = Tarball::new_targetless(builder, "rust-src");
1216
1217 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1225
1226 copy_src_dirs(
1229 builder,
1230 &builder.src,
1231 &["library", "src/llvm-project/libunwind"],
1232 &[
1233 "library/backtrace/crates",
1236 ],
1237 &dst_src,
1238 );
1239
1240 let vendor = builder.ensure(Vendor {
1242 sync_args: vec![],
1243 versioned_dirs: true,
1244 root_dir: dst_src.clone(),
1245 output_dir: None,
1246 only_library_workspace: true,
1247 });
1248
1249 let library_cargo_config_dir = dst_src.join("library").join(".cargo");
1250 builder.create_dir(&library_cargo_config_dir);
1251 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1252
1253 tarball.generate()
1254 }
1255
1256 fn metadata(&self) -> Option<StepMetadata> {
1257 Some(StepMetadata::dist("src", TargetSelection::default()))
1258 }
1259}
1260
1261#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1265pub struct PlainSourceTarball;
1266
1267impl CommandLineStep for PlainSourceTarball {
1268 type Output = GeneratedTarball;
1270 const IS_HOST: bool = true;
1271
1272 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1273 run.alias("rustc-src")
1274 }
1275
1276 fn is_default_step(builder: &Builder<'_>) -> bool {
1277 builder.config.rust_dist_src
1278 }
1279
1280 fn make_run(run: RunConfig<'_>) {
1281 run.builder.ensure(PlainSourceTarball);
1282 }
1283
1284 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1286 let tarball = prepare_source_tarball(
1287 builder,
1288 "src",
1289 &[
1290 "src/gcc",
1294 ],
1295 );
1296
1297 let plain_dst_src = tarball.image_dir();
1298 if !builder.config.dry_run() {
1303 builder.create_dir(&plain_dst_src.join("src/gcc"));
1304 t!(std::fs::write(
1305 plain_dst_src.join("src/gcc/notice.txt"),
1306 "The GCC source code is not included due to unclear licensing implications\n"
1307 ));
1308 }
1309 tarball.bare()
1310 }
1311}
1312
1313#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1315pub struct PlainSourceTarballGpl;
1316
1317impl CommandLineStep for PlainSourceTarballGpl {
1318 type Output = GeneratedTarball;
1320 const IS_HOST: bool = true;
1321
1322 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1323 run.alias("rustc-src-gpl")
1324 }
1325
1326 fn is_default_step(builder: &Builder<'_>) -> bool {
1327 builder.config.rust_dist_src
1328 }
1329
1330 fn make_run(run: RunConfig<'_>) {
1331 run.builder.ensure(PlainSourceTarballGpl);
1332 }
1333
1334 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1336 let tarball = prepare_source_tarball(builder, "src-gpl", &[]);
1337 tarball.bare()
1338 }
1339}
1340
1341fn prepare_source_tarball<'a>(
1342 builder: &'a Builder<'a>,
1343 name: &str,
1344 exclude_dirs: &[&str],
1345) -> Tarball<'a> {
1346 let mut tarball = Tarball::new(builder, "rustc", name);
1351 tarball.permit_symlinks(true);
1352 let plain_dst_src = tarball.image_dir();
1353
1354 let src_files = [
1356 ".gitmodules",
1358 "CONTRIBUTING.md",
1359 "COPYRIGHT",
1360 "Cargo.lock",
1361 "Cargo.toml",
1362 "LICENSE-APACHE",
1363 "LICENSE-MIT",
1364 "README.md",
1365 "RELEASES.md",
1366 "REUSE.toml",
1367 "bootstrap.example.toml",
1368 "configure",
1369 "license-metadata.json",
1370 "package.json",
1371 "x",
1372 "x.ps1",
1373 "x.py",
1374 "yarn.lock",
1375 ];
1377 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1378
1379 copy_src_dirs(builder, &builder.src, &src_dirs, exclude_dirs, plain_dst_src);
1380
1381 for item in &src_files {
1383 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item), FileType::Regular);
1384 }
1385
1386 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1388
1389 let write_git_info = |info: Option<&Info>, path: &Path| {
1391 if let Some(info) = info {
1392 t!(std::fs::create_dir_all(path));
1393 channel::write_commit_hash_file(path, &info.sha);
1394 channel::write_commit_info_file(path, info);
1395 }
1396 };
1397 write_git_info(builder.rust_info().info(), plain_dst_src);
1398 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1399
1400 if builder.config.dist_vendor {
1401 builder.require_and_update_all_submodules();
1402
1403 let pkgs_for_pgo_training =
1405 build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| {
1406 let mut manifest_path =
1407 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1408 manifest_path.push(pkg);
1409 manifest_path.push("Cargo.toml");
1410 manifest_path
1411 });
1412
1413 let vendor = builder.ensure(Vendor {
1415 sync_args: pkgs_for_pgo_training.collect(),
1416 versioned_dirs: true,
1417 root_dir: plain_dst_src.into(),
1418 output_dir: None,
1419 only_library_workspace: false,
1420 });
1421
1422 let cargo_config_dir = plain_dst_src.join(".cargo");
1423 builder.create_dir(&cargo_config_dir);
1424 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1425
1426 let library_cargo_config_dir = plain_dst_src.join("library").join(".cargo");
1427 builder.create_dir(&library_cargo_config_dir);
1428 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1429 }
1430
1431 for entry in walkdir::WalkDir::new(tarball.image_dir())
1435 .follow_links(true)
1436 .into_iter()
1437 .filter_map(|e| e.ok())
1438 {
1439 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__")) {
1440 t!(fs::remove_dir_all(entry.path()));
1441 }
1442 }
1443 tarball
1444}
1445
1446#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1447pub struct Cargo {
1448 pub build_compiler: Compiler,
1449 pub target: TargetSelection,
1450}
1451
1452impl CommandLineStep for Cargo {
1453 type Output = Option<GeneratedTarball>;
1454 const IS_HOST: bool = true;
1455
1456 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1457 run.alias("cargo")
1458 }
1459
1460 fn is_default_step(builder: &Builder<'_>) -> bool {
1461 should_build_extended_tool(builder, "cargo")
1462 }
1463
1464 fn make_run(run: RunConfig<'_>) {
1465 run.builder.ensure(Cargo {
1466 build_compiler: get_tool_target_compiler(
1467 run.builder,
1468 ToolTargetBuildMode::Build(run.target),
1469 ),
1470 target: run.target,
1471 });
1472 }
1473
1474 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1475 let build_compiler = self.build_compiler;
1476 let target = self.target;
1477
1478 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1479 let src = builder.src.join("src/tools/cargo");
1480 let etc = src.join("etc");
1481
1482 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1484 tarball.set_overlay(OverlayKind::Cargo);
1485
1486 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1487 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1488 tarball.add_renamed_file(
1489 etc.join("cargo.bashcomp.sh"),
1490 "etc/bash_completion.d",
1491 "cargo",
1492 FileType::Regular,
1493 );
1494 tarball.add_dir(etc.join("man"), "share/man/man1");
1495 tarball.add_legal_and_readme_to("share/doc/cargo");
1496
1497 Some(tarball.generate())
1498 }
1499
1500 fn metadata(&self) -> Option<StepMetadata> {
1501 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1502 }
1503}
1504
1505#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1507pub struct RustAnalyzer {
1508 pub compilers: RustcPrivateCompilers,
1509 pub target: TargetSelection,
1510}
1511
1512impl CommandLineStep for RustAnalyzer {
1513 type Output = Option<GeneratedTarball>;
1514 const IS_HOST: bool = true;
1515
1516 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1517 run.alias("rust-analyzer")
1518 }
1519
1520 fn is_default_step(builder: &Builder<'_>) -> bool {
1521 should_build_extended_tool(builder, "rust-analyzer")
1522 }
1523
1524 fn make_run(run: RunConfig<'_>) {
1525 run.builder.ensure(RustAnalyzer {
1526 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1527 target: run.target,
1528 });
1529 }
1530
1531 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1532 let target = self.target;
1533 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1534
1535 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1536 tarball.set_overlay(OverlayKind::RustAnalyzer);
1537 tarball.is_preview(true);
1538 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1539 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1540 Some(tarball.generate())
1541 }
1542
1543 fn metadata(&self) -> Option<StepMetadata> {
1544 Some(
1545 StepMetadata::dist("rust-analyzer", self.target)
1546 .built_by(self.compilers.build_compiler()),
1547 )
1548 }
1549}
1550
1551#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1552pub struct Clippy {
1553 pub compilers: RustcPrivateCompilers,
1554 pub target: TargetSelection,
1555}
1556
1557impl CommandLineStep for Clippy {
1558 type Output = Option<GeneratedTarball>;
1559 const IS_HOST: bool = true;
1560
1561 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1562 run.alias("clippy")
1563 }
1564
1565 fn is_default_step(builder: &Builder<'_>) -> bool {
1566 should_build_extended_tool(builder, "clippy")
1567 }
1568
1569 fn make_run(run: RunConfig<'_>) {
1570 run.builder.ensure(Clippy {
1571 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1572 target: run.target,
1573 });
1574 }
1575
1576 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1577 let target = self.target;
1578
1579 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1583 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1584
1585 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1586 tarball.set_overlay(OverlayKind::Clippy);
1587 tarball.is_preview(true);
1588 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1589 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1590 tarball.add_legal_and_readme_to("share/doc/clippy");
1591 Some(tarball.generate())
1592 }
1593
1594 fn metadata(&self) -> Option<StepMetadata> {
1595 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1596 }
1597}
1598
1599#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1600pub struct Miri {
1601 pub compilers: RustcPrivateCompilers,
1602 pub target: TargetSelection,
1603}
1604
1605impl CommandLineStep for Miri {
1606 type Output = Option<GeneratedTarball>;
1607 const IS_HOST: bool = true;
1608
1609 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1610 run.alias("miri")
1611 }
1612
1613 fn is_default_step(builder: &Builder<'_>) -> bool {
1614 should_build_extended_tool(builder, "miri")
1615 }
1616
1617 fn make_run(run: RunConfig<'_>) {
1618 run.builder.ensure(Miri {
1619 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1620 target: run.target,
1621 });
1622 }
1623
1624 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1625 if !builder.sess.unstable_features() {
1629 return None;
1630 }
1631
1632 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1633 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1634
1635 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1636 tarball.set_overlay(OverlayKind::Miri);
1637 tarball.is_preview(true);
1638 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1639 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1640 tarball.add_legal_and_readme_to("share/doc/miri");
1641 Some(tarball.generate())
1642 }
1643
1644 fn metadata(&self) -> Option<StepMetadata> {
1645 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1646 }
1647}
1648
1649#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1650pub struct CraneliftCodegenBackend {
1651 pub compilers: RustcPrivateCompilers,
1652 pub target: TargetSelection,
1653}
1654
1655impl CommandLineStep for CraneliftCodegenBackend {
1656 type Output = Option<GeneratedTarball>;
1657 const IS_HOST: bool = true;
1658
1659 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1660 run.alias("rustc_codegen_cranelift")
1661 }
1662
1663 fn is_default_step(builder: &Builder<'_>) -> bool {
1664 builder
1669 .config
1670 .enabled_codegen_backends(builder.host_target)
1671 .contains(&CodegenBackendKind::Cranelift)
1672 }
1673
1674 fn make_run(run: RunConfig<'_>) {
1675 run.builder.ensure(CraneliftCodegenBackend {
1676 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1677 target: run.target,
1678 });
1679 }
1680
1681 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1682 if !builder.sess.unstable_features() {
1686 return None;
1687 }
1688
1689 let target = self.target;
1690 if !target_supports_cranelift_backend(target) {
1691 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1692 return None;
1693 }
1694
1695 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1696 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1697 tarball.is_preview(true);
1698 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1699
1700 let compilers = self.compilers;
1701 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1702
1703 if builder.config.dry_run() {
1704 return None;
1705 }
1706
1707 add_codegen_backend_to_tarball(builder, &tarball, compilers.target_compiler(), &stamp);
1708
1709 Some(tarball.generate())
1710 }
1711
1712 fn metadata(&self) -> Option<StepMetadata> {
1713 Some(
1714 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1715 .built_by(self.compilers.build_compiler()),
1716 )
1717 }
1718}
1719
1720#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1724pub struct GccCodegenBackend {
1725 pub compilers: RustcPrivateCompilers,
1726 pub target: TargetSelection,
1727}
1728
1729impl CommandLineStep for GccCodegenBackend {
1730 type Output = Option<GeneratedTarball>;
1731 const IS_HOST: bool = true;
1732
1733 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1734 run.alias("rustc_codegen_gcc")
1735 }
1736
1737 fn is_default_step(builder: &Builder<'_>) -> bool {
1738 builder
1743 .config
1744 .enabled_codegen_backends(builder.host_target)
1745 .contains(&CodegenBackendKind::Gcc)
1746 }
1747
1748 fn make_run(run: RunConfig<'_>) {
1749 run.builder.ensure(GccCodegenBackend {
1750 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1751 target: run.target,
1752 });
1753 }
1754
1755 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1756 if !builder.sess.unstable_features() {
1760 return None;
1761 }
1762
1763 let target = self.target;
1764 if target != "x86_64-unknown-linux-gnu" {
1765 builder
1766 .info(&format!("target `{target}` not supported by rustc_codegen_gcc. skipping"));
1767 return None;
1768 }
1769
1770 let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", &target.triple);
1771 tarball.set_overlay(OverlayKind::RustcCodegenGcc);
1772 tarball.is_preview(true);
1773 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
1774
1775 let compilers = self.compilers;
1776 let backend = builder.ensure(compile::GccCodegenBackend::for_target(compilers, target));
1777
1778 if builder.config.dry_run() {
1779 return None;
1780 }
1781
1782 add_codegen_backend_to_tarball(
1783 builder,
1784 &tarball,
1785 compilers.target_compiler(),
1786 backend.stamp(),
1787 );
1788
1789 Some(tarball.generate())
1790 }
1791
1792 fn metadata(&self) -> Option<StepMetadata> {
1793 Some(
1794 StepMetadata::dist("rustc_codegen_gcc", self.target)
1795 .built_by(self.compilers.build_compiler()),
1796 )
1797 }
1798}
1799
1800fn add_codegen_backend_to_tarball(
1803 builder: &Builder<'_>,
1804 tarball: &Tarball<'_>,
1805 compiler: Compiler,
1806 stamp: &BuildStamp,
1807) {
1808 let backends_dst = builder.sysroot_codegen_backends(compiler);
1810 let backends_rel = backends_dst
1811 .strip_prefix(builder.sysroot(compiler))
1812 .unwrap()
1813 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1814 .unwrap();
1815 let backends_dst = PathBuf::from("lib").join(backends_rel);
1817
1818 let codegen_backend_dylib = get_codegen_backend_file(stamp);
1819 tarball.add_renamed_file(
1820 &codegen_backend_dylib,
1821 &backends_dst,
1822 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1823 FileType::NativeLibrary,
1824 );
1825}
1826
1827#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1828pub struct Rustfmt {
1829 pub compilers: RustcPrivateCompilers,
1830 pub target: TargetSelection,
1831}
1832
1833impl CommandLineStep for Rustfmt {
1834 type Output = Option<GeneratedTarball>;
1835 const IS_HOST: bool = true;
1836
1837 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1838 run.alias("rustfmt")
1839 }
1840
1841 fn is_default_step(builder: &Builder<'_>) -> bool {
1842 should_build_extended_tool(builder, "rustfmt")
1843 }
1844
1845 fn make_run(run: RunConfig<'_>) {
1846 run.builder.ensure(Rustfmt {
1847 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1848 target: run.target,
1849 });
1850 }
1851
1852 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1853 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1854 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1855
1856 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1857 tarball.set_overlay(OverlayKind::Rustfmt);
1858 tarball.is_preview(true);
1859 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1860 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1861 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1862 Some(tarball.generate())
1863 }
1864
1865 fn metadata(&self) -> Option<StepMetadata> {
1866 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1867 }
1868}
1869
1870#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1872pub struct Extended {
1873 build_compiler: Compiler,
1874 target: TargetSelection,
1875}
1876
1877impl CommandLineStep for Extended {
1878 type Output = ();
1879 const IS_HOST: bool = true;
1880
1881 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1882 run.alias("extended")
1883 }
1884
1885 fn is_default_step(builder: &Builder<'_>) -> bool {
1886 builder.config.extended
1887 }
1888
1889 fn make_run(run: RunConfig<'_>) {
1890 run.builder.ensure(Extended {
1891 build_compiler: run
1892 .builder
1893 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1894 target: run.target,
1895 });
1896 }
1897
1898 fn run(self, builder: &Builder<'_>) {
1900 let target = self.target;
1901 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1902
1903 let mut tarballs = Vec::new();
1904 let mut built_tools = HashSet::new();
1905 macro_rules! add_component {
1906 ($name:expr => $step:expr) => {
1907 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1908 tarballs.push(tarball);
1909 built_tools.insert($name);
1910 }
1911 };
1912 }
1913
1914 let rustc_private_compilers =
1915 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1916 let build_compiler = rustc_private_compilers.build_compiler();
1917 let target_compiler = rustc_private_compilers.target_compiler();
1918
1919 tarballs.push(builder.ensure(Rustc { target_compiler }));
1924 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1925
1926 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1927 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1928 }
1929
1930 add_component!("rust-docs" => Docs { host: target });
1931 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1933 add_component!("cargo" => Cargo { build_compiler, target });
1934 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1935 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1936 add_component!("llvm-components" => LlvmTools { target });
1937 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1938 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1939 add_component!("analysis" => Analysis { build_compiler, target });
1940 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1941 compilers: rustc_private_compilers,
1942 target
1943 });
1944 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1945 build_compiler,
1946 target
1947 });
1948
1949 let etc = builder.src.join("src/etc/installer");
1950
1951 if builder.config.dry_run() {
1953 return;
1954 }
1955
1956 let tarball = Tarball::new(builder, "rust", &target.triple);
1957 let generated = tarball.combine(&tarballs);
1958
1959 let tmp = tmpdir(builder).join("combined-tarball");
1960 let work = generated.work_dir();
1961
1962 let mut license = String::new();
1963 license += &builder.read(&builder.src.join("COPYRIGHT"));
1964 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1965 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1966 license.push('\n');
1967 license.push('\n');
1968
1969 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1970 let mut rtf = rtf.to_string();
1971 rtf.push('\n');
1972 for line in license.lines() {
1973 rtf.push_str(line);
1974 rtf.push_str("\\line ");
1975 }
1976 rtf.push('}');
1977
1978 fn filter(contents: &str, marker: &str) -> String {
1979 let start = format!("tool-{marker}-start");
1980 let end = format!("tool-{marker}-end");
1981 let mut lines = Vec::new();
1982 let mut omitted = false;
1983 for line in contents.lines() {
1984 if line.contains(&start) {
1985 omitted = true;
1986 } else if line.contains(&end) {
1987 omitted = false;
1988 } else if !omitted {
1989 lines.push(line);
1990 }
1991 }
1992
1993 lines.join("\n")
1994 }
1995
1996 let xform = |p: &Path| {
1997 let mut contents = t!(fs::read_to_string(p));
1998 for tool in &["miri", "rust-docs"] {
1999 if !built_tools.contains(tool) {
2000 contents = filter(&contents, tool);
2001 }
2002 }
2003 let ret = tmp.join(p.file_name().unwrap());
2004 t!(fs::write(&ret, &contents));
2005 ret
2006 };
2007
2008 if target.contains("apple-darwin") {
2009 builder.info("building pkg installer");
2010 let pkg = tmp.join("pkg");
2011 let _ = fs::remove_dir_all(&pkg);
2012
2013 let pkgbuild = |component: &str| {
2014 let mut cmd = command("pkgbuild");
2015 cmd.arg("--identifier")
2016 .arg(format!("org.rust-lang.{component}"))
2017 .arg("--scripts")
2018 .arg(pkg.join(component))
2019 .arg("--nopayload")
2020 .arg(pkg.join(component).with_extension("pkg"));
2021 cmd.run(builder);
2022 };
2023
2024 let prepare = |name: &str| {
2025 builder.create_dir(&pkg.join(name));
2026 builder.cp_link_r(
2027 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
2028 &pkg.join(name),
2029 );
2030 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
2031 pkgbuild(name);
2032 };
2033 prepare("rustc");
2034 prepare("cargo");
2035 prepare("rust-std");
2036 prepare("rust-analysis");
2037
2038 for tool in &[
2039 "clippy",
2040 "rustfmt",
2041 "rust-analyzer",
2042 "rust-docs",
2043 "miri",
2044 "rustc-codegen-cranelift",
2045 ] {
2046 if built_tools.contains(tool) {
2047 prepare(tool);
2048 }
2049 }
2050 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
2052 pkgbuild("uninstall");
2053
2054 builder.create_dir(&pkg.join("res"));
2055 builder.create(&pkg.join("res/LICENSE.txt"), &license);
2056 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
2057 let mut cmd = command("productbuild");
2058 cmd.arg("--distribution")
2059 .arg(xform(&etc.join("pkg/Distribution.xml")))
2060 .arg("--resources")
2061 .arg(pkg.join("res"))
2062 .arg(distdir(builder).join(format!(
2063 "{}-{}.pkg",
2064 pkgname(builder, "rust"),
2065 target.triple
2066 )))
2067 .arg("--package-path")
2068 .arg(&pkg);
2069 let _time = timeit(builder);
2070 cmd.run(builder);
2071 }
2072
2073 if target.is_windows() {
2074 let exe = tmp.join("exe");
2075 let _ = fs::remove_dir_all(&exe);
2076
2077 let prepare = |name: &str| {
2078 builder.create_dir(&exe.join(name));
2079 let dir = if name == "rust-std" || name == "rust-analysis" {
2080 format!("{}-{}", name, target.triple)
2081 } else if name == "rust-analyzer" {
2082 "rust-analyzer-preview".to_string()
2083 } else if name == "clippy" {
2084 "clippy-preview".to_string()
2085 } else if name == "rustfmt" {
2086 "rustfmt-preview".to_string()
2087 } else if name == "miri" {
2088 "miri-preview".to_string()
2089 } else if name == "rustc-codegen-cranelift" {
2090 unreachable!("cg_clif shouldn't be built for windows");
2093 } else {
2094 name.to_string()
2095 };
2096 builder.cp_link_r(
2097 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2098 &exe.join(name),
2099 );
2100 builder.remove(&exe.join(name).join("manifest.in"));
2101 };
2102 prepare("rustc");
2103 prepare("cargo");
2104 prepare("rust-analysis");
2105 prepare("rust-std");
2106 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
2107 if built_tools.contains(tool) {
2108 prepare(tool);
2109 }
2110 }
2111 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2112 prepare("rust-mingw");
2113 }
2114
2115 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
2116
2117 let wix_path = env::var_os("WIX")
2119 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
2120 let wix = PathBuf::from(wix_path);
2121 let heat = wix.join("bin/heat.exe");
2122 let candle = wix.join("bin/candle.exe");
2123 let light = wix.join("bin/light.exe");
2124
2125 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2126 command(&heat)
2127 .current_dir(&exe)
2128 .arg("dir")
2129 .arg("rustc")
2130 .args(heat_flags)
2131 .arg("-cg")
2132 .arg("RustcGroup")
2133 .arg("-dr")
2134 .arg("Rustc")
2135 .arg("-var")
2136 .arg("var.RustcDir")
2137 .arg("-out")
2138 .arg(exe.join("RustcGroup.wxs"))
2139 .run(builder);
2140 if built_tools.contains("rust-docs") {
2141 command(&heat)
2142 .current_dir(&exe)
2143 .arg("dir")
2144 .arg("rust-docs")
2145 .args(heat_flags)
2146 .arg("-cg")
2147 .arg("DocsGroup")
2148 .arg("-dr")
2149 .arg("Docs")
2150 .arg("-var")
2151 .arg("var.DocsDir")
2152 .arg("-out")
2153 .arg(exe.join("DocsGroup.wxs"))
2154 .arg("-t")
2155 .arg(etc.join("msi/squash-components.xsl"))
2156 .run(builder);
2157 }
2158 command(&heat)
2159 .current_dir(&exe)
2160 .arg("dir")
2161 .arg("cargo")
2162 .args(heat_flags)
2163 .arg("-cg")
2164 .arg("CargoGroup")
2165 .arg("-dr")
2166 .arg("Cargo")
2167 .arg("-var")
2168 .arg("var.CargoDir")
2169 .arg("-out")
2170 .arg(exe.join("CargoGroup.wxs"))
2171 .arg("-t")
2172 .arg(etc.join("msi/remove-duplicates.xsl"))
2173 .run(builder);
2174 command(&heat)
2175 .current_dir(&exe)
2176 .arg("dir")
2177 .arg("rust-std")
2178 .args(heat_flags)
2179 .arg("-cg")
2180 .arg("StdGroup")
2181 .arg("-dr")
2182 .arg("Std")
2183 .arg("-var")
2184 .arg("var.StdDir")
2185 .arg("-out")
2186 .arg(exe.join("StdGroup.wxs"))
2187 .run(builder);
2188 if built_tools.contains("rust-analyzer") {
2189 command(&heat)
2190 .current_dir(&exe)
2191 .arg("dir")
2192 .arg("rust-analyzer")
2193 .args(heat_flags)
2194 .arg("-cg")
2195 .arg("RustAnalyzerGroup")
2196 .arg("-dr")
2197 .arg("RustAnalyzer")
2198 .arg("-var")
2199 .arg("var.RustAnalyzerDir")
2200 .arg("-out")
2201 .arg(exe.join("RustAnalyzerGroup.wxs"))
2202 .arg("-t")
2203 .arg(etc.join("msi/remove-duplicates.xsl"))
2204 .run(builder);
2205 }
2206 if built_tools.contains("clippy") {
2207 command(&heat)
2208 .current_dir(&exe)
2209 .arg("dir")
2210 .arg("clippy")
2211 .args(heat_flags)
2212 .arg("-cg")
2213 .arg("ClippyGroup")
2214 .arg("-dr")
2215 .arg("Clippy")
2216 .arg("-var")
2217 .arg("var.ClippyDir")
2218 .arg("-out")
2219 .arg(exe.join("ClippyGroup.wxs"))
2220 .arg("-t")
2221 .arg(etc.join("msi/remove-duplicates.xsl"))
2222 .run(builder);
2223 }
2224 if built_tools.contains("rustfmt") {
2225 command(&heat)
2226 .current_dir(&exe)
2227 .arg("dir")
2228 .arg("rustfmt")
2229 .args(heat_flags)
2230 .arg("-cg")
2231 .arg("RustFmtGroup")
2232 .arg("-dr")
2233 .arg("RustFmt")
2234 .arg("-var")
2235 .arg("var.RustFmtDir")
2236 .arg("-out")
2237 .arg(exe.join("RustFmtGroup.wxs"))
2238 .arg("-t")
2239 .arg(etc.join("msi/remove-duplicates.xsl"))
2240 .run(builder);
2241 }
2242 if built_tools.contains("miri") {
2243 command(&heat)
2244 .current_dir(&exe)
2245 .arg("dir")
2246 .arg("miri")
2247 .args(heat_flags)
2248 .arg("-cg")
2249 .arg("MiriGroup")
2250 .arg("-dr")
2251 .arg("Miri")
2252 .arg("-var")
2253 .arg("var.MiriDir")
2254 .arg("-out")
2255 .arg(exe.join("MiriGroup.wxs"))
2256 .arg("-t")
2257 .arg(etc.join("msi/remove-duplicates.xsl"))
2258 .run(builder);
2259 }
2260 command(&heat)
2261 .current_dir(&exe)
2262 .arg("dir")
2263 .arg("rust-analysis")
2264 .args(heat_flags)
2265 .arg("-cg")
2266 .arg("AnalysisGroup")
2267 .arg("-dr")
2268 .arg("Analysis")
2269 .arg("-var")
2270 .arg("var.AnalysisDir")
2271 .arg("-out")
2272 .arg(exe.join("AnalysisGroup.wxs"))
2273 .arg("-t")
2274 .arg(etc.join("msi/remove-duplicates.xsl"))
2275 .run(builder);
2276 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2277 command(&heat)
2278 .current_dir(&exe)
2279 .arg("dir")
2280 .arg("rust-mingw")
2281 .args(heat_flags)
2282 .arg("-cg")
2283 .arg("GccGroup")
2284 .arg("-dr")
2285 .arg("Gcc")
2286 .arg("-var")
2287 .arg("var.GccDir")
2288 .arg("-out")
2289 .arg(exe.join("GccGroup.wxs"))
2290 .run(builder);
2291 }
2292
2293 let candle = |input: &Path| {
2294 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2295 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2296 let mut cmd = command(&candle);
2297 cmd.current_dir(&exe)
2298 .arg("-nologo")
2299 .arg("-dRustcDir=rustc")
2300 .arg("-dCargoDir=cargo")
2301 .arg("-dStdDir=rust-std")
2302 .arg("-dAnalysisDir=rust-analysis")
2303 .arg("-arch")
2304 .arg(arch)
2305 .arg("-out")
2306 .arg(&output)
2307 .arg(input);
2308 add_env(builder, &mut cmd, target, &built_tools);
2309
2310 if built_tools.contains("clippy") {
2311 cmd.arg("-dClippyDir=clippy");
2312 }
2313 if built_tools.contains("rustfmt") {
2314 cmd.arg("-dRustFmtDir=rustfmt");
2315 }
2316 if built_tools.contains("rust-docs") {
2317 cmd.arg("-dDocsDir=rust-docs");
2318 }
2319 if built_tools.contains("rust-analyzer") {
2320 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2321 }
2322 if built_tools.contains("miri") {
2323 cmd.arg("-dMiriDir=miri");
2324 }
2325 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2326 cmd.arg("-dGccDir=rust-mingw");
2327 }
2328 cmd.run(builder);
2329 };
2330 candle(&xform(&etc.join("msi/rust.wxs")));
2331 candle(&etc.join("msi/ui.wxs"));
2332 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2333 candle("RustcGroup.wxs".as_ref());
2334 if built_tools.contains("rust-docs") {
2335 candle("DocsGroup.wxs".as_ref());
2336 }
2337 candle("CargoGroup.wxs".as_ref());
2338 candle("StdGroup.wxs".as_ref());
2339 if built_tools.contains("clippy") {
2340 candle("ClippyGroup.wxs".as_ref());
2341 }
2342 if built_tools.contains("rustfmt") {
2343 candle("RustFmtGroup.wxs".as_ref());
2344 }
2345 if built_tools.contains("miri") {
2346 candle("MiriGroup.wxs".as_ref());
2347 }
2348 if built_tools.contains("rust-analyzer") {
2349 candle("RustAnalyzerGroup.wxs".as_ref());
2350 }
2351 candle("AnalysisGroup.wxs".as_ref());
2352
2353 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2354 candle("GccGroup.wxs".as_ref());
2355 }
2356
2357 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2358 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2359 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2360
2361 builder.info(&format!("building `msi` installer with {light:?}"));
2362 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2363 let mut cmd = command(&light);
2364 cmd.arg("-nologo")
2365 .arg("-ext")
2366 .arg("WixUIExtension")
2367 .arg("-ext")
2368 .arg("WixUtilExtension")
2369 .arg("-out")
2370 .arg(exe.join(&filename))
2371 .arg("rust.wixobj")
2372 .arg("ui.wixobj")
2373 .arg("rustwelcomedlg.wixobj")
2374 .arg("RustcGroup.wixobj")
2375 .arg("CargoGroup.wixobj")
2376 .arg("StdGroup.wixobj")
2377 .arg("AnalysisGroup.wixobj")
2378 .current_dir(&exe);
2379
2380 if built_tools.contains("clippy") {
2381 cmd.arg("ClippyGroup.wixobj");
2382 }
2383 if built_tools.contains("rustfmt") {
2384 cmd.arg("RustFmtGroup.wixobj");
2385 }
2386 if built_tools.contains("miri") {
2387 cmd.arg("MiriGroup.wixobj");
2388 }
2389 if built_tools.contains("rust-analyzer") {
2390 cmd.arg("RustAnalyzerGroup.wixobj");
2391 }
2392 if built_tools.contains("rust-docs") {
2393 cmd.arg("DocsGroup.wixobj");
2394 }
2395
2396 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2397 cmd.arg("GccGroup.wixobj");
2398 }
2399 cmd.arg("-sice:ICE57");
2401
2402 let _time = timeit(builder);
2403 cmd.run(builder);
2404
2405 if !builder.config.dry_run() {
2406 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2407 }
2408 }
2409 }
2410
2411 fn metadata(&self) -> Option<StepMetadata> {
2412 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2413 }
2414}
2415
2416fn add_env(
2417 builder: &Builder<'_>,
2418 cmd: &mut BootstrapCommand,
2419 target: TargetSelection,
2420 built_tools: &HashSet<&'static str>,
2421) {
2422 let mut parts = builder.version.split('.');
2423 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2424 .env("CFG_RELEASE_NUM", &builder.version)
2425 .env("CFG_RELEASE", builder.rust_release())
2426 .env("CFG_VER_MAJOR", parts.next().unwrap())
2427 .env("CFG_VER_MINOR", parts.next().unwrap())
2428 .env("CFG_VER_PATCH", parts.next().unwrap())
2429 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2431 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2432 .env("CFG_BUILD", target.triple)
2433 .env("CFG_CHANNEL", &builder.config.channel);
2434
2435 if target.is_windows_gnullvm() {
2436 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2437 } else if target.is_windows_gnu() {
2438 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2439 } else {
2440 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2441 }
2442
2443 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2445 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2446 };
2447 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2448 define_optional_tool("clippy", "CFG_CLIPPY");
2449 define_optional_tool("miri", "CFG_MIRI");
2450 define_optional_tool("rust-analyzer", "CFG_RA");
2451}
2452
2453fn install_llvm_file(
2454 builder: &Builder<'_>,
2455 source: &Path,
2456 destination: &Path,
2457 install_symlink: bool,
2458) {
2459 if builder.config.dry_run() {
2460 return;
2461 }
2462
2463 if source.is_symlink() {
2464 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2467
2468 let full_dest = destination.join(source.file_name().unwrap());
2469 if install_symlink {
2470 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2473 } else {
2474 let link = t!(fs::read_link(source));
2478 let mut linker_script = t!(fs::File::create(full_dest));
2479 t!(write!(linker_script, "INPUT({})\n", link.display()));
2480
2481 let meta = t!(fs::metadata(source));
2484 if let Ok(mtime) = meta.modified() {
2485 t!(linker_script.set_modified(mtime));
2486 }
2487 }
2488 } else {
2489 builder.install(source, destination, FileType::NativeLibrary);
2490 }
2491}
2492
2493#[cfg_attr(
2497 feature = "tracing",
2498 instrument(
2499 level = "trace",
2500 name = "maybe_install_llvm",
2501 skip_all,
2502 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2503 ),
2504)]
2505fn maybe_install_llvm(
2506 builder: &Builder<'_>,
2507 llvm: &LlvmBuildStatus,
2508 target: TargetSelection,
2509 dst_libdir: &Path,
2510 install_symlink: bool,
2511) -> bool {
2512 let is_system_llvm =
2532 builder.config.target_config.get(&target).and_then(|t| t.llvm_config.as_ref()).is_some()
2533 && !(builder.config.llvm_ci_mode.download_from_ci()
2534 && builder.config.is_host_target(target));
2535 if is_system_llvm {
2536 trace!("system LLVM requested, no install");
2537 return false;
2538 }
2539
2540 if target.contains("apple-darwin") && llvm.llvm_output().link_shared() {
2546 let src_libdir = llvm.llvm_output().root_dir().join("lib");
2547 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2548 if llvm_dylib_path.exists() {
2549 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2550
2551 if install_symlink {
2552 let major = llvm::get_llvm_version_major(builder, &builder.host_llvm_config());
2553 let versioned_name = match &builder.config.llvm_version_suffix {
2554 Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.dylib"),
2555 None => {
2556 if builder.config.channel == "dev" {
2558 format!("libLLVM-{major}-rust-dev.dylib")
2559 } else {
2560 format!(
2561 "libLLVM-{major}-rust-{}-{}.dylib",
2562 builder.version, builder.config.channel
2563 )
2564 }
2565 }
2566 };
2567 t!(builder.symlink_file("libLLVM.dylib", dst_libdir.join(versioned_name)));
2568 }
2569 }
2570 !builder.config.dry_run()
2571 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm_output) = llvm {
2572 trace!("LLVM already built, installing LLVM files");
2573
2574 let host_llvm = builder.ensure(llvm::Llvm { target: builder.host_target });
2575 let mut cmd = command(host_llvm.llvm_config());
2576 cmd.cached();
2577 cmd.arg("--libfiles");
2578 builder.do_if_verbose(|| println!("running {cmd:?}"));
2579 let files = cmd.run_capture_stdout(builder).stdout();
2580 let build_llvm_out = host_llvm.root_dir();
2581 let target_llvm_out = llvm_output.root_dir();
2582 for file in files.trim_end().split(' ') {
2583 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2585 target_llvm_out.join(relative_path)
2586 } else {
2587 PathBuf::from(file)
2588 };
2589 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2590 }
2591 !builder.config.dry_run()
2592 } else {
2593 false
2594 }
2595}
2596
2597#[cfg_attr(
2599 feature = "tracing",
2600 instrument(
2601 level = "trace",
2602 name = "maybe_install_llvm_target",
2603 skip_all,
2604 fields(
2605 target = ?target,
2606 sysroot = ?sysroot,
2607 ),
2608 ),
2609)]
2610pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2611 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2612
2613 let config = get_llvm_build_status(builder, target);
2616
2617 if config.llvm_output().link_shared() {
2621 maybe_install_llvm(builder, &config, target, &dst_libdir, false);
2622 }
2623}
2624
2625#[cfg_attr(
2627 feature = "tracing",
2628 instrument(
2629 level = "trace",
2630 name = "maybe_install_llvm_runtime",
2631 skip_all,
2632 fields(
2633 target = ?target,
2634 sysroot = ?sysroot,
2635 ),
2636 ),
2637)]
2638pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2639 let dst_libdir = sysroot.join(builder.libdir_relative(Compiler::new(1, target)));
2640
2641 let config = get_llvm_build_status(builder, target);
2644
2645 if config.llvm_output().link_shared() {
2649 maybe_install_llvm(builder, &config, target, &dst_libdir, false);
2650
2651 if target.triple.contains("windows") {
2655 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("bin");
2656 maybe_install_llvm(builder, &config, target, &dst_libdir, false);
2657 }
2658 }
2659}
2660
2661#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2662pub struct LlvmTools {
2663 pub target: TargetSelection,
2664}
2665
2666impl CommandLineStep for LlvmTools {
2667 type Output = Option<GeneratedTarball>;
2668 const IS_HOST: bool = true;
2669
2670 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2671 let mut run = run.alias("llvm-tools");
2672 for tool in LLVM_TOOLS {
2673 run = run.alias(tool);
2674 }
2675
2676 run
2677 }
2678
2679 fn is_default_step(builder: &Builder<'_>) -> bool {
2680 should_build_extended_tool(builder, "llvm-tools")
2681 }
2682
2683 fn make_run(run: RunConfig<'_>) {
2684 run.builder.ensure(LlvmTools { target: run.target });
2685 }
2686
2687 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2688 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2689 let mut tools = vec![];
2690
2691 for path in paths {
2692 let path = path.to_str().unwrap();
2693
2694 if path == "llvm-tools" {
2696 return LLVM_TOOLS.to_owned();
2697 }
2698
2699 for tool in LLVM_TOOLS {
2700 if path == *tool {
2701 tools.push(*tool);
2702 }
2703 }
2704 }
2705
2706 if tools.is_empty() {
2708 tools = LLVM_TOOLS.to_owned();
2709 }
2710
2711 tools
2712 }
2713
2714 let target = self.target;
2715
2716 if let Some(config) = builder.config.target_config.get(&target)
2718 && !builder.config.llvm_ci_mode.download_from_ci()
2719 && config.llvm_config.is_some()
2720 {
2721 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2722 return None;
2723 }
2724
2725 if !builder.config.dry_run() {
2726 builder.require_submodule("src/llvm-project", None);
2727 }
2728
2729 let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2730
2731 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2732 tarball.set_overlay(OverlayKind::Llvm);
2733 tarball.is_preview(true);
2734
2735 if builder.config.llvm_tools_enabled {
2736 let src_bindir = llvm_output.root_dir().join("bin");
2738 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2739 for tool in tools_to_install(&builder.paths) {
2740 let exe = src_bindir.join(exe(tool, target));
2741 if !exe.exists() && builder.config.llvm_ci_mode.download_from_ci() {
2743 eprintln!("{} does not exist; skipping copy", exe.display());
2744 continue;
2745 }
2746
2747 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2748 }
2749 }
2750
2751 maybe_install_llvm_target(builder, target, tarball.image_dir());
2756
2757 Some(tarball.generate())
2758 }
2759}
2760
2761#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2764pub struct LlvmBitcodeLinker {
2765 pub build_compiler: Compiler,
2767 pub target: TargetSelection,
2769}
2770
2771impl CommandLineStep for LlvmBitcodeLinker {
2772 type Output = Option<GeneratedTarball>;
2773 const IS_HOST: bool = true;
2774
2775 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2776 run.alias("llvm-bitcode-linker")
2777 }
2778
2779 fn is_default_step(builder: &Builder<'_>) -> bool {
2780 should_build_extended_tool(builder, "llvm-bitcode-linker")
2781 }
2782
2783 fn make_run(run: RunConfig<'_>) {
2784 run.builder.ensure(LlvmBitcodeLinker {
2785 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2786 run.builder,
2787 run.target,
2788 ),
2789 target: run.target,
2790 });
2791 }
2792
2793 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2794 let target = self.target;
2795
2796 let llbc_linker = builder
2797 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2798
2799 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2800
2801 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2803 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2804 tarball.is_preview(true);
2805
2806 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2807
2808 Some(tarball.generate())
2809 }
2810}
2811
2812#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2815pub struct Enzyme {
2816 pub target: TargetSelection,
2818}
2819
2820impl CommandLineStep for Enzyme {
2821 type Output = Option<GeneratedTarball>;
2822 const IS_HOST: bool = true;
2823
2824 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2825 run.alias("enzyme")
2826 }
2827
2828 fn is_default_step(builder: &Builder<'_>) -> bool {
2829 builder.config.llvm_enzyme
2830 }
2831
2832 fn make_run(run: RunConfig<'_>) {
2833 run.builder.ensure(Enzyme { target: run.target });
2834 }
2835
2836 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2837 if !builder.sess.unstable_features() {
2841 return None;
2842 }
2843
2844 let target = self.target;
2845
2846 let enzyme = builder.ensure(llvm::Enzyme { target });
2847
2848 let target_libdir = format!("lib/rustlib/{}/lib", target.triple);
2849
2850 let mut tarball = Tarball::new(builder, "enzyme", &target.triple);
2852 tarball.set_overlay(OverlayKind::Enzyme);
2853 tarball.is_preview(true);
2854
2855 tarball.add_file(enzyme.enzyme_path(), target_libdir, FileType::NativeLibrary);
2856
2857 Some(tarball.generate())
2858 }
2859}
2860
2861#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2862pub struct Offload {
2863 pub target: TargetSelection,
2864}
2865
2866impl CommandLineStep for Offload {
2867 type Output = Option<GeneratedTarball>;
2868 const IS_HOST: bool = true;
2869
2870 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2871 run.alias("offload")
2872 }
2873
2874 fn is_default_step(builder: &Builder<'_>) -> bool {
2875 builder.config.llvm_offload
2876 }
2877
2878 fn make_run(run: RunConfig<'_>) {
2879 run.builder.ensure(Offload { target: run.target });
2880 }
2881
2882 fn run(self, builder: &Builder<'_>) -> Self::Output {
2883 if !builder.unstable_features() {
2884 return None;
2885 }
2886
2887 let target = self.target;
2888
2889 let omp_offload = builder.ensure(llvm::OmpOffload { target });
2890 let rust_offload = builder.ensure(llvm::RustOffload { target });
2891
2892 if builder.config.dry_run() {
2893 return None;
2894 }
2895
2896 let target_libdir = PathBuf::from(format!("lib/rustlib/{}/lib", target.triple));
2897
2898 let mut tarball = Tarball::new(builder, "offload", &target.triple);
2899 tarball.set_overlay(OverlayKind::Offload);
2900 tarball.is_preview(true);
2901
2902 let omp_offload_libdir = builder.out.join(target).join("offload").join("lib");
2903
2904 for path in omp_offload.artifact_paths_with_symlink_targets() {
2905 let relative = t!(path.strip_prefix(&omp_offload_libdir));
2906 let destdir = target_libdir.join(relative.parent().unwrap());
2907
2908 tarball.add_file(path, destdir, FileType::NativeLibrary);
2909 }
2910
2911 tarball.add_file(rust_offload.rust_offload_path(), target_libdir, FileType::NativeLibrary);
2912
2913 Some(tarball.generate())
2914 }
2915}
2916
2917#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2926pub struct RustDev {
2927 pub target: TargetSelection,
2928}
2929
2930impl CommandLineStep for RustDev {
2931 type Output = Option<GeneratedTarball>;
2932 const IS_HOST: bool = true;
2933
2934 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2935 run.alias("rust-dev")
2936 }
2937
2938 fn is_default_step(_builder: &Builder<'_>) -> bool {
2939 true
2940 }
2941
2942 fn make_run(run: RunConfig<'_>) {
2943 run.builder.ensure(RustDev { target: run.target });
2944 }
2945
2946 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2947 let target = self.target;
2948
2949 if let Some(config) = builder.config.target_config.get(&target)
2951 && let Some(ref _s) = config.llvm_config
2952 {
2953 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2954 return None;
2955 }
2956
2957 if !builder.config.dry_run() {
2958 builder.require_submodule("src/llvm-project", None);
2959 }
2960
2961 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2962 tarball.set_overlay(OverlayKind::Llvm);
2963 tarball.permit_symlinks(true);
2965
2966 let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2967
2968 let src_bindir = llvm_output.root_dir().join("bin");
2969 if src_bindir.exists() {
2975 for entry in walkdir::WalkDir::new(&src_bindir) {
2976 let entry = t!(entry);
2977 if entry.file_type().is_file() && !entry.path_is_symlink() {
2978 let name = entry.file_name().to_str().unwrap();
2979 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2980 }
2981 }
2982 }
2983
2984 if builder.config.lld_enabled {
2985 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2987
2988 let lld_path = lld_out.join("bin").join(exe("lld", target));
2990 if lld_path.exists() {
2991 tarball.add_file(&lld_path, "bin", FileType::Executable);
2992 }
2993 }
2994
2995 let filecheck = builder.ensure(llvm::FileCheck { target });
2996 tarball.add_file(filecheck, "bin", FileType::Executable);
2997
2998 tarball.add_dir(llvm_output.root_dir().join("include"), "include");
3002
3003 let dst_libdir = tarball.image_dir().join("lib");
3008
3009 let config = get_llvm_build_status(builder, target);
3010 maybe_install_llvm(builder, &config, target, &dst_libdir, true);
3011
3012 let link_type = if llvm_output.link_shared() { "dynamic" } else { "static" };
3014 t!(std::fs::write(tarball.image_dir().join(LLVM_CI_LINK_TYPE_PATH), link_type), dst_libdir);
3015
3016 copy_src_dirs(
3020 builder,
3021 &builder.src.join("src").join("llvm-project"),
3022 &["compiler-rt"],
3023 &["compiler-rt/test"],
3026 tarball.image_dir(),
3027 );
3028
3029 Some(tarball.generate())
3030 }
3031}
3032
3033#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3039pub struct Bootstrap {
3040 target: TargetSelection,
3041}
3042
3043impl CommandLineStep for Bootstrap {
3044 type Output = Option<GeneratedTarball>;
3045
3046 const IS_HOST: bool = true;
3047
3048 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3049 run.alias("bootstrap")
3050 }
3051
3052 fn make_run(run: RunConfig<'_>) {
3053 run.builder.ensure(Bootstrap { target: run.target });
3054 }
3055
3056 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
3057 let target = self.target;
3058
3059 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
3060
3061 let bootstrap_outdir = &builder.bootstrap_out;
3062 for file in &["bootstrap", "rustc", "rustdoc"] {
3063 tarball.add_file(
3064 bootstrap_outdir.join(exe(file, target)),
3065 "bootstrap/bin",
3066 FileType::Executable,
3067 );
3068 }
3069
3070 Some(tarball.generate())
3071 }
3072
3073 fn metadata(&self) -> Option<StepMetadata> {
3074 Some(StepMetadata::dist("bootstrap", self.target))
3075 }
3076}
3077
3078#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3083pub struct BuildManifest {
3084 target: TargetSelection,
3085}
3086
3087impl CommandLineStep for BuildManifest {
3088 type Output = GeneratedTarball;
3089
3090 const IS_HOST: bool = true;
3091
3092 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3093 run.alias("build-manifest")
3094 }
3095
3096 fn make_run(run: RunConfig<'_>) {
3097 run.builder.ensure(BuildManifest { target: run.target });
3098 }
3099
3100 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
3101 let build_manifest =
3105 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
3106
3107 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
3108 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
3109 tarball.generate()
3110 }
3111
3112 fn metadata(&self) -> Option<StepMetadata> {
3113 Some(StepMetadata::dist("build-manifest", self.target))
3114 }
3115}
3116
3117#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3123pub struct ReproducibleArtifacts {
3124 target: TargetSelection,
3125}
3126
3127impl CommandLineStep for ReproducibleArtifacts {
3128 type Output = Option<GeneratedTarball>;
3129 const IS_HOST: bool = true;
3130
3131 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3132 run.alias("reproducible-artifacts")
3133 }
3134
3135 fn is_default_step(_builder: &Builder<'_>) -> bool {
3136 true
3137 }
3138
3139 fn make_run(run: RunConfig<'_>) {
3140 run.builder.ensure(ReproducibleArtifacts { target: run.target });
3141 }
3142
3143 fn run(self, builder: &Builder<'_>) -> Self::Output {
3144 let mut added_anything = false;
3145 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
3146
3147 let pgo_profiles = [
3148 &builder.config.rust_pgo.use_profile,
3149 &builder.config.llvm_pgo.use_profile,
3150 &builder.config.rustdoc_pgo.use_profile,
3151 &builder.config.cargo_pgo.use_profile,
3152 &builder.config.clippy_pgo.use_profile,
3153 ];
3154 for profile in pgo_profiles {
3155 if let Some(path) = profile.as_ref() {
3156 tarball.add_file(path, ".", FileType::Regular);
3157 added_anything = true;
3158 }
3159 }
3160 for profile in &builder.config.reproducible_artifacts {
3161 tarball.add_file(profile, ".", FileType::Regular);
3162 added_anything = true;
3163 }
3164 if added_anything { Some(tarball.generate()) } else { None }
3165 }
3166
3167 fn metadata(&self) -> Option<StepMetadata> {
3168 Some(StepMetadata::dist("reproducible-artifacts", self.target))
3169 }
3170}
3171
3172#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3178pub struct GccDev {
3179 target: TargetSelection,
3180}
3181
3182impl CommandLineStep for GccDev {
3183 type Output = GeneratedTarball;
3184
3185 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3186 run.alias("gcc-dev")
3187 }
3188
3189 fn make_run(run: RunConfig<'_>) {
3190 run.builder.ensure(GccDev { target: run.target });
3191 }
3192
3193 fn run(self, builder: &Builder<'_>) -> Self::Output {
3194 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
3195 let output = builder
3196 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
3197 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
3198 tarball.generate()
3199 }
3200
3201 fn metadata(&self) -> Option<StepMetadata> {
3202 Some(StepMetadata::dist("gcc-dev", self.target))
3203 }
3204}
3205
3206#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3212pub struct Gcc {
3213 host: TargetSelection,
3214 target: TargetSelection,
3215}
3216
3217impl CommandLineStep for Gcc {
3218 type Output = Option<GeneratedTarball>;
3219
3220 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3221 run.alias("gcc")
3222 }
3223
3224 fn make_run(run: RunConfig<'_>) {
3225 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3229 }
3230
3231 fn run(self, builder: &Builder<'_>) -> Self::Output {
3232 if !builder.sess.unstable_features() {
3236 return None;
3237 }
3238
3239 let host = self.host;
3240 let target = self.target;
3241 if host != "x86_64-unknown-linux-gnu" {
3242 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3243 return None;
3244 }
3245
3246 if builder.config.is_running_on_ci() {
3247 assert_eq!(
3248 builder.config.gcc_ci_mode,
3249 GccCiMode::BuildLocally,
3250 "Cannot use gcc.download-ci-gcc when distributing GCC on CI"
3251 );
3252 }
3253
3254 builder.require_submodule(
3257 "src/gcc",
3258 Some("The src/gcc submodule is required for disting libgccjit"),
3259 );
3260
3261 let target_pair = GccTargetPair::for_target_pair(host, target);
3262 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3263
3264 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3268 tarball.set_overlay(OverlayKind::Gcc);
3269 tarball.is_preview(true);
3270 tarball.add_legal_and_readme_to("share/doc/gcc");
3271
3272 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3277
3278 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3280 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3281
3282 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3283 Some(tarball.generate())
3284 }
3285
3286 fn metadata(&self) -> Option<StepMetadata> {
3287 Some(StepMetadata::dist(
3288 "gcc",
3289 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3290 ))
3291 }
3292}