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