1use std::collections::HashSet;
12use std::ffi::OsStr;
13use std::io::Write;
14use std::path::{Path, PathBuf};
15use std::{env, fs};
16
17use object::BinaryFormat;
18use object::read::archive::ArchiveFile;
19#[cfg(feature = "tracing")]
20use tracing::instrument;
21
22use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
23use crate::core::build_steps::doc::DocumentationFormat;
24use crate::core::build_steps::gcc::GccTargetPair;
25use crate::core::build_steps::tool::{
26 self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
27};
28use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
29use crate::core::build_steps::{compile, llvm};
30use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
31use crate::core::config::TargetSelection;
32use crate::utils::build_stamp::{self, BuildStamp};
33use crate::utils::channel::{self, Info};
34use crate::utils::exec::{BootstrapCommand, command};
35use crate::utils::helpers::{
36 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
37};
38use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
39use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
40
41pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
42 format!("{}-{}", component, builder.rust_package_vers())
43}
44
45pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
46 builder.out.join("dist")
47}
48
49pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
50 builder.out.join("tmp/dist")
51}
52
53fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
54 if !builder.config.extended {
55 return false;
56 }
57 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
58}
59
60#[derive(Debug, Clone, Hash, PartialEq, Eq)]
61pub struct Docs {
62 pub host: TargetSelection,
63}
64
65impl Step for Docs {
66 type Output = Option<GeneratedTarball>;
67
68 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
69 run.alias("rust-docs")
70 }
71
72 fn is_default_step(builder: &Builder<'_>) -> bool {
73 builder.config.docs
74 }
75
76 fn make_run(run: RunConfig<'_>) {
77 run.builder.ensure(Docs { host: run.target });
78 }
79
80 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
82 let host = self.host;
83 builder.run_default_doc_steps();
87
88 let dest = "share/doc/rust/html";
89
90 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
91 tarball.set_product_name("Rust Documentation");
92 tarball.add_bulk_dir(builder.doc_out(host), dest);
93 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
94 tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular);
95 Some(tarball.generate())
96 }
97
98 fn metadata(&self) -> Option<StepMetadata> {
99 Some(StepMetadata::dist("docs", self.host))
100 }
101}
102
103#[derive(Debug, Clone, Hash, PartialEq, Eq)]
106pub struct JsonDocs {
107 build_compiler: Compiler,
108 target: TargetSelection,
109}
110
111impl Step for JsonDocs {
112 type Output = Option<GeneratedTarball>;
113
114 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
115 run.alias("rust-docs-json")
116 }
117
118 fn is_default_step(builder: &Builder<'_>) -> bool {
119 builder.config.docs
120 }
121
122 fn make_run(run: RunConfig<'_>) {
123 run.builder.ensure(JsonDocs {
124 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
125 target: run.target,
126 });
127 }
128
129 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
130 let target = self.target;
131 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
132 self.build_compiler,
133 target,
134 DocumentationFormat::Json,
135 ));
136
137 let dest = "share/doc/rust/json";
138
139 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
140 tarball.set_product_name("Rust Documentation In JSON Format");
141 tarball.is_preview(true);
142 tarball.add_bulk_dir(directory, dest);
143 Some(tarball.generate())
144 }
145
146 fn metadata(&self) -> Option<StepMetadata> {
147 Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
148 }
149}
150
151#[derive(Debug, Clone, Hash, PartialEq, Eq)]
158pub struct RustcDocs {
159 target: TargetSelection,
160}
161
162impl Step for RustcDocs {
163 type Output = GeneratedTarball;
164 const IS_HOST: bool = true;
165
166 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
167 run.alias("rustc-docs")
168 }
169
170 fn is_default_step(builder: &Builder<'_>) -> bool {
171 builder.config.compiler_docs
172 }
173
174 fn make_run(run: RunConfig<'_>) {
175 run.builder.ensure(RustcDocs { target: run.target });
176 }
177
178 fn run(self, builder: &Builder<'_>) -> Self::Output {
179 let target = self.target;
180 builder.run_default_doc_steps();
181
182 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
183 tarball.set_product_name("Rustc Documentation");
184 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc-docs");
185 tarball.generate()
186 }
187}
188
189fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
190 let mut found = Vec::with_capacity(files.len());
191
192 for file in files {
193 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
194
195 if let Some(file_path) = file_path {
196 found.push(file_path);
197 } else {
198 panic!("Could not find '{file}' in {path:?}");
199 }
200 }
201
202 found
203}
204
205fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
206 if builder.config.dry_run() {
207 return;
208 }
209
210 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
211
212 let compiler = if target == "i686-pc-windows-gnu" {
213 "i686-w64-mingw32-gcc.exe"
214 } else if target == "x86_64-pc-windows-gnu" {
215 "x86_64-w64-mingw32-gcc.exe"
216 } else {
217 "gcc.exe"
218 };
219 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
220
221 let target_libs = [
224 "libgcc.a",
226 "libgcc_eh.a",
227 "libgcc_s.a",
228 "libm.a",
229 "libmingw32.a",
230 "libmingwex.a",
231 "libstdc++.a",
232 "libiconv.a",
233 "libmoldname.a",
234 "libpthread.a",
235 "libadvapi32.a",
240 "libbcrypt.a",
241 "libcomctl32.a",
242 "libcomdlg32.a",
243 "libcredui.a",
244 "libcrypt32.a",
245 "libdbghelp.a",
246 "libgdi32.a",
247 "libimagehlp.a",
248 "libiphlpapi.a",
249 "libkernel32.a",
250 "libmsimg32.a",
251 "libmsvcrt.a",
252 "libntdll.a",
253 "libodbc32.a",
254 "libole32.a",
255 "liboleaut32.a",
256 "libopengl32.a",
257 "libpsapi.a",
258 "librpcrt4.a",
259 "libsecur32.a",
260 "libsetupapi.a",
261 "libshell32.a",
262 "libsynchronization.a",
263 "libuser32.a",
264 "libuserenv.a",
265 "libuuid.a",
266 "libwinhttp.a",
267 "libwinmm.a",
268 "libwinspool.a",
269 "libws2_32.a",
270 "libwsock32.a",
271 ];
272
273 let target_tools = find_files(&target_tools, &bin_path);
275 let target_libs = find_files(&target_libs, &lib_path);
276
277 let plat_target_bin_self_contained_dir =
279 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
280 fs::create_dir_all(&plat_target_bin_self_contained_dir)
281 .expect("creating plat_target_bin_self_contained_dir failed");
282 for src in target_tools {
283 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
284 }
285
286 builder.create(
288 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
289 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
290 used as a linker. In order to be able to compile projects containing C code use \
291 the GCC provided by MinGW or Cygwin.",
292 );
293
294 let plat_target_lib_self_contained_dir =
296 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
297 fs::create_dir_all(&plat_target_lib_self_contained_dir)
298 .expect("creating plat_target_lib_self_contained_dir failed");
299 for src in target_libs {
300 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
301 }
302}
303
304fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
305 if builder.config.dry_run() {
306 return;
307 }
308
309 let (_, lib_path) = get_cc_search_dirs(target, builder);
310
311 let target_libs = [
314 "libunwind.a",
316 "libunwind.dll.a",
317 "libmingw32.a",
318 "libmingwex.a",
319 "libmsvcrt.a",
320 "libkernel32.a",
322 "libuser32.a",
323 "libntdll.a",
324 "libuserenv.a",
325 "libws2_32.a",
326 "libdbghelp.a",
327 ];
328
329 let target_libs = find_files(&target_libs, &lib_path);
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 runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
343 if builder.config.dry_run() {
344 return;
345 }
346
347 let (bin_path, _) = get_cc_search_dirs(target, builder);
348
349 let mut rustc_dlls = vec![];
350 if target.is_windows_gnu() {
352 rustc_dlls.push("libwinpthread-1.dll");
353 if target.starts_with("i686-") {
354 rustc_dlls.push("libgcc_s_dw2-1.dll");
355 } else {
356 rustc_dlls.push("libgcc_s_seh-1.dll");
357 }
358 } else if target.is_windows_gnullvm() {
359 rustc_dlls.push("libunwind.dll");
360 } else {
361 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
362 }
363 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
364
365 let rust_bin_dir = rust_root.join("bin/");
367 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
368 for src in &rustc_dlls {
369 builder.copy_link_to_folder(src, &rust_bin_dir);
370 }
371
372 if builder.config.lld_enabled {
373 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
375 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
376 for src in &rustc_dlls {
377 builder.copy_link_to_folder(src, &rust_target_bin_dir);
378 }
379 }
380}
381
382fn get_cc_search_dirs(
383 target: TargetSelection,
384 builder: &Builder<'_>,
385) -> (Vec<PathBuf>, Vec<PathBuf>) {
386 let mut cmd = command(builder.cc(target));
388 cmd.arg("-print-search-dirs");
389 let gcc_out = cmd.run_capture_stdout(builder).stdout();
390
391 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
392 let mut lib_path = Vec::new();
393
394 for line in gcc_out.lines() {
395 let idx = line.find(':').unwrap();
396 let key = &line[..idx];
397 let trim_chars: &[_] = &[' ', '='];
398 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
399
400 if key == "programs" {
401 bin_path.extend(value);
402 } else if key == "libraries" {
403 lib_path.extend(value);
404 }
405 }
406 (bin_path, lib_path)
407}
408
409#[derive(Debug, Clone, Hash, PartialEq, Eq)]
414pub struct Mingw {
415 target: TargetSelection,
416}
417
418impl Step for Mingw {
419 type Output = Option<GeneratedTarball>;
420
421 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
422 run.alias("rust-mingw")
423 }
424
425 fn is_default_step(_builder: &Builder<'_>) -> bool {
426 true
427 }
428
429 fn make_run(run: RunConfig<'_>) {
430 run.builder.ensure(Mingw { target: run.target });
431 }
432
433 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
434 let target = self.target;
435 if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
436 return None;
437 }
438
439 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
440 tarball.set_product_name("Rust MinGW");
441
442 if target.ends_with("pc-windows-gnu") {
443 make_win_dist(tarball.image_dir(), target, builder);
444 } else if target.ends_with("pc-windows-gnullvm") {
445 make_win_llvm_dist(tarball.image_dir(), target, builder);
446 } else {
447 unreachable!();
448 }
449
450 Some(tarball.generate())
451 }
452
453 fn metadata(&self) -> Option<StepMetadata> {
454 Some(StepMetadata::dist("mingw", self.target))
455 }
456}
457
458#[derive(Debug, Clone, Hash, PartialEq, Eq)]
468pub struct Rustc {
469 pub target_compiler: Compiler,
471}
472
473impl Step for Rustc {
474 type Output = GeneratedTarball;
475 const IS_HOST: bool = true;
476
477 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
478 run.alias("rustc")
479 }
480
481 fn is_default_step(_builder: &Builder<'_>) -> bool {
482 true
483 }
484
485 fn make_run(run: RunConfig<'_>) {
486 run.builder.ensure(Rustc {
487 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
488 });
489 }
490
491 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
492 let target_compiler = self.target_compiler;
493 let target = self.target_compiler.host;
494
495 let tarball = Tarball::new(builder, "rustc", &target.triple);
496
497 prepare_image(builder, target_compiler, tarball.image_dir());
499
500 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
508 runtime_dll_dist(tarball.image_dir(), target, builder);
509 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
510 }
511
512 return tarball.generate();
513
514 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
515 let target = target_compiler.host;
516 let src = builder.sysroot(target_compiler);
517
518 t!(fs::create_dir_all(image.join("bin")));
520 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
521
522 if builder
524 .config
525 .tools
526 .as_ref()
527 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
528 {
529 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
530 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
531 }
532
533 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
534
535 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
536 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
537 builder.kind,
538 ) {
539 let dst = image.join("libexec");
540 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
541 }
542
543 let libdir_relative = builder.libdir_relative(target_compiler);
544
545 if libdir_relative.to_str() != Some("bin") {
547 let libdir = builder.rustc_libdir(target_compiler);
548 for entry in builder.read_dir(&libdir) {
549 if is_dylib(&entry.path())
555 && !entry
556 .path()
557 .file_name()
558 .and_then(|n| n.to_str())
559 .map(|n| n.contains("libgccjit"))
560 .unwrap_or(false)
561 {
562 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
565 }
566 }
567 }
568
569 maybe_install_llvm_runtime(builder, target, image);
575
576 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
577 t!(fs::create_dir_all(&dst_dir));
578
579 if builder.config.lld_enabled {
581 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
582 let rust_lld = exe("rust-lld", target_compiler.host);
583 builder.copy_link(
584 &src_dir.join(&rust_lld),
585 &dst_dir.join(&rust_lld),
586 FileType::Executable,
587 );
588 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
589 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
590 t!(fs::create_dir(&self_contained_lld_dst_dir));
591 for name in crate::LLD_FILE_NAMES {
592 let exe_name = exe(name, target_compiler.host);
593 builder.copy_link(
594 &self_contained_lld_src_dir.join(&exe_name),
595 &self_contained_lld_dst_dir.join(&exe_name),
596 FileType::Executable,
597 );
598 }
599 }
600
601 if builder.config.llvm_enabled(target_compiler.host)
602 && builder.config.llvm_tools_enabled
603 {
604 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
605 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
606 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
607 builder.copy_link(
608 &src_dir.join(&llvm_objcopy),
609 &dst_dir.join(&rust_objcopy),
610 FileType::Executable,
611 );
612 }
613
614 if builder.tool_enabled("wasm-component-ld") {
615 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
616 let ld = exe("wasm-component-ld", target_compiler.host);
617 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
618 }
619
620 t!(fs::create_dir_all(image.join("share/man/man1")));
622 let man_src = builder.src.join("src/doc/man");
623 let man_dst = image.join("share/man/man1");
624
625 for file_entry in builder.read_dir(&man_src) {
628 let page_src = file_entry.path();
629 let page_dst = man_dst.join(file_entry.file_name());
630 let src_text = t!(std::fs::read_to_string(&page_src));
631 let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version);
632 t!(std::fs::write(&page_dst, &new_text));
633 t!(fs::copy(&page_src, &page_dst));
634 }
635
636 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
638
639 generate_target_spec_json_schema(builder, image);
640
641 let file_list = builder.ensure(super::run::GenerateCopyright);
643 for file in file_list {
644 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
645 }
646
647 builder.install(
649 &builder.src.join("README.md"),
650 &image.join("share/doc/rust"),
651 FileType::Regular,
652 );
653
654 let license = |path: &Path| {
656 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
657 };
658 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
659 license(&entry.path());
660 }
661 }
662 }
663
664 fn metadata(&self) -> Option<StepMetadata> {
665 Some(StepMetadata::dist("rustc", self.target_compiler.host))
666 }
667}
668
669fn generate_target_spec_json_schema(builder: &Builder<'_>, sysroot: &Path) {
670 let stage1_host = builder.compiler(1, builder.host_target);
674 let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
675 rustc
676 .env("RUSTC_BOOTSTRAP", "1")
677 .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
678 let schema = rustc.run_capture(builder).stdout();
679
680 let schema_dir = tmpdir(builder);
681 t!(fs::create_dir_all(&schema_dir));
682 let schema_file = schema_dir.join("target-spec-json-schema.json");
683 t!(std::fs::write(&schema_file, schema));
684
685 let dst = sysroot.join("etc");
686 t!(fs::create_dir_all(&dst));
687
688 builder.install(&schema_file, &dst, FileType::Regular);
689}
690
691#[derive(Debug, Clone, Hash, PartialEq, Eq)]
693pub struct DebuggerScripts {
694 pub sysroot: PathBuf,
696 pub target: TargetSelection,
697}
698
699impl Step for DebuggerScripts {
700 type Output = ();
701
702 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
703 run.never()
704 }
705
706 fn run(self, builder: &Builder<'_>) {
707 let target = self.target;
708 let sysroot = self.sysroot;
709 let dst = sysroot.join("lib/rustlib/etc");
710 t!(fs::create_dir_all(&dst));
711 let cp_debugger_script = |file: &str| {
712 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
713 };
714 if target.contains("windows-msvc") {
715 builder.install(
717 &builder.src.join("src/etc/rust-windbg.cmd"),
718 &sysroot.join("bin"),
719 FileType::Script,
720 );
721
722 cp_debugger_script("natvis/intrinsic.natvis");
723 cp_debugger_script("natvis/liballoc.natvis");
724 cp_debugger_script("natvis/libcore.natvis");
725 cp_debugger_script("natvis/libstd.natvis");
726 }
727
728 cp_debugger_script("rust_types.py");
729
730 builder.install(
732 &builder.src.join("src/etc/rust-gdb"),
733 &sysroot.join("bin"),
734 FileType::Script,
735 );
736 builder.install(
737 &builder.src.join("src/etc/rust-gdbgui"),
738 &sysroot.join("bin"),
739 FileType::Script,
740 );
741
742 cp_debugger_script("gdb_load_rust_pretty_printers.py");
743 cp_debugger_script("gdb_lookup.py");
744 cp_debugger_script("gdb_providers.py");
745
746 builder.install(
748 &builder.src.join("src/etc/rust-lldb"),
749 &sysroot.join("bin"),
750 FileType::Script,
751 );
752
753 cp_debugger_script("lldb_lookup.py");
754 cp_debugger_script("lldb_providers.py");
755 cp_debugger_script("lldb_commands")
756 }
757}
758
759fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
760 if !builder.config.is_host_target(compiler.host) {
763 builder.info("\tskipping, not a build host");
764 true
765 } else {
766 false
767 }
768}
769
770fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
774 if !target.ends_with("-uefi") {
775 return;
776 }
777
778 for (path, _) in builder.read_stamp_file(stamp) {
779 if path.extension() != Some(OsStr::new("rlib")) {
780 continue;
781 }
782
783 let data = t!(fs::read(&path));
784 let data = data.as_slice();
785 let archive = t!(ArchiveFile::parse(data));
786 for member in archive.members() {
787 let member = t!(member);
788 let member_data = t!(member.data(data));
789
790 let is_coff = match object::File::parse(member_data) {
791 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
792 Err(_) => false,
793 };
794
795 if !is_coff {
796 let member_name = String::from_utf8_lossy(member.name());
797 panic!("member {} in {} is not COFF", member_name, path.display());
798 }
799 }
800 }
801}
802
803fn copy_target_libs(
805 builder: &Builder<'_>,
806 target: TargetSelection,
807 image: &Path,
808 stamp: &BuildStamp,
809) {
810 let dst = image.join("lib/rustlib").join(target).join("lib");
811 let self_contained_dst = dst.join("self-contained");
812 t!(fs::create_dir_all(&dst));
813 t!(fs::create_dir_all(&self_contained_dst));
814 for (path, dependency_type) in builder.read_stamp_file(stamp) {
815 if dependency_type == DependencyType::TargetSelfContained {
816 builder.copy_link(
817 &path,
818 &self_contained_dst.join(path.file_name().unwrap()),
819 FileType::NativeLibrary,
820 );
821 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
822 {
823 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
824 }
825 }
826}
827
828#[derive(Debug, Clone, Hash, PartialEq, Eq)]
835pub struct Std {
836 pub build_compiler: Compiler,
838 pub target: TargetSelection,
839}
840
841impl Std {
842 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
843 Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
844 }
845}
846
847impl Step for Std {
848 type Output = Option<GeneratedTarball>;
849
850 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
851 run.alias("rust-std")
852 }
853
854 fn is_default_step(_builder: &Builder<'_>) -> bool {
855 true
856 }
857
858 fn make_run(run: RunConfig<'_>) {
859 run.builder.ensure(Std::new(run.builder, run.target));
860 }
861
862 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
863 let build_compiler = self.build_compiler;
864 let target = self.target;
865
866 if skip_host_target_lib(builder, build_compiler) {
867 return None;
868 }
869
870 let stamp =
873 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
874
875 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
876 tarball.include_target_in_component_name(true);
877
878 verify_uefi_rlib_format(builder, target, &stamp);
879 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
880
881 Some(tarball.generate())
882 }
883
884 fn metadata(&self) -> Option<StepMetadata> {
885 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
886 }
887}
888
889#[derive(Debug, Clone, Hash, PartialEq, Eq)]
894pub struct RustcDev {
895 pub build_compiler: Compiler,
897 pub target: TargetSelection,
898}
899
900impl RustcDev {
901 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
902 Self {
903 build_compiler: builder.compiler(1, builder.config.host_target),
907 target,
908 }
909 }
910}
911
912impl Step for RustcDev {
913 type Output = Option<GeneratedTarball>;
914 const IS_HOST: bool = true;
915
916 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
917 run.alias("rustc-dev")
918 }
919
920 fn is_default_step(_builder: &Builder<'_>) -> bool {
921 true
922 }
923
924 fn make_run(run: RunConfig<'_>) {
925 run.builder.ensure(RustcDev::new(run.builder, run.target));
926 }
927
928 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
929 let build_compiler = self.build_compiler;
930 let target = self.target;
931 if skip_host_target_lib(builder, build_compiler) {
932 return None;
933 }
934
935 builder.ensure(compile::Rustc::new(build_compiler, target));
937
938 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
939
940 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
941 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
942
943 let src_files = &["Cargo.lock"];
944 copy_src_dirs(
947 builder,
948 &builder.src,
949 &["compiler", "library/proc_macro"],
951 &[],
952 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
953 );
954 for file in src_files {
955 tarball.add_file(
956 builder.src.join(file),
957 "lib/rustlib/rustc-src/rust",
958 FileType::Regular,
959 );
960 }
961
962 Some(tarball.generate())
963 }
964
965 fn metadata(&self) -> Option<StepMetadata> {
966 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
967 }
968}
969
970#[derive(Debug, Clone, Hash, PartialEq, Eq)]
975pub struct Analysis {
976 build_compiler: Compiler,
977 target: TargetSelection,
978}
979
980impl Step for Analysis {
981 type Output = Option<GeneratedTarball>;
982
983 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
984 run.alias("rust-analysis")
985 }
986
987 fn is_default_step(builder: &Builder<'_>) -> bool {
988 should_build_extended_tool(builder, "analysis")
989 }
990
991 fn make_run(run: RunConfig<'_>) {
992 run.builder.ensure(Analysis {
994 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
995 target: run.target,
996 });
997 }
998
999 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1000 let compiler = self.build_compiler;
1001 let target = self.target;
1002 if skip_host_target_lib(builder, compiler) {
1003 return None;
1004 }
1005
1006 let src = builder
1007 .stage_out(compiler, Mode::Std)
1008 .join(target)
1009 .join(builder.cargo_dir())
1010 .join("deps")
1011 .join("save-analysis");
1012
1013 t!(std::fs::create_dir_all(&src));
1015 let mut removed = src.clone();
1016 removed.push("removed.json");
1017 let mut f = t!(std::fs::File::create(removed));
1018 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
1019
1020 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
1021 tarball.include_target_in_component_name(true);
1022 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
1023 Some(tarball.generate())
1024 }
1025
1026 fn metadata(&self) -> Option<StepMetadata> {
1027 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
1028 }
1029}
1030
1031fn copy_src_dirs(
1034 builder: &Builder<'_>,
1035 base: &Path,
1036 src_dirs: &[&str],
1037 exclude_dirs: &[&str],
1038 dst_dir: &Path,
1039) {
1040 for src_dir in src_dirs {
1043 assert!(Path::new(src_dir).is_relative());
1044 }
1045
1046 if builder.config.dry_run() {
1049 return;
1050 }
1051
1052 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
1053 let spath = match path.to_str() {
1055 Some(path) => path,
1056 None => return false,
1057 };
1058 if spath.ends_with('~') || spath.ends_with(".pyc") {
1059 return false;
1060 }
1061 let spath = spath.replace("\\", "/");
1063
1064 static LLVM_PROJECTS: &[&str] = &[
1065 "llvm-project/clang",
1066 "llvm-project/libunwind",
1067 "llvm-project/lld",
1068 "llvm-project/lldb",
1069 "llvm-project/llvm",
1070 "llvm-project/compiler-rt",
1071 "llvm-project/cmake",
1072 "llvm-project/runtimes",
1073 "llvm-project/third-party",
1074 ];
1075 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1076 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1077 return false;
1078 }
1079
1080 if spath.starts_with("llvm-project/third-party")
1082 && spath != "llvm-project/third-party"
1083 && !spath.starts_with("llvm-project/third-party/siphash")
1084 {
1085 return false;
1086 }
1087
1088 if spath.starts_with("llvm-project/llvm/test")
1089 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1090 {
1091 return false;
1092 }
1093 }
1094
1095 if spath.starts_with("tools/cargo/tests") {
1097 return true;
1098 }
1099
1100 if !exclude_dirs.is_empty() {
1101 let full_path = Path::new(dir).join(path);
1102 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1103 return false;
1104 }
1105 }
1106
1107 static EXCLUDES: &[&str] = &[
1108 "CVS",
1109 "RCS",
1110 "SCCS",
1111 ".git",
1112 ".gitignore",
1113 ".gitmodules",
1114 ".gitattributes",
1115 ".cvsignore",
1116 ".svn",
1117 ".arch-ids",
1118 "{arch}",
1119 "=RELEASE-ID",
1120 "=meta-update",
1121 "=update",
1122 ".bzr",
1123 ".bzrignore",
1124 ".bzrtags",
1125 ".hg",
1126 ".hgignore",
1127 ".hgrags",
1128 "_darcs",
1129 ];
1130
1131 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1138 !EXCLUDES.contains(&last_component)
1139 }
1140
1141 for item in src_dirs {
1143 let dst = &dst_dir.join(item);
1144 t!(fs::create_dir_all(dst));
1145 builder
1146 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1147 }
1148}
1149
1150#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1151pub struct Src;
1152
1153impl Step for Src {
1154 type Output = GeneratedTarball;
1156 const IS_HOST: bool = true;
1157
1158 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1159 run.alias("rust-src")
1160 }
1161
1162 fn is_default_step(_builder: &Builder<'_>) -> bool {
1163 true
1164 }
1165
1166 fn make_run(run: RunConfig<'_>) {
1167 run.builder.ensure(Src);
1168 }
1169
1170 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1172 if !builder.config.dry_run() {
1173 builder.require_submodule("src/llvm-project", None);
1174 }
1175
1176 let tarball = Tarball::new_targetless(builder, "rust-src");
1177
1178 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1186
1187 copy_src_dirs(
1190 builder,
1191 &builder.src,
1192 &["library", "src/llvm-project/libunwind"],
1193 &[
1194 "library/backtrace/crates",
1197 "library/stdarch/Cargo.toml",
1200 "library/stdarch/crates/stdarch-verify",
1201 "library/stdarch/crates/intrinsic-test",
1202 ],
1203 &dst_src,
1204 );
1205
1206 tarball.generate()
1207 }
1208
1209 fn metadata(&self) -> Option<StepMetadata> {
1210 Some(StepMetadata::dist("src", TargetSelection::default()))
1211 }
1212}
1213
1214#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1218pub struct PlainSourceTarball;
1219
1220impl Step for PlainSourceTarball {
1221 type Output = GeneratedTarball;
1223 const IS_HOST: bool = true;
1224
1225 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1226 run.alias("rustc-src")
1227 }
1228
1229 fn is_default_step(builder: &Builder<'_>) -> bool {
1230 builder.config.rust_dist_src
1231 }
1232
1233 fn make_run(run: RunConfig<'_>) {
1234 run.builder.ensure(PlainSourceTarball);
1235 }
1236
1237 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1239 let tarball = prepare_source_tarball(
1240 builder,
1241 "src",
1242 &[
1243 "src/gcc",
1247 ],
1248 );
1249
1250 let plain_dst_src = tarball.image_dir();
1251 if !builder.config.dry_run() {
1256 builder.create_dir(&plain_dst_src.join("src/gcc"));
1257 t!(std::fs::write(
1258 plain_dst_src.join("src/gcc/notice.txt"),
1259 "The GCC source code is not included due to unclear licensing implications\n"
1260 ));
1261 }
1262 tarball.bare()
1263 }
1264}
1265
1266#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1268pub struct PlainSourceTarballGpl;
1269
1270impl Step for PlainSourceTarballGpl {
1271 type Output = GeneratedTarball;
1273 const IS_HOST: bool = true;
1274
1275 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1276 run.alias("rustc-src-gpl")
1277 }
1278
1279 fn is_default_step(builder: &Builder<'_>) -> bool {
1280 builder.config.rust_dist_src
1281 }
1282
1283 fn make_run(run: RunConfig<'_>) {
1284 run.builder.ensure(PlainSourceTarballGpl);
1285 }
1286
1287 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1289 let tarball = prepare_source_tarball(builder, "src-gpl", &[]);
1290 tarball.bare()
1291 }
1292}
1293
1294fn prepare_source_tarball<'a>(
1295 builder: &'a Builder<'a>,
1296 name: &str,
1297 exclude_dirs: &[&str],
1298) -> Tarball<'a> {
1299 let mut tarball = Tarball::new(builder, "rustc", name);
1304 tarball.permit_symlinks(true);
1305 let plain_dst_src = tarball.image_dir();
1306
1307 let src_files = [
1309 ".gitmodules",
1311 "CONTRIBUTING.md",
1312 "COPYRIGHT",
1313 "Cargo.lock",
1314 "Cargo.toml",
1315 "LICENSE-APACHE",
1316 "LICENSE-MIT",
1317 "README.md",
1318 "RELEASES.md",
1319 "REUSE.toml",
1320 "bootstrap.example.toml",
1321 "configure",
1322 "license-metadata.json",
1323 "package.json",
1324 "x",
1325 "x.ps1",
1326 "x.py",
1327 "yarn.lock",
1328 ];
1330 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1331
1332 copy_src_dirs(builder, &builder.src, &src_dirs, exclude_dirs, plain_dst_src);
1333
1334 for item in &src_files {
1336 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item), FileType::Regular);
1337 }
1338
1339 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1341
1342 let write_git_info = |info: Option<&Info>, path: &Path| {
1344 if let Some(info) = info {
1345 t!(std::fs::create_dir_all(path));
1346 channel::write_commit_hash_file(path, &info.sha);
1347 channel::write_commit_info_file(path, info);
1348 }
1349 };
1350 write_git_info(builder.rust_info().info(), plain_dst_src);
1351 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1352
1353 if builder.config.dist_vendor {
1354 builder.require_and_update_all_submodules();
1355
1356 let pkgs_for_pgo_training =
1358 build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| {
1359 let mut manifest_path =
1360 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1361 manifest_path.push(pkg);
1362 manifest_path.push("Cargo.toml");
1363 manifest_path
1364 });
1365
1366 let vendor = builder.ensure(Vendor {
1368 sync_args: pkgs_for_pgo_training.collect(),
1369 versioned_dirs: true,
1370 root_dir: plain_dst_src.into(),
1371 output_dir: VENDOR_DIR.into(),
1372 });
1373
1374 let cargo_config_dir = plain_dst_src.join(".cargo");
1375 builder.create_dir(&cargo_config_dir);
1376 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1377 }
1378
1379 for entry in walkdir::WalkDir::new(tarball.image_dir())
1383 .follow_links(true)
1384 .into_iter()
1385 .filter_map(|e| e.ok())
1386 {
1387 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__")) {
1388 t!(fs::remove_dir_all(entry.path()));
1389 }
1390 }
1391 tarball
1392}
1393
1394#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1395pub struct Cargo {
1396 pub build_compiler: Compiler,
1397 pub target: TargetSelection,
1398}
1399
1400impl Step for Cargo {
1401 type Output = Option<GeneratedTarball>;
1402 const IS_HOST: bool = true;
1403
1404 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1405 run.alias("cargo")
1406 }
1407
1408 fn is_default_step(builder: &Builder<'_>) -> bool {
1409 should_build_extended_tool(builder, "cargo")
1410 }
1411
1412 fn make_run(run: RunConfig<'_>) {
1413 run.builder.ensure(Cargo {
1414 build_compiler: get_tool_target_compiler(
1415 run.builder,
1416 ToolTargetBuildMode::Build(run.target),
1417 ),
1418 target: run.target,
1419 });
1420 }
1421
1422 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1423 let build_compiler = self.build_compiler;
1424 let target = self.target;
1425
1426 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1427 let src = builder.src.join("src/tools/cargo");
1428 let etc = src.join("src/etc");
1429
1430 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1432 tarball.set_overlay(OverlayKind::Cargo);
1433
1434 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1435 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1436 tarball.add_renamed_file(
1437 etc.join("cargo.bashcomp.sh"),
1438 "etc/bash_completion.d",
1439 "cargo",
1440 FileType::Regular,
1441 );
1442 tarball.add_dir(etc.join("man"), "share/man/man1");
1443 tarball.add_legal_and_readme_to("share/doc/cargo");
1444
1445 Some(tarball.generate())
1446 }
1447
1448 fn metadata(&self) -> Option<StepMetadata> {
1449 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1450 }
1451}
1452
1453#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1455pub struct RustAnalyzer {
1456 pub compilers: RustcPrivateCompilers,
1457 pub target: TargetSelection,
1458}
1459
1460impl Step for RustAnalyzer {
1461 type Output = Option<GeneratedTarball>;
1462 const IS_HOST: bool = true;
1463
1464 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1465 run.alias("rust-analyzer")
1466 }
1467
1468 fn is_default_step(builder: &Builder<'_>) -> bool {
1469 should_build_extended_tool(builder, "rust-analyzer")
1470 }
1471
1472 fn make_run(run: RunConfig<'_>) {
1473 run.builder.ensure(RustAnalyzer {
1474 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1475 target: run.target,
1476 });
1477 }
1478
1479 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1480 let target = self.target;
1481 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1482
1483 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1484 tarball.set_overlay(OverlayKind::RustAnalyzer);
1485 tarball.is_preview(true);
1486 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1487 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1488 Some(tarball.generate())
1489 }
1490
1491 fn metadata(&self) -> Option<StepMetadata> {
1492 Some(
1493 StepMetadata::dist("rust-analyzer", self.target)
1494 .built_by(self.compilers.build_compiler()),
1495 )
1496 }
1497}
1498
1499#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1500pub struct Clippy {
1501 pub compilers: RustcPrivateCompilers,
1502 pub target: TargetSelection,
1503}
1504
1505impl Step for Clippy {
1506 type Output = Option<GeneratedTarball>;
1507 const IS_HOST: bool = true;
1508
1509 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1510 run.alias("clippy")
1511 }
1512
1513 fn is_default_step(builder: &Builder<'_>) -> bool {
1514 should_build_extended_tool(builder, "clippy")
1515 }
1516
1517 fn make_run(run: RunConfig<'_>) {
1518 run.builder.ensure(Clippy {
1519 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1520 target: run.target,
1521 });
1522 }
1523
1524 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1525 let target = self.target;
1526
1527 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1531 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1532
1533 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1534 tarball.set_overlay(OverlayKind::Clippy);
1535 tarball.is_preview(true);
1536 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1537 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1538 tarball.add_legal_and_readme_to("share/doc/clippy");
1539 Some(tarball.generate())
1540 }
1541
1542 fn metadata(&self) -> Option<StepMetadata> {
1543 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1544 }
1545}
1546
1547#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1548pub struct Miri {
1549 pub compilers: RustcPrivateCompilers,
1550 pub target: TargetSelection,
1551}
1552
1553impl Step for Miri {
1554 type Output = Option<GeneratedTarball>;
1555 const IS_HOST: bool = true;
1556
1557 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1558 run.alias("miri")
1559 }
1560
1561 fn is_default_step(builder: &Builder<'_>) -> bool {
1562 should_build_extended_tool(builder, "miri")
1563 }
1564
1565 fn make_run(run: RunConfig<'_>) {
1566 run.builder.ensure(Miri {
1567 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1568 target: run.target,
1569 });
1570 }
1571
1572 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1573 if !builder.build.unstable_features() {
1577 return None;
1578 }
1579
1580 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1581 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1582
1583 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1584 tarball.set_overlay(OverlayKind::Miri);
1585 tarball.is_preview(true);
1586 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1587 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1588 tarball.add_legal_and_readme_to("share/doc/miri");
1589 Some(tarball.generate())
1590 }
1591
1592 fn metadata(&self) -> Option<StepMetadata> {
1593 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1594 }
1595}
1596
1597#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1598pub struct CraneliftCodegenBackend {
1599 pub compilers: RustcPrivateCompilers,
1600 pub target: TargetSelection,
1601}
1602
1603impl Step for CraneliftCodegenBackend {
1604 type Output = Option<GeneratedTarball>;
1605 const IS_HOST: bool = true;
1606
1607 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1608 run.alias("rustc_codegen_cranelift")
1609 }
1610
1611 fn is_default_step(builder: &Builder<'_>) -> bool {
1612 builder
1617 .config
1618 .enabled_codegen_backends(builder.host_target)
1619 .contains(&CodegenBackendKind::Cranelift)
1620 }
1621
1622 fn make_run(run: RunConfig<'_>) {
1623 run.builder.ensure(CraneliftCodegenBackend {
1624 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1625 target: run.target,
1626 });
1627 }
1628
1629 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1630 if !builder.build.unstable_features() {
1634 return None;
1635 }
1636
1637 let target = self.target;
1638 if !target_supports_cranelift_backend(target) {
1639 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1640 return None;
1641 }
1642
1643 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1644 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1645 tarball.is_preview(true);
1646 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1647
1648 let compilers = self.compilers;
1649 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1650
1651 if builder.config.dry_run() {
1652 return None;
1653 }
1654
1655 add_codegen_backend_to_tarball(builder, &tarball, compilers.target_compiler(), &stamp);
1656
1657 Some(tarball.generate())
1658 }
1659
1660 fn metadata(&self) -> Option<StepMetadata> {
1661 Some(
1662 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1663 .built_by(self.compilers.build_compiler()),
1664 )
1665 }
1666}
1667
1668#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1672pub struct GccCodegenBackend {
1673 pub compilers: RustcPrivateCompilers,
1674 pub target: TargetSelection,
1675}
1676
1677impl Step for GccCodegenBackend {
1678 type Output = Option<GeneratedTarball>;
1679 const IS_HOST: bool = true;
1680
1681 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1682 run.alias("rustc_codegen_gcc")
1683 }
1684
1685 fn is_default_step(builder: &Builder<'_>) -> bool {
1686 builder
1691 .config
1692 .enabled_codegen_backends(builder.host_target)
1693 .contains(&CodegenBackendKind::Gcc)
1694 }
1695
1696 fn make_run(run: RunConfig<'_>) {
1697 run.builder.ensure(GccCodegenBackend {
1698 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1699 target: run.target,
1700 });
1701 }
1702
1703 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1704 if !builder.build.unstable_features() {
1708 return None;
1709 }
1710
1711 let target = self.target;
1712 if target != "x86_64-unknown-linux-gnu" {
1713 builder
1714 .info(&format!("target `{target}` not supported by rustc_codegen_gcc. skipping"));
1715 return None;
1716 }
1717
1718 let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", &target.triple);
1719 tarball.set_overlay(OverlayKind::RustcCodegenGcc);
1720 tarball.is_preview(true);
1721 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
1722
1723 let compilers = self.compilers;
1724 let backend = builder.ensure(compile::GccCodegenBackend::for_target(compilers, target));
1725
1726 if builder.config.dry_run() {
1727 return None;
1728 }
1729
1730 add_codegen_backend_to_tarball(
1731 builder,
1732 &tarball,
1733 compilers.target_compiler(),
1734 backend.stamp(),
1735 );
1736
1737 Some(tarball.generate())
1738 }
1739
1740 fn metadata(&self) -> Option<StepMetadata> {
1741 Some(
1742 StepMetadata::dist("rustc_codegen_gcc", self.target)
1743 .built_by(self.compilers.build_compiler()),
1744 )
1745 }
1746}
1747
1748fn add_codegen_backend_to_tarball(
1751 builder: &Builder<'_>,
1752 tarball: &Tarball<'_>,
1753 compiler: Compiler,
1754 stamp: &BuildStamp,
1755) {
1756 let backends_dst = builder.sysroot_codegen_backends(compiler);
1758 let backends_rel = backends_dst
1759 .strip_prefix(builder.sysroot(compiler))
1760 .unwrap()
1761 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1762 .unwrap();
1763 let backends_dst = PathBuf::from("lib").join(backends_rel);
1765
1766 let codegen_backend_dylib = get_codegen_backend_file(stamp);
1767 tarball.add_renamed_file(
1768 &codegen_backend_dylib,
1769 &backends_dst,
1770 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1771 FileType::NativeLibrary,
1772 );
1773}
1774
1775#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1776pub struct Rustfmt {
1777 pub compilers: RustcPrivateCompilers,
1778 pub target: TargetSelection,
1779}
1780
1781impl Step for Rustfmt {
1782 type Output = Option<GeneratedTarball>;
1783 const IS_HOST: bool = true;
1784
1785 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1786 run.alias("rustfmt")
1787 }
1788
1789 fn is_default_step(builder: &Builder<'_>) -> bool {
1790 should_build_extended_tool(builder, "rustfmt")
1791 }
1792
1793 fn make_run(run: RunConfig<'_>) {
1794 run.builder.ensure(Rustfmt {
1795 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1796 target: run.target,
1797 });
1798 }
1799
1800 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1801 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1802 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1803
1804 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1805 tarball.set_overlay(OverlayKind::Rustfmt);
1806 tarball.is_preview(true);
1807 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1808 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1809 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1810 Some(tarball.generate())
1811 }
1812
1813 fn metadata(&self) -> Option<StepMetadata> {
1814 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1815 }
1816}
1817
1818#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1820pub struct Extended {
1821 build_compiler: Compiler,
1822 target: TargetSelection,
1823}
1824
1825impl Step for Extended {
1826 type Output = ();
1827 const IS_HOST: bool = true;
1828
1829 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1830 run.alias("extended")
1831 }
1832
1833 fn is_default_step(builder: &Builder<'_>) -> bool {
1834 builder.config.extended
1835 }
1836
1837 fn make_run(run: RunConfig<'_>) {
1838 run.builder.ensure(Extended {
1839 build_compiler: run
1840 .builder
1841 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1842 target: run.target,
1843 });
1844 }
1845
1846 fn run(self, builder: &Builder<'_>) {
1848 let target = self.target;
1849 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1850
1851 let mut tarballs = Vec::new();
1852 let mut built_tools = HashSet::new();
1853 macro_rules! add_component {
1854 ($name:expr => $step:expr) => {
1855 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1856 tarballs.push(tarball);
1857 built_tools.insert($name);
1858 }
1859 };
1860 }
1861
1862 let rustc_private_compilers =
1863 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1864 let build_compiler = rustc_private_compilers.build_compiler();
1865 let target_compiler = rustc_private_compilers.target_compiler();
1866
1867 tarballs.push(builder.ensure(Rustc { target_compiler }));
1872 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1873
1874 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1875 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1876 }
1877
1878 add_component!("rust-docs" => Docs { host: target });
1879 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1881 add_component!("cargo" => Cargo { build_compiler, target });
1882 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1883 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1884 add_component!("llvm-components" => LlvmTools { target });
1885 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1886 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1887 add_component!("analysis" => Analysis { build_compiler, target });
1888 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1889 compilers: rustc_private_compilers,
1890 target
1891 });
1892 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1893 build_compiler,
1894 target
1895 });
1896
1897 let etc = builder.src.join("src/etc/installer");
1898
1899 if builder.config.dry_run() {
1901 return;
1902 }
1903
1904 let tarball = Tarball::new(builder, "rust", &target.triple);
1905 let generated = tarball.combine(&tarballs);
1906
1907 let tmp = tmpdir(builder).join("combined-tarball");
1908 let work = generated.work_dir();
1909
1910 let mut license = String::new();
1911 license += &builder.read(&builder.src.join("COPYRIGHT"));
1912 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1913 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1914 license.push('\n');
1915 license.push('\n');
1916
1917 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1918 let mut rtf = rtf.to_string();
1919 rtf.push('\n');
1920 for line in license.lines() {
1921 rtf.push_str(line);
1922 rtf.push_str("\\line ");
1923 }
1924 rtf.push('}');
1925
1926 fn filter(contents: &str, marker: &str) -> String {
1927 let start = format!("tool-{marker}-start");
1928 let end = format!("tool-{marker}-end");
1929 let mut lines = Vec::new();
1930 let mut omitted = false;
1931 for line in contents.lines() {
1932 if line.contains(&start) {
1933 omitted = true;
1934 } else if line.contains(&end) {
1935 omitted = false;
1936 } else if !omitted {
1937 lines.push(line);
1938 }
1939 }
1940
1941 lines.join("\n")
1942 }
1943
1944 let xform = |p: &Path| {
1945 let mut contents = t!(fs::read_to_string(p));
1946 for tool in &["miri", "rust-docs"] {
1947 if !built_tools.contains(tool) {
1948 contents = filter(&contents, tool);
1949 }
1950 }
1951 let ret = tmp.join(p.file_name().unwrap());
1952 t!(fs::write(&ret, &contents));
1953 ret
1954 };
1955
1956 if target.contains("apple-darwin") {
1957 builder.info("building pkg installer");
1958 let pkg = tmp.join("pkg");
1959 let _ = fs::remove_dir_all(&pkg);
1960
1961 let pkgbuild = |component: &str| {
1962 let mut cmd = command("pkgbuild");
1963 cmd.arg("--identifier")
1964 .arg(format!("org.rust-lang.{component}"))
1965 .arg("--scripts")
1966 .arg(pkg.join(component))
1967 .arg("--nopayload")
1968 .arg(pkg.join(component).with_extension("pkg"));
1969 cmd.run(builder);
1970 };
1971
1972 let prepare = |name: &str| {
1973 builder.create_dir(&pkg.join(name));
1974 builder.cp_link_r(
1975 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1976 &pkg.join(name),
1977 );
1978 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1979 pkgbuild(name);
1980 };
1981 prepare("rustc");
1982 prepare("cargo");
1983 prepare("rust-std");
1984 prepare("rust-analysis");
1985
1986 for tool in &[
1987 "clippy",
1988 "rustfmt",
1989 "rust-analyzer",
1990 "rust-docs",
1991 "miri",
1992 "rustc-codegen-cranelift",
1993 ] {
1994 if built_tools.contains(tool) {
1995 prepare(tool);
1996 }
1997 }
1998 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
2000 pkgbuild("uninstall");
2001
2002 builder.create_dir(&pkg.join("res"));
2003 builder.create(&pkg.join("res/LICENSE.txt"), &license);
2004 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
2005 let mut cmd = command("productbuild");
2006 cmd.arg("--distribution")
2007 .arg(xform(&etc.join("pkg/Distribution.xml")))
2008 .arg("--resources")
2009 .arg(pkg.join("res"))
2010 .arg(distdir(builder).join(format!(
2011 "{}-{}.pkg",
2012 pkgname(builder, "rust"),
2013 target.triple
2014 )))
2015 .arg("--package-path")
2016 .arg(&pkg);
2017 let _time = timeit(builder);
2018 cmd.run(builder);
2019 }
2020
2021 if target.is_windows() {
2022 let exe = tmp.join("exe");
2023 let _ = fs::remove_dir_all(&exe);
2024
2025 let prepare = |name: &str| {
2026 builder.create_dir(&exe.join(name));
2027 let dir = if name == "rust-std" || name == "rust-analysis" {
2028 format!("{}-{}", name, target.triple)
2029 } else if name == "rust-analyzer" {
2030 "rust-analyzer-preview".to_string()
2031 } else if name == "clippy" {
2032 "clippy-preview".to_string()
2033 } else if name == "rustfmt" {
2034 "rustfmt-preview".to_string()
2035 } else if name == "miri" {
2036 "miri-preview".to_string()
2037 } else if name == "rustc-codegen-cranelift" {
2038 unreachable!("cg_clif shouldn't be built for windows");
2041 } else {
2042 name.to_string()
2043 };
2044 builder.cp_link_r(
2045 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2046 &exe.join(name),
2047 );
2048 builder.remove(&exe.join(name).join("manifest.in"));
2049 };
2050 prepare("rustc");
2051 prepare("cargo");
2052 prepare("rust-analysis");
2053 prepare("rust-std");
2054 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
2055 if built_tools.contains(tool) {
2056 prepare(tool);
2057 }
2058 }
2059 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2060 prepare("rust-mingw");
2061 }
2062
2063 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
2064
2065 let wix_path = env::var_os("WIX")
2067 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
2068 let wix = PathBuf::from(wix_path);
2069 let heat = wix.join("bin/heat.exe");
2070 let candle = wix.join("bin/candle.exe");
2071 let light = wix.join("bin/light.exe");
2072
2073 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2074 command(&heat)
2075 .current_dir(&exe)
2076 .arg("dir")
2077 .arg("rustc")
2078 .args(heat_flags)
2079 .arg("-cg")
2080 .arg("RustcGroup")
2081 .arg("-dr")
2082 .arg("Rustc")
2083 .arg("-var")
2084 .arg("var.RustcDir")
2085 .arg("-out")
2086 .arg(exe.join("RustcGroup.wxs"))
2087 .run(builder);
2088 if built_tools.contains("rust-docs") {
2089 command(&heat)
2090 .current_dir(&exe)
2091 .arg("dir")
2092 .arg("rust-docs")
2093 .args(heat_flags)
2094 .arg("-cg")
2095 .arg("DocsGroup")
2096 .arg("-dr")
2097 .arg("Docs")
2098 .arg("-var")
2099 .arg("var.DocsDir")
2100 .arg("-out")
2101 .arg(exe.join("DocsGroup.wxs"))
2102 .arg("-t")
2103 .arg(etc.join("msi/squash-components.xsl"))
2104 .run(builder);
2105 }
2106 command(&heat)
2107 .current_dir(&exe)
2108 .arg("dir")
2109 .arg("cargo")
2110 .args(heat_flags)
2111 .arg("-cg")
2112 .arg("CargoGroup")
2113 .arg("-dr")
2114 .arg("Cargo")
2115 .arg("-var")
2116 .arg("var.CargoDir")
2117 .arg("-out")
2118 .arg(exe.join("CargoGroup.wxs"))
2119 .arg("-t")
2120 .arg(etc.join("msi/remove-duplicates.xsl"))
2121 .run(builder);
2122 command(&heat)
2123 .current_dir(&exe)
2124 .arg("dir")
2125 .arg("rust-std")
2126 .args(heat_flags)
2127 .arg("-cg")
2128 .arg("StdGroup")
2129 .arg("-dr")
2130 .arg("Std")
2131 .arg("-var")
2132 .arg("var.StdDir")
2133 .arg("-out")
2134 .arg(exe.join("StdGroup.wxs"))
2135 .run(builder);
2136 if built_tools.contains("rust-analyzer") {
2137 command(&heat)
2138 .current_dir(&exe)
2139 .arg("dir")
2140 .arg("rust-analyzer")
2141 .args(heat_flags)
2142 .arg("-cg")
2143 .arg("RustAnalyzerGroup")
2144 .arg("-dr")
2145 .arg("RustAnalyzer")
2146 .arg("-var")
2147 .arg("var.RustAnalyzerDir")
2148 .arg("-out")
2149 .arg(exe.join("RustAnalyzerGroup.wxs"))
2150 .arg("-t")
2151 .arg(etc.join("msi/remove-duplicates.xsl"))
2152 .run(builder);
2153 }
2154 if built_tools.contains("clippy") {
2155 command(&heat)
2156 .current_dir(&exe)
2157 .arg("dir")
2158 .arg("clippy")
2159 .args(heat_flags)
2160 .arg("-cg")
2161 .arg("ClippyGroup")
2162 .arg("-dr")
2163 .arg("Clippy")
2164 .arg("-var")
2165 .arg("var.ClippyDir")
2166 .arg("-out")
2167 .arg(exe.join("ClippyGroup.wxs"))
2168 .arg("-t")
2169 .arg(etc.join("msi/remove-duplicates.xsl"))
2170 .run(builder);
2171 }
2172 if built_tools.contains("rustfmt") {
2173 command(&heat)
2174 .current_dir(&exe)
2175 .arg("dir")
2176 .arg("rustfmt")
2177 .args(heat_flags)
2178 .arg("-cg")
2179 .arg("RustFmtGroup")
2180 .arg("-dr")
2181 .arg("RustFmt")
2182 .arg("-var")
2183 .arg("var.RustFmtDir")
2184 .arg("-out")
2185 .arg(exe.join("RustFmtGroup.wxs"))
2186 .arg("-t")
2187 .arg(etc.join("msi/remove-duplicates.xsl"))
2188 .run(builder);
2189 }
2190 if built_tools.contains("miri") {
2191 command(&heat)
2192 .current_dir(&exe)
2193 .arg("dir")
2194 .arg("miri")
2195 .args(heat_flags)
2196 .arg("-cg")
2197 .arg("MiriGroup")
2198 .arg("-dr")
2199 .arg("Miri")
2200 .arg("-var")
2201 .arg("var.MiriDir")
2202 .arg("-out")
2203 .arg(exe.join("MiriGroup.wxs"))
2204 .arg("-t")
2205 .arg(etc.join("msi/remove-duplicates.xsl"))
2206 .run(builder);
2207 }
2208 command(&heat)
2209 .current_dir(&exe)
2210 .arg("dir")
2211 .arg("rust-analysis")
2212 .args(heat_flags)
2213 .arg("-cg")
2214 .arg("AnalysisGroup")
2215 .arg("-dr")
2216 .arg("Analysis")
2217 .arg("-var")
2218 .arg("var.AnalysisDir")
2219 .arg("-out")
2220 .arg(exe.join("AnalysisGroup.wxs"))
2221 .arg("-t")
2222 .arg(etc.join("msi/remove-duplicates.xsl"))
2223 .run(builder);
2224 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2225 command(&heat)
2226 .current_dir(&exe)
2227 .arg("dir")
2228 .arg("rust-mingw")
2229 .args(heat_flags)
2230 .arg("-cg")
2231 .arg("GccGroup")
2232 .arg("-dr")
2233 .arg("Gcc")
2234 .arg("-var")
2235 .arg("var.GccDir")
2236 .arg("-out")
2237 .arg(exe.join("GccGroup.wxs"))
2238 .run(builder);
2239 }
2240
2241 let candle = |input: &Path| {
2242 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2243 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2244 let mut cmd = command(&candle);
2245 cmd.current_dir(&exe)
2246 .arg("-nologo")
2247 .arg("-dRustcDir=rustc")
2248 .arg("-dCargoDir=cargo")
2249 .arg("-dStdDir=rust-std")
2250 .arg("-dAnalysisDir=rust-analysis")
2251 .arg("-arch")
2252 .arg(arch)
2253 .arg("-out")
2254 .arg(&output)
2255 .arg(input);
2256 add_env(builder, &mut cmd, target, &built_tools);
2257
2258 if built_tools.contains("clippy") {
2259 cmd.arg("-dClippyDir=clippy");
2260 }
2261 if built_tools.contains("rustfmt") {
2262 cmd.arg("-dRustFmtDir=rustfmt");
2263 }
2264 if built_tools.contains("rust-docs") {
2265 cmd.arg("-dDocsDir=rust-docs");
2266 }
2267 if built_tools.contains("rust-analyzer") {
2268 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2269 }
2270 if built_tools.contains("miri") {
2271 cmd.arg("-dMiriDir=miri");
2272 }
2273 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2274 cmd.arg("-dGccDir=rust-mingw");
2275 }
2276 cmd.run(builder);
2277 };
2278 candle(&xform(&etc.join("msi/rust.wxs")));
2279 candle(&etc.join("msi/ui.wxs"));
2280 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2281 candle("RustcGroup.wxs".as_ref());
2282 if built_tools.contains("rust-docs") {
2283 candle("DocsGroup.wxs".as_ref());
2284 }
2285 candle("CargoGroup.wxs".as_ref());
2286 candle("StdGroup.wxs".as_ref());
2287 if built_tools.contains("clippy") {
2288 candle("ClippyGroup.wxs".as_ref());
2289 }
2290 if built_tools.contains("rustfmt") {
2291 candle("RustFmtGroup.wxs".as_ref());
2292 }
2293 if built_tools.contains("miri") {
2294 candle("MiriGroup.wxs".as_ref());
2295 }
2296 if built_tools.contains("rust-analyzer") {
2297 candle("RustAnalyzerGroup.wxs".as_ref());
2298 }
2299 candle("AnalysisGroup.wxs".as_ref());
2300
2301 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2302 candle("GccGroup.wxs".as_ref());
2303 }
2304
2305 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2306 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2307 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2308
2309 builder.info(&format!("building `msi` installer with {light:?}"));
2310 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2311 let mut cmd = command(&light);
2312 cmd.arg("-nologo")
2313 .arg("-ext")
2314 .arg("WixUIExtension")
2315 .arg("-ext")
2316 .arg("WixUtilExtension")
2317 .arg("-out")
2318 .arg(exe.join(&filename))
2319 .arg("rust.wixobj")
2320 .arg("ui.wixobj")
2321 .arg("rustwelcomedlg.wixobj")
2322 .arg("RustcGroup.wixobj")
2323 .arg("CargoGroup.wixobj")
2324 .arg("StdGroup.wixobj")
2325 .arg("AnalysisGroup.wixobj")
2326 .current_dir(&exe);
2327
2328 if built_tools.contains("clippy") {
2329 cmd.arg("ClippyGroup.wixobj");
2330 }
2331 if built_tools.contains("rustfmt") {
2332 cmd.arg("RustFmtGroup.wixobj");
2333 }
2334 if built_tools.contains("miri") {
2335 cmd.arg("MiriGroup.wixobj");
2336 }
2337 if built_tools.contains("rust-analyzer") {
2338 cmd.arg("RustAnalyzerGroup.wixobj");
2339 }
2340 if built_tools.contains("rust-docs") {
2341 cmd.arg("DocsGroup.wixobj");
2342 }
2343
2344 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2345 cmd.arg("GccGroup.wixobj");
2346 }
2347 cmd.arg("-sice:ICE57");
2349
2350 let _time = timeit(builder);
2351 cmd.run(builder);
2352
2353 if !builder.config.dry_run() {
2354 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2355 }
2356 }
2357 }
2358
2359 fn metadata(&self) -> Option<StepMetadata> {
2360 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2361 }
2362}
2363
2364fn add_env(
2365 builder: &Builder<'_>,
2366 cmd: &mut BootstrapCommand,
2367 target: TargetSelection,
2368 built_tools: &HashSet<&'static str>,
2369) {
2370 let mut parts = builder.version.split('.');
2371 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2372 .env("CFG_RELEASE_NUM", &builder.version)
2373 .env("CFG_RELEASE", builder.rust_release())
2374 .env("CFG_VER_MAJOR", parts.next().unwrap())
2375 .env("CFG_VER_MINOR", parts.next().unwrap())
2376 .env("CFG_VER_PATCH", parts.next().unwrap())
2377 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2379 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2380 .env("CFG_BUILD", target.triple)
2381 .env("CFG_CHANNEL", &builder.config.channel);
2382
2383 if target.is_windows_gnullvm() {
2384 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2385 } else if target.is_windows_gnu() {
2386 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2387 } else {
2388 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2389 }
2390
2391 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2393 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2394 };
2395 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2396 define_optional_tool("clippy", "CFG_CLIPPY");
2397 define_optional_tool("miri", "CFG_MIRI");
2398 define_optional_tool("rust-analyzer", "CFG_RA");
2399}
2400
2401fn install_llvm_file(
2402 builder: &Builder<'_>,
2403 source: &Path,
2404 destination: &Path,
2405 install_symlink: bool,
2406) {
2407 if builder.config.dry_run() {
2408 return;
2409 }
2410
2411 if source.is_symlink() {
2412 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2415
2416 let full_dest = destination.join(source.file_name().unwrap());
2417 if install_symlink {
2418 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2421 } else {
2422 let link = t!(fs::read_link(source));
2426 let mut linker_script = t!(fs::File::create(full_dest));
2427 t!(write!(linker_script, "INPUT({})\n", link.display()));
2428
2429 let meta = t!(fs::metadata(source));
2432 if let Ok(mtime) = meta.modified() {
2433 t!(linker_script.set_modified(mtime));
2434 }
2435 }
2436 } else {
2437 builder.install(source, destination, FileType::NativeLibrary);
2438 }
2439}
2440
2441#[cfg_attr(
2445 feature = "tracing",
2446 instrument(
2447 level = "trace",
2448 name = "maybe_install_llvm",
2449 skip_all,
2450 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2451 ),
2452)]
2453fn maybe_install_llvm(
2454 builder: &Builder<'_>,
2455 target: TargetSelection,
2456 dst_libdir: &Path,
2457 install_symlink: bool,
2458) -> bool {
2459 if builder.config.is_system_llvm(target) {
2476 trace!("system LLVM requested, no install");
2477 return false;
2478 }
2479
2480 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2486 let src_libdir = builder.llvm_out(target).join("lib");
2487 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2488 if llvm_dylib_path.exists() {
2489 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2490 }
2491 !builder.config.dry_run()
2492 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2493 host_llvm_config, ..
2494 }) = llvm::prebuilt_llvm_config(builder, target, true)
2495 {
2496 trace!("LLVM already built, installing LLVM files");
2497 let mut cmd = command(host_llvm_config);
2498 cmd.cached();
2499 cmd.arg("--libfiles");
2500 builder.do_if_verbose(|| println!("running {cmd:?}"));
2501 let files = cmd.run_capture_stdout(builder).stdout();
2502 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2503 let target_llvm_out = &builder.llvm_out(target);
2504 for file in files.trim_end().split(' ') {
2505 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2507 target_llvm_out.join(relative_path)
2508 } else {
2509 PathBuf::from(file)
2510 };
2511 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2512 }
2513 !builder.config.dry_run()
2514 } else {
2515 false
2516 }
2517}
2518
2519#[cfg_attr(
2521 feature = "tracing",
2522 instrument(
2523 level = "trace",
2524 name = "maybe_install_llvm_target",
2525 skip_all,
2526 fields(
2527 llvm_link_shared = ?builder.llvm_link_shared(),
2528 target = ?target,
2529 sysroot = ?sysroot,
2530 ),
2531 ),
2532)]
2533pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2534 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2535 if builder.llvm_link_shared() {
2539 maybe_install_llvm(builder, target, &dst_libdir, false);
2540 }
2541}
2542
2543#[cfg_attr(
2545 feature = "tracing",
2546 instrument(
2547 level = "trace",
2548 name = "maybe_install_llvm_runtime",
2549 skip_all,
2550 fields(
2551 llvm_link_shared = ?builder.llvm_link_shared(),
2552 target = ?target,
2553 sysroot = ?sysroot,
2554 ),
2555 ),
2556)]
2557pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2558 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2559 if builder.llvm_link_shared() {
2563 maybe_install_llvm(builder, target, &dst_libdir, false);
2564 }
2565}
2566
2567#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2568pub struct LlvmTools {
2569 pub target: TargetSelection,
2570}
2571
2572impl Step for LlvmTools {
2573 type Output = Option<GeneratedTarball>;
2574 const IS_HOST: bool = true;
2575
2576 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2577 let mut run = run.alias("llvm-tools");
2578 for tool in LLVM_TOOLS {
2579 run = run.alias(tool);
2580 }
2581
2582 run
2583 }
2584
2585 fn is_default_step(builder: &Builder<'_>) -> bool {
2586 should_build_extended_tool(builder, "llvm-tools")
2587 }
2588
2589 fn make_run(run: RunConfig<'_>) {
2590 run.builder.ensure(LlvmTools { target: run.target });
2591 }
2592
2593 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2594 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2595 let mut tools = vec![];
2596
2597 for path in paths {
2598 let path = path.to_str().unwrap();
2599
2600 if path == "llvm-tools" {
2602 return LLVM_TOOLS.to_owned();
2603 }
2604
2605 for tool in LLVM_TOOLS {
2606 if path == *tool {
2607 tools.push(*tool);
2608 }
2609 }
2610 }
2611
2612 if tools.is_empty() {
2614 tools = LLVM_TOOLS.to_owned();
2615 }
2616
2617 tools
2618 }
2619
2620 let target = self.target;
2621
2622 if let Some(config) = builder.config.target_config.get(&target)
2624 && !builder.config.llvm_from_ci
2625 && config.llvm_config.is_some()
2626 {
2627 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2628 return None;
2629 }
2630
2631 if !builder.config.dry_run() {
2632 builder.require_submodule("src/llvm-project", None);
2633 }
2634
2635 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2636
2637 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2638 tarball.set_overlay(OverlayKind::Llvm);
2639 tarball.is_preview(true);
2640
2641 if builder.config.llvm_tools_enabled {
2642 let src_bindir = builder.llvm_out(target).join("bin");
2644 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2645 for tool in tools_to_install(&builder.paths) {
2646 let exe = src_bindir.join(exe(tool, target));
2647 if !exe.exists() && builder.config.llvm_from_ci {
2649 eprintln!("{} does not exist; skipping copy", exe.display());
2650 continue;
2651 }
2652
2653 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2654 }
2655 }
2656
2657 maybe_install_llvm_target(builder, target, tarball.image_dir());
2662
2663 Some(tarball.generate())
2664 }
2665}
2666
2667#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2670pub struct LlvmBitcodeLinker {
2671 pub build_compiler: Compiler,
2673 pub target: TargetSelection,
2675}
2676
2677impl Step for LlvmBitcodeLinker {
2678 type Output = Option<GeneratedTarball>;
2679 const IS_HOST: bool = true;
2680
2681 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2682 run.alias("llvm-bitcode-linker")
2683 }
2684
2685 fn is_default_step(builder: &Builder<'_>) -> bool {
2686 should_build_extended_tool(builder, "llvm-bitcode-linker")
2687 }
2688
2689 fn make_run(run: RunConfig<'_>) {
2690 run.builder.ensure(LlvmBitcodeLinker {
2691 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2692 run.builder,
2693 run.target,
2694 ),
2695 target: run.target,
2696 });
2697 }
2698
2699 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2700 let target = self.target;
2701
2702 let llbc_linker = builder
2703 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2704
2705 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2706
2707 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2709 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2710 tarball.is_preview(true);
2711
2712 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2713
2714 Some(tarball.generate())
2715 }
2716}
2717
2718#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2727pub struct RustDev {
2728 pub target: TargetSelection,
2729}
2730
2731impl Step for RustDev {
2732 type Output = Option<GeneratedTarball>;
2733 const IS_HOST: bool = true;
2734
2735 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2736 run.alias("rust-dev")
2737 }
2738
2739 fn is_default_step(_builder: &Builder<'_>) -> bool {
2740 true
2741 }
2742
2743 fn make_run(run: RunConfig<'_>) {
2744 run.builder.ensure(RustDev { target: run.target });
2745 }
2746
2747 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2748 let target = self.target;
2749
2750 if let Some(config) = builder.config.target_config.get(&target)
2752 && let Some(ref _s) = config.llvm_config
2753 {
2754 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2755 return None;
2756 }
2757
2758 if !builder.config.dry_run() {
2759 builder.require_submodule("src/llvm-project", None);
2760 }
2761
2762 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2763 tarball.set_overlay(OverlayKind::Llvm);
2764 tarball.permit_symlinks(true);
2766
2767 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2768
2769 let src_bindir = builder.llvm_out(target).join("bin");
2770 if src_bindir.exists() {
2776 for entry in walkdir::WalkDir::new(&src_bindir) {
2777 let entry = t!(entry);
2778 if entry.file_type().is_file() && !entry.path_is_symlink() {
2779 let name = entry.file_name().to_str().unwrap();
2780 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2781 }
2782 }
2783 }
2784
2785 if builder.config.lld_enabled {
2786 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2788
2789 let lld_path = lld_out.join("bin").join(exe("lld", target));
2791 if lld_path.exists() {
2792 tarball.add_file(&lld_path, "bin", FileType::Executable);
2793 }
2794 }
2795
2796 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2797
2798 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2802
2803 let dst_libdir = tarball.image_dir().join("lib");
2808 maybe_install_llvm(builder, target, &dst_libdir, true);
2809 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2810 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2811
2812 copy_src_dirs(
2816 builder,
2817 &builder.src.join("src").join("llvm-project"),
2818 &["compiler-rt"],
2819 &["compiler-rt/test"],
2822 tarball.image_dir(),
2823 );
2824
2825 Some(tarball.generate())
2826 }
2827}
2828
2829#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2835pub struct Bootstrap {
2836 target: TargetSelection,
2837}
2838
2839impl Step for Bootstrap {
2840 type Output = Option<GeneratedTarball>;
2841
2842 const IS_HOST: bool = true;
2843
2844 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2845 run.alias("bootstrap")
2846 }
2847
2848 fn make_run(run: RunConfig<'_>) {
2849 run.builder.ensure(Bootstrap { target: run.target });
2850 }
2851
2852 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2853 let target = self.target;
2854
2855 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2856
2857 let bootstrap_outdir = &builder.bootstrap_out;
2858 for file in &["bootstrap", "rustc", "rustdoc"] {
2859 tarball.add_file(
2860 bootstrap_outdir.join(exe(file, target)),
2861 "bootstrap/bin",
2862 FileType::Executable,
2863 );
2864 }
2865
2866 Some(tarball.generate())
2867 }
2868
2869 fn metadata(&self) -> Option<StepMetadata> {
2870 Some(StepMetadata::dist("bootstrap", self.target))
2871 }
2872}
2873
2874#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2879pub struct BuildManifest {
2880 target: TargetSelection,
2881}
2882
2883impl Step for BuildManifest {
2884 type Output = GeneratedTarball;
2885
2886 const IS_HOST: bool = true;
2887
2888 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2889 run.alias("build-manifest")
2890 }
2891
2892 fn make_run(run: RunConfig<'_>) {
2893 run.builder.ensure(BuildManifest { target: run.target });
2894 }
2895
2896 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2897 let build_manifest =
2901 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
2902
2903 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2904 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
2905 tarball.generate()
2906 }
2907
2908 fn metadata(&self) -> Option<StepMetadata> {
2909 Some(StepMetadata::dist("build-manifest", self.target))
2910 }
2911}
2912
2913#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2919pub struct ReproducibleArtifacts {
2920 target: TargetSelection,
2921}
2922
2923impl Step for ReproducibleArtifacts {
2924 type Output = Option<GeneratedTarball>;
2925 const IS_HOST: bool = true;
2926
2927 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2928 run.alias("reproducible-artifacts")
2929 }
2930
2931 fn is_default_step(_builder: &Builder<'_>) -> bool {
2932 true
2933 }
2934
2935 fn make_run(run: RunConfig<'_>) {
2936 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2937 }
2938
2939 fn run(self, builder: &Builder<'_>) -> Self::Output {
2940 let mut added_anything = false;
2941 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2942 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2943 tarball.add_file(path, ".", FileType::Regular);
2944 added_anything = true;
2945 }
2946 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2947 tarball.add_file(path, ".", FileType::Regular);
2948 added_anything = true;
2949 }
2950 for profile in &builder.config.reproducible_artifacts {
2951 tarball.add_file(profile, ".", FileType::Regular);
2952 added_anything = true;
2953 }
2954 if added_anything { Some(tarball.generate()) } else { None }
2955 }
2956
2957 fn metadata(&self) -> Option<StepMetadata> {
2958 Some(StepMetadata::dist("reproducible-artifacts", self.target))
2959 }
2960}
2961
2962#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2968pub struct GccDev {
2969 target: TargetSelection,
2970}
2971
2972impl Step for GccDev {
2973 type Output = GeneratedTarball;
2974
2975 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2976 run.alias("gcc-dev")
2977 }
2978
2979 fn make_run(run: RunConfig<'_>) {
2980 run.builder.ensure(GccDev { target: run.target });
2981 }
2982
2983 fn run(self, builder: &Builder<'_>) -> Self::Output {
2984 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
2985 let output = builder
2986 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
2987 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
2988 tarball.generate()
2989 }
2990
2991 fn metadata(&self) -> Option<StepMetadata> {
2992 Some(StepMetadata::dist("gcc-dev", self.target))
2993 }
2994}