]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Allow downloading LLVM on Windows
[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(None);
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(None);
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         for file in src_files {
649             tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
650         }
651
652         Some(tarball.generate())
653     }
654 }
655
656 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
657 pub struct Analysis {
658     pub compiler: Compiler,
659     pub target: TargetSelection,
660 }
661
662 impl Step for Analysis {
663     type Output = Option<GeneratedTarball>;
664     const DEFAULT: bool = true;
665
666     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
667         let builder = run.builder;
668         run.path("analysis").default_condition(builder.config.extended)
669     }
670
671     fn make_run(run: RunConfig<'_>) {
672         run.builder.ensure(Analysis {
673             // Find the actual compiler (handling the full bootstrap option) which
674             // produced the save-analysis data because that data isn't copied
675             // through the sysroot uplifting.
676             compiler: run.builder.compiler_for(
677                 run.builder.top_stage,
678                 run.builder.config.build,
679                 run.target,
680             ),
681             target: run.target,
682         });
683     }
684
685     /// Creates a tarball of save-analysis metadata, if available.
686     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
687         let compiler = self.compiler;
688         let target = self.target;
689         assert!(builder.config.extended);
690         if compiler.host != builder.config.build {
691             return None;
692         }
693
694         builder.ensure(compile::Std { compiler, target });
695         let src = builder
696             .stage_out(compiler, Mode::Std)
697             .join(target.triple)
698             .join(builder.cargo_dir())
699             .join("deps")
700             .join("save-analysis");
701
702         let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
703         tarball.include_target_in_component_name(true);
704         tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
705         Some(tarball.generate())
706     }
707 }
708
709 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
710 /// `dst_dir`.
711 fn copy_src_dirs(
712     builder: &Builder<'_>,
713     base: &Path,
714     src_dirs: &[&str],
715     exclude_dirs: &[&str],
716     dst_dir: &Path,
717 ) {
718     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
719         let spath = match path.to_str() {
720             Some(path) => path,
721             None => return false,
722         };
723         if spath.ends_with('~') || spath.ends_with(".pyc") {
724             return false;
725         }
726
727         const LLVM_PROJECTS: &[&str] = &[
728             "llvm-project/clang",
729             "llvm-project\\clang",
730             "llvm-project/libunwind",
731             "llvm-project\\libunwind",
732             "llvm-project/lld",
733             "llvm-project\\lld",
734             "llvm-project/lldb",
735             "llvm-project\\lldb",
736             "llvm-project/llvm",
737             "llvm-project\\llvm",
738             "llvm-project/compiler-rt",
739             "llvm-project\\compiler-rt",
740         ];
741         if spath.contains("llvm-project")
742             && !spath.ends_with("llvm-project")
743             && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
744         {
745             return false;
746         }
747
748         const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
749         if LLVM_TEST.iter().any(|path| spath.contains(path))
750             && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
751         {
752             return false;
753         }
754
755         let full_path = Path::new(dir).join(path);
756         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
757             return false;
758         }
759
760         let excludes = [
761             "CVS",
762             "RCS",
763             "SCCS",
764             ".git",
765             ".gitignore",
766             ".gitmodules",
767             ".gitattributes",
768             ".cvsignore",
769             ".svn",
770             ".arch-ids",
771             "{arch}",
772             "=RELEASE-ID",
773             "=meta-update",
774             "=update",
775             ".bzr",
776             ".bzrignore",
777             ".bzrtags",
778             ".hg",
779             ".hgignore",
780             ".hgrags",
781             "_darcs",
782         ];
783         !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
784     }
785
786     // Copy the directories using our filter
787     for item in src_dirs {
788         let dst = &dst_dir.join(item);
789         t!(fs::create_dir_all(dst));
790         builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
791     }
792 }
793
794 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
795 pub struct Src;
796
797 impl Step for Src {
798     /// The output path of the src installer tarball
799     type Output = GeneratedTarball;
800     const DEFAULT: bool = true;
801     const ONLY_HOSTS: bool = true;
802
803     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
804         run.path("src")
805     }
806
807     fn make_run(run: RunConfig<'_>) {
808         run.builder.ensure(Src);
809     }
810
811     /// Creates the `rust-src` installer component
812     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
813         let tarball = Tarball::new_targetless(builder, "rust-src");
814
815         // A lot of tools expect the rust-src component to be entirely in this directory, so if you
816         // change that (e.g. by adding another directory `lib/rustlib/src/foo` or
817         // `lib/rustlib/src/rust/foo`), you will need to go around hunting for implicit assumptions
818         // and fix them...
819         //
820         // NOTE: if you update the paths here, you also should update the "virtual" path
821         // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
822         let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
823
824         let src_files = ["Cargo.lock"];
825         // This is the reduced set of paths which will become the rust-src component
826         // (essentially libstd and all of its path dependencies).
827         copy_src_dirs(
828             builder,
829             &builder.src,
830             &["library", "src/llvm-project/libunwind"],
831             &[
832                 // not needed and contains symlinks which rustup currently
833                 // chokes on when unpacking.
834                 "library/backtrace/crates",
835             ],
836             &dst_src,
837         );
838         for file in src_files.iter() {
839             builder.copy(&builder.src.join(file), &dst_src.join(file));
840         }
841
842         tarball.generate()
843     }
844 }
845
846 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
847 pub struct PlainSourceTarball;
848
849 impl Step for PlainSourceTarball {
850     /// Produces the location of the tarball generated
851     type Output = GeneratedTarball;
852     const DEFAULT: bool = true;
853     const ONLY_HOSTS: bool = true;
854
855     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
856         let builder = run.builder;
857         run.path("src").default_condition(builder.config.rust_dist_src)
858     }
859
860     fn make_run(run: RunConfig<'_>) {
861         run.builder.ensure(PlainSourceTarball);
862     }
863
864     /// Creates the plain source tarball
865     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
866         let tarball = Tarball::new(builder, "rustc", "src");
867         let plain_dst_src = tarball.image_dir();
868
869         // This is the set of root paths which will become part of the source package
870         let src_files = [
871             "COPYRIGHT",
872             "LICENSE-APACHE",
873             "LICENSE-MIT",
874             "CONTRIBUTING.md",
875             "README.md",
876             "RELEASES.md",
877             "configure",
878             "x.py",
879             "config.toml.example",
880             "Cargo.toml",
881             "Cargo.lock",
882         ];
883         let src_dirs = ["src", "compiler", "library"];
884
885         copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
886
887         // Copy the files normally
888         for item in &src_files {
889             builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
890         }
891
892         // Create the version file
893         builder.create(&plain_dst_src.join("version"), &builder.rust_version());
894         if let Some(sha) = builder.rust_sha() {
895             builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
896         }
897
898         // If we're building from git sources, we need to vendor a complete distribution.
899         if builder.rust_info.is_git() {
900             // Vendor all Cargo dependencies
901             let mut cmd = Command::new(&builder.initial_cargo);
902             cmd.arg("vendor")
903                 .arg("--sync")
904                 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
905                 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
906                 .current_dir(&plain_dst_src);
907             builder.run(&mut cmd);
908         }
909
910         tarball.bare()
911     }
912 }
913
914 // We have to run a few shell scripts, which choke quite a bit on both `\`
915 // characters and on `C:\` paths, so normalize both of them away.
916 pub fn sanitize_sh(path: &Path) -> String {
917     let path = path.to_str().unwrap().replace("\\", "/");
918     return change_drive(unc_to_lfs(&path)).unwrap_or(path);
919
920     fn unc_to_lfs(s: &str) -> &str {
921         s.strip_prefix("//?/").unwrap_or(s)
922     }
923
924     fn change_drive(s: &str) -> Option<String> {
925         let mut ch = s.chars();
926         let drive = ch.next().unwrap_or('C');
927         if ch.next() != Some(':') {
928             return None;
929         }
930         if ch.next() != Some('/') {
931             return None;
932         }
933         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
934     }
935 }
936
937 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
938 pub struct Cargo {
939     pub compiler: Compiler,
940     pub target: TargetSelection,
941 }
942
943 impl Step for Cargo {
944     type Output = GeneratedTarball;
945     const ONLY_HOSTS: bool = true;
946
947     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
948         run.path("cargo")
949     }
950
951     fn make_run(run: RunConfig<'_>) {
952         run.builder.ensure(Cargo {
953             compiler: run.builder.compiler_for(
954                 run.builder.top_stage,
955                 run.builder.config.build,
956                 run.target,
957             ),
958             target: run.target,
959         });
960     }
961
962     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
963         let compiler = self.compiler;
964         let target = self.target;
965
966         let cargo = builder.ensure(tool::Cargo { compiler, target });
967         let src = builder.src.join("src/tools/cargo");
968         let etc = src.join("src/etc");
969
970         // Prepare the image directory
971         let mut tarball = Tarball::new(builder, "cargo", &target.triple);
972         tarball.set_overlay(OverlayKind::Cargo);
973
974         tarball.add_file(&cargo, "bin", 0o755);
975         tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
976         tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
977         tarball.add_dir(etc.join("man"), "share/man/man1");
978         tarball.add_legal_and_readme_to("share/doc/cargo");
979
980         for dirent in fs::read_dir(cargo.parent().unwrap()).expect("read_dir") {
981             let dirent = dirent.expect("read dir entry");
982             if dirent.file_name().to_str().expect("utf8").starts_with("cargo-credential-") {
983                 tarball.add_file(&dirent.path(), "libexec", 0o755);
984             }
985         }
986
987         tarball.generate()
988     }
989 }
990
991 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
992 pub struct Rls {
993     pub compiler: Compiler,
994     pub target: TargetSelection,
995 }
996
997 impl Step for Rls {
998     type Output = Option<GeneratedTarball>;
999     const ONLY_HOSTS: bool = true;
1000
1001     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1002         run.path("rls")
1003     }
1004
1005     fn make_run(run: RunConfig<'_>) {
1006         run.builder.ensure(Rls {
1007             compiler: run.builder.compiler_for(
1008                 run.builder.top_stage,
1009                 run.builder.config.build,
1010                 run.target,
1011             ),
1012             target: run.target,
1013         });
1014     }
1015
1016     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1017         let compiler = self.compiler;
1018         let target = self.target;
1019         assert!(builder.config.extended);
1020
1021         let rls = builder
1022             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1023             .or_else(|| {
1024                 missing_tool("RLS", builder.build.config.missing_tools);
1025                 None
1026             })?;
1027
1028         let mut tarball = Tarball::new(builder, "rls", &target.triple);
1029         tarball.set_overlay(OverlayKind::RLS);
1030         tarball.is_preview(true);
1031         tarball.add_file(rls, "bin", 0o755);
1032         tarball.add_legal_and_readme_to("share/doc/rls");
1033         Some(tarball.generate())
1034     }
1035 }
1036
1037 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1038 pub struct RustAnalyzer {
1039     pub compiler: Compiler,
1040     pub target: TargetSelection,
1041 }
1042
1043 impl Step for RustAnalyzer {
1044     type Output = Option<GeneratedTarball>;
1045     const ONLY_HOSTS: bool = true;
1046
1047     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1048         run.path("rust-analyzer")
1049     }
1050
1051     fn make_run(run: RunConfig<'_>) {
1052         run.builder.ensure(RustAnalyzer {
1053             compiler: run.builder.compiler_for(
1054                 run.builder.top_stage,
1055                 run.builder.config.build,
1056                 run.target,
1057             ),
1058             target: run.target,
1059         });
1060     }
1061
1062     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1063         let compiler = self.compiler;
1064         let target = self.target;
1065         assert!(builder.config.extended);
1066
1067         if target.contains("riscv64") {
1068             // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1069             // to build. See #74813 for details.
1070             return None;
1071         }
1072
1073         let rust_analyzer = builder
1074             .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1075             .expect("rust-analyzer always builds");
1076
1077         let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1078         tarball.set_overlay(OverlayKind::RustAnalyzer);
1079         tarball.is_preview(true);
1080         tarball.add_file(rust_analyzer, "bin", 0o755);
1081         tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1082         Some(tarball.generate())
1083     }
1084 }
1085
1086 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1087 pub struct Clippy {
1088     pub compiler: Compiler,
1089     pub target: TargetSelection,
1090 }
1091
1092 impl Step for Clippy {
1093     type Output = GeneratedTarball;
1094     const ONLY_HOSTS: bool = true;
1095
1096     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1097         run.path("clippy")
1098     }
1099
1100     fn make_run(run: RunConfig<'_>) {
1101         run.builder.ensure(Clippy {
1102             compiler: run.builder.compiler_for(
1103                 run.builder.top_stage,
1104                 run.builder.config.build,
1105                 run.target,
1106             ),
1107             target: run.target,
1108         });
1109     }
1110
1111     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1112         let compiler = self.compiler;
1113         let target = self.target;
1114         assert!(builder.config.extended);
1115
1116         // Prepare the image directory
1117         // We expect clippy to build, because we've exited this step above if tool
1118         // state for clippy isn't testing.
1119         let clippy = builder
1120             .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1121             .expect("clippy expected to build - essential tool");
1122         let cargoclippy = builder
1123             .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1124             .expect("clippy expected to build - essential tool");
1125
1126         let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1127         tarball.set_overlay(OverlayKind::Clippy);
1128         tarball.is_preview(true);
1129         tarball.add_file(clippy, "bin", 0o755);
1130         tarball.add_file(cargoclippy, "bin", 0o755);
1131         tarball.add_legal_and_readme_to("share/doc/clippy");
1132         tarball.generate()
1133     }
1134 }
1135
1136 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1137 pub struct Miri {
1138     pub compiler: Compiler,
1139     pub target: TargetSelection,
1140 }
1141
1142 impl Step for Miri {
1143     type Output = Option<GeneratedTarball>;
1144     const ONLY_HOSTS: bool = true;
1145
1146     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1147         run.path("miri")
1148     }
1149
1150     fn make_run(run: RunConfig<'_>) {
1151         run.builder.ensure(Miri {
1152             compiler: run.builder.compiler_for(
1153                 run.builder.top_stage,
1154                 run.builder.config.build,
1155                 run.target,
1156             ),
1157             target: run.target,
1158         });
1159     }
1160
1161     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1162         let compiler = self.compiler;
1163         let target = self.target;
1164         assert!(builder.config.extended);
1165
1166         let miri = builder
1167             .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1168             .or_else(|| {
1169                 missing_tool("miri", builder.build.config.missing_tools);
1170                 None
1171             })?;
1172         let cargomiri = builder
1173             .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1174             .or_else(|| {
1175                 missing_tool("cargo miri", builder.build.config.missing_tools);
1176                 None
1177             })?;
1178
1179         let mut tarball = Tarball::new(builder, "miri", &target.triple);
1180         tarball.set_overlay(OverlayKind::Miri);
1181         tarball.is_preview(true);
1182         tarball.add_file(miri, "bin", 0o755);
1183         tarball.add_file(cargomiri, "bin", 0o755);
1184         tarball.add_legal_and_readme_to("share/doc/miri");
1185         Some(tarball.generate())
1186     }
1187 }
1188
1189 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1190 pub struct Rustfmt {
1191     pub compiler: Compiler,
1192     pub target: TargetSelection,
1193 }
1194
1195 impl Step for Rustfmt {
1196     type Output = Option<GeneratedTarball>;
1197     const ONLY_HOSTS: bool = true;
1198
1199     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1200         run.path("rustfmt")
1201     }
1202
1203     fn make_run(run: RunConfig<'_>) {
1204         run.builder.ensure(Rustfmt {
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 rustfmt = builder
1219             .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1220             .or_else(|| {
1221                 missing_tool("Rustfmt", builder.build.config.missing_tools);
1222                 None
1223             })?;
1224         let cargofmt = builder
1225             .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1226             .or_else(|| {
1227                 missing_tool("Cargofmt", builder.build.config.missing_tools);
1228                 None
1229             })?;
1230
1231         let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
1232         tarball.set_overlay(OverlayKind::Rustfmt);
1233         tarball.is_preview(true);
1234         tarball.add_file(rustfmt, "bin", 0o755);
1235         tarball.add_file(cargofmt, "bin", 0o755);
1236         tarball.add_legal_and_readme_to("share/doc/rustfmt");
1237         Some(tarball.generate())
1238     }
1239 }
1240
1241 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1242 pub struct Extended {
1243     stage: u32,
1244     host: TargetSelection,
1245     target: TargetSelection,
1246 }
1247
1248 impl Step for Extended {
1249     type Output = ();
1250     const DEFAULT: bool = true;
1251     const ONLY_HOSTS: bool = true;
1252
1253     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1254         let builder = run.builder;
1255         run.path("extended").default_condition(builder.config.extended)
1256     }
1257
1258     fn make_run(run: RunConfig<'_>) {
1259         run.builder.ensure(Extended {
1260             stage: run.builder.top_stage,
1261             host: run.builder.config.build,
1262             target: run.target,
1263         });
1264     }
1265
1266     /// Creates a combined installer for the specified target in the provided stage.
1267     fn run(self, builder: &Builder<'_>) {
1268         let target = self.target;
1269         let stage = self.stage;
1270         let compiler = builder.compiler_for(self.stage, self.host, self.target);
1271
1272         builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1273
1274         let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
1275         let cargo_installer = builder.ensure(Cargo { compiler, target });
1276         let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1277         let rls_installer = builder.ensure(Rls { compiler, target });
1278         let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
1279         let llvm_tools_installer = builder.ensure(LlvmTools { target });
1280         let clippy_installer = builder.ensure(Clippy { compiler, target });
1281         let miri_installer = builder.ensure(Miri { compiler, target });
1282         let mingw_installer = builder.ensure(Mingw { host: target });
1283         let analysis_installer = builder.ensure(Analysis { compiler, target });
1284
1285         let docs_installer = builder.ensure(Docs { host: target });
1286         let std_installer = builder.ensure(Std { compiler, target });
1287
1288         let etc = builder.src.join("src/etc/installer");
1289
1290         // Avoid producing tarballs during a dry run.
1291         if builder.config.dry_run {
1292             return;
1293         }
1294
1295         // When rust-std package split from rustc, we needed to ensure that during
1296         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1297         // the std files during uninstall. To do this ensure that rustc comes
1298         // before rust-std in the list below.
1299         let mut tarballs = Vec::new();
1300         tarballs.push(rustc_installer);
1301         tarballs.push(cargo_installer);
1302         tarballs.extend(rls_installer.clone());
1303         tarballs.extend(rust_analyzer_installer.clone());
1304         tarballs.push(clippy_installer);
1305         tarballs.extend(miri_installer.clone());
1306         tarballs.extend(rustfmt_installer.clone());
1307         tarballs.extend(llvm_tools_installer);
1308         if let Some(analysis_installer) = analysis_installer {
1309             tarballs.push(analysis_installer);
1310         }
1311         tarballs.push(std_installer.expect("missing std"));
1312         if let Some(docs_installer) = docs_installer {
1313             tarballs.push(docs_installer);
1314         }
1315         if target.contains("pc-windows-gnu") {
1316             tarballs.push(mingw_installer.unwrap());
1317         }
1318
1319         let tarball = Tarball::new(builder, "rust", &target.triple);
1320         let generated = tarball.combine(&tarballs);
1321
1322         let tmp = tmpdir(builder).join("combined-tarball");
1323         let work = generated.work_dir();
1324
1325         let mut license = String::new();
1326         license += &builder.read(&builder.src.join("COPYRIGHT"));
1327         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1328         license += &builder.read(&builder.src.join("LICENSE-MIT"));
1329         license.push('\n');
1330         license.push('\n');
1331
1332         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1333         let mut rtf = rtf.to_string();
1334         rtf.push('\n');
1335         for line in license.lines() {
1336             rtf.push_str(line);
1337             rtf.push_str("\\line ");
1338         }
1339         rtf.push('}');
1340
1341         fn filter(contents: &str, marker: &str) -> String {
1342             let start = format!("tool-{}-start", marker);
1343             let end = format!("tool-{}-end", marker);
1344             let mut lines = Vec::new();
1345             let mut omitted = false;
1346             for line in contents.lines() {
1347                 if line.contains(&start) {
1348                     omitted = true;
1349                 } else if line.contains(&end) {
1350                     omitted = false;
1351                 } else if !omitted {
1352                     lines.push(line);
1353                 }
1354             }
1355
1356             lines.join("\n")
1357         }
1358
1359         let xform = |p: &Path| {
1360             let mut contents = t!(fs::read_to_string(p));
1361             if rls_installer.is_none() {
1362                 contents = filter(&contents, "rls");
1363             }
1364             if rust_analyzer_installer.is_none() {
1365                 contents = filter(&contents, "rust-analyzer");
1366             }
1367             if miri_installer.is_none() {
1368                 contents = filter(&contents, "miri");
1369             }
1370             if rustfmt_installer.is_none() {
1371                 contents = filter(&contents, "rustfmt");
1372             }
1373             let ret = tmp.join(p.file_name().unwrap());
1374             t!(fs::write(&ret, &contents));
1375             ret
1376         };
1377
1378         if target.contains("apple-darwin") {
1379             builder.info("building pkg installer");
1380             let pkg = tmp.join("pkg");
1381             let _ = fs::remove_dir_all(&pkg);
1382
1383             let pkgbuild = |component: &str| {
1384                 let mut cmd = Command::new("pkgbuild");
1385                 cmd.arg("--identifier")
1386                     .arg(format!("org.rust-lang.{}", component))
1387                     .arg("--scripts")
1388                     .arg(pkg.join(component))
1389                     .arg("--nopayload")
1390                     .arg(pkg.join(component).with_extension("pkg"));
1391                 builder.run(&mut cmd);
1392             };
1393
1394             let prepare = |name: &str| {
1395                 builder.create_dir(&pkg.join(name));
1396                 builder.cp_r(
1397                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1398                     &pkg.join(name),
1399                 );
1400                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1401                 pkgbuild(name);
1402             };
1403             prepare("rustc");
1404             prepare("cargo");
1405             prepare("rust-docs");
1406             prepare("rust-std");
1407             prepare("rust-analysis");
1408             prepare("clippy");
1409
1410             if rls_installer.is_some() {
1411                 prepare("rls");
1412             }
1413             if rust_analyzer_installer.is_some() {
1414                 prepare("rust-analyzer");
1415             }
1416             if miri_installer.is_some() {
1417                 prepare("miri");
1418             }
1419
1420             // create an 'uninstall' package
1421             builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1422             pkgbuild("uninstall");
1423
1424             builder.create_dir(&pkg.join("res"));
1425             builder.create(&pkg.join("res/LICENSE.txt"), &license);
1426             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1427             let mut cmd = Command::new("productbuild");
1428             cmd.arg("--distribution")
1429                 .arg(xform(&etc.join("pkg/Distribution.xml")))
1430                 .arg("--resources")
1431                 .arg(pkg.join("res"))
1432                 .arg(distdir(builder).join(format!(
1433                     "{}-{}.pkg",
1434                     pkgname(builder, "rust"),
1435                     target.triple
1436                 )))
1437                 .arg("--package-path")
1438                 .arg(&pkg);
1439             let _time = timeit(builder);
1440             builder.run(&mut cmd);
1441         }
1442
1443         if target.contains("windows") {
1444             let exe = tmp.join("exe");
1445             let _ = fs::remove_dir_all(&exe);
1446
1447             let prepare = |name: &str| {
1448                 builder.create_dir(&exe.join(name));
1449                 let dir = if name == "rust-std" || name == "rust-analysis" {
1450                     format!("{}-{}", name, target.triple)
1451                 } else if name == "rls" {
1452                     "rls-preview".to_string()
1453                 } else if name == "rust-analyzer" {
1454                     "rust-analyzer-preview".to_string()
1455                 } else if name == "clippy" {
1456                     "clippy-preview".to_string()
1457                 } else if name == "miri" {
1458                     "miri-preview".to_string()
1459                 } else {
1460                     name.to_string()
1461                 };
1462                 builder.cp_r(
1463                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1464                     &exe.join(name),
1465                 );
1466                 builder.remove(&exe.join(name).join("manifest.in"));
1467             };
1468             prepare("rustc");
1469             prepare("cargo");
1470             prepare("rust-analysis");
1471             prepare("rust-docs");
1472             prepare("rust-std");
1473             prepare("clippy");
1474             if rls_installer.is_some() {
1475                 prepare("rls");
1476             }
1477             if rust_analyzer_installer.is_some() {
1478                 prepare("rust-analyzer");
1479             }
1480             if miri_installer.is_some() {
1481                 prepare("miri");
1482             }
1483             if target.contains("windows-gnu") {
1484                 prepare("rust-mingw");
1485             }
1486
1487             builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1488
1489             // Generate msi installer
1490             let wix = PathBuf::from(env::var_os("WIX").unwrap());
1491             let heat = wix.join("bin/heat.exe");
1492             let candle = wix.join("bin/candle.exe");
1493             let light = wix.join("bin/light.exe");
1494
1495             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1496             builder.run(
1497                 Command::new(&heat)
1498                     .current_dir(&exe)
1499                     .arg("dir")
1500                     .arg("rustc")
1501                     .args(&heat_flags)
1502                     .arg("-cg")
1503                     .arg("RustcGroup")
1504                     .arg("-dr")
1505                     .arg("Rustc")
1506                     .arg("-var")
1507                     .arg("var.RustcDir")
1508                     .arg("-out")
1509                     .arg(exe.join("RustcGroup.wxs")),
1510             );
1511             builder.run(
1512                 Command::new(&heat)
1513                     .current_dir(&exe)
1514                     .arg("dir")
1515                     .arg("rust-docs")
1516                     .args(&heat_flags)
1517                     .arg("-cg")
1518                     .arg("DocsGroup")
1519                     .arg("-dr")
1520                     .arg("Docs")
1521                     .arg("-var")
1522                     .arg("var.DocsDir")
1523                     .arg("-out")
1524                     .arg(exe.join("DocsGroup.wxs"))
1525                     .arg("-t")
1526                     .arg(etc.join("msi/squash-components.xsl")),
1527             );
1528             builder.run(
1529                 Command::new(&heat)
1530                     .current_dir(&exe)
1531                     .arg("dir")
1532                     .arg("cargo")
1533                     .args(&heat_flags)
1534                     .arg("-cg")
1535                     .arg("CargoGroup")
1536                     .arg("-dr")
1537                     .arg("Cargo")
1538                     .arg("-var")
1539                     .arg("var.CargoDir")
1540                     .arg("-out")
1541                     .arg(exe.join("CargoGroup.wxs"))
1542                     .arg("-t")
1543                     .arg(etc.join("msi/remove-duplicates.xsl")),
1544             );
1545             builder.run(
1546                 Command::new(&heat)
1547                     .current_dir(&exe)
1548                     .arg("dir")
1549                     .arg("rust-std")
1550                     .args(&heat_flags)
1551                     .arg("-cg")
1552                     .arg("StdGroup")
1553                     .arg("-dr")
1554                     .arg("Std")
1555                     .arg("-var")
1556                     .arg("var.StdDir")
1557                     .arg("-out")
1558                     .arg(exe.join("StdGroup.wxs")),
1559             );
1560             if rls_installer.is_some() {
1561                 builder.run(
1562                     Command::new(&heat)
1563                         .current_dir(&exe)
1564                         .arg("dir")
1565                         .arg("rls")
1566                         .args(&heat_flags)
1567                         .arg("-cg")
1568                         .arg("RlsGroup")
1569                         .arg("-dr")
1570                         .arg("Rls")
1571                         .arg("-var")
1572                         .arg("var.RlsDir")
1573                         .arg("-out")
1574                         .arg(exe.join("RlsGroup.wxs"))
1575                         .arg("-t")
1576                         .arg(etc.join("msi/remove-duplicates.xsl")),
1577                 );
1578             }
1579             if rust_analyzer_installer.is_some() {
1580                 builder.run(
1581                     Command::new(&heat)
1582                         .current_dir(&exe)
1583                         .arg("dir")
1584                         .arg("rust-analyzer")
1585                         .args(&heat_flags)
1586                         .arg("-cg")
1587                         .arg("RustAnalyzerGroup")
1588                         .arg("-dr")
1589                         .arg("RustAnalyzer")
1590                         .arg("-var")
1591                         .arg("var.RustAnalyzerDir")
1592                         .arg("-out")
1593                         .arg(exe.join("RustAnalyzerGroup.wxs"))
1594                         .arg("-t")
1595                         .arg(etc.join("msi/remove-duplicates.xsl")),
1596                 );
1597             }
1598             builder.run(
1599                 Command::new(&heat)
1600                     .current_dir(&exe)
1601                     .arg("dir")
1602                     .arg("clippy")
1603                     .args(&heat_flags)
1604                     .arg("-cg")
1605                     .arg("ClippyGroup")
1606                     .arg("-dr")
1607                     .arg("Clippy")
1608                     .arg("-var")
1609                     .arg("var.ClippyDir")
1610                     .arg("-out")
1611                     .arg(exe.join("ClippyGroup.wxs"))
1612                     .arg("-t")
1613                     .arg(etc.join("msi/remove-duplicates.xsl")),
1614             );
1615             if miri_installer.is_some() {
1616                 builder.run(
1617                     Command::new(&heat)
1618                         .current_dir(&exe)
1619                         .arg("dir")
1620                         .arg("miri")
1621                         .args(&heat_flags)
1622                         .arg("-cg")
1623                         .arg("MiriGroup")
1624                         .arg("-dr")
1625                         .arg("Miri")
1626                         .arg("-var")
1627                         .arg("var.MiriDir")
1628                         .arg("-out")
1629                         .arg(exe.join("MiriGroup.wxs"))
1630                         .arg("-t")
1631                         .arg(etc.join("msi/remove-duplicates.xsl")),
1632                 );
1633             }
1634             builder.run(
1635                 Command::new(&heat)
1636                     .current_dir(&exe)
1637                     .arg("dir")
1638                     .arg("rust-analysis")
1639                     .args(&heat_flags)
1640                     .arg("-cg")
1641                     .arg("AnalysisGroup")
1642                     .arg("-dr")
1643                     .arg("Analysis")
1644                     .arg("-var")
1645                     .arg("var.AnalysisDir")
1646                     .arg("-out")
1647                     .arg(exe.join("AnalysisGroup.wxs"))
1648                     .arg("-t")
1649                     .arg(etc.join("msi/remove-duplicates.xsl")),
1650             );
1651             if target.contains("windows-gnu") {
1652                 builder.run(
1653                     Command::new(&heat)
1654                         .current_dir(&exe)
1655                         .arg("dir")
1656                         .arg("rust-mingw")
1657                         .args(&heat_flags)
1658                         .arg("-cg")
1659                         .arg("GccGroup")
1660                         .arg("-dr")
1661                         .arg("Gcc")
1662                         .arg("-var")
1663                         .arg("var.GccDir")
1664                         .arg("-out")
1665                         .arg(exe.join("GccGroup.wxs")),
1666                 );
1667             }
1668
1669             let candle = |input: &Path| {
1670                 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1671                 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1672                 let mut cmd = Command::new(&candle);
1673                 cmd.current_dir(&exe)
1674                     .arg("-nologo")
1675                     .arg("-dRustcDir=rustc")
1676                     .arg("-dDocsDir=rust-docs")
1677                     .arg("-dCargoDir=cargo")
1678                     .arg("-dStdDir=rust-std")
1679                     .arg("-dAnalysisDir=rust-analysis")
1680                     .arg("-dClippyDir=clippy")
1681                     .arg("-arch")
1682                     .arg(&arch)
1683                     .arg("-out")
1684                     .arg(&output)
1685                     .arg(&input);
1686                 add_env(builder, &mut cmd, target);
1687
1688                 if rls_installer.is_some() {
1689                     cmd.arg("-dRlsDir=rls");
1690                 }
1691                 if rust_analyzer_installer.is_some() {
1692                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1693                 }
1694                 if miri_installer.is_some() {
1695                     cmd.arg("-dMiriDir=miri");
1696                 }
1697                 if target.contains("windows-gnu") {
1698                     cmd.arg("-dGccDir=rust-mingw");
1699                 }
1700                 builder.run(&mut cmd);
1701             };
1702             candle(&xform(&etc.join("msi/rust.wxs")));
1703             candle(&etc.join("msi/ui.wxs"));
1704             candle(&etc.join("msi/rustwelcomedlg.wxs"));
1705             candle("RustcGroup.wxs".as_ref());
1706             candle("DocsGroup.wxs".as_ref());
1707             candle("CargoGroup.wxs".as_ref());
1708             candle("StdGroup.wxs".as_ref());
1709             candle("ClippyGroup.wxs".as_ref());
1710             if rls_installer.is_some() {
1711                 candle("RlsGroup.wxs".as_ref());
1712             }
1713             if rust_analyzer_installer.is_some() {
1714                 candle("RustAnalyzerGroup.wxs".as_ref());
1715             }
1716             if miri_installer.is_some() {
1717                 candle("MiriGroup.wxs".as_ref());
1718             }
1719             candle("AnalysisGroup.wxs".as_ref());
1720
1721             if target.contains("windows-gnu") {
1722                 candle("GccGroup.wxs".as_ref());
1723             }
1724
1725             builder.create(&exe.join("LICENSE.rtf"), &rtf);
1726             builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1727             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1728
1729             builder.info(&format!("building `msi` installer with {:?}", light));
1730             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1731             let mut cmd = Command::new(&light);
1732             cmd.arg("-nologo")
1733                 .arg("-ext")
1734                 .arg("WixUIExtension")
1735                 .arg("-ext")
1736                 .arg("WixUtilExtension")
1737                 .arg("-out")
1738                 .arg(exe.join(&filename))
1739                 .arg("rust.wixobj")
1740                 .arg("ui.wixobj")
1741                 .arg("rustwelcomedlg.wixobj")
1742                 .arg("RustcGroup.wixobj")
1743                 .arg("DocsGroup.wixobj")
1744                 .arg("CargoGroup.wixobj")
1745                 .arg("StdGroup.wixobj")
1746                 .arg("AnalysisGroup.wixobj")
1747                 .arg("ClippyGroup.wixobj")
1748                 .current_dir(&exe);
1749
1750             if rls_installer.is_some() {
1751                 cmd.arg("RlsGroup.wixobj");
1752             }
1753             if rust_analyzer_installer.is_some() {
1754                 cmd.arg("RustAnalyzerGroup.wixobj");
1755             }
1756             if miri_installer.is_some() {
1757                 cmd.arg("MiriGroup.wixobj");
1758             }
1759
1760             if target.contains("windows-gnu") {
1761                 cmd.arg("GccGroup.wixobj");
1762             }
1763             // ICE57 wrongly complains about the shortcuts
1764             cmd.arg("-sice:ICE57");
1765
1766             let _time = timeit(builder);
1767             builder.run(&mut cmd);
1768
1769             if !builder.config.dry_run {
1770                 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
1771             }
1772         }
1773     }
1774 }
1775
1776 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
1777     let mut parts = builder.version.split('.');
1778     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
1779         .env("CFG_RELEASE_NUM", &builder.version)
1780         .env("CFG_RELEASE", builder.rust_release())
1781         .env("CFG_VER_MAJOR", parts.next().unwrap())
1782         .env("CFG_VER_MINOR", parts.next().unwrap())
1783         .env("CFG_VER_PATCH", parts.next().unwrap())
1784         .env("CFG_VER_BUILD", "0") // just needed to build
1785         .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
1786         .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
1787         .env("CFG_BUILD", target.triple)
1788         .env("CFG_CHANNEL", &builder.config.channel);
1789
1790     if target.contains("windows-gnu") {
1791         cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
1792     } else {
1793         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
1794     }
1795
1796     if target.contains("x86_64") {
1797         cmd.env("CFG_PLATFORM", "x64");
1798     } else {
1799         cmd.env("CFG_PLATFORM", "x86");
1800     }
1801 }
1802
1803 /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
1804 ///
1805
1806 /// Returns whether the files were actually copied.
1807 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
1808     if let Some(config) = builder.config.target_config.get(&target) {
1809         if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
1810             // If the LLVM was externally provided, then we don't currently copy
1811             // artifacts into the sysroot. This is not necessarily the right
1812             // choice (in particular, it will require the LLVM dylib to be in
1813             // the linker's load path at runtime), but the common use case for
1814             // external LLVMs is distribution provided LLVMs, and in that case
1815             // they're usually in the standard search path (e.g., /usr/lib) and
1816             // copying them here is going to cause problems as we may end up
1817             // with the wrong files and isn't what distributions want.
1818             //
1819             // This behavior may be revisited in the future though.
1820             //
1821             // If the LLVM is coming from ourselves (just from CI) though, we
1822             // still want to install it, as it otherwise won't be available.
1823             return false;
1824         }
1825     }
1826
1827     // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
1828     // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
1829     // clear why this is the case, though. llvm-config will emit the versioned
1830     // paths and we don't want those in the sysroot (as we're expecting
1831     // unversioned paths).
1832     if target.contains("apple-darwin") && builder.config.llvm_link_shared {
1833         let src_libdir = builder.llvm_out(target).join("lib");
1834         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
1835         if llvm_dylib_path.exists() {
1836             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
1837         }
1838         !builder.config.dry_run
1839     } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
1840         let mut cmd = Command::new(llvm_config);
1841         cmd.arg("--libfiles");
1842         builder.verbose(&format!("running {:?}", cmd));
1843         let files = output(&mut cmd);
1844         for file in files.trim_end().split(' ') {
1845             builder.install(Path::new(file), dst_libdir, 0o644);
1846         }
1847         !builder.config.dry_run
1848     } else {
1849         false
1850     }
1851 }
1852
1853 /// Maybe add libLLVM.so to the target lib-dir for linking.
1854 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1855     let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
1856     // We do not need to copy LLVM files into the sysroot if it is not
1857     // dynamically linked; it is already included into librustc_llvm
1858     // statically.
1859     if builder.config.llvm_link_shared {
1860         maybe_install_llvm(builder, target, &dst_libdir);
1861     }
1862 }
1863
1864 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
1865 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1866     let dst_libdir =
1867         sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
1868     // We do not need to copy LLVM files into the sysroot if it is not
1869     // dynamically linked; it is already included into librustc_llvm
1870     // statically.
1871     if builder.config.llvm_link_shared {
1872         maybe_install_llvm(builder, target, &dst_libdir);
1873     }
1874 }
1875
1876 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1877 pub struct LlvmTools {
1878     pub target: TargetSelection,
1879 }
1880
1881 impl Step for LlvmTools {
1882     type Output = Option<GeneratedTarball>;
1883     const ONLY_HOSTS: bool = true;
1884
1885     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1886         run.path("llvm-tools")
1887     }
1888
1889     fn make_run(run: RunConfig<'_>) {
1890         run.builder.ensure(LlvmTools { target: run.target });
1891     }
1892
1893     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1894         let target = self.target;
1895         assert!(builder.config.extended);
1896
1897         /* run only if llvm-config isn't used */
1898         if let Some(config) = builder.config.target_config.get(&target) {
1899             if let Some(ref _s) = config.llvm_config {
1900                 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
1901                 return None;
1902             }
1903         }
1904
1905         let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
1906         tarball.set_overlay(OverlayKind::LLVM);
1907         tarball.is_preview(true);
1908
1909         // Prepare the image directory
1910         let src_bindir = builder.llvm_out(target).join("bin");
1911         let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
1912         for tool in LLVM_TOOLS {
1913             let exe = src_bindir.join(exe(tool, target));
1914             tarball.add_file(&exe, &dst_bindir, 0o755);
1915         }
1916
1917         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
1918         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
1919         // of `rustc-dev` to support the inherited `-lLLVM` when using the
1920         // compiler libraries.
1921         maybe_install_llvm_target(builder, target, tarball.image_dir());
1922
1923         Some(tarball.generate())
1924     }
1925 }
1926
1927 // Tarball intended for internal consumption to ease rustc/std development.
1928 //
1929 // Should not be considered stable by end users.
1930 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1931 pub struct RustDev {
1932     pub target: TargetSelection,
1933 }
1934
1935 impl Step for RustDev {
1936     type Output = Option<GeneratedTarball>;
1937     const DEFAULT: bool = true;
1938     const ONLY_HOSTS: bool = true;
1939
1940     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1941         run.path("rust-dev")
1942     }
1943
1944     fn make_run(run: RunConfig<'_>) {
1945         run.builder.ensure(RustDev { target: run.target });
1946     }
1947
1948     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1949         let target = self.target;
1950
1951         /* run only if llvm-config isn't used */
1952         if let Some(config) = builder.config.target_config.get(&target) {
1953             if let Some(ref _s) = config.llvm_config {
1954                 builder.info(&format!("Skipping RustDev ({}): external LLVM", target));
1955                 return None;
1956             }
1957         }
1958
1959         let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
1960         tarball.set_overlay(OverlayKind::LLVM);
1961
1962         let src_bindir = builder.llvm_out(target).join("bin");
1963         for bin in &[
1964             "llvm-config",
1965             "llvm-ar",
1966             "llvm-objdump",
1967             "llvm-profdata",
1968             "llvm-bcanalyzer",
1969             "llvm-cov",
1970             "llvm-dwp",
1971         ] {
1972             tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
1973         }
1974         tarball.add_file(&builder.llvm_filecheck(target), "bin", 0o755);
1975
1976         // Copy the include directory as well; needed mostly to build
1977         // librustc_llvm properly (e.g., llvm-config.h is in here). But also
1978         // just broadly useful to be able to link against the bundled LLVM.
1979         tarball.add_dir(&builder.llvm_out(target).join("include"), "include");
1980
1981         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
1982         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
1983         // of `rustc-dev` to support the inherited `-lLLVM` when using the
1984         // compiler libraries.
1985         let dst_libdir = tarball.image_dir().join("lib");
1986         maybe_install_llvm(builder, target, &dst_libdir);
1987         let link_type = if builder.config.llvm_link_shared { "dynamic" } else { "static" };
1988         t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
1989
1990         Some(tarball.generate())
1991     }
1992 }
1993
1994 /// Tarball containing a prebuilt version of the build-manifest tool, intented to be used by the
1995 /// release process to avoid cloning the monorepo and building stuff.
1996 ///
1997 /// Should not be considered stable by end users.
1998 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1999 pub struct BuildManifest {
2000     pub target: TargetSelection,
2001 }
2002
2003 impl Step for BuildManifest {
2004     type Output = GeneratedTarball;
2005     const DEFAULT: bool = false;
2006     const ONLY_HOSTS: bool = true;
2007
2008     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2009         run.path("src/tools/build-manifest")
2010     }
2011
2012     fn make_run(run: RunConfig<'_>) {
2013         run.builder.ensure(BuildManifest { target: run.target });
2014     }
2015
2016     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2017         let build_manifest = builder.tool_exe(Tool::BuildManifest);
2018
2019         let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2020         tarball.add_file(&build_manifest, "bin", 0o755);
2021         tarball.generate()
2022     }
2023 }
2024
2025 /// Tarball containing artifacts necessary to reproduce the build of rustc.
2026 ///
2027 /// Currently this is the PGO profile data.
2028 ///
2029 /// Should not be considered stable by end users.
2030 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2031 pub struct ReproducibleArtifacts {
2032     pub target: TargetSelection,
2033 }
2034
2035 impl Step for ReproducibleArtifacts {
2036     type Output = Option<GeneratedTarball>;
2037     const DEFAULT: bool = true;
2038     const ONLY_HOSTS: bool = true;
2039
2040     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2041         run.path("reproducible")
2042     }
2043
2044     fn make_run(run: RunConfig<'_>) {
2045         run.builder.ensure(ReproducibleArtifacts { target: run.target });
2046     }
2047
2048     fn run(self, builder: &Builder<'_>) -> Self::Output {
2049         let path = builder.config.rust_profile_use.as_ref()?;
2050
2051         let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2052         tarball.add_file(path, ".", 0o644);
2053         Some(tarball.generate())
2054     }
2055 }