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