]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Rollup merge of #82598 - GuillaumeGomez:rustdoc-rustc-pass, r=jyn514
[rust.git] / src / bootstrap / dist.rs
1 //! Implementation of the various distribution aspects of the compiler.
2 //!
3 //! This module is responsible for creating tarballs of the standard library,
4 //! compiler, and documentation. This ends up being what we distribute to
5 //! everyone as well.
6 //!
7 //! No tarball is actually created literally in this file, but rather we shell
8 //! out to `rust-installer` still. This may one day be replaced with bits and
9 //! pieces of `rustup.rs`!
10
11 use std::env;
12 use std::fs;
13 use std::path::{Path, PathBuf};
14 use std::process::Command;
15
16 use build_helper::{output, t};
17
18 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
19 use crate::cache::{Interned, INTERNER};
20 use crate::compile;
21 use crate::config::TargetSelection;
22 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
23 use crate::tool::{self, Tool};
24 use crate::util::{exe, is_dylib, timeit};
25 use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
26 use time::{self, Timespec};
27
28 pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
29     format!("{}-{}", component, builder.rust_package_vers())
30 }
31
32 pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
33     builder.out.join("dist")
34 }
35
36 pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
37     builder.out.join("tmp/dist")
38 }
39
40 fn missing_tool(tool_name: &str, skip: bool) {
41     if skip {
42         println!("Unable to build {}, skipping dist", tool_name)
43     } else {
44         panic!("Unable to build {}", tool_name)
45     }
46 }
47
48 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
49 pub struct Docs {
50     pub host: TargetSelection,
51 }
52
53 impl Step for Docs {
54     type Output = Option<GeneratedTarball>;
55     const DEFAULT: bool = true;
56
57     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
58         run.path("src/doc")
59     }
60
61     fn make_run(run: RunConfig<'_>) {
62         run.builder.ensure(Docs { host: run.target });
63     }
64
65     /// Builds the `rust-docs` installer component.
66     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
67         let host = self.host;
68         if !builder.config.docs {
69             return None;
70         }
71         builder.default_doc(&[]);
72
73         let dest = "share/doc/rust/html";
74
75         let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
76         tarball.set_product_name("Rust Documentation");
77         tarball.add_dir(&builder.doc_out(host), dest);
78         tarball.add_file(&builder.src.join("src/doc/robots.txt"), dest, 0o644);
79         Some(tarball.generate())
80     }
81 }
82
83 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
84 pub struct RustcDocs {
85     pub host: TargetSelection,
86 }
87
88 impl Step for RustcDocs {
89     type Output = Option<GeneratedTarball>;
90     const DEFAULT: bool = true;
91
92     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
93         run.path("src/librustc")
94     }
95
96     fn make_run(run: RunConfig<'_>) {
97         run.builder.ensure(RustcDocs { host: run.target });
98     }
99
100     /// Builds the `rustc-docs` installer component.
101     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
102         let host = self.host;
103         if !builder.config.compiler_docs {
104             return None;
105         }
106         builder.default_doc(&[]);
107
108         let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
109         tarball.set_product_name("Rustc Documentation");
110         tarball.add_dir(&builder.compiler_doc_out(host), "share/doc/rust/html/rustc");
111         Some(tarball.generate())
112     }
113 }
114
115 fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
116     let mut found = Vec::with_capacity(files.len());
117
118     for file in files {
119         let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
120
121         if let Some(file_path) = file_path {
122             found.push(file_path);
123         } else {
124             panic!("Could not find '{}' in {:?}", file, path);
125         }
126     }
127
128     found
129 }
130
131 fn make_win_dist(
132     rust_root: &Path,
133     plat_root: &Path,
134     target: TargetSelection,
135     builder: &Builder<'_>,
136 ) {
137     //Ask gcc where it keeps its stuff
138     let mut cmd = Command::new(builder.cc(target));
139     cmd.arg("-print-search-dirs");
140     let gcc_out = output(&mut cmd);
141
142     let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
143     let mut lib_path = Vec::new();
144
145     for line in gcc_out.lines() {
146         let idx = line.find(':').unwrap();
147         let key = &line[..idx];
148         let trim_chars: &[_] = &[' ', '='];
149         let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
150
151         if key == "programs" {
152             bin_path.extend(value);
153         } else if key == "libraries" {
154             lib_path.extend(value);
155         }
156     }
157
158     let compiler = if target == "i686-pc-windows-gnu" {
159         "i686-w64-mingw32-gcc.exe"
160     } else if target == "x86_64-pc-windows-gnu" {
161         "x86_64-w64-mingw32-gcc.exe"
162     } else {
163         "gcc.exe"
164     };
165     let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
166     let mut rustc_dlls = vec!["libwinpthread-1.dll"];
167     if target.starts_with("i686-") {
168         rustc_dlls.push("libgcc_s_dw2-1.dll");
169     } else {
170         rustc_dlls.push("libgcc_s_seh-1.dll");
171     }
172
173     let target_libs = [
174         //MinGW libs
175         "libgcc.a",
176         "libgcc_eh.a",
177         "libgcc_s.a",
178         "libm.a",
179         "libmingw32.a",
180         "libmingwex.a",
181         "libstdc++.a",
182         "libiconv.a",
183         "libmoldname.a",
184         "libpthread.a",
185         //Windows import libs
186         "libadvapi32.a",
187         "libbcrypt.a",
188         "libcomctl32.a",
189         "libcomdlg32.a",
190         "libcredui.a",
191         "libcrypt32.a",
192         "libdbghelp.a",
193         "libgdi32.a",
194         "libimagehlp.a",
195         "libiphlpapi.a",
196         "libkernel32.a",
197         "libmsimg32.a",
198         "libmsvcrt.a",
199         "libodbc32.a",
200         "libole32.a",
201         "liboleaut32.a",
202         "libopengl32.a",
203         "libpsapi.a",
204         "librpcrt4.a",
205         "libsecur32.a",
206         "libsetupapi.a",
207         "libshell32.a",
208         "libsynchronization.a",
209         "libuser32.a",
210         "libuserenv.a",
211         "libuuid.a",
212         "libwinhttp.a",
213         "libwinmm.a",
214         "libwinspool.a",
215         "libws2_32.a",
216         "libwsock32.a",
217     ];
218
219     //Find mingw artifacts we want to bundle
220     let target_tools = find_files(&target_tools, &bin_path);
221     let rustc_dlls = find_files(&rustc_dlls, &bin_path);
222     let target_libs = find_files(&target_libs, &lib_path);
223
224     // Copy runtime dlls next to rustc.exe
225     let dist_bin_dir = rust_root.join("bin/");
226     fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
227     for src in rustc_dlls {
228         builder.copy_to_folder(&src, &dist_bin_dir);
229     }
230
231     //Copy platform tools to platform-specific bin directory
232     let target_bin_dir = plat_root
233         .join("lib")
234         .join("rustlib")
235         .join(target.triple)
236         .join("bin")
237         .join("self-contained");
238     fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
239     for src in target_tools {
240         builder.copy_to_folder(&src, &target_bin_dir);
241     }
242
243     // Warn windows-gnu users that the bundled GCC cannot compile C files
244     builder.create(
245         &target_bin_dir.join("GCC-WARNING.txt"),
246         "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
247          used as a linker. In order to be able to compile projects containing C code use \
248          the GCC provided by MinGW or Cygwin.",
249     );
250
251     //Copy platform libs to platform-specific lib directory
252     let target_lib_dir = plat_root
253         .join("lib")
254         .join("rustlib")
255         .join(target.triple)
256         .join("lib")
257         .join("self-contained");
258     fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
259     for src in target_libs {
260         builder.copy_to_folder(&src, &target_lib_dir);
261     }
262 }
263
264 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
265 pub struct Mingw {
266     pub host: TargetSelection,
267 }
268
269 impl Step for Mingw {
270     type Output = Option<GeneratedTarball>;
271     const DEFAULT: bool = true;
272
273     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
274         run.never()
275     }
276
277     fn make_run(run: RunConfig<'_>) {
278         run.builder.ensure(Mingw { host: run.target });
279     }
280
281     /// Builds the `rust-mingw` installer component.
282     ///
283     /// This contains all the bits and pieces to run the MinGW Windows targets
284     /// without any extra installed software (e.g., we bundle gcc, libraries, etc).
285     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
286         let host = self.host;
287         if !host.contains("pc-windows-gnu") {
288             return None;
289         }
290
291         let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple);
292         tarball.set_product_name("Rust MinGW");
293
294         // The first argument is a "temporary directory" which is just
295         // thrown away (this contains the runtime DLLs included in the rustc package
296         // above) and the second argument is where to place all the MinGW components
297         // (which is what we want).
298         make_win_dist(&tmpdir(builder), tarball.image_dir(), host, &builder);
299
300         Some(tarball.generate())
301     }
302 }
303
304 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
305 pub struct Rustc {
306     pub compiler: Compiler,
307 }
308
309 impl Step for Rustc {
310     type Output = GeneratedTarball;
311     const DEFAULT: bool = true;
312     const ONLY_HOSTS: bool = true;
313
314     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
315         run.path("src/librustc")
316     }
317
318     fn make_run(run: RunConfig<'_>) {
319         run.builder
320             .ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.target) });
321     }
322
323     /// Creates the `rustc` installer component.
324     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
325         let compiler = self.compiler;
326         let host = self.compiler.host;
327
328         let tarball = Tarball::new(builder, "rustc", &host.triple);
329
330         // Prepare the rustc "image", what will actually end up getting installed
331         prepare_image(builder, compiler, tarball.image_dir());
332
333         // On MinGW we've got a few runtime DLL dependencies that we need to
334         // include. The first argument to this script is where to put these DLLs
335         // (the image we're creating), and the second argument is a junk directory
336         // to ignore all other MinGW stuff the script creates.
337         //
338         // On 32-bit MinGW we're always including a DLL which needs some extra
339         // licenses to distribute. On 64-bit MinGW we don't actually distribute
340         // anything requiring us to distribute a license, but it's likely the
341         // install will *also* include the rust-mingw package, which also needs
342         // licenses, so to be safe we just include it here in all MinGW packages.
343         if host.contains("pc-windows-gnu") {
344             make_win_dist(tarball.image_dir(), &tmpdir(builder), host, builder);
345             tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
346         }
347
348         return tarball.generate();
349
350         fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
351             let host = compiler.host;
352             let src = builder.sysroot(compiler);
353
354             // Copy rustc/rustdoc binaries
355             t!(fs::create_dir_all(image.join("bin")));
356             builder.cp_r(&src.join("bin"), &image.join("bin"));
357
358             builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
359
360             let libdir_relative = builder.libdir_relative(compiler);
361
362             // Copy runtime DLLs needed by the compiler
363             if libdir_relative.to_str() != Some("bin") {
364                 let libdir = builder.rustc_libdir(compiler);
365                 for entry in builder.read_dir(&libdir) {
366                     let name = entry.file_name();
367                     if let Some(s) = name.to_str() {
368                         if is_dylib(s) {
369                             // Don't use custom libdir here because ^lib/ will be resolved again
370                             // with installer
371                             builder.install(&entry.path(), &image.join("lib"), 0o644);
372                         }
373                     }
374                 }
375             }
376
377             // Copy over the codegen backends
378             let backends_src = builder.sysroot_codegen_backends(compiler);
379             let backends_rel = backends_src
380                 .strip_prefix(&src)
381                 .unwrap()
382                 .strip_prefix(builder.sysroot_libdir_relative(compiler))
383                 .unwrap();
384             // Don't use custom libdir here because ^lib/ will be resolved again with installer
385             let backends_dst = image.join("lib").join(&backends_rel);
386
387             t!(fs::create_dir_all(&backends_dst));
388             builder.cp_r(&backends_src, &backends_dst);
389
390             // Copy libLLVM.so to the lib dir as well, if needed. While not
391             // technically needed by rustc itself it's needed by lots of other
392             // components like the llvm tools and LLD. LLD is included below and
393             // tools/LLDB come later, so let's just throw it in the rustc
394             // component for now.
395             maybe_install_llvm_runtime(builder, host, image);
396
397             let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
398             let dst_dir = image.join("lib/rustlib").join(&*host.triple).join("bin");
399             t!(fs::create_dir_all(&dst_dir));
400
401             // Copy over lld if it's there
402             if builder.config.lld_enabled {
403                 let exe = exe("rust-lld", compiler.host);
404                 builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
405             }
406
407             // Copy over llvm-dwp if it's there
408             let exe = exe("rust-llvm-dwp", compiler.host);
409             builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
410
411             // Man pages
412             t!(fs::create_dir_all(image.join("share/man/man1")));
413             let man_src = builder.src.join("src/doc/man");
414             let man_dst = image.join("share/man/man1");
415
416             // Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time.
417             let time = env::var("SOURCE_DATE_EPOCH")
418                 .map(|timestamp| {
419                     let epoch = timestamp
420                         .parse()
421                         .map_err(|err| format!("could not parse SOURCE_DATE_EPOCH: {}", err))
422                         .unwrap();
423
424                     time::at(Timespec::new(epoch, 0))
425                 })
426                 .unwrap_or_else(|_| time::now());
427
428             let month_year = t!(time::strftime("%B %Y", &time));
429             // don't use our `bootstrap::util::{copy, cp_r}`, because those try
430             // to hardlink, and we don't want to edit the source templates
431             for file_entry in builder.read_dir(&man_src) {
432                 let page_src = file_entry.path();
433                 let page_dst = man_dst.join(file_entry.file_name());
434                 t!(fs::copy(&page_src, &page_dst));
435                 // template in month/year and version number
436                 builder.replace_in_file(
437                     &page_dst,
438                     &[
439                         ("<INSERT DATE HERE>", &month_year),
440                         ("<INSERT VERSION HERE>", &builder.version),
441                     ],
442                 );
443             }
444
445             // Debugger scripts
446             builder
447                 .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host });
448
449             // Misc license info
450             let cp = |file: &str| {
451                 builder.install(&builder.src.join(file), &image.join("share/doc/rust"), 0o644);
452             };
453             cp("COPYRIGHT");
454             cp("LICENSE-APACHE");
455             cp("LICENSE-MIT");
456             cp("README.md");
457         }
458     }
459 }
460
461 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
462 pub struct DebuggerScripts {
463     pub sysroot: Interned<PathBuf>,
464     pub host: TargetSelection,
465 }
466
467 impl Step for DebuggerScripts {
468     type Output = ();
469
470     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
471         run.path("src/lldb_batchmode.py")
472     }
473
474     fn make_run(run: RunConfig<'_>) {
475         run.builder.ensure(DebuggerScripts {
476             sysroot: run
477                 .builder
478                 .sysroot(run.builder.compiler(run.builder.top_stage, run.build_triple())),
479             host: run.target,
480         });
481     }
482
483     /// Copies debugger scripts for `target` into the `sysroot` specified.
484     fn run(self, builder: &Builder<'_>) {
485         let host = self.host;
486         let sysroot = self.sysroot;
487         let dst = sysroot.join("lib/rustlib/etc");
488         t!(fs::create_dir_all(&dst));
489         let cp_debugger_script = |file: &str| {
490             builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
491         };
492         if host.contains("windows-msvc") {
493             // windbg debugger scripts
494             builder.install(
495                 &builder.src.join("src/etc/rust-windbg.cmd"),
496                 &sysroot.join("bin"),
497                 0o755,
498             );
499
500             cp_debugger_script("natvis/intrinsic.natvis");
501             cp_debugger_script("natvis/liballoc.natvis");
502             cp_debugger_script("natvis/libcore.natvis");
503             cp_debugger_script("natvis/libstd.natvis");
504         } else {
505             cp_debugger_script("rust_types.py");
506
507             // gdb debugger scripts
508             builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
509             builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
510
511             cp_debugger_script("gdb_load_rust_pretty_printers.py");
512             cp_debugger_script("gdb_lookup.py");
513             cp_debugger_script("gdb_providers.py");
514
515             // lldb debugger scripts
516             builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
517
518             cp_debugger_script("lldb_lookup.py");
519             cp_debugger_script("lldb_providers.py");
520             cp_debugger_script("lldb_commands")
521         }
522     }
523 }
524
525 fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
526     // The only true set of target libraries came from the build triple, so
527     // let's reduce redundant work by only producing archives from that host.
528     if compiler.host != builder.config.build {
529         builder.info("\tskipping, not a build host");
530         true
531     } else {
532         false
533     }
534 }
535
536 /// Copy stamped files into an image's `target/lib` directory.
537 fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
538     let dst = image.join("lib/rustlib").join(target.triple).join("lib");
539     let self_contained_dst = dst.join("self-contained");
540     t!(fs::create_dir_all(&dst));
541     t!(fs::create_dir_all(&self_contained_dst));
542     for (path, dependency_type) in builder.read_stamp_file(stamp) {
543         if dependency_type == DependencyType::TargetSelfContained {
544             builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
545         } else if dependency_type == DependencyType::Target || builder.config.build == target {
546             builder.copy(&path, &dst.join(path.file_name().unwrap()));
547         }
548     }
549 }
550
551 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
552 pub struct Std {
553     pub compiler: Compiler,
554     pub target: TargetSelection,
555 }
556
557 impl Step for Std {
558     type Output = Option<GeneratedTarball>;
559     const DEFAULT: bool = true;
560
561     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
562         run.path("library/std")
563     }
564
565     fn make_run(run: RunConfig<'_>) {
566         run.builder.ensure(Std {
567             compiler: run.builder.compiler_for(
568                 run.builder.top_stage,
569                 run.builder.config.build,
570                 run.target,
571             ),
572             target: run.target,
573         });
574     }
575
576     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
577         let compiler = self.compiler;
578         let target = self.target;
579
580         if skip_host_target_lib(builder, compiler) {
581             return None;
582         }
583
584         builder.ensure(compile::Std { compiler, target });
585
586         let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
587         tarball.include_target_in_component_name(true);
588
589         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
590         let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
591         copy_target_libs(builder, target, &tarball.image_dir(), &stamp);
592
593         Some(tarball.generate())
594     }
595 }
596
597 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
598 pub struct RustcDev {
599     pub compiler: Compiler,
600     pub target: TargetSelection,
601 }
602
603 impl Step for RustcDev {
604     type Output = Option<GeneratedTarball>;
605     const DEFAULT: bool = true;
606     const ONLY_HOSTS: bool = true;
607
608     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
609         run.path("rustc-dev")
610     }
611
612     fn make_run(run: RunConfig<'_>) {
613         run.builder.ensure(RustcDev {
614             compiler: run.builder.compiler_for(
615                 run.builder.top_stage,
616                 run.builder.config.build,
617                 run.target,
618             ),
619             target: run.target,
620         });
621     }
622
623     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
624         let compiler = self.compiler;
625         let target = self.target;
626         if skip_host_target_lib(builder, compiler) {
627             return None;
628         }
629
630         builder.ensure(compile::Rustc { compiler, target });
631
632         let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
633
634         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
635         let stamp = compile::librustc_stamp(builder, compiler_to_use, target);
636         copy_target_libs(builder, target, tarball.image_dir(), &stamp);
637
638         let src_files = &["Cargo.lock"];
639         // This is the reduced set of paths which will become the rustc-dev component
640         // (essentially the compiler crates and all of their path dependencies).
641         copy_src_dirs(
642             builder,
643             &builder.src,
644             &["compiler"],
645             &[],
646             &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
647         );
648         // This particular crate is used as a build dependency of the above.
649         copy_src_dirs(
650             builder,
651             &builder.src,
652             &["src/build_helper"],
653             &[],
654             &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
655         );
656         for file in src_files {
657             tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
658         }
659
660         Some(tarball.generate())
661     }
662 }
663
664 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
665 pub struct Analysis {
666     pub compiler: Compiler,
667     pub target: TargetSelection,
668 }
669
670 impl Step for Analysis {
671     type Output = Option<GeneratedTarball>;
672     const DEFAULT: bool = true;
673
674     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
675         let builder = run.builder;
676         run.path("analysis").default_condition(builder.config.extended)
677     }
678
679     fn make_run(run: RunConfig<'_>) {
680         run.builder.ensure(Analysis {
681             // Find the actual compiler (handling the full bootstrap option) which
682             // produced the save-analysis data because that data isn't copied
683             // through the sysroot uplifting.
684             compiler: run.builder.compiler_for(
685                 run.builder.top_stage,
686                 run.builder.config.build,
687                 run.target,
688             ),
689             target: run.target,
690         });
691     }
692
693     /// Creates a tarball of save-analysis metadata, if available.
694     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
695         let compiler = self.compiler;
696         let target = self.target;
697         assert!(builder.config.extended);
698         if compiler.host != builder.config.build {
699             return None;
700         }
701
702         builder.ensure(compile::Std { compiler, target });
703         let src = builder
704             .stage_out(compiler, Mode::Std)
705             .join(target.triple)
706             .join(builder.cargo_dir())
707             .join("deps")
708             .join("save-analysis");
709
710         let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
711         tarball.include_target_in_component_name(true);
712         tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
713         Some(tarball.generate())
714     }
715 }
716
717 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
718 /// `dst_dir`.
719 fn copy_src_dirs(
720     builder: &Builder<'_>,
721     base: &Path,
722     src_dirs: &[&str],
723     exclude_dirs: &[&str],
724     dst_dir: &Path,
725 ) {
726     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
727         let spath = match path.to_str() {
728             Some(path) => path,
729             None => return false,
730         };
731         if spath.ends_with('~') || spath.ends_with(".pyc") {
732             return false;
733         }
734
735         const LLVM_PROJECTS: &[&str] = &[
736             "llvm-project/clang",
737             "llvm-project\\clang",
738             "llvm-project/libunwind",
739             "llvm-project\\libunwind",
740             "llvm-project/lld",
741             "llvm-project\\lld",
742             "llvm-project/lldb",
743             "llvm-project\\lldb",
744             "llvm-project/llvm",
745             "llvm-project\\llvm",
746             "llvm-project/compiler-rt",
747             "llvm-project\\compiler-rt",
748         ];
749         if spath.contains("llvm-project")
750             && !spath.ends_with("llvm-project")
751             && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
752         {
753             return false;
754         }
755
756         const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
757         if LLVM_TEST.iter().any(|path| spath.contains(path))
758             && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
759         {
760             return false;
761         }
762
763         let full_path = Path::new(dir).join(path);
764         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
765             return false;
766         }
767
768         let excludes = [
769             "CVS",
770             "RCS",
771             "SCCS",
772             ".git",
773             ".gitignore",
774             ".gitmodules",
775             ".gitattributes",
776             ".cvsignore",
777             ".svn",
778             ".arch-ids",
779             "{arch}",
780             "=RELEASE-ID",
781             "=meta-update",
782             "=update",
783             ".bzr",
784             ".bzrignore",
785             ".bzrtags",
786             ".hg",
787             ".hgignore",
788             ".hgrags",
789             "_darcs",
790         ];
791         !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
792     }
793
794     // Copy the directories using our filter
795     for item in src_dirs {
796         let dst = &dst_dir.join(item);
797         t!(fs::create_dir_all(dst));
798         builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
799     }
800 }
801
802 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
803 pub struct Src;
804
805 impl Step for Src {
806     /// The output path of the src installer tarball
807     type Output = GeneratedTarball;
808     const DEFAULT: bool = true;
809     const ONLY_HOSTS: bool = true;
810
811     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
812         run.path("src")
813     }
814
815     fn make_run(run: RunConfig<'_>) {
816         run.builder.ensure(Src);
817     }
818
819     /// Creates the `rust-src` installer component
820     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
821         let tarball = Tarball::new_targetless(builder, "rust-src");
822
823         // A lot of tools expect the rust-src component to be entirely in this directory, so if you
824         // change that (e.g. by adding another directory `lib/rustlib/src/foo` or
825         // `lib/rustlib/src/rust/foo`), you will need to go around hunting for implicit assumptions
826         // and fix them...
827         //
828         // NOTE: if you update the paths here, you also should update the "virtual" path
829         // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
830         let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
831
832         let src_files = ["Cargo.lock"];
833         // This is the reduced set of paths which will become the rust-src component
834         // (essentially libstd and all of its path dependencies).
835         copy_src_dirs(
836             builder,
837             &builder.src,
838             &["library", "src/llvm-project/libunwind"],
839             &[
840                 // not needed and contains symlinks which rustup currently
841                 // chokes on when unpacking.
842                 "library/backtrace/crates",
843             ],
844             &dst_src,
845         );
846         for file in src_files.iter() {
847             builder.copy(&builder.src.join(file), &dst_src.join(file));
848         }
849
850         tarball.generate()
851     }
852 }
853
854 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
855 pub struct PlainSourceTarball;
856
857 impl Step for PlainSourceTarball {
858     /// Produces the location of the tarball generated
859     type Output = GeneratedTarball;
860     const DEFAULT: bool = true;
861     const ONLY_HOSTS: bool = true;
862
863     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
864         let builder = run.builder;
865         run.path("src").default_condition(builder.config.rust_dist_src)
866     }
867
868     fn make_run(run: RunConfig<'_>) {
869         run.builder.ensure(PlainSourceTarball);
870     }
871
872     /// Creates the plain source tarball
873     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
874         let tarball = Tarball::new(builder, "rustc", "src");
875         let plain_dst_src = tarball.image_dir();
876
877         // This is the set of root paths which will become part of the source package
878         let src_files = [
879             "COPYRIGHT",
880             "LICENSE-APACHE",
881             "LICENSE-MIT",
882             "CONTRIBUTING.md",
883             "README.md",
884             "RELEASES.md",
885             "configure",
886             "x.py",
887             "config.toml.example",
888             "Cargo.toml",
889             "Cargo.lock",
890         ];
891         let src_dirs = ["src", "compiler", "library"];
892
893         copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
894
895         // Copy the files normally
896         for item in &src_files {
897             builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
898         }
899
900         // Create the version file
901         builder.create(&plain_dst_src.join("version"), &builder.rust_version());
902         if let Some(sha) = builder.rust_sha() {
903             builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
904         }
905
906         // If we're building from git sources, we need to vendor a complete distribution.
907         if builder.rust_info.is_git() {
908             // Vendor all Cargo dependencies
909             let mut cmd = Command::new(&builder.initial_cargo);
910             cmd.arg("vendor")
911                 .arg("--sync")
912                 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
913                 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
914                 .current_dir(&plain_dst_src);
915             builder.run(&mut cmd);
916         }
917
918         tarball.bare()
919     }
920 }
921
922 // We have to run a few shell scripts, which choke quite a bit on both `\`
923 // characters and on `C:\` paths, so normalize both of them away.
924 pub fn sanitize_sh(path: &Path) -> String {
925     let path = path.to_str().unwrap().replace("\\", "/");
926     return change_drive(unc_to_lfs(&path)).unwrap_or(path);
927
928     fn unc_to_lfs(s: &str) -> &str {
929         s.strip_prefix("//?/").unwrap_or(s)
930     }
931
932     fn change_drive(s: &str) -> Option<String> {
933         let mut ch = s.chars();
934         let drive = ch.next().unwrap_or('C');
935         if ch.next() != Some(':') {
936             return None;
937         }
938         if ch.next() != Some('/') {
939             return None;
940         }
941         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
942     }
943 }
944
945 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
946 pub struct Cargo {
947     pub compiler: Compiler,
948     pub target: TargetSelection,
949 }
950
951 impl Step for Cargo {
952     type Output = GeneratedTarball;
953     const ONLY_HOSTS: bool = true;
954
955     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
956         run.path("cargo")
957     }
958
959     fn make_run(run: RunConfig<'_>) {
960         run.builder.ensure(Cargo {
961             compiler: run.builder.compiler_for(
962                 run.builder.top_stage,
963                 run.builder.config.build,
964                 run.target,
965             ),
966             target: run.target,
967         });
968     }
969
970     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
971         let compiler = self.compiler;
972         let target = self.target;
973
974         let cargo = builder.ensure(tool::Cargo { compiler, target });
975         let src = builder.src.join("src/tools/cargo");
976         let etc = src.join("src/etc");
977
978         // Prepare the image directory
979         let mut tarball = Tarball::new(builder, "cargo", &target.triple);
980         tarball.set_overlay(OverlayKind::Cargo);
981
982         tarball.add_file(&cargo, "bin", 0o755);
983         tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
984         tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
985         tarball.add_dir(etc.join("man"), "share/man/man1");
986         tarball.add_legal_and_readme_to("share/doc/cargo");
987
988         for dirent in fs::read_dir(cargo.parent().unwrap()).expect("read_dir") {
989             let dirent = dirent.expect("read dir entry");
990             if dirent.file_name().to_str().expect("utf8").starts_with("cargo-credential-") {
991                 tarball.add_file(&dirent.path(), "libexec", 0o755);
992             }
993         }
994
995         tarball.generate()
996     }
997 }
998
999 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1000 pub struct Rls {
1001     pub compiler: Compiler,
1002     pub target: TargetSelection,
1003 }
1004
1005 impl Step for Rls {
1006     type Output = Option<GeneratedTarball>;
1007     const ONLY_HOSTS: bool = true;
1008
1009     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1010         run.path("rls")
1011     }
1012
1013     fn make_run(run: RunConfig<'_>) {
1014         run.builder.ensure(Rls {
1015             compiler: run.builder.compiler_for(
1016                 run.builder.top_stage,
1017                 run.builder.config.build,
1018                 run.target,
1019             ),
1020             target: run.target,
1021         });
1022     }
1023
1024     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1025         let compiler = self.compiler;
1026         let target = self.target;
1027         assert!(builder.config.extended);
1028
1029         let rls = builder
1030             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1031             .or_else(|| {
1032                 missing_tool("RLS", builder.build.config.missing_tools);
1033                 None
1034             })?;
1035
1036         let mut tarball = Tarball::new(builder, "rls", &target.triple);
1037         tarball.set_overlay(OverlayKind::RLS);
1038         tarball.is_preview(true);
1039         tarball.add_file(rls, "bin", 0o755);
1040         tarball.add_legal_and_readme_to("share/doc/rls");
1041         Some(tarball.generate())
1042     }
1043 }
1044
1045 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1046 pub struct RustAnalyzer {
1047     pub compiler: Compiler,
1048     pub target: TargetSelection,
1049 }
1050
1051 impl Step for RustAnalyzer {
1052     type Output = Option<GeneratedTarball>;
1053     const ONLY_HOSTS: bool = true;
1054
1055     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1056         run.path("rust-analyzer")
1057     }
1058
1059     fn make_run(run: RunConfig<'_>) {
1060         run.builder.ensure(RustAnalyzer {
1061             compiler: run.builder.compiler_for(
1062                 run.builder.top_stage,
1063                 run.builder.config.build,
1064                 run.target,
1065             ),
1066             target: run.target,
1067         });
1068     }
1069
1070     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1071         let compiler = self.compiler;
1072         let target = self.target;
1073         assert!(builder.config.extended);
1074
1075         if target.contains("riscv64") {
1076             // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1077             // to build. See #74813 for details.
1078             return None;
1079         }
1080
1081         let rust_analyzer = builder
1082             .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1083             .expect("rust-analyzer always builds");
1084
1085         let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1086         tarball.set_overlay(OverlayKind::RustAnalyzer);
1087         tarball.is_preview(true);
1088         tarball.add_file(rust_analyzer, "bin", 0o755);
1089         tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1090         Some(tarball.generate())
1091     }
1092 }
1093
1094 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1095 pub struct Clippy {
1096     pub compiler: Compiler,
1097     pub target: TargetSelection,
1098 }
1099
1100 impl Step for Clippy {
1101     type Output = GeneratedTarball;
1102     const ONLY_HOSTS: bool = true;
1103
1104     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1105         run.path("clippy")
1106     }
1107
1108     fn make_run(run: RunConfig<'_>) {
1109         run.builder.ensure(Clippy {
1110             compiler: run.builder.compiler_for(
1111                 run.builder.top_stage,
1112                 run.builder.config.build,
1113                 run.target,
1114             ),
1115             target: run.target,
1116         });
1117     }
1118
1119     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1120         let compiler = self.compiler;
1121         let target = self.target;
1122         assert!(builder.config.extended);
1123
1124         // Prepare the image directory
1125         // We expect clippy to build, because we've exited this step above if tool
1126         // state for clippy isn't testing.
1127         let clippy = builder
1128             .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1129             .expect("clippy expected to build - essential tool");
1130         let cargoclippy = builder
1131             .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1132             .expect("clippy expected to build - essential tool");
1133
1134         let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1135         tarball.set_overlay(OverlayKind::Clippy);
1136         tarball.is_preview(true);
1137         tarball.add_file(clippy, "bin", 0o755);
1138         tarball.add_file(cargoclippy, "bin", 0o755);
1139         tarball.add_legal_and_readme_to("share/doc/clippy");
1140         tarball.generate()
1141     }
1142 }
1143
1144 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1145 pub struct Miri {
1146     pub compiler: Compiler,
1147     pub target: TargetSelection,
1148 }
1149
1150 impl Step for Miri {
1151     type Output = Option<GeneratedTarball>;
1152     const ONLY_HOSTS: bool = true;
1153
1154     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1155         run.path("miri")
1156     }
1157
1158     fn make_run(run: RunConfig<'_>) {
1159         run.builder.ensure(Miri {
1160             compiler: run.builder.compiler_for(
1161                 run.builder.top_stage,
1162                 run.builder.config.build,
1163                 run.target,
1164             ),
1165             target: run.target,
1166         });
1167     }
1168
1169     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1170         let compiler = self.compiler;
1171         let target = self.target;
1172         assert!(builder.config.extended);
1173
1174         let miri = builder
1175             .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1176             .or_else(|| {
1177                 missing_tool("miri", builder.build.config.missing_tools);
1178                 None
1179             })?;
1180         let cargomiri = builder
1181             .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1182             .or_else(|| {
1183                 missing_tool("cargo miri", builder.build.config.missing_tools);
1184                 None
1185             })?;
1186
1187         let mut tarball = Tarball::new(builder, "miri", &target.triple);
1188         tarball.set_overlay(OverlayKind::Miri);
1189         tarball.is_preview(true);
1190         tarball.add_file(miri, "bin", 0o755);
1191         tarball.add_file(cargomiri, "bin", 0o755);
1192         tarball.add_legal_and_readme_to("share/doc/miri");
1193         Some(tarball.generate())
1194     }
1195 }
1196
1197 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1198 pub struct Rustfmt {
1199     pub compiler: Compiler,
1200     pub target: TargetSelection,
1201 }
1202
1203 impl Step for Rustfmt {
1204     type Output = Option<GeneratedTarball>;
1205     const ONLY_HOSTS: bool = true;
1206
1207     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1208         run.path("rustfmt")
1209     }
1210
1211     fn make_run(run: RunConfig<'_>) {
1212         run.builder.ensure(Rustfmt {
1213             compiler: run.builder.compiler_for(
1214                 run.builder.top_stage,
1215                 run.builder.config.build,
1216                 run.target,
1217             ),
1218             target: run.target,
1219         });
1220     }
1221
1222     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1223         let compiler = self.compiler;
1224         let target = self.target;
1225
1226         let rustfmt = builder
1227             .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1228             .or_else(|| {
1229                 missing_tool("Rustfmt", builder.build.config.missing_tools);
1230                 None
1231             })?;
1232         let cargofmt = builder
1233             .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1234             .or_else(|| {
1235                 missing_tool("Cargofmt", builder.build.config.missing_tools);
1236                 None
1237             })?;
1238
1239         let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
1240         tarball.set_overlay(OverlayKind::Rustfmt);
1241         tarball.is_preview(true);
1242         tarball.add_file(rustfmt, "bin", 0o755);
1243         tarball.add_file(cargofmt, "bin", 0o755);
1244         tarball.add_legal_and_readme_to("share/doc/rustfmt");
1245         Some(tarball.generate())
1246     }
1247 }
1248
1249 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1250 pub struct Extended {
1251     stage: u32,
1252     host: TargetSelection,
1253     target: TargetSelection,
1254 }
1255
1256 impl Step for Extended {
1257     type Output = ();
1258     const DEFAULT: bool = true;
1259     const ONLY_HOSTS: bool = true;
1260
1261     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1262         let builder = run.builder;
1263         run.path("extended").default_condition(builder.config.extended)
1264     }
1265
1266     fn make_run(run: RunConfig<'_>) {
1267         run.builder.ensure(Extended {
1268             stage: run.builder.top_stage,
1269             host: run.builder.config.build,
1270             target: run.target,
1271         });
1272     }
1273
1274     /// Creates a combined installer for the specified target in the provided stage.
1275     fn run(self, builder: &Builder<'_>) {
1276         let target = self.target;
1277         let stage = self.stage;
1278         let compiler = builder.compiler_for(self.stage, self.host, self.target);
1279
1280         builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1281
1282         let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
1283         let cargo_installer = builder.ensure(Cargo { compiler, target });
1284         let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1285         let rls_installer = builder.ensure(Rls { compiler, target });
1286         let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
1287         let llvm_tools_installer = builder.ensure(LlvmTools { target });
1288         let clippy_installer = builder.ensure(Clippy { compiler, target });
1289         let miri_installer = builder.ensure(Miri { compiler, target });
1290         let mingw_installer = builder.ensure(Mingw { host: target });
1291         let analysis_installer = builder.ensure(Analysis { compiler, target });
1292
1293         let docs_installer = builder.ensure(Docs { host: target });
1294         let std_installer = builder.ensure(Std { compiler, target });
1295
1296         let etc = builder.src.join("src/etc/installer");
1297
1298         // Avoid producing tarballs during a dry run.
1299         if builder.config.dry_run {
1300             return;
1301         }
1302
1303         // When rust-std package split from rustc, we needed to ensure that during
1304         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1305         // the std files during uninstall. To do this ensure that rustc comes
1306         // before rust-std in the list below.
1307         let mut tarballs = Vec::new();
1308         tarballs.push(rustc_installer);
1309         tarballs.push(cargo_installer);
1310         tarballs.extend(rls_installer.clone());
1311         tarballs.extend(rust_analyzer_installer.clone());
1312         tarballs.push(clippy_installer);
1313         tarballs.extend(miri_installer.clone());
1314         tarballs.extend(rustfmt_installer.clone());
1315         tarballs.extend(llvm_tools_installer);
1316         if let Some(analysis_installer) = analysis_installer {
1317             tarballs.push(analysis_installer);
1318         }
1319         tarballs.push(std_installer.expect("missing std"));
1320         if let Some(docs_installer) = docs_installer {
1321             tarballs.push(docs_installer);
1322         }
1323         if target.contains("pc-windows-gnu") {
1324             tarballs.push(mingw_installer.unwrap());
1325         }
1326
1327         let tarball = Tarball::new(builder, "rust", &target.triple);
1328         let generated = tarball.combine(&tarballs);
1329
1330         let tmp = tmpdir(builder).join("combined-tarball");
1331         let work = generated.work_dir();
1332
1333         let mut license = String::new();
1334         license += &builder.read(&builder.src.join("COPYRIGHT"));
1335         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1336         license += &builder.read(&builder.src.join("LICENSE-MIT"));
1337         license.push('\n');
1338         license.push('\n');
1339
1340         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1341         let mut rtf = rtf.to_string();
1342         rtf.push('\n');
1343         for line in license.lines() {
1344             rtf.push_str(line);
1345             rtf.push_str("\\line ");
1346         }
1347         rtf.push('}');
1348
1349         fn filter(contents: &str, marker: &str) -> String {
1350             let start = format!("tool-{}-start", marker);
1351             let end = format!("tool-{}-end", marker);
1352             let mut lines = Vec::new();
1353             let mut omitted = false;
1354             for line in contents.lines() {
1355                 if line.contains(&start) {
1356                     omitted = true;
1357                 } else if line.contains(&end) {
1358                     omitted = false;
1359                 } else if !omitted {
1360                     lines.push(line);
1361                 }
1362             }
1363
1364             lines.join("\n")
1365         }
1366
1367         let xform = |p: &Path| {
1368             let mut contents = t!(fs::read_to_string(p));
1369             if rls_installer.is_none() {
1370                 contents = filter(&contents, "rls");
1371             }
1372             if rust_analyzer_installer.is_none() {
1373                 contents = filter(&contents, "rust-analyzer");
1374             }
1375             if miri_installer.is_none() {
1376                 contents = filter(&contents, "miri");
1377             }
1378             if rustfmt_installer.is_none() {
1379                 contents = filter(&contents, "rustfmt");
1380             }
1381             let ret = tmp.join(p.file_name().unwrap());
1382             t!(fs::write(&ret, &contents));
1383             ret
1384         };
1385
1386         if target.contains("apple-darwin") {
1387             builder.info("building pkg installer");
1388             let pkg = tmp.join("pkg");
1389             let _ = fs::remove_dir_all(&pkg);
1390
1391             let pkgbuild = |component: &str| {
1392                 let mut cmd = Command::new("pkgbuild");
1393                 cmd.arg("--identifier")
1394                     .arg(format!("org.rust-lang.{}", component))
1395                     .arg("--scripts")
1396                     .arg(pkg.join(component))
1397                     .arg("--nopayload")
1398                     .arg(pkg.join(component).with_extension("pkg"));
1399                 builder.run(&mut cmd);
1400             };
1401
1402             let prepare = |name: &str| {
1403                 builder.create_dir(&pkg.join(name));
1404                 builder.cp_r(
1405                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1406                     &pkg.join(name),
1407                 );
1408                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1409                 pkgbuild(name);
1410             };
1411             prepare("rustc");
1412             prepare("cargo");
1413             prepare("rust-docs");
1414             prepare("rust-std");
1415             prepare("rust-analysis");
1416             prepare("clippy");
1417
1418             if rls_installer.is_some() {
1419                 prepare("rls");
1420             }
1421             if rust_analyzer_installer.is_some() {
1422                 prepare("rust-analyzer");
1423             }
1424             if miri_installer.is_some() {
1425                 prepare("miri");
1426             }
1427
1428             // create an 'uninstall' package
1429             builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1430             pkgbuild("uninstall");
1431
1432             builder.create_dir(&pkg.join("res"));
1433             builder.create(&pkg.join("res/LICENSE.txt"), &license);
1434             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1435             let mut cmd = Command::new("productbuild");
1436             cmd.arg("--distribution")
1437                 .arg(xform(&etc.join("pkg/Distribution.xml")))
1438                 .arg("--resources")
1439                 .arg(pkg.join("res"))
1440                 .arg(distdir(builder).join(format!(
1441                     "{}-{}.pkg",
1442                     pkgname(builder, "rust"),
1443                     target.triple
1444                 )))
1445                 .arg("--package-path")
1446                 .arg(&pkg);
1447             let _time = timeit(builder);
1448             builder.run(&mut cmd);
1449         }
1450
1451         if target.contains("windows") {
1452             let exe = tmp.join("exe");
1453             let _ = fs::remove_dir_all(&exe);
1454
1455             let prepare = |name: &str| {
1456                 builder.create_dir(&exe.join(name));
1457                 let dir = if name == "rust-std" || name == "rust-analysis" {
1458                     format!("{}-{}", name, target.triple)
1459                 } else if name == "rls" {
1460                     "rls-preview".to_string()
1461                 } else if name == "rust-analyzer" {
1462                     "rust-analyzer-preview".to_string()
1463                 } else if name == "clippy" {
1464                     "clippy-preview".to_string()
1465                 } else if name == "miri" {
1466                     "miri-preview".to_string()
1467                 } else {
1468                     name.to_string()
1469                 };
1470                 builder.cp_r(
1471                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1472                     &exe.join(name),
1473                 );
1474                 builder.remove(&exe.join(name).join("manifest.in"));
1475             };
1476             prepare("rustc");
1477             prepare("cargo");
1478             prepare("rust-analysis");
1479             prepare("rust-docs");
1480             prepare("rust-std");
1481             prepare("clippy");
1482             if rls_installer.is_some() {
1483                 prepare("rls");
1484             }
1485             if rust_analyzer_installer.is_some() {
1486                 prepare("rust-analyzer");
1487             }
1488             if miri_installer.is_some() {
1489                 prepare("miri");
1490             }
1491             if target.contains("windows-gnu") {
1492                 prepare("rust-mingw");
1493             }
1494
1495             builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1496
1497             // Generate msi installer
1498             let wix = PathBuf::from(env::var_os("WIX").unwrap());
1499             let heat = wix.join("bin/heat.exe");
1500             let candle = wix.join("bin/candle.exe");
1501             let light = wix.join("bin/light.exe");
1502
1503             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1504             builder.run(
1505                 Command::new(&heat)
1506                     .current_dir(&exe)
1507                     .arg("dir")
1508                     .arg("rustc")
1509                     .args(&heat_flags)
1510                     .arg("-cg")
1511                     .arg("RustcGroup")
1512                     .arg("-dr")
1513                     .arg("Rustc")
1514                     .arg("-var")
1515                     .arg("var.RustcDir")
1516                     .arg("-out")
1517                     .arg(exe.join("RustcGroup.wxs")),
1518             );
1519             builder.run(
1520                 Command::new(&heat)
1521                     .current_dir(&exe)
1522                     .arg("dir")
1523                     .arg("rust-docs")
1524                     .args(&heat_flags)
1525                     .arg("-cg")
1526                     .arg("DocsGroup")
1527                     .arg("-dr")
1528                     .arg("Docs")
1529                     .arg("-var")
1530                     .arg("var.DocsDir")
1531                     .arg("-out")
1532                     .arg(exe.join("DocsGroup.wxs"))
1533                     .arg("-t")
1534                     .arg(etc.join("msi/squash-components.xsl")),
1535             );
1536             builder.run(
1537                 Command::new(&heat)
1538                     .current_dir(&exe)
1539                     .arg("dir")
1540                     .arg("cargo")
1541                     .args(&heat_flags)
1542                     .arg("-cg")
1543                     .arg("CargoGroup")
1544                     .arg("-dr")
1545                     .arg("Cargo")
1546                     .arg("-var")
1547                     .arg("var.CargoDir")
1548                     .arg("-out")
1549                     .arg(exe.join("CargoGroup.wxs"))
1550                     .arg("-t")
1551                     .arg(etc.join("msi/remove-duplicates.xsl")),
1552             );
1553             builder.run(
1554                 Command::new(&heat)
1555                     .current_dir(&exe)
1556                     .arg("dir")
1557                     .arg("rust-std")
1558                     .args(&heat_flags)
1559                     .arg("-cg")
1560                     .arg("StdGroup")
1561                     .arg("-dr")
1562                     .arg("Std")
1563                     .arg("-var")
1564                     .arg("var.StdDir")
1565                     .arg("-out")
1566                     .arg(exe.join("StdGroup.wxs")),
1567             );
1568             if rls_installer.is_some() {
1569                 builder.run(
1570                     Command::new(&heat)
1571                         .current_dir(&exe)
1572                         .arg("dir")
1573                         .arg("rls")
1574                         .args(&heat_flags)
1575                         .arg("-cg")
1576                         .arg("RlsGroup")
1577                         .arg("-dr")
1578                         .arg("Rls")
1579                         .arg("-var")
1580                         .arg("var.RlsDir")
1581                         .arg("-out")
1582                         .arg(exe.join("RlsGroup.wxs"))
1583                         .arg("-t")
1584                         .arg(etc.join("msi/remove-duplicates.xsl")),
1585                 );
1586             }
1587             if rust_analyzer_installer.is_some() {
1588                 builder.run(
1589                     Command::new(&heat)
1590                         .current_dir(&exe)
1591                         .arg("dir")
1592                         .arg("rust-analyzer")
1593                         .args(&heat_flags)
1594                         .arg("-cg")
1595                         .arg("RustAnalyzerGroup")
1596                         .arg("-dr")
1597                         .arg("RustAnalyzer")
1598                         .arg("-var")
1599                         .arg("var.RustAnalyzerDir")
1600                         .arg("-out")
1601                         .arg(exe.join("RustAnalyzerGroup.wxs"))
1602                         .arg("-t")
1603                         .arg(etc.join("msi/remove-duplicates.xsl")),
1604                 );
1605             }
1606             builder.run(
1607                 Command::new(&heat)
1608                     .current_dir(&exe)
1609                     .arg("dir")
1610                     .arg("clippy")
1611                     .args(&heat_flags)
1612                     .arg("-cg")
1613                     .arg("ClippyGroup")
1614                     .arg("-dr")
1615                     .arg("Clippy")
1616                     .arg("-var")
1617                     .arg("var.ClippyDir")
1618                     .arg("-out")
1619                     .arg(exe.join("ClippyGroup.wxs"))
1620                     .arg("-t")
1621                     .arg(etc.join("msi/remove-duplicates.xsl")),
1622             );
1623             if miri_installer.is_some() {
1624                 builder.run(
1625                     Command::new(&heat)
1626                         .current_dir(&exe)
1627                         .arg("dir")
1628                         .arg("miri")
1629                         .args(&heat_flags)
1630                         .arg("-cg")
1631                         .arg("MiriGroup")
1632                         .arg("-dr")
1633                         .arg("Miri")
1634                         .arg("-var")
1635                         .arg("var.MiriDir")
1636                         .arg("-out")
1637                         .arg(exe.join("MiriGroup.wxs"))
1638                         .arg("-t")
1639                         .arg(etc.join("msi/remove-duplicates.xsl")),
1640                 );
1641             }
1642             builder.run(
1643                 Command::new(&heat)
1644                     .current_dir(&exe)
1645                     .arg("dir")
1646                     .arg("rust-analysis")
1647                     .args(&heat_flags)
1648                     .arg("-cg")
1649                     .arg("AnalysisGroup")
1650                     .arg("-dr")
1651                     .arg("Analysis")
1652                     .arg("-var")
1653                     .arg("var.AnalysisDir")
1654                     .arg("-out")
1655                     .arg(exe.join("AnalysisGroup.wxs"))
1656                     .arg("-t")
1657                     .arg(etc.join("msi/remove-duplicates.xsl")),
1658             );
1659             if target.contains("windows-gnu") {
1660                 builder.run(
1661                     Command::new(&heat)
1662                         .current_dir(&exe)
1663                         .arg("dir")
1664                         .arg("rust-mingw")
1665                         .args(&heat_flags)
1666                         .arg("-cg")
1667                         .arg("GccGroup")
1668                         .arg("-dr")
1669                         .arg("Gcc")
1670                         .arg("-var")
1671                         .arg("var.GccDir")
1672                         .arg("-out")
1673                         .arg(exe.join("GccGroup.wxs")),
1674                 );
1675             }
1676
1677             let candle = |input: &Path| {
1678                 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1679                 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1680                 let mut cmd = Command::new(&candle);
1681                 cmd.current_dir(&exe)
1682                     .arg("-nologo")
1683                     .arg("-dRustcDir=rustc")
1684                     .arg("-dDocsDir=rust-docs")
1685                     .arg("-dCargoDir=cargo")
1686                     .arg("-dStdDir=rust-std")
1687                     .arg("-dAnalysisDir=rust-analysis")
1688                     .arg("-dClippyDir=clippy")
1689                     .arg("-arch")
1690                     .arg(&arch)
1691                     .arg("-out")
1692                     .arg(&output)
1693                     .arg(&input);
1694                 add_env(builder, &mut cmd, target);
1695
1696                 if rls_installer.is_some() {
1697                     cmd.arg("-dRlsDir=rls");
1698                 }
1699                 if rust_analyzer_installer.is_some() {
1700                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1701                 }
1702                 if miri_installer.is_some() {
1703                     cmd.arg("-dMiriDir=miri");
1704                 }
1705                 if target.contains("windows-gnu") {
1706                     cmd.arg("-dGccDir=rust-mingw");
1707                 }
1708                 builder.run(&mut cmd);
1709             };
1710             candle(&xform(&etc.join("msi/rust.wxs")));
1711             candle(&etc.join("msi/ui.wxs"));
1712             candle(&etc.join("msi/rustwelcomedlg.wxs"));
1713             candle("RustcGroup.wxs".as_ref());
1714             candle("DocsGroup.wxs".as_ref());
1715             candle("CargoGroup.wxs".as_ref());
1716             candle("StdGroup.wxs".as_ref());
1717             candle("ClippyGroup.wxs".as_ref());
1718             if rls_installer.is_some() {
1719                 candle("RlsGroup.wxs".as_ref());
1720             }
1721             if rust_analyzer_installer.is_some() {
1722                 candle("RustAnalyzerGroup.wxs".as_ref());
1723             }
1724             if miri_installer.is_some() {
1725                 candle("MiriGroup.wxs".as_ref());
1726             }
1727             candle("AnalysisGroup.wxs".as_ref());
1728
1729             if target.contains("windows-gnu") {
1730                 candle("GccGroup.wxs".as_ref());
1731             }
1732
1733             builder.create(&exe.join("LICENSE.rtf"), &rtf);
1734             builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1735             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1736
1737             builder.info(&format!("building `msi` installer with {:?}", light));
1738             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1739             let mut cmd = Command::new(&light);
1740             cmd.arg("-nologo")
1741                 .arg("-ext")
1742                 .arg("WixUIExtension")
1743                 .arg("-ext")
1744                 .arg("WixUtilExtension")
1745                 .arg("-out")
1746                 .arg(exe.join(&filename))
1747                 .arg("rust.wixobj")
1748                 .arg("ui.wixobj")
1749                 .arg("rustwelcomedlg.wixobj")
1750                 .arg("RustcGroup.wixobj")
1751                 .arg("DocsGroup.wixobj")
1752                 .arg("CargoGroup.wixobj")
1753                 .arg("StdGroup.wixobj")
1754                 .arg("AnalysisGroup.wixobj")
1755                 .arg("ClippyGroup.wixobj")
1756                 .current_dir(&exe);
1757
1758             if rls_installer.is_some() {
1759                 cmd.arg("RlsGroup.wixobj");
1760             }
1761             if rust_analyzer_installer.is_some() {
1762                 cmd.arg("RustAnalyzerGroup.wixobj");
1763             }
1764             if miri_installer.is_some() {
1765                 cmd.arg("MiriGroup.wixobj");
1766             }
1767
1768             if target.contains("windows-gnu") {
1769                 cmd.arg("GccGroup.wixobj");
1770             }
1771             // ICE57 wrongly complains about the shortcuts
1772             cmd.arg("-sice:ICE57");
1773
1774             let _time = timeit(builder);
1775             builder.run(&mut cmd);
1776
1777             if !builder.config.dry_run {
1778                 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
1779             }
1780         }
1781     }
1782 }
1783
1784 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
1785     let mut parts = builder.version.split('.');
1786     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
1787         .env("CFG_RELEASE_NUM", &builder.version)
1788         .env("CFG_RELEASE", builder.rust_release())
1789         .env("CFG_VER_MAJOR", parts.next().unwrap())
1790         .env("CFG_VER_MINOR", parts.next().unwrap())
1791         .env("CFG_VER_PATCH", parts.next().unwrap())
1792         .env("CFG_VER_BUILD", "0") // just needed to build
1793         .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
1794         .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
1795         .env("CFG_BUILD", target.triple)
1796         .env("CFG_CHANNEL", &builder.config.channel);
1797
1798     if target.contains("windows-gnu") {
1799         cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
1800     } else {
1801         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
1802     }
1803
1804     if target.contains("x86_64") {
1805         cmd.env("CFG_PLATFORM", "x64");
1806     } else {
1807         cmd.env("CFG_PLATFORM", "x86");
1808     }
1809 }
1810
1811 /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
1812 ///
1813
1814 /// Returns whether the files were actually copied.
1815 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
1816     if let Some(config) = builder.config.target_config.get(&target) {
1817         if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
1818             // If the LLVM was externally provided, then we don't currently copy
1819             // artifacts into the sysroot. This is not necessarily the right
1820             // choice (in particular, it will require the LLVM dylib to be in
1821             // the linker's load path at runtime), but the common use case for
1822             // external LLVMs is distribution provided LLVMs, and in that case
1823             // they're usually in the standard search path (e.g., /usr/lib) and
1824             // copying them here is going to cause problems as we may end up
1825             // with the wrong files and isn't what distributions want.
1826             //
1827             // This behavior may be revisited in the future though.
1828             //
1829             // If the LLVM is coming from ourselves (just from CI) though, we
1830             // still want to install it, as it otherwise won't be available.
1831             return false;
1832         }
1833     }
1834
1835     // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
1836     // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
1837     // clear why this is the case, though. llvm-config will emit the versioned
1838     // paths and we don't want those in the sysroot (as we're expecting
1839     // unversioned paths).
1840     if target.contains("apple-darwin") && builder.config.llvm_link_shared {
1841         let src_libdir = builder.llvm_out(target).join("lib");
1842         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
1843         if llvm_dylib_path.exists() {
1844             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
1845         }
1846         !builder.config.dry_run
1847     } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
1848         let mut cmd = Command::new(llvm_config);
1849         cmd.arg("--libfiles");
1850         builder.verbose(&format!("running {:?}", cmd));
1851         let files = output(&mut cmd);
1852         for file in files.trim_end().split(' ') {
1853             builder.install(Path::new(file), dst_libdir, 0o644);
1854         }
1855         !builder.config.dry_run
1856     } else {
1857         false
1858     }
1859 }
1860
1861 /// Maybe add libLLVM.so to the target lib-dir for linking.
1862 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1863     let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
1864     // We do not need to copy LLVM files into the sysroot if it is not
1865     // dynamically linked; it is already included into librustc_llvm
1866     // statically.
1867     if builder.config.llvm_link_shared {
1868         maybe_install_llvm(builder, target, &dst_libdir);
1869     }
1870 }
1871
1872 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
1873 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1874     let dst_libdir =
1875         sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
1876     // We do not need to copy LLVM files into the sysroot if it is not
1877     // dynamically linked; it is already included into librustc_llvm
1878     // statically.
1879     if builder.config.llvm_link_shared {
1880         maybe_install_llvm(builder, target, &dst_libdir);
1881     }
1882 }
1883
1884 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1885 pub struct LlvmTools {
1886     pub target: TargetSelection,
1887 }
1888
1889 impl Step for LlvmTools {
1890     type Output = Option<GeneratedTarball>;
1891     const ONLY_HOSTS: bool = true;
1892
1893     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1894         run.path("llvm-tools")
1895     }
1896
1897     fn make_run(run: RunConfig<'_>) {
1898         run.builder.ensure(LlvmTools { target: run.target });
1899     }
1900
1901     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1902         let target = self.target;
1903         assert!(builder.config.extended);
1904
1905         /* run only if llvm-config isn't used */
1906         if let Some(config) = builder.config.target_config.get(&target) {
1907             if let Some(ref _s) = config.llvm_config {
1908                 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
1909                 return None;
1910             }
1911         }
1912
1913         let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
1914         tarball.set_overlay(OverlayKind::LLVM);
1915         tarball.is_preview(true);
1916
1917         // Prepare the image directory
1918         let src_bindir = builder.llvm_out(target).join("bin");
1919         let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
1920         for tool in LLVM_TOOLS {
1921             let exe = src_bindir.join(exe(tool, target));
1922             tarball.add_file(&exe, &dst_bindir, 0o755);
1923         }
1924
1925         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
1926         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
1927         // of `rustc-dev` to support the inherited `-lLLVM` when using the
1928         // compiler libraries.
1929         maybe_install_llvm_target(builder, target, tarball.image_dir());
1930
1931         Some(tarball.generate())
1932     }
1933 }
1934
1935 // Tarball intended for internal consumption to ease rustc/std development.
1936 //
1937 // Should not be considered stable by end users.
1938 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1939 pub struct RustDev {
1940     pub target: TargetSelection,
1941 }
1942
1943 impl Step for RustDev {
1944     type Output = Option<GeneratedTarball>;
1945     const DEFAULT: bool = true;
1946     const ONLY_HOSTS: bool = true;
1947
1948     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1949         run.path("rust-dev")
1950     }
1951
1952     fn make_run(run: RunConfig<'_>) {
1953         run.builder.ensure(RustDev { target: run.target });
1954     }
1955
1956     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1957         let target = self.target;
1958
1959         /* run only if llvm-config isn't used */
1960         if let Some(config) = builder.config.target_config.get(&target) {
1961             if let Some(ref _s) = config.llvm_config {
1962                 builder.info(&format!("Skipping RustDev ({}): external LLVM", target));
1963                 return None;
1964             }
1965         }
1966
1967         let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
1968         tarball.set_overlay(OverlayKind::LLVM);
1969
1970         let src_bindir = builder.llvm_out(target).join("bin");
1971         for bin in &[
1972             "llvm-config",
1973             "llvm-ar",
1974             "llvm-objdump",
1975             "llvm-profdata",
1976             "llvm-bcanalyzer",
1977             "llvm-cov",
1978             "llvm-dwp",
1979         ] {
1980             tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
1981         }
1982         tarball.add_file(&builder.llvm_filecheck(target), "bin", 0o755);
1983
1984         // Copy the include directory as well; needed mostly to build
1985         // librustc_llvm properly (e.g., llvm-config.h is in here). But also
1986         // just broadly useful to be able to link against the bundled LLVM.
1987         tarball.add_dir(&builder.llvm_out(target).join("include"), "include");
1988
1989         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
1990         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
1991         // of `rustc-dev` to support the inherited `-lLLVM` when using the
1992         // compiler libraries.
1993         let dst_libdir = tarball.image_dir().join("lib");
1994         maybe_install_llvm(builder, target, &dst_libdir);
1995         let link_type = if builder.config.llvm_link_shared { "dynamic" } else { "static" };
1996         t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
1997
1998         Some(tarball.generate())
1999     }
2000 }
2001
2002 /// Tarball containing a prebuilt version of the build-manifest tool, intented to be used by the
2003 /// release process to avoid cloning the monorepo and building stuff.
2004 ///
2005 /// Should not be considered stable by end users.
2006 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2007 pub struct BuildManifest {
2008     pub target: TargetSelection,
2009 }
2010
2011 impl Step for BuildManifest {
2012     type Output = GeneratedTarball;
2013     const DEFAULT: bool = false;
2014     const ONLY_HOSTS: bool = true;
2015
2016     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2017         run.path("src/tools/build-manifest")
2018     }
2019
2020     fn make_run(run: RunConfig<'_>) {
2021         run.builder.ensure(BuildManifest { target: run.target });
2022     }
2023
2024     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2025         let build_manifest = builder.tool_exe(Tool::BuildManifest);
2026
2027         let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2028         tarball.add_file(&build_manifest, "bin", 0o755);
2029         tarball.generate()
2030     }
2031 }
2032
2033 /// Tarball containing artifacts necessary to reproduce the build of rustc.
2034 ///
2035 /// Currently this is the PGO profile data.
2036 ///
2037 /// Should not be considered stable by end users.
2038 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2039 pub struct ReproducibleArtifacts {
2040     pub target: TargetSelection,
2041 }
2042
2043 impl Step for ReproducibleArtifacts {
2044     type Output = Option<GeneratedTarball>;
2045     const DEFAULT: bool = true;
2046     const ONLY_HOSTS: bool = true;
2047
2048     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2049         run.path("reproducible")
2050     }
2051
2052     fn make_run(run: RunConfig<'_>) {
2053         run.builder.ensure(ReproducibleArtifacts { target: run.target });
2054     }
2055
2056     fn run(self, builder: &Builder<'_>) -> Self::Output {
2057         let path = builder.config.rust_profile_use.as_ref()?;
2058
2059         let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2060         tarball.add_file(path, ".", 0o644);
2061         Some(tarball.generate())
2062     }
2063 }