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