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
20use crate::core::build_steps::doc::DocumentationFormat;
21use crate::core::build_steps::tool::{self, Tool};
22use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
23use crate::core::build_steps::{compile, llvm};
24use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
25use crate::core::config::TargetSelection;
26use crate::utils::build_stamp::{self, BuildStamp};
27use crate::utils::channel::{self, Info};
28use crate::utils::exec::{BootstrapCommand, command};
29use crate::utils::helpers::{
30 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
31};
32use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
33use crate::{Compiler, DependencyType, LLVM_TOOLS, Mode};
34
35pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
36 format!("{}-{}", component, builder.rust_package_vers())
37}
38
39pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
40 builder.out.join("dist")
41}
42
43pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
44 builder.out.join("tmp/dist")
45}
46
47fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
48 if !builder.config.extended {
49 return false;
50 }
51 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
52}
53
54#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
55pub struct Docs {
56 pub host: TargetSelection,
57}
58
59impl Step for Docs {
60 type Output = Option<GeneratedTarball>;
61 const DEFAULT: bool = true;
62
63 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
64 let default = run.builder.config.docs;
65 run.alias("rust-docs").default_condition(default)
66 }
67
68 fn make_run(run: RunConfig<'_>) {
69 run.builder.ensure(Docs { host: run.target });
70 }
71
72 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
74 let host = self.host;
75 builder.default_doc(&[]);
76
77 let dest = "share/doc/rust/html";
78
79 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
80 tarball.set_product_name("Rust Documentation");
81 tarball.add_bulk_dir(builder.doc_out(host), dest);
82 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, 0o644);
83 Some(tarball.generate())
84 }
85}
86
87#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
88pub struct JsonDocs {
89 pub host: TargetSelection,
90}
91
92impl Step for JsonDocs {
93 type Output = Option<GeneratedTarball>;
94 const DEFAULT: bool = true;
95
96 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
97 let default = run.builder.config.docs;
98 run.alias("rust-docs-json").default_condition(default)
99 }
100
101 fn make_run(run: RunConfig<'_>) {
102 run.builder.ensure(JsonDocs { host: run.target });
103 }
104
105 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
107 let host = self.host;
108 builder.ensure(crate::core::build_steps::doc::Std::new(
109 builder.top_stage,
110 host,
111 DocumentationFormat::Json,
112 ));
113
114 let dest = "share/doc/rust/json";
115
116 let mut tarball = Tarball::new(builder, "rust-docs-json", &host.triple);
117 tarball.set_product_name("Rust Documentation In JSON Format");
118 tarball.is_preview(true);
119 tarball.add_bulk_dir(builder.json_doc_out(host), dest);
120 Some(tarball.generate())
121 }
122}
123
124#[derive(Debug, Clone, Hash, PartialEq, Eq)]
125pub struct RustcDocs {
126 pub host: TargetSelection,
127}
128
129impl Step for RustcDocs {
130 type Output = Option<GeneratedTarball>;
131 const DEFAULT: bool = true;
132 const ONLY_HOSTS: bool = true;
133
134 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
135 let builder = run.builder;
136 run.alias("rustc-docs").default_condition(builder.config.compiler_docs)
137 }
138
139 fn make_run(run: RunConfig<'_>) {
140 run.builder.ensure(RustcDocs { host: run.target });
141 }
142
143 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
145 let host = self.host;
146 builder.default_doc(&[]);
147
148 let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
149 tarball.set_product_name("Rustc Documentation");
150 tarball.add_bulk_dir(builder.compiler_doc_out(host), "share/doc/rust/html/rustc");
151 Some(tarball.generate())
152 }
153}
154
155fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
156 let mut found = Vec::with_capacity(files.len());
157
158 for file in files {
159 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
160
161 if let Some(file_path) = file_path {
162 found.push(file_path);
163 } else {
164 panic!("Could not find '{file}' in {path:?}");
165 }
166 }
167
168 found
169}
170
171fn make_win_dist(
172 rust_root: &Path,
173 plat_root: &Path,
174 target: TargetSelection,
175 builder: &Builder<'_>,
176) {
177 if builder.config.dry_run() {
178 return;
179 }
180
181 let mut cmd = command(builder.cc(target));
183 cmd.arg("-print-search-dirs");
184 let gcc_out = cmd.run_capture_stdout(builder).stdout();
185
186 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
187 let mut lib_path = Vec::new();
188
189 for line in gcc_out.lines() {
190 let idx = line.find(':').unwrap();
191 let key = &line[..idx];
192 let trim_chars: &[_] = &[' ', '='];
193 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
194
195 if key == "programs" {
196 bin_path.extend(value);
197 } else if key == "libraries" {
198 lib_path.extend(value);
199 }
200 }
201
202 let compiler = if target == "i686-pc-windows-gnu" {
203 "i686-w64-mingw32-gcc.exe"
204 } else if target == "x86_64-pc-windows-gnu" {
205 "x86_64-w64-mingw32-gcc.exe"
206 } else {
207 "gcc.exe"
208 };
209 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
210 let mut rustc_dlls = vec!["libwinpthread-1.dll"];
211 if target.starts_with("i686-") {
212 rustc_dlls.push("libgcc_s_dw2-1.dll");
213 } else {
214 rustc_dlls.push("libgcc_s_seh-1.dll");
215 }
216
217 let target_libs = [
220 "libgcc.a",
222 "libgcc_eh.a",
223 "libgcc_s.a",
224 "libm.a",
225 "libmingw32.a",
226 "libmingwex.a",
227 "libstdc++.a",
228 "libiconv.a",
229 "libmoldname.a",
230 "libpthread.a",
231 "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 rustc_dlls = find_files(&rustc_dlls, &bin_path);
270 let target_libs = find_files(&target_libs, &lib_path);
271
272 let rust_bin_dir = rust_root.join("bin/");
274 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
275 for src in &rustc_dlls {
276 builder.copy_link_to_folder(src, &rust_bin_dir);
277 }
278
279 if builder.config.lld_enabled {
280 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
282 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
283 for src in &rustc_dlls {
284 builder.copy_link_to_folder(src, &rust_target_bin_dir);
285 }
286 }
287
288 let plat_target_bin_self_contained_dir =
290 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
291 fs::create_dir_all(&plat_target_bin_self_contained_dir)
292 .expect("creating plat_target_bin_self_contained_dir failed");
293 for src in target_tools {
294 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
295 }
296
297 builder.create(
299 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
300 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
301 used as a linker. In order to be able to compile projects containing C code use \
302 the GCC provided by MinGW or Cygwin.",
303 );
304
305 let plat_target_lib_self_contained_dir =
307 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
308 fs::create_dir_all(&plat_target_lib_self_contained_dir)
309 .expect("creating plat_target_lib_self_contained_dir failed");
310 for src in target_libs {
311 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
312 }
313}
314
315#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
316pub struct Mingw {
317 pub host: TargetSelection,
318}
319
320impl Step for Mingw {
321 type Output = Option<GeneratedTarball>;
322 const DEFAULT: bool = true;
323
324 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
325 run.alias("rust-mingw")
326 }
327
328 fn make_run(run: RunConfig<'_>) {
329 run.builder.ensure(Mingw { host: run.target });
330 }
331
332 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
337 let host = self.host;
338 if !host.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
339 return None;
340 }
341
342 let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple);
343 tarball.set_product_name("Rust MinGW");
344
345 make_win_dist(&tmpdir(builder), tarball.image_dir(), host, builder);
350
351 Some(tarball.generate())
352 }
353}
354
355#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
356pub struct Rustc {
357 pub compiler: Compiler,
358}
359
360impl Step for Rustc {
361 type Output = GeneratedTarball;
362 const DEFAULT: bool = true;
363 const ONLY_HOSTS: bool = true;
364
365 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
366 run.alias("rustc")
367 }
368
369 fn make_run(run: RunConfig<'_>) {
370 run.builder
371 .ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.target) });
372 }
373
374 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
376 let compiler = self.compiler;
377 let host = self.compiler.host;
378
379 let tarball = Tarball::new(builder, "rustc", &host.triple);
380
381 prepare_image(builder, compiler, tarball.image_dir());
383
384 if host.ends_with("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
395 make_win_dist(tarball.image_dir(), &tmpdir(builder), host, builder);
396 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
397 }
398
399 return tarball.generate();
400
401 fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
402 let host = compiler.host;
403 let src = builder.sysroot(compiler);
404
405 t!(fs::create_dir_all(image.join("bin")));
407 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
408
409 if builder
411 .config
412 .tools
413 .as_ref()
414 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
415 {
416 let rustdoc = builder.rustdoc(compiler);
417 builder.install(&rustdoc, &image.join("bin"), 0o755);
418 }
419
420 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
421 tool::RustAnalyzerProcMacroSrv {
422 compiler: builder.compiler_for(
423 compiler.stage,
424 builder.config.build,
425 compiler.host,
426 ),
427 target: compiler.host,
428 },
429 builder.kind,
430 ) {
431 builder.install(&ra_proc_macro_srv, &image.join("libexec"), 0o755);
432 }
433
434 let libdir_relative = builder.libdir_relative(compiler);
435
436 if libdir_relative.to_str() != Some("bin") {
438 let libdir = builder.rustc_libdir(compiler);
439 for entry in builder.read_dir(&libdir) {
440 if is_dylib(&entry.path()) {
441 builder.install(&entry.path(), &image.join("lib"), 0o644);
444 }
445 }
446 }
447
448 maybe_install_llvm_runtime(builder, host, image);
454
455 let dst_dir = image.join("lib/rustlib").join(host).join("bin");
456 t!(fs::create_dir_all(&dst_dir));
457
458 if builder.config.lld_enabled {
460 let src_dir = builder.sysroot_target_bindir(compiler, host);
461 let rust_lld = exe("rust-lld", compiler.host);
462 builder.copy_link(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
463 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
464 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
465 t!(fs::create_dir(&self_contained_lld_dst_dir));
466 for name in crate::LLD_FILE_NAMES {
467 let exe_name = exe(name, compiler.host);
468 builder.copy_link(
469 &self_contained_lld_src_dir.join(&exe_name),
470 &self_contained_lld_dst_dir.join(&exe_name),
471 );
472 }
473 }
474
475 if builder.config.llvm_enabled(compiler.host) && builder.config.llvm_tools_enabled {
476 let src_dir = builder.sysroot_target_bindir(compiler, host);
477 let llvm_objcopy = exe("llvm-objcopy", compiler.host);
478 let rust_objcopy = exe("rust-objcopy", compiler.host);
479 builder.copy_link(&src_dir.join(&llvm_objcopy), &dst_dir.join(&rust_objcopy));
480 }
481
482 if builder.tool_enabled("wasm-component-ld") {
483 let src_dir = builder.sysroot_target_bindir(compiler, host);
484 let ld = exe("wasm-component-ld", compiler.host);
485 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld));
486 }
487
488 t!(fs::create_dir_all(image.join("share/man/man1")));
490 let man_src = builder.src.join("src/doc/man");
491 let man_dst = image.join("share/man/man1");
492
493 for file_entry in builder.read_dir(&man_src) {
496 let page_src = file_entry.path();
497 let page_dst = man_dst.join(file_entry.file_name());
498 let src_text = t!(std::fs::read_to_string(&page_src));
499 let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version);
500 t!(std::fs::write(&page_dst, &new_text));
501 t!(fs::copy(&page_src, &page_dst));
502 }
503
504 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), host });
506
507 let file_list = builder.ensure(super::run::GenerateCopyright);
509 for file in file_list {
510 builder.install(&file, &image.join("share/doc/rust"), 0o644);
511 }
512
513 builder.install(&builder.src.join("README.md"), &image.join("share/doc/rust"), 0o644);
515
516 let license = |path: &Path| {
518 builder.install(path, &image.join("share/doc/rust/licenses"), 0o644);
519 };
520 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
521 license(&entry.path());
522 }
523 }
524 }
525}
526
527#[derive(Debug, Clone, Hash, PartialEq, Eq)]
528pub struct DebuggerScripts {
529 pub sysroot: PathBuf,
530 pub host: TargetSelection,
531}
532
533impl Step for DebuggerScripts {
534 type Output = ();
535
536 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
537 run.never()
538 }
539
540 fn run(self, builder: &Builder<'_>) {
542 let host = self.host;
543 let sysroot = self.sysroot;
544 let dst = sysroot.join("lib/rustlib/etc");
545 t!(fs::create_dir_all(&dst));
546 let cp_debugger_script = |file: &str| {
547 builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
548 };
549 if host.contains("windows-msvc") {
550 builder.install(
552 &builder.src.join("src/etc/rust-windbg.cmd"),
553 &sysroot.join("bin"),
554 0o755,
555 );
556
557 cp_debugger_script("natvis/intrinsic.natvis");
558 cp_debugger_script("natvis/liballoc.natvis");
559 cp_debugger_script("natvis/libcore.natvis");
560 cp_debugger_script("natvis/libstd.natvis");
561 }
562
563 cp_debugger_script("rust_types.py");
564
565 builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
567 builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
568
569 cp_debugger_script("gdb_load_rust_pretty_printers.py");
570 cp_debugger_script("gdb_lookup.py");
571 cp_debugger_script("gdb_providers.py");
572
573 builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
575
576 cp_debugger_script("lldb_lookup.py");
577 cp_debugger_script("lldb_providers.py");
578 cp_debugger_script("lldb_commands")
579 }
580}
581
582fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
583 if !builder.is_builder_target(&compiler.host) {
586 builder.info("\tskipping, not a build host");
587 true
588 } else {
589 false
590 }
591}
592
593fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
597 if !target.ends_with("-uefi") {
598 return;
599 }
600
601 for (path, _) in builder.read_stamp_file(stamp) {
602 if path.extension() != Some(OsStr::new("rlib")) {
603 continue;
604 }
605
606 let data = t!(fs::read(&path));
607 let data = data.as_slice();
608 let archive = t!(ArchiveFile::parse(data));
609 for member in archive.members() {
610 let member = t!(member);
611 let member_data = t!(member.data(data));
612
613 let is_coff = match object::File::parse(member_data) {
614 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
615 Err(_) => false,
616 };
617
618 if !is_coff {
619 let member_name = String::from_utf8_lossy(member.name());
620 panic!("member {} in {} is not COFF", member_name, path.display());
621 }
622 }
623 }
624}
625
626fn copy_target_libs(
628 builder: &Builder<'_>,
629 target: TargetSelection,
630 image: &Path,
631 stamp: &BuildStamp,
632) {
633 let dst = image.join("lib/rustlib").join(target).join("lib");
634 let self_contained_dst = dst.join("self-contained");
635 t!(fs::create_dir_all(&dst));
636 t!(fs::create_dir_all(&self_contained_dst));
637 for (path, dependency_type) in builder.read_stamp_file(stamp) {
638 if dependency_type == DependencyType::TargetSelfContained {
639 builder.copy_link(&path, &self_contained_dst.join(path.file_name().unwrap()));
640 } else if dependency_type == DependencyType::Target || builder.is_builder_target(&target) {
641 builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
642 }
643 }
644}
645
646#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
647pub struct Std {
648 pub compiler: Compiler,
649 pub target: TargetSelection,
650}
651
652impl Step for Std {
653 type Output = Option<GeneratedTarball>;
654 const DEFAULT: bool = true;
655
656 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
657 run.alias("rust-std")
658 }
659
660 fn make_run(run: RunConfig<'_>) {
661 run.builder.ensure(Std {
662 compiler: run.builder.compiler_for(
663 run.builder.top_stage,
664 run.builder.config.build,
665 run.target,
666 ),
667 target: run.target,
668 });
669 }
670
671 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
672 let compiler = self.compiler;
673 let target = self.target;
674
675 if skip_host_target_lib(builder, compiler) {
676 return None;
677 }
678
679 builder.ensure(compile::Std::new(compiler, target));
680
681 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
682 tarball.include_target_in_component_name(true);
683
684 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
685 let stamp = build_stamp::libstd_stamp(builder, compiler_to_use, target);
686 verify_uefi_rlib_format(builder, target, &stamp);
687 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
688
689 Some(tarball.generate())
690 }
691}
692
693#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
698pub struct RustcDev {
699 pub compiler: Compiler,
700 pub target: TargetSelection,
701}
702
703impl Step for RustcDev {
704 type Output = Option<GeneratedTarball>;
705 const DEFAULT: bool = true;
706 const ONLY_HOSTS: bool = true;
707
708 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
709 run.alias("rustc-dev")
710 }
711
712 fn make_run(run: RunConfig<'_>) {
713 run.builder.ensure(RustcDev {
714 compiler: run.builder.compiler_for(
715 run.builder.top_stage,
716 run.builder.config.build,
717 run.target,
718 ),
719 target: run.target,
720 });
721 }
722
723 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
724 let compiler = self.compiler;
725 let target = self.target;
726 if skip_host_target_lib(builder, compiler) {
727 return None;
728 }
729
730 builder.ensure(compile::Rustc::new(compiler, target));
731
732 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
733
734 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
735 let stamp = build_stamp::librustc_stamp(builder, compiler_to_use, target);
736 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
737
738 let src_files = &["Cargo.lock"];
739 copy_src_dirs(
742 builder,
743 &builder.src,
744 &["compiler"],
745 &[],
746 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
747 );
748 for file in src_files {
749 tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
750 }
751
752 Some(tarball.generate())
753 }
754}
755
756#[derive(Debug, Clone, Hash, PartialEq, Eq)]
757pub struct Analysis {
758 pub compiler: Compiler,
759 pub target: TargetSelection,
760}
761
762impl Step for Analysis {
763 type Output = Option<GeneratedTarball>;
764 const DEFAULT: bool = true;
765
766 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
767 let default = should_build_extended_tool(run.builder, "analysis");
768 run.alias("rust-analysis").default_condition(default)
769 }
770
771 fn make_run(run: RunConfig<'_>) {
772 run.builder.ensure(Analysis {
773 compiler: run.builder.compiler_for(
777 run.builder.top_stage,
778 run.builder.config.build,
779 run.target,
780 ),
781 target: run.target,
782 });
783 }
784
785 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
787 let compiler = self.compiler;
788 let target = self.target;
789 if !builder.is_builder_target(&compiler.host) {
790 return None;
791 }
792
793 let src = builder
794 .stage_out(compiler, Mode::Std)
795 .join(target)
796 .join(builder.cargo_dir())
797 .join("deps")
798 .join("save-analysis");
799
800 t!(std::fs::create_dir_all(&src));
802 let mut removed = src.clone();
803 removed.push("removed.json");
804 let mut f = t!(std::fs::File::create(removed));
805 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
806
807 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
808 tarball.include_target_in_component_name(true);
809 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
810 Some(tarball.generate())
811 }
812}
813
814fn copy_src_dirs(
817 builder: &Builder<'_>,
818 base: &Path,
819 src_dirs: &[&str],
820 exclude_dirs: &[&str],
821 dst_dir: &Path,
822) {
823 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
824 let spath = match path.to_str() {
825 Some(path) => path,
826 None => return false,
827 };
828 if spath.ends_with('~') || spath.ends_with(".pyc") {
829 return false;
830 }
831
832 const LLVM_PROJECTS: &[&str] = &[
833 "llvm-project/clang",
834 "llvm-project\\clang",
835 "llvm-project/libunwind",
836 "llvm-project\\libunwind",
837 "llvm-project/lld",
838 "llvm-project\\lld",
839 "llvm-project/lldb",
840 "llvm-project\\lldb",
841 "llvm-project/llvm",
842 "llvm-project\\llvm",
843 "llvm-project/compiler-rt",
844 "llvm-project\\compiler-rt",
845 "llvm-project/cmake",
846 "llvm-project\\cmake",
847 "llvm-project/runtimes",
848 "llvm-project\\runtimes",
849 ];
850 if spath.contains("llvm-project")
851 && !spath.ends_with("llvm-project")
852 && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
853 {
854 return false;
855 }
856
857 const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
858 if LLVM_TEST.iter().any(|path| spath.contains(path))
859 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
860 {
861 return false;
862 }
863
864 const CARGO_TESTS: &[&str] = &["tools/cargo/tests", "tools\\cargo\\tests"];
866 if CARGO_TESTS.iter().any(|path| spath.contains(path)) {
867 return true;
868 }
869
870 let full_path = Path::new(dir).join(path);
871 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
872 return false;
873 }
874
875 let excludes = [
876 "CVS",
877 "RCS",
878 "SCCS",
879 ".git",
880 ".gitignore",
881 ".gitmodules",
882 ".gitattributes",
883 ".cvsignore",
884 ".svn",
885 ".arch-ids",
886 "{arch}",
887 "=RELEASE-ID",
888 "=meta-update",
889 "=update",
890 ".bzr",
891 ".bzrignore",
892 ".bzrtags",
893 ".hg",
894 ".hgignore",
895 ".hgrags",
896 "_darcs",
897 ];
898 !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
899 }
900
901 for item in src_dirs {
903 let dst = &dst_dir.join(item);
904 t!(fs::create_dir_all(dst));
905 builder
906 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
907 }
908}
909
910#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
911pub struct Src;
912
913impl Step for Src {
914 type Output = GeneratedTarball;
916 const DEFAULT: bool = true;
917 const ONLY_HOSTS: bool = true;
918
919 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
920 run.alias("rust-src")
921 }
922
923 fn make_run(run: RunConfig<'_>) {
924 run.builder.ensure(Src);
925 }
926
927 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
929 if !builder.config.dry_run() {
930 builder.require_submodule("src/llvm-project", None);
931 }
932
933 let tarball = Tarball::new_targetless(builder, "rust-src");
934
935 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
943
944 copy_src_dirs(
947 builder,
948 &builder.src,
949 &["library", "src/llvm-project/libunwind"],
950 &[
951 "library/backtrace/crates",
954 "library/stdarch/Cargo.toml",
957 "library/stdarch/crates/stdarch-verify",
958 "library/stdarch/crates/intrinsic-test",
959 ],
960 &dst_src,
961 );
962
963 tarball.generate()
964 }
965}
966
967#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
968pub struct PlainSourceTarball;
969
970impl Step for PlainSourceTarball {
971 type Output = GeneratedTarball;
973 const DEFAULT: bool = true;
974 const ONLY_HOSTS: bool = true;
975
976 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
977 let builder = run.builder;
978 run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
979 }
980
981 fn make_run(run: RunConfig<'_>) {
982 run.builder.ensure(PlainSourceTarball);
983 }
984
985 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
987 let mut tarball = Tarball::new(builder, "rustc", "src");
992 tarball.permit_symlinks(true);
993 let plain_dst_src = tarball.image_dir();
994
995 let src_files = [
997 ".gitmodules",
999 "Cargo.lock",
1000 "Cargo.toml",
1001 "config.example.toml",
1002 "configure",
1003 "CONTRIBUTING.md",
1004 "COPYRIGHT",
1005 "LICENSE-APACHE",
1006 "license-metadata.json",
1007 "LICENSE-MIT",
1008 "README.md",
1009 "RELEASES.md",
1010 "REUSE.toml",
1011 "x",
1012 "x.ps1",
1013 "x.py",
1014 ];
1016 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1017
1018 copy_src_dirs(
1019 builder,
1020 &builder.src,
1021 &src_dirs,
1022 &[
1023 "src/gcc",
1027 ],
1028 plain_dst_src,
1029 );
1030
1031 for item in &src_files {
1033 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item));
1034 }
1035
1036 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1038
1039 let write_git_info = |info: Option<&Info>, path: &Path| {
1041 if let Some(info) = info {
1042 t!(std::fs::create_dir_all(path));
1043 channel::write_commit_hash_file(path, &info.sha);
1044 channel::write_commit_info_file(path, info);
1045 }
1046 };
1047 write_git_info(builder.rust_info().info(), plain_dst_src);
1048 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1049
1050 if builder.config.dist_vendor {
1051 builder.require_and_update_all_submodules();
1052
1053 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1055 .iter()
1056 .chain(build_helper::RUSTC_PGO_CRATES)
1057 .map(|pkg| {
1058 let mut manifest_path =
1059 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1060 manifest_path.push(pkg);
1061 manifest_path.push("Cargo.toml");
1062 manifest_path
1063 });
1064
1065 let vendor = builder.ensure(Vendor {
1067 sync_args: pkgs_for_pgo_training.collect(),
1068 versioned_dirs: true,
1069 root_dir: plain_dst_src.into(),
1070 output_dir: VENDOR_DIR.into(),
1071 });
1072
1073 let cargo_config_dir = plain_dst_src.join(".cargo");
1074 builder.create_dir(&cargo_config_dir);
1075 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1076 }
1077
1078 for entry in walkdir::WalkDir::new(tarball.image_dir())
1082 .follow_links(true)
1083 .into_iter()
1084 .filter_map(|e| e.ok())
1085 {
1086 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1087 {
1088 t!(fs::remove_dir_all(entry.path()));
1089 }
1090 }
1091
1092 tarball.bare()
1093 }
1094}
1095
1096#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1097pub struct Cargo {
1098 pub compiler: Compiler,
1099 pub target: TargetSelection,
1100}
1101
1102impl Step for Cargo {
1103 type Output = Option<GeneratedTarball>;
1104 const DEFAULT: bool = true;
1105 const ONLY_HOSTS: bool = true;
1106
1107 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1108 let default = should_build_extended_tool(run.builder, "cargo");
1109 run.alias("cargo").default_condition(default)
1110 }
1111
1112 fn make_run(run: RunConfig<'_>) {
1113 run.builder.ensure(Cargo {
1114 compiler: run.builder.compiler_for(
1115 run.builder.top_stage,
1116 run.builder.config.build,
1117 run.target,
1118 ),
1119 target: run.target,
1120 });
1121 }
1122
1123 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1124 let compiler = self.compiler;
1125 let target = self.target;
1126
1127 let cargo = builder.ensure(tool::Cargo { compiler, target });
1128 let src = builder.src.join("src/tools/cargo");
1129 let etc = src.join("src/etc");
1130
1131 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1133 tarball.set_overlay(OverlayKind::Cargo);
1134
1135 tarball.add_file(cargo, "bin", 0o755);
1136 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
1137 tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
1138 tarball.add_dir(etc.join("man"), "share/man/man1");
1139 tarball.add_legal_and_readme_to("share/doc/cargo");
1140
1141 Some(tarball.generate())
1142 }
1143}
1144
1145#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1146pub struct Rls {
1147 pub compiler: Compiler,
1148 pub target: TargetSelection,
1149}
1150
1151impl Step for Rls {
1152 type Output = Option<GeneratedTarball>;
1153 const ONLY_HOSTS: bool = true;
1154 const DEFAULT: bool = true;
1155
1156 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1157 let default = should_build_extended_tool(run.builder, "rls");
1158 run.alias("rls").default_condition(default)
1159 }
1160
1161 fn make_run(run: RunConfig<'_>) {
1162 run.builder.ensure(Rls {
1163 compiler: run.builder.compiler_for(
1164 run.builder.top_stage,
1165 run.builder.config.build,
1166 run.target,
1167 ),
1168 target: run.target,
1169 });
1170 }
1171
1172 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1173 let compiler = self.compiler;
1174 let target = self.target;
1175
1176 let rls = builder.ensure(tool::Rls { compiler, target });
1177
1178 let mut tarball = Tarball::new(builder, "rls", &target.triple);
1179 tarball.set_overlay(OverlayKind::Rls);
1180 tarball.is_preview(true);
1181 tarball.add_file(rls, "bin", 0o755);
1182 tarball.add_legal_and_readme_to("share/doc/rls");
1183 Some(tarball.generate())
1184 }
1185}
1186
1187#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1188pub struct RustAnalyzer {
1189 pub compiler: Compiler,
1190 pub target: TargetSelection,
1191}
1192
1193impl Step for RustAnalyzer {
1194 type Output = Option<GeneratedTarball>;
1195 const DEFAULT: bool = true;
1196 const ONLY_HOSTS: bool = true;
1197
1198 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1199 let default = should_build_extended_tool(run.builder, "rust-analyzer");
1200 run.alias("rust-analyzer").default_condition(default)
1201 }
1202
1203 fn make_run(run: RunConfig<'_>) {
1204 run.builder.ensure(RustAnalyzer {
1205 compiler: run.builder.compiler_for(
1206 run.builder.top_stage,
1207 run.builder.config.build,
1208 run.target,
1209 ),
1210 target: run.target,
1211 });
1212 }
1213
1214 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1215 let compiler = self.compiler;
1216 let target = self.target;
1217
1218 let rust_analyzer = builder.ensure(tool::RustAnalyzer { compiler, target });
1219
1220 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1221 tarball.set_overlay(OverlayKind::RustAnalyzer);
1222 tarball.is_preview(true);
1223 tarball.add_file(rust_analyzer, "bin", 0o755);
1224 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1225 Some(tarball.generate())
1226 }
1227}
1228
1229#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1230pub struct Clippy {
1231 pub compiler: Compiler,
1232 pub target: TargetSelection,
1233}
1234
1235impl Step for Clippy {
1236 type Output = Option<GeneratedTarball>;
1237 const DEFAULT: bool = true;
1238 const ONLY_HOSTS: bool = true;
1239
1240 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1241 let default = should_build_extended_tool(run.builder, "clippy");
1242 run.alias("clippy").default_condition(default)
1243 }
1244
1245 fn make_run(run: RunConfig<'_>) {
1246 run.builder.ensure(Clippy {
1247 compiler: run.builder.compiler_for(
1248 run.builder.top_stage,
1249 run.builder.config.build,
1250 run.target,
1251 ),
1252 target: run.target,
1253 });
1254 }
1255
1256 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1257 let compiler = self.compiler;
1258 let target = self.target;
1259
1260 let clippy = builder.ensure(tool::Clippy { compiler, target });
1264 let cargoclippy = builder.ensure(tool::CargoClippy { compiler, target });
1265
1266 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1267 tarball.set_overlay(OverlayKind::Clippy);
1268 tarball.is_preview(true);
1269 tarball.add_file(clippy, "bin", 0o755);
1270 tarball.add_file(cargoclippy, "bin", 0o755);
1271 tarball.add_legal_and_readme_to("share/doc/clippy");
1272 Some(tarball.generate())
1273 }
1274}
1275
1276#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1277pub struct Miri {
1278 pub compiler: Compiler,
1279 pub target: TargetSelection,
1280}
1281
1282impl Step for Miri {
1283 type Output = Option<GeneratedTarball>;
1284 const DEFAULT: bool = true;
1285 const ONLY_HOSTS: bool = true;
1286
1287 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1288 let default = should_build_extended_tool(run.builder, "miri");
1289 run.alias("miri").default_condition(default)
1290 }
1291
1292 fn make_run(run: RunConfig<'_>) {
1293 run.builder.ensure(Miri {
1294 compiler: run.builder.compiler_for(
1295 run.builder.top_stage,
1296 run.builder.config.build,
1297 run.target,
1298 ),
1299 target: run.target,
1300 });
1301 }
1302
1303 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1304 if !builder.build.unstable_features() {
1308 return None;
1309 }
1310 let compiler = self.compiler;
1311 let target = self.target;
1312
1313 let miri = builder.ensure(tool::Miri { compiler, target });
1314 let cargomiri = builder.ensure(tool::CargoMiri { compiler, target });
1315
1316 let mut tarball = Tarball::new(builder, "miri", &target.triple);
1317 tarball.set_overlay(OverlayKind::Miri);
1318 tarball.is_preview(true);
1319 tarball.add_file(miri, "bin", 0o755);
1320 tarball.add_file(cargomiri, "bin", 0o755);
1321 tarball.add_legal_and_readme_to("share/doc/miri");
1322 Some(tarball.generate())
1323 }
1324}
1325
1326#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1327pub struct CodegenBackend {
1328 pub compiler: Compiler,
1329 pub backend: String,
1330}
1331
1332impl Step for CodegenBackend {
1333 type Output = Option<GeneratedTarball>;
1334 const DEFAULT: bool = true;
1335 const ONLY_HOSTS: bool = true;
1336
1337 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1338 run.path("compiler/rustc_codegen_cranelift")
1339 }
1340
1341 fn make_run(run: RunConfig<'_>) {
1342 for backend in run.builder.config.codegen_backends(run.target) {
1343 if backend == "llvm" {
1344 continue; }
1346
1347 run.builder.ensure(CodegenBackend {
1348 compiler: run.builder.compiler(run.builder.top_stage, run.target),
1349 backend: backend.clone(),
1350 });
1351 }
1352 }
1353
1354 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1355 if builder.config.dry_run() {
1356 return None;
1357 }
1358
1359 if !builder.build.unstable_features() {
1363 return None;
1364 }
1365
1366 if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend.to_string())
1367 {
1368 return None;
1369 }
1370
1371 if self.backend == "cranelift" && !target_supports_cranelift_backend(self.compiler.host) {
1372 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1373 return None;
1374 }
1375
1376 let compiler = self.compiler;
1377 let backend = self.backend;
1378
1379 let mut tarball =
1380 Tarball::new(builder, &format!("rustc-codegen-{}", backend), &compiler.host.triple);
1381 if backend == "cranelift" {
1382 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1383 } else {
1384 panic!("Unknown backend rustc_codegen_{}", backend);
1385 }
1386 tarball.is_preview(true);
1387 tarball.add_legal_and_readme_to(format!("share/doc/rustc_codegen_{}", backend));
1388
1389 let src = builder.sysroot(compiler);
1390 let backends_src = builder.sysroot_codegen_backends(compiler);
1391 let backends_rel = backends_src
1392 .strip_prefix(src)
1393 .unwrap()
1394 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1395 .unwrap();
1396 let backends_dst = PathBuf::from("lib").join(backends_rel);
1398
1399 let backend_name = format!("rustc_codegen_{}", backend);
1400 let mut found_backend = false;
1401 for backend in fs::read_dir(&backends_src).unwrap() {
1402 let file_name = backend.unwrap().file_name();
1403 if file_name.to_str().unwrap().contains(&backend_name) {
1404 tarball.add_file(backends_src.join(file_name), &backends_dst, 0o644);
1405 found_backend = true;
1406 }
1407 }
1408 assert!(found_backend);
1409
1410 Some(tarball.generate())
1411 }
1412}
1413
1414#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1415pub struct Rustfmt {
1416 pub compiler: Compiler,
1417 pub target: TargetSelection,
1418}
1419
1420impl Step for Rustfmt {
1421 type Output = Option<GeneratedTarball>;
1422 const DEFAULT: bool = true;
1423 const ONLY_HOSTS: bool = true;
1424
1425 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1426 let default = should_build_extended_tool(run.builder, "rustfmt");
1427 run.alias("rustfmt").default_condition(default)
1428 }
1429
1430 fn make_run(run: RunConfig<'_>) {
1431 run.builder.ensure(Rustfmt {
1432 compiler: run.builder.compiler_for(
1433 run.builder.top_stage,
1434 run.builder.config.build,
1435 run.target,
1436 ),
1437 target: run.target,
1438 });
1439 }
1440
1441 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1442 let compiler = self.compiler;
1443 let target = self.target;
1444
1445 let rustfmt = builder.ensure(tool::Rustfmt { compiler, target });
1446 let cargofmt = builder.ensure(tool::Cargofmt { compiler, target });
1447 let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
1448 tarball.set_overlay(OverlayKind::Rustfmt);
1449 tarball.is_preview(true);
1450 tarball.add_file(rustfmt, "bin", 0o755);
1451 tarball.add_file(cargofmt, "bin", 0o755);
1452 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1453 Some(tarball.generate())
1454 }
1455}
1456
1457#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1458pub struct Extended {
1459 stage: u32,
1460 host: TargetSelection,
1461 target: TargetSelection,
1462}
1463
1464impl Step for Extended {
1465 type Output = ();
1466 const DEFAULT: bool = true;
1467 const ONLY_HOSTS: bool = true;
1468
1469 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1470 let builder = run.builder;
1471 run.alias("extended").default_condition(builder.config.extended)
1472 }
1473
1474 fn make_run(run: RunConfig<'_>) {
1475 run.builder.ensure(Extended {
1476 stage: run.builder.top_stage,
1477 host: run.builder.config.build,
1478 target: run.target,
1479 });
1480 }
1481
1482 fn run(self, builder: &Builder<'_>) {
1484 let target = self.target;
1485 let stage = self.stage;
1486 let compiler = builder.compiler_for(self.stage, self.host, self.target);
1487
1488 builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1489
1490 let mut tarballs = Vec::new();
1491 let mut built_tools = HashSet::new();
1492 macro_rules! add_component {
1493 ($name:expr => $step:expr) => {
1494 if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) {
1495 tarballs.push(tarball);
1496 built_tools.insert($name);
1497 }
1498 };
1499 }
1500
1501 tarballs.push(builder.ensure(Rustc { compiler: builder.compiler(stage, target) }));
1506 tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
1507
1508 if target.is_windows_gnu() {
1509 tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
1510 }
1511
1512 add_component!("rust-docs" => Docs { host: target });
1513 add_component!("rust-json-docs" => JsonDocs { host: target });
1514 add_component!("cargo" => Cargo { compiler, target });
1515 add_component!("rustfmt" => Rustfmt { compiler, target });
1516 add_component!("rls" => Rls { compiler, target });
1517 add_component!("rust-analyzer" => RustAnalyzer { compiler, target });
1518 add_component!("llvm-components" => LlvmTools { target });
1519 add_component!("clippy" => Clippy { compiler, target });
1520 add_component!("miri" => Miri { compiler, target });
1521 add_component!("analysis" => Analysis { compiler, target });
1522 add_component!("rustc-codegen-cranelift" => CodegenBackend {
1523 compiler: builder.compiler(stage, target),
1524 backend: "cranelift".to_string(),
1525 });
1526 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {compiler, target});
1527
1528 let etc = builder.src.join("src/etc/installer");
1529
1530 if builder.config.dry_run() {
1532 return;
1533 }
1534
1535 let tarball = Tarball::new(builder, "rust", &target.triple);
1536 let generated = tarball.combine(&tarballs);
1537
1538 let tmp = tmpdir(builder).join("combined-tarball");
1539 let work = generated.work_dir();
1540
1541 let mut license = String::new();
1542 license += &builder.read(&builder.src.join("COPYRIGHT"));
1543 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1544 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1545 license.push('\n');
1546 license.push('\n');
1547
1548 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1549 let mut rtf = rtf.to_string();
1550 rtf.push('\n');
1551 for line in license.lines() {
1552 rtf.push_str(line);
1553 rtf.push_str("\\line ");
1554 }
1555 rtf.push('}');
1556
1557 fn filter(contents: &str, marker: &str) -> String {
1558 let start = format!("tool-{marker}-start");
1559 let end = format!("tool-{marker}-end");
1560 let mut lines = Vec::new();
1561 let mut omitted = false;
1562 for line in contents.lines() {
1563 if line.contains(&start) {
1564 omitted = true;
1565 } else if line.contains(&end) {
1566 omitted = false;
1567 } else if !omitted {
1568 lines.push(line);
1569 }
1570 }
1571
1572 lines.join("\n")
1573 }
1574
1575 let xform = |p: &Path| {
1576 let mut contents = t!(fs::read_to_string(p));
1577 for tool in &["miri", "rust-docs"] {
1578 if !built_tools.contains(tool) {
1579 contents = filter(&contents, tool);
1580 }
1581 }
1582 let ret = tmp.join(p.file_name().unwrap());
1583 t!(fs::write(&ret, &contents));
1584 ret
1585 };
1586
1587 if target.contains("apple-darwin") {
1588 builder.info("building pkg installer");
1589 let pkg = tmp.join("pkg");
1590 let _ = fs::remove_dir_all(&pkg);
1591
1592 let pkgbuild = |component: &str| {
1593 let mut cmd = command("pkgbuild");
1594 cmd.arg("--identifier")
1595 .arg(format!("org.rust-lang.{}", component))
1596 .arg("--scripts")
1597 .arg(pkg.join(component))
1598 .arg("--nopayload")
1599 .arg(pkg.join(component).with_extension("pkg"));
1600 cmd.run(builder);
1601 };
1602
1603 let prepare = |name: &str| {
1604 builder.create_dir(&pkg.join(name));
1605 builder.cp_link_r(
1606 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1607 &pkg.join(name),
1608 );
1609 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1610 pkgbuild(name);
1611 };
1612 prepare("rustc");
1613 prepare("cargo");
1614 prepare("rust-std");
1615 prepare("rust-analysis");
1616 prepare("clippy");
1617 prepare("rust-analyzer");
1618 for tool in &["rust-docs", "miri", "rustc-codegen-cranelift"] {
1619 if built_tools.contains(tool) {
1620 prepare(tool);
1621 }
1622 }
1623 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1625 pkgbuild("uninstall");
1626
1627 builder.create_dir(&pkg.join("res"));
1628 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1629 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1630 let mut cmd = command("productbuild");
1631 cmd.arg("--distribution")
1632 .arg(xform(&etc.join("pkg/Distribution.xml")))
1633 .arg("--resources")
1634 .arg(pkg.join("res"))
1635 .arg(distdir(builder).join(format!(
1636 "{}-{}.pkg",
1637 pkgname(builder, "rust"),
1638 target.triple
1639 )))
1640 .arg("--package-path")
1641 .arg(&pkg);
1642 let _time = timeit(builder);
1643 cmd.run(builder);
1644 }
1645
1646 if target.is_windows() {
1647 let exe = tmp.join("exe");
1648 let _ = fs::remove_dir_all(&exe);
1649
1650 let prepare = |name: &str| {
1651 builder.create_dir(&exe.join(name));
1652 let dir = if name == "rust-std" || name == "rust-analysis" {
1653 format!("{}-{}", name, target.triple)
1654 } else if name == "rust-analyzer" {
1655 "rust-analyzer-preview".to_string()
1656 } else if name == "clippy" {
1657 "clippy-preview".to_string()
1658 } else if name == "miri" {
1659 "miri-preview".to_string()
1660 } else if name == "rustc-codegen-cranelift" {
1661 unreachable!("cg_clif shouldn't be built for windows");
1664 } else {
1665 name.to_string()
1666 };
1667 builder.cp_link_r(
1668 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1669 &exe.join(name),
1670 );
1671 builder.remove(&exe.join(name).join("manifest.in"));
1672 };
1673 prepare("rustc");
1674 prepare("cargo");
1675 prepare("rust-analysis");
1676 prepare("rust-std");
1677 for tool in &["clippy", "rust-analyzer", "rust-docs", "miri"] {
1678 if built_tools.contains(tool) {
1679 prepare(tool);
1680 }
1681 }
1682 if target.is_windows_gnu() {
1683 prepare("rust-mingw");
1684 }
1685
1686 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1687
1688 let wix_path = env::var_os("WIX")
1690 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1691 let wix = PathBuf::from(wix_path);
1692 let heat = wix.join("bin/heat.exe");
1693 let candle = wix.join("bin/candle.exe");
1694 let light = wix.join("bin/light.exe");
1695
1696 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1697 command(&heat)
1698 .current_dir(&exe)
1699 .arg("dir")
1700 .arg("rustc")
1701 .args(heat_flags)
1702 .arg("-cg")
1703 .arg("RustcGroup")
1704 .arg("-dr")
1705 .arg("Rustc")
1706 .arg("-var")
1707 .arg("var.RustcDir")
1708 .arg("-out")
1709 .arg(exe.join("RustcGroup.wxs"))
1710 .run(builder);
1711 if built_tools.contains("rust-docs") {
1712 command(&heat)
1713 .current_dir(&exe)
1714 .arg("dir")
1715 .arg("rust-docs")
1716 .args(heat_flags)
1717 .arg("-cg")
1718 .arg("DocsGroup")
1719 .arg("-dr")
1720 .arg("Docs")
1721 .arg("-var")
1722 .arg("var.DocsDir")
1723 .arg("-out")
1724 .arg(exe.join("DocsGroup.wxs"))
1725 .arg("-t")
1726 .arg(etc.join("msi/squash-components.xsl"))
1727 .run(builder);
1728 }
1729 command(&heat)
1730 .current_dir(&exe)
1731 .arg("dir")
1732 .arg("cargo")
1733 .args(heat_flags)
1734 .arg("-cg")
1735 .arg("CargoGroup")
1736 .arg("-dr")
1737 .arg("Cargo")
1738 .arg("-var")
1739 .arg("var.CargoDir")
1740 .arg("-out")
1741 .arg(exe.join("CargoGroup.wxs"))
1742 .arg("-t")
1743 .arg(etc.join("msi/remove-duplicates.xsl"))
1744 .run(builder);
1745 command(&heat)
1746 .current_dir(&exe)
1747 .arg("dir")
1748 .arg("rust-std")
1749 .args(heat_flags)
1750 .arg("-cg")
1751 .arg("StdGroup")
1752 .arg("-dr")
1753 .arg("Std")
1754 .arg("-var")
1755 .arg("var.StdDir")
1756 .arg("-out")
1757 .arg(exe.join("StdGroup.wxs"))
1758 .run(builder);
1759 if built_tools.contains("rust-analyzer") {
1760 command(&heat)
1761 .current_dir(&exe)
1762 .arg("dir")
1763 .arg("rust-analyzer")
1764 .args(heat_flags)
1765 .arg("-cg")
1766 .arg("RustAnalyzerGroup")
1767 .arg("-dr")
1768 .arg("RustAnalyzer")
1769 .arg("-var")
1770 .arg("var.RustAnalyzerDir")
1771 .arg("-out")
1772 .arg(exe.join("RustAnalyzerGroup.wxs"))
1773 .arg("-t")
1774 .arg(etc.join("msi/remove-duplicates.xsl"))
1775 .run(builder);
1776 }
1777 if built_tools.contains("clippy") {
1778 command(&heat)
1779 .current_dir(&exe)
1780 .arg("dir")
1781 .arg("clippy")
1782 .args(heat_flags)
1783 .arg("-cg")
1784 .arg("ClippyGroup")
1785 .arg("-dr")
1786 .arg("Clippy")
1787 .arg("-var")
1788 .arg("var.ClippyDir")
1789 .arg("-out")
1790 .arg(exe.join("ClippyGroup.wxs"))
1791 .arg("-t")
1792 .arg(etc.join("msi/remove-duplicates.xsl"))
1793 .run(builder);
1794 }
1795 if built_tools.contains("miri") {
1796 command(&heat)
1797 .current_dir(&exe)
1798 .arg("dir")
1799 .arg("miri")
1800 .args(heat_flags)
1801 .arg("-cg")
1802 .arg("MiriGroup")
1803 .arg("-dr")
1804 .arg("Miri")
1805 .arg("-var")
1806 .arg("var.MiriDir")
1807 .arg("-out")
1808 .arg(exe.join("MiriGroup.wxs"))
1809 .arg("-t")
1810 .arg(etc.join("msi/remove-duplicates.xsl"))
1811 .run(builder);
1812 }
1813 command(&heat)
1814 .current_dir(&exe)
1815 .arg("dir")
1816 .arg("rust-analysis")
1817 .args(heat_flags)
1818 .arg("-cg")
1819 .arg("AnalysisGroup")
1820 .arg("-dr")
1821 .arg("Analysis")
1822 .arg("-var")
1823 .arg("var.AnalysisDir")
1824 .arg("-out")
1825 .arg(exe.join("AnalysisGroup.wxs"))
1826 .arg("-t")
1827 .arg(etc.join("msi/remove-duplicates.xsl"))
1828 .run(builder);
1829 if target.is_windows_gnu() {
1830 command(&heat)
1831 .current_dir(&exe)
1832 .arg("dir")
1833 .arg("rust-mingw")
1834 .args(heat_flags)
1835 .arg("-cg")
1836 .arg("GccGroup")
1837 .arg("-dr")
1838 .arg("Gcc")
1839 .arg("-var")
1840 .arg("var.GccDir")
1841 .arg("-out")
1842 .arg(exe.join("GccGroup.wxs"))
1843 .run(builder);
1844 }
1845
1846 let candle = |input: &Path| {
1847 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1848 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1849 let mut cmd = command(&candle);
1850 cmd.current_dir(&exe)
1851 .arg("-nologo")
1852 .arg("-dRustcDir=rustc")
1853 .arg("-dCargoDir=cargo")
1854 .arg("-dStdDir=rust-std")
1855 .arg("-dAnalysisDir=rust-analysis")
1856 .arg("-arch")
1857 .arg(arch)
1858 .arg("-out")
1859 .arg(&output)
1860 .arg(input);
1861 add_env(builder, &mut cmd, target);
1862
1863 if built_tools.contains("clippy") {
1864 cmd.arg("-dClippyDir=clippy");
1865 }
1866 if built_tools.contains("rust-docs") {
1867 cmd.arg("-dDocsDir=rust-docs");
1868 }
1869 if built_tools.contains("rust-analyzer") {
1870 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1871 }
1872 if built_tools.contains("miri") {
1873 cmd.arg("-dMiriDir=miri");
1874 }
1875 if target.is_windows_gnu() {
1876 cmd.arg("-dGccDir=rust-mingw");
1877 }
1878 cmd.run(builder);
1879 };
1880 candle(&xform(&etc.join("msi/rust.wxs")));
1881 candle(&etc.join("msi/ui.wxs"));
1882 candle(&etc.join("msi/rustwelcomedlg.wxs"));
1883 candle("RustcGroup.wxs".as_ref());
1884 if built_tools.contains("rust-docs") {
1885 candle("DocsGroup.wxs".as_ref());
1886 }
1887 candle("CargoGroup.wxs".as_ref());
1888 candle("StdGroup.wxs".as_ref());
1889 if built_tools.contains("clippy") {
1890 candle("ClippyGroup.wxs".as_ref());
1891 }
1892 if built_tools.contains("miri") {
1893 candle("MiriGroup.wxs".as_ref());
1894 }
1895 if built_tools.contains("rust-analyzer") {
1896 candle("RustAnalyzerGroup.wxs".as_ref());
1897 }
1898 candle("AnalysisGroup.wxs".as_ref());
1899
1900 if target.is_windows_gnu() {
1901 candle("GccGroup.wxs".as_ref());
1902 }
1903
1904 builder.create(&exe.join("LICENSE.rtf"), &rtf);
1905 builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1906 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1907
1908 builder.info(&format!("building `msi` installer with {light:?}"));
1909 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1910 let mut cmd = command(&light);
1911 cmd.arg("-nologo")
1912 .arg("-ext")
1913 .arg("WixUIExtension")
1914 .arg("-ext")
1915 .arg("WixUtilExtension")
1916 .arg("-out")
1917 .arg(exe.join(&filename))
1918 .arg("rust.wixobj")
1919 .arg("ui.wixobj")
1920 .arg("rustwelcomedlg.wixobj")
1921 .arg("RustcGroup.wixobj")
1922 .arg("CargoGroup.wixobj")
1923 .arg("StdGroup.wixobj")
1924 .arg("AnalysisGroup.wixobj")
1925 .current_dir(&exe);
1926
1927 if built_tools.contains("clippy") {
1928 cmd.arg("ClippyGroup.wixobj");
1929 }
1930 if built_tools.contains("miri") {
1931 cmd.arg("MiriGroup.wixobj");
1932 }
1933 if built_tools.contains("rust-analyzer") {
1934 cmd.arg("RustAnalyzerGroup.wixobj");
1935 }
1936 if built_tools.contains("rust-docs") {
1937 cmd.arg("DocsGroup.wixobj");
1938 }
1939
1940 if target.is_windows_gnu() {
1941 cmd.arg("GccGroup.wixobj");
1942 }
1943 cmd.arg("-sice:ICE57");
1945
1946 let _time = timeit(builder);
1947 cmd.run(builder);
1948
1949 if !builder.config.dry_run() {
1950 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
1951 }
1952 }
1953 }
1954}
1955
1956fn add_env(builder: &Builder<'_>, cmd: &mut BootstrapCommand, target: TargetSelection) {
1957 let mut parts = builder.version.split('.');
1958 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
1959 .env("CFG_RELEASE_NUM", &builder.version)
1960 .env("CFG_RELEASE", builder.rust_release())
1961 .env("CFG_VER_MAJOR", parts.next().unwrap())
1962 .env("CFG_VER_MINOR", parts.next().unwrap())
1963 .env("CFG_VER_PATCH", parts.next().unwrap())
1964 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
1966 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
1967 .env("CFG_BUILD", target.triple)
1968 .env("CFG_CHANNEL", &builder.config.channel);
1969
1970 if target.contains("windows-gnullvm") {
1971 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
1972 } else if target.is_windows_gnu() {
1973 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
1974 } else {
1975 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
1976 }
1977}
1978
1979fn install_llvm_file(
1980 builder: &Builder<'_>,
1981 source: &Path,
1982 destination: &Path,
1983 install_symlink: bool,
1984) {
1985 if builder.config.dry_run() {
1986 return;
1987 }
1988
1989 if source.is_symlink() {
1990 builder.install(&t!(fs::canonicalize(source)), destination, 0o644);
1993
1994 let full_dest = destination.join(source.file_name().unwrap());
1995 if install_symlink {
1996 builder.copy_link(source, &full_dest);
1999 } else {
2000 let link = t!(fs::read_link(source));
2004 let mut linker_script = t!(fs::File::create(full_dest));
2005 t!(write!(linker_script, "INPUT({})\n", link.display()));
2006
2007 let meta = t!(fs::metadata(source));
2010 if let Ok(mtime) = meta.modified() {
2011 t!(linker_script.set_modified(mtime));
2012 }
2013 }
2014 } else {
2015 builder.install(source, destination, 0o644);
2016 }
2017}
2018
2019fn maybe_install_llvm(
2023 builder: &Builder<'_>,
2024 target: TargetSelection,
2025 dst_libdir: &Path,
2026 install_symlink: bool,
2027) -> bool {
2028 if builder.is_system_llvm(target) {
2045 return false;
2046 }
2047
2048 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2054 let src_libdir = builder.llvm_out(target).join("lib");
2055 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2056 if llvm_dylib_path.exists() {
2057 builder.install(&llvm_dylib_path, dst_libdir, 0o644);
2058 }
2059 !builder.config.dry_run()
2060 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
2061 llvm::prebuilt_llvm_config(builder, target, true)
2062 {
2063 let mut cmd = command(llvm_config);
2064 cmd.arg("--libfiles");
2065 builder.verbose(|| println!("running {cmd:?}"));
2066 let files = cmd.run_capture_stdout(builder).stdout();
2067 let build_llvm_out = &builder.llvm_out(builder.config.build);
2068 let target_llvm_out = &builder.llvm_out(target);
2069 for file in files.trim_end().split(' ') {
2070 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2072 target_llvm_out.join(relative_path)
2073 } else {
2074 PathBuf::from(file)
2075 };
2076 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2077 }
2078 !builder.config.dry_run()
2079 } else {
2080 false
2081 }
2082}
2083
2084pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2086 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2087 if builder.llvm_link_shared() {
2091 maybe_install_llvm(builder, target, &dst_libdir, false);
2092 }
2093}
2094
2095pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2097 let dst_libdir =
2098 sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
2099 if builder.llvm_link_shared() {
2103 maybe_install_llvm(builder, target, &dst_libdir, false);
2104 }
2105}
2106
2107#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2108pub struct LlvmTools {
2109 pub target: TargetSelection,
2110}
2111
2112impl Step for LlvmTools {
2113 type Output = Option<GeneratedTarball>;
2114 const ONLY_HOSTS: bool = true;
2115 const DEFAULT: bool = true;
2116
2117 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2118 let default = should_build_extended_tool(run.builder, "llvm-tools");
2119
2120 let mut run = run.alias("llvm-tools");
2121 for tool in LLVM_TOOLS {
2122 run = run.alias(tool);
2123 }
2124
2125 run.default_condition(default)
2126 }
2127
2128 fn make_run(run: RunConfig<'_>) {
2129 run.builder.ensure(LlvmTools { target: run.target });
2130 }
2131
2132 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2133 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2134 let mut tools = vec![];
2135
2136 for path in paths {
2137 let path = path.to_str().unwrap();
2138
2139 if path == "llvm-tools" {
2141 return LLVM_TOOLS.to_owned();
2142 }
2143
2144 for tool in LLVM_TOOLS {
2145 if path == *tool {
2146 tools.push(*tool);
2147 }
2148 }
2149 }
2150
2151 if tools.is_empty() {
2153 tools = LLVM_TOOLS.to_owned();
2154 }
2155
2156 tools
2157 }
2158
2159 let target = self.target;
2160
2161 if let Some(config) = builder.config.target_config.get(&target) {
2163 if let Some(ref _s) = config.llvm_config {
2164 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2165 return None;
2166 }
2167 }
2168
2169 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2170
2171 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2172 tarball.set_overlay(OverlayKind::Llvm);
2173 tarball.is_preview(true);
2174
2175 if builder.config.llvm_tools_enabled {
2176 let src_bindir = builder.llvm_out(target).join("bin");
2178 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2179 for tool in tools_to_install(&builder.paths) {
2180 let exe = src_bindir.join(exe(tool, target));
2181 tarball.add_file(&exe, &dst_bindir, 0o755);
2182 }
2183 }
2184
2185 maybe_install_llvm_target(builder, target, tarball.image_dir());
2190
2191 Some(tarball.generate())
2192 }
2193}
2194
2195#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
2196pub struct LlvmBitcodeLinker {
2197 pub compiler: Compiler,
2198 pub target: TargetSelection,
2199}
2200
2201impl Step for LlvmBitcodeLinker {
2202 type Output = Option<GeneratedTarball>;
2203 const DEFAULT: bool = true;
2204 const ONLY_HOSTS: bool = true;
2205
2206 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2207 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2208 run.alias("llvm-bitcode-linker").default_condition(default)
2209 }
2210
2211 fn make_run(run: RunConfig<'_>) {
2212 run.builder.ensure(LlvmBitcodeLinker {
2213 compiler: run.builder.compiler_for(
2214 run.builder.top_stage,
2215 run.builder.config.build,
2216 run.target,
2217 ),
2218 target: run.target,
2219 });
2220 }
2221
2222 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2223 let compiler = self.compiler;
2224 let target = self.target;
2225
2226 let llbc_linker =
2227 builder.ensure(tool::LlvmBitcodeLinker { compiler, target, extra_features: vec![] });
2228
2229 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2230
2231 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2233 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2234 tarball.is_preview(true);
2235
2236 tarball.add_file(llbc_linker, self_contained_bin_dir, 0o755);
2237
2238 Some(tarball.generate())
2239 }
2240}
2241
2242#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2251pub struct RustDev {
2252 pub target: TargetSelection,
2253}
2254
2255impl Step for RustDev {
2256 type Output = Option<GeneratedTarball>;
2257 const DEFAULT: bool = true;
2258 const ONLY_HOSTS: bool = true;
2259
2260 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2261 run.alias("rust-dev")
2262 }
2263
2264 fn make_run(run: RunConfig<'_>) {
2265 run.builder.ensure(RustDev { target: run.target });
2266 }
2267
2268 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2269 let target = self.target;
2270
2271 if let Some(config) = builder.config.target_config.get(&target) {
2273 if let Some(ref _s) = config.llvm_config {
2274 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2275 return None;
2276 }
2277 }
2278
2279 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2280 tarball.set_overlay(OverlayKind::Llvm);
2281 tarball.permit_symlinks(true);
2283
2284 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2285
2286 let src_bindir = builder.llvm_out(target).join("bin");
2287 if src_bindir.exists() {
2293 for entry in walkdir::WalkDir::new(&src_bindir) {
2294 let entry = t!(entry);
2295 if entry.file_type().is_file() && !entry.path_is_symlink() {
2296 let name = entry.file_name().to_str().unwrap();
2297 tarball.add_file(src_bindir.join(name), "bin", 0o755);
2298 }
2299 }
2300 }
2301
2302 if builder.config.lld_enabled {
2303 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2305
2306 let lld_path = lld_out.join("bin").join(exe("lld", target));
2308 if lld_path.exists() {
2309 tarball.add_file(lld_path, "bin", 0o755);
2310 }
2311 }
2312
2313 tarball.add_file(builder.llvm_filecheck(target), "bin", 0o755);
2314
2315 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2319
2320 let dst_libdir = tarball.image_dir().join("lib");
2325 maybe_install_llvm(builder, target, &dst_libdir, true);
2326 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2327 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2328
2329 copy_src_dirs(
2333 builder,
2334 &builder.src.join("src").join("llvm-project"),
2335 &["compiler-rt"],
2336 &["compiler-rt/test"],
2339 tarball.image_dir(),
2340 );
2341
2342 Some(tarball.generate())
2343 }
2344}
2345
2346#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2350pub struct Bootstrap {
2351 pub target: TargetSelection,
2352}
2353
2354impl Step for Bootstrap {
2355 type Output = Option<GeneratedTarball>;
2356 const DEFAULT: bool = false;
2357 const ONLY_HOSTS: bool = true;
2358
2359 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2360 run.alias("bootstrap")
2361 }
2362
2363 fn make_run(run: RunConfig<'_>) {
2364 run.builder.ensure(Bootstrap { target: run.target });
2365 }
2366
2367 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2368 let target = self.target;
2369
2370 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2371
2372 let bootstrap_outdir = &builder.bootstrap_out;
2373 for file in &["bootstrap", "rustc", "rustdoc", "sccache-plus-cl"] {
2374 tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755);
2375 }
2376
2377 Some(tarball.generate())
2378 }
2379}
2380
2381#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2386pub struct BuildManifest {
2387 pub target: TargetSelection,
2388}
2389
2390impl Step for BuildManifest {
2391 type Output = GeneratedTarball;
2392 const DEFAULT: bool = false;
2393 const ONLY_HOSTS: bool = true;
2394
2395 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2396 run.alias("build-manifest")
2397 }
2398
2399 fn make_run(run: RunConfig<'_>) {
2400 run.builder.ensure(BuildManifest { target: run.target });
2401 }
2402
2403 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2404 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2405
2406 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2407 tarball.add_file(build_manifest, "bin", 0o755);
2408 tarball.generate()
2409 }
2410}
2411
2412#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2418pub struct ReproducibleArtifacts {
2419 pub target: TargetSelection,
2420}
2421
2422impl Step for ReproducibleArtifacts {
2423 type Output = Option<GeneratedTarball>;
2424 const DEFAULT: bool = true;
2425 const ONLY_HOSTS: bool = true;
2426
2427 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2428 run.alias("reproducible-artifacts")
2429 }
2430
2431 fn make_run(run: RunConfig<'_>) {
2432 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2433 }
2434
2435 fn run(self, builder: &Builder<'_>) -> Self::Output {
2436 let mut added_anything = false;
2437 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2438 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2439 tarball.add_file(path, ".", 0o644);
2440 added_anything = true;
2441 }
2442 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2443 tarball.add_file(path, ".", 0o644);
2444 added_anything = true;
2445 }
2446 for profile in &builder.config.reproducible_artifacts {
2447 tarball.add_file(profile, ".", 0o644);
2448 added_anything = true;
2449 }
2450 if added_anything { Some(tarball.generate()) } else { None }
2451 }
2452}