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