]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Rollup merge of #80072 - richkadel:llvm-coverage-counters-2.2.1, r=tmandry
[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::tool::{self, Tool};
23 use crate::util::{exe, is_dylib, timeit};
24 use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
25 use time::{self, Timespec};
26
27 pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
28     format!("{}-{}", component, builder.rust_package_vers())
29 }
30
31 pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
32     builder.out.join("dist")
33 }
34
35 pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
36     builder.out.join("tmp/dist")
37 }
38
39 fn rust_installer(builder: &Builder<'_>) -> Command {
40     builder.tool_cmd(Tool::RustInstaller)
41 }
42
43 fn missing_tool(tool_name: &str, skip: bool) {
44     if skip {
45         println!("Unable to build {}, skipping dist", tool_name)
46     } else {
47         panic!("Unable to build {}", tool_name)
48     }
49 }
50
51 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
52 pub struct Docs {
53     pub host: TargetSelection,
54 }
55
56 impl Step for Docs {
57     type Output = PathBuf;
58     const DEFAULT: bool = true;
59
60     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
61         run.path("src/doc")
62     }
63
64     fn make_run(run: RunConfig<'_>) {
65         run.builder.ensure(Docs { host: run.target });
66     }
67
68     /// Builds the `rust-docs` installer component.
69     fn run(self, builder: &Builder<'_>) -> PathBuf {
70         let host = self.host;
71
72         let name = pkgname(builder, "rust-docs");
73
74         if !builder.config.docs {
75             return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple));
76         }
77
78         builder.default_doc(None);
79
80         builder.info(&format!("Dist docs ({})", host));
81         let _time = timeit(builder);
82
83         let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
84         let _ = fs::remove_dir_all(&image);
85
86         let dst = image.join("share/doc/rust/html");
87         t!(fs::create_dir_all(&dst));
88         let src = builder.doc_out(host);
89         builder.cp_r(&src, &dst);
90         builder.install(&builder.src.join("src/doc/robots.txt"), &dst, 0o644);
91
92         let mut cmd = rust_installer(builder);
93         cmd.arg("generate")
94             .arg("--product-name=Rust-Documentation")
95             .arg("--rel-manifest-dir=rustlib")
96             .arg("--success-message=Rust-documentation-is-installed.")
97             .arg("--image-dir")
98             .arg(&image)
99             .arg("--work-dir")
100             .arg(&tmpdir(builder))
101             .arg("--output-dir")
102             .arg(&distdir(builder))
103             .arg(format!("--package-name={}-{}", name, host.triple))
104             .arg("--component-name=rust-docs")
105             .arg("--legacy-manifest-dirs=rustlib,cargo")
106             .arg("--bulk-dirs=share/doc/rust/html");
107         builder.run(&mut cmd);
108         builder.remove_dir(&image);
109
110         distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple))
111     }
112 }
113
114 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
115 pub struct RustcDocs {
116     pub host: TargetSelection,
117 }
118
119 impl Step for RustcDocs {
120     type Output = PathBuf;
121     const DEFAULT: bool = true;
122
123     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
124         run.path("src/librustc")
125     }
126
127     fn make_run(run: RunConfig<'_>) {
128         run.builder.ensure(RustcDocs { host: run.target });
129     }
130
131     /// Builds the `rustc-docs` installer component.
132     fn run(self, builder: &Builder<'_>) -> PathBuf {
133         let host = self.host;
134
135         let name = pkgname(builder, "rustc-docs");
136
137         if !builder.config.compiler_docs {
138             return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple));
139         }
140
141         builder.default_doc(None);
142
143         let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
144         let _ = fs::remove_dir_all(&image);
145
146         let dst = image.join("share/doc/rust/html/rustc");
147         t!(fs::create_dir_all(&dst));
148         let src = builder.compiler_doc_out(host);
149         builder.cp_r(&src, &dst);
150
151         let mut cmd = rust_installer(builder);
152         cmd.arg("generate")
153             .arg("--product-name=Rustc-Documentation")
154             .arg("--rel-manifest-dir=rustlib")
155             .arg("--success-message=Rustc-documentation-is-installed.")
156             .arg("--image-dir")
157             .arg(&image)
158             .arg("--work-dir")
159             .arg(&tmpdir(builder))
160             .arg("--output-dir")
161             .arg(&distdir(builder))
162             .arg(format!("--package-name={}-{}", name, host.triple))
163             .arg("--component-name=rustc-docs")
164             .arg("--legacy-manifest-dirs=rustlib,cargo")
165             .arg("--bulk-dirs=share/doc/rust/html/rustc");
166
167         builder.info(&format!("Dist compiler docs ({})", host));
168         let _time = timeit(builder);
169         builder.run(&mut cmd);
170         builder.remove_dir(&image);
171
172         distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple))
173     }
174 }
175
176 fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
177     let mut found = Vec::with_capacity(files.len());
178
179     for file in files {
180         let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
181
182         if let Some(file_path) = file_path {
183             found.push(file_path);
184         } else {
185             panic!("Could not find '{}' in {:?}", file, path);
186         }
187     }
188
189     found
190 }
191
192 fn make_win_dist(
193     rust_root: &Path,
194     plat_root: &Path,
195     target: TargetSelection,
196     builder: &Builder<'_>,
197 ) {
198     //Ask gcc where it keeps its stuff
199     let mut cmd = Command::new(builder.cc(target));
200     cmd.arg("-print-search-dirs");
201     let gcc_out = output(&mut cmd);
202
203     let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
204     let mut lib_path = Vec::new();
205
206     for line in gcc_out.lines() {
207         let idx = line.find(':').unwrap();
208         let key = &line[..idx];
209         let trim_chars: &[_] = &[' ', '='];
210         let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
211
212         if key == "programs" {
213             bin_path.extend(value);
214         } else if key == "libraries" {
215             lib_path.extend(value);
216         }
217     }
218
219     let compiler = if target == "i686-pc-windows-gnu" {
220         "i686-w64-mingw32-gcc.exe"
221     } else if target == "x86_64-pc-windows-gnu" {
222         "x86_64-w64-mingw32-gcc.exe"
223     } else {
224         "gcc.exe"
225     };
226     let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
227     let mut rustc_dlls = vec!["libwinpthread-1.dll"];
228     if target.starts_with("i686-") {
229         rustc_dlls.push("libgcc_s_dw2-1.dll");
230     } else {
231         rustc_dlls.push("libgcc_s_seh-1.dll");
232     }
233
234     let target_libs = [
235         //MinGW libs
236         "libgcc.a",
237         "libgcc_eh.a",
238         "libgcc_s.a",
239         "libm.a",
240         "libmingw32.a",
241         "libmingwex.a",
242         "libstdc++.a",
243         "libiconv.a",
244         "libmoldname.a",
245         "libpthread.a",
246         //Windows import libs
247         "libadvapi32.a",
248         "libbcrypt.a",
249         "libcomctl32.a",
250         "libcomdlg32.a",
251         "libcredui.a",
252         "libcrypt32.a",
253         "libdbghelp.a",
254         "libgdi32.a",
255         "libimagehlp.a",
256         "libiphlpapi.a",
257         "libkernel32.a",
258         "libmsimg32.a",
259         "libmsvcrt.a",
260         "libodbc32.a",
261         "libole32.a",
262         "liboleaut32.a",
263         "libopengl32.a",
264         "libpsapi.a",
265         "librpcrt4.a",
266         "libsecur32.a",
267         "libsetupapi.a",
268         "libshell32.a",
269         "libsynchronization.a",
270         "libuser32.a",
271         "libuserenv.a",
272         "libuuid.a",
273         "libwinhttp.a",
274         "libwinmm.a",
275         "libwinspool.a",
276         "libws2_32.a",
277         "libwsock32.a",
278     ];
279
280     //Find mingw artifacts we want to bundle
281     let target_tools = find_files(&target_tools, &bin_path);
282     let rustc_dlls = find_files(&rustc_dlls, &bin_path);
283     let target_libs = find_files(&target_libs, &lib_path);
284
285     // Copy runtime dlls next to rustc.exe
286     let dist_bin_dir = rust_root.join("bin/");
287     fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
288     for src in rustc_dlls {
289         builder.copy_to_folder(&src, &dist_bin_dir);
290     }
291
292     //Copy platform tools to platform-specific bin directory
293     let target_bin_dir = plat_root
294         .join("lib")
295         .join("rustlib")
296         .join(target.triple)
297         .join("bin")
298         .join("self-contained");
299     fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
300     for src in target_tools {
301         builder.copy_to_folder(&src, &target_bin_dir);
302     }
303
304     // Warn windows-gnu users that the bundled GCC cannot compile C files
305     builder.create(
306         &target_bin_dir.join("GCC-WARNING.txt"),
307         "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
308          used as a linker. In order to be able to compile projects containing C code use \
309          the GCC provided by MinGW or Cygwin.",
310     );
311
312     //Copy platform libs to platform-specific lib directory
313     let target_lib_dir = plat_root
314         .join("lib")
315         .join("rustlib")
316         .join(target.triple)
317         .join("lib")
318         .join("self-contained");
319     fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
320     for src in target_libs {
321         builder.copy_to_folder(&src, &target_lib_dir);
322     }
323 }
324
325 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
326 pub struct Mingw {
327     pub host: TargetSelection,
328 }
329
330 impl Step for Mingw {
331     type Output = Option<PathBuf>;
332     const DEFAULT: bool = true;
333
334     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
335         run.never()
336     }
337
338     fn make_run(run: RunConfig<'_>) {
339         run.builder.ensure(Mingw { host: run.target });
340     }
341
342     /// Builds the `rust-mingw` installer component.
343     ///
344     /// This contains all the bits and pieces to run the MinGW Windows targets
345     /// without any extra installed software (e.g., we bundle gcc, libraries, etc).
346     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
347         let host = self.host;
348
349         if !host.contains("pc-windows-gnu") {
350             return None;
351         }
352
353         builder.info(&format!("Dist mingw ({})", host));
354         let _time = timeit(builder);
355         let name = pkgname(builder, "rust-mingw");
356         let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
357         let _ = fs::remove_dir_all(&image);
358         t!(fs::create_dir_all(&image));
359
360         // The first argument is a "temporary directory" which is just
361         // thrown away (this contains the runtime DLLs included in the rustc package
362         // above) and the second argument is where to place all the MinGW components
363         // (which is what we want).
364         make_win_dist(&tmpdir(builder), &image, host, &builder);
365
366         let mut cmd = rust_installer(builder);
367         cmd.arg("generate")
368             .arg("--product-name=Rust-MinGW")
369             .arg("--rel-manifest-dir=rustlib")
370             .arg("--success-message=Rust-MinGW-is-installed.")
371             .arg("--image-dir")
372             .arg(&image)
373             .arg("--work-dir")
374             .arg(&tmpdir(builder))
375             .arg("--output-dir")
376             .arg(&distdir(builder))
377             .arg(format!("--package-name={}-{}", name, host.triple))
378             .arg("--component-name=rust-mingw")
379             .arg("--legacy-manifest-dirs=rustlib,cargo");
380         builder.run(&mut cmd);
381         t!(fs::remove_dir_all(&image));
382         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)))
383     }
384 }
385
386 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
387 pub struct Rustc {
388     pub compiler: Compiler,
389 }
390
391 impl Step for Rustc {
392     type Output = PathBuf;
393     const DEFAULT: bool = true;
394     const ONLY_HOSTS: bool = true;
395
396     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
397         run.path("src/librustc")
398     }
399
400     fn make_run(run: RunConfig<'_>) {
401         run.builder
402             .ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.target) });
403     }
404
405     /// Creates the `rustc` installer component.
406     fn run(self, builder: &Builder<'_>) -> PathBuf {
407         let compiler = self.compiler;
408         let host = self.compiler.host;
409
410         let name = pkgname(builder, "rustc");
411         let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
412         let _ = fs::remove_dir_all(&image);
413         let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host.triple));
414         let _ = fs::remove_dir_all(&overlay);
415
416         // Prepare the rustc "image", what will actually end up getting installed
417         prepare_image(builder, compiler, &image);
418
419         // Prepare the overlay which is part of the tarball but won't actually be
420         // installed
421         let cp = |file: &str| {
422             builder.install(&builder.src.join(file), &overlay, 0o644);
423         };
424         cp("COPYRIGHT");
425         cp("LICENSE-APACHE");
426         cp("LICENSE-MIT");
427         cp("README.md");
428         // tiny morsel of metadata is used by rust-packaging
429         let version = builder.rust_version();
430         builder.create(&overlay.join("version"), &version);
431         if let Some(sha) = builder.rust_sha() {
432             builder.create(&overlay.join("git-commit-hash"), &sha);
433         }
434
435         // On MinGW we've got a few runtime DLL dependencies that we need to
436         // include. The first argument to this script is where to put these DLLs
437         // (the image we're creating), and the second argument is a junk directory
438         // to ignore all other MinGW stuff the script creates.
439         //
440         // On 32-bit MinGW we're always including a DLL which needs some extra
441         // licenses to distribute. On 64-bit MinGW we don't actually distribute
442         // anything requiring us to distribute a license, but it's likely the
443         // install will *also* include the rust-mingw package, which also needs
444         // licenses, so to be safe we just include it here in all MinGW packages.
445         if host.contains("pc-windows-gnu") {
446             make_win_dist(&image, &tmpdir(builder), host, builder);
447
448             let dst = image.join("share/doc");
449             t!(fs::create_dir_all(&dst));
450             builder.cp_r(&builder.src.join("src/etc/third-party"), &dst);
451         }
452
453         // Finally, wrap everything up in a nice tarball!
454         let mut cmd = rust_installer(builder);
455         cmd.arg("generate")
456             .arg("--product-name=Rust")
457             .arg("--rel-manifest-dir=rustlib")
458             .arg("--success-message=Rust-is-ready-to-roll.")
459             .arg("--image-dir")
460             .arg(&image)
461             .arg("--work-dir")
462             .arg(&tmpdir(builder))
463             .arg("--output-dir")
464             .arg(&distdir(builder))
465             .arg("--non-installed-overlay")
466             .arg(&overlay)
467             .arg(format!("--package-name={}-{}", name, host.triple))
468             .arg("--component-name=rustc")
469             .arg("--legacy-manifest-dirs=rustlib,cargo");
470
471         builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host.triple));
472         let _time = timeit(builder);
473         builder.run(&mut cmd);
474         builder.remove_dir(&image);
475         builder.remove_dir(&overlay);
476
477         return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple));
478
479         fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
480             let host = compiler.host;
481             let src = builder.sysroot(compiler);
482
483             // Copy rustc/rustdoc binaries
484             t!(fs::create_dir_all(image.join("bin")));
485             builder.cp_r(&src.join("bin"), &image.join("bin"));
486
487             builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
488
489             let libdir_relative = builder.libdir_relative(compiler);
490
491             // Copy runtime DLLs needed by the compiler
492             if libdir_relative.to_str() != Some("bin") {
493                 let libdir = builder.rustc_libdir(compiler);
494                 for entry in builder.read_dir(&libdir) {
495                     let name = entry.file_name();
496                     if let Some(s) = name.to_str() {
497                         if is_dylib(s) {
498                             // Don't use custom libdir here because ^lib/ will be resolved again
499                             // with installer
500                             builder.install(&entry.path(), &image.join("lib"), 0o644);
501                         }
502                     }
503                 }
504             }
505
506             // Copy over the codegen backends
507             let backends_src = builder.sysroot_codegen_backends(compiler);
508             let backends_rel = backends_src
509                 .strip_prefix(&src)
510                 .unwrap()
511                 .strip_prefix(builder.sysroot_libdir_relative(compiler))
512                 .unwrap();
513             // Don't use custom libdir here because ^lib/ will be resolved again with installer
514             let backends_dst = image.join("lib").join(&backends_rel);
515
516             t!(fs::create_dir_all(&backends_dst));
517             builder.cp_r(&backends_src, &backends_dst);
518
519             // Copy libLLVM.so to the lib dir as well, if needed. While not
520             // technically needed by rustc itself it's needed by lots of other
521             // components like the llvm tools and LLD. LLD is included below and
522             // tools/LLDB come later, so let's just throw it in the rustc
523             // component for now.
524             maybe_install_llvm_runtime(builder, host, image);
525
526             let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
527             let dst_dir = image.join("lib/rustlib").join(&*host.triple).join("bin");
528             t!(fs::create_dir_all(&dst_dir));
529
530             // Copy over lld if it's there
531             if builder.config.lld_enabled {
532                 let exe = exe("rust-lld", compiler.host);
533                 builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
534             }
535
536             // Copy over llvm-dwp if it's there
537             let exe = exe("rust-llvm-dwp", compiler.host);
538             builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
539
540             // Man pages
541             t!(fs::create_dir_all(image.join("share/man/man1")));
542             let man_src = builder.src.join("src/doc/man");
543             let man_dst = image.join("share/man/man1");
544
545             // Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time.
546             let time = env::var("SOURCE_DATE_EPOCH")
547                 .map(|timestamp| {
548                     let epoch = timestamp
549                         .parse()
550                         .map_err(|err| format!("could not parse SOURCE_DATE_EPOCH: {}", err))
551                         .unwrap();
552
553                     time::at(Timespec::new(epoch, 0))
554                 })
555                 .unwrap_or_else(|_| time::now());
556
557             let month_year = t!(time::strftime("%B %Y", &time));
558             // don't use our `bootstrap::util::{copy, cp_r}`, because those try
559             // to hardlink, and we don't want to edit the source templates
560             for file_entry in builder.read_dir(&man_src) {
561                 let page_src = file_entry.path();
562                 let page_dst = man_dst.join(file_entry.file_name());
563                 t!(fs::copy(&page_src, &page_dst));
564                 // template in month/year and version number
565                 builder.replace_in_file(
566                     &page_dst,
567                     &[
568                         ("<INSERT DATE HERE>", &month_year),
569                         ("<INSERT VERSION HERE>", &builder.version),
570                     ],
571                 );
572             }
573
574             // Debugger scripts
575             builder
576                 .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host });
577
578             // Misc license info
579             let cp = |file: &str| {
580                 builder.install(&builder.src.join(file), &image.join("share/doc/rust"), 0o644);
581             };
582             cp("COPYRIGHT");
583             cp("LICENSE-APACHE");
584             cp("LICENSE-MIT");
585             cp("README.md");
586         }
587     }
588 }
589
590 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
591 pub struct DebuggerScripts {
592     pub sysroot: Interned<PathBuf>,
593     pub host: TargetSelection,
594 }
595
596 impl Step for DebuggerScripts {
597     type Output = ();
598
599     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
600         run.path("src/lldb_batchmode.py")
601     }
602
603     fn make_run(run: RunConfig<'_>) {
604         run.builder.ensure(DebuggerScripts {
605             sysroot: run
606                 .builder
607                 .sysroot(run.builder.compiler(run.builder.top_stage, run.build_triple())),
608             host: run.target,
609         });
610     }
611
612     /// Copies debugger scripts for `target` into the `sysroot` specified.
613     fn run(self, builder: &Builder<'_>) {
614         let host = self.host;
615         let sysroot = self.sysroot;
616         let dst = sysroot.join("lib/rustlib/etc");
617         t!(fs::create_dir_all(&dst));
618         let cp_debugger_script = |file: &str| {
619             builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
620         };
621         if host.contains("windows-msvc") {
622             // windbg debugger scripts
623             builder.install(
624                 &builder.src.join("src/etc/rust-windbg.cmd"),
625                 &sysroot.join("bin"),
626                 0o755,
627             );
628
629             cp_debugger_script("natvis/intrinsic.natvis");
630             cp_debugger_script("natvis/liballoc.natvis");
631             cp_debugger_script("natvis/libcore.natvis");
632             cp_debugger_script("natvis/libstd.natvis");
633         } else {
634             cp_debugger_script("rust_types.py");
635
636             // gdb debugger scripts
637             builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
638             builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
639
640             cp_debugger_script("gdb_load_rust_pretty_printers.py");
641             cp_debugger_script("gdb_lookup.py");
642             cp_debugger_script("gdb_providers.py");
643
644             // lldb debugger scripts
645             builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
646
647             cp_debugger_script("lldb_lookup.py");
648             cp_debugger_script("lldb_providers.py");
649             cp_debugger_script("lldb_commands")
650         }
651     }
652 }
653
654 fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
655     // The only true set of target libraries came from the build triple, so
656     // let's reduce redundant work by only producing archives from that host.
657     if compiler.host != builder.config.build {
658         builder.info("\tskipping, not a build host");
659         true
660     } else {
661         false
662     }
663 }
664
665 /// Copy stamped files into an image's `target/lib` directory.
666 fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
667     let dst = image.join("lib/rustlib").join(target.triple).join("lib");
668     let self_contained_dst = dst.join("self-contained");
669     t!(fs::create_dir_all(&dst));
670     t!(fs::create_dir_all(&self_contained_dst));
671     for (path, dependency_type) in builder.read_stamp_file(stamp) {
672         if dependency_type == DependencyType::TargetSelfContained {
673             builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
674         } else if dependency_type == DependencyType::Target || builder.config.build == target {
675             builder.copy(&path, &dst.join(path.file_name().unwrap()));
676         }
677     }
678 }
679
680 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
681 pub struct Std {
682     pub compiler: Compiler,
683     pub target: TargetSelection,
684 }
685
686 impl Step for Std {
687     type Output = PathBuf;
688     const DEFAULT: bool = true;
689
690     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
691         run.path("library/std")
692     }
693
694     fn make_run(run: RunConfig<'_>) {
695         run.builder.ensure(Std {
696             compiler: run.builder.compiler_for(
697                 run.builder.top_stage,
698                 run.builder.config.build,
699                 run.target,
700             ),
701             target: run.target,
702         });
703     }
704
705     fn run(self, builder: &Builder<'_>) -> PathBuf {
706         let compiler = self.compiler;
707         let target = self.target;
708
709         let name = pkgname(builder, "rust-std");
710         let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
711         if skip_host_target_lib(builder, compiler) {
712             return archive;
713         }
714
715         builder.ensure(compile::Std { compiler, target });
716
717         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
718         let _ = fs::remove_dir_all(&image);
719
720         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
721         let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
722         copy_target_libs(builder, target, &image, &stamp);
723
724         let mut cmd = rust_installer(builder);
725         cmd.arg("generate")
726             .arg("--product-name=Rust")
727             .arg("--rel-manifest-dir=rustlib")
728             .arg("--success-message=std-is-standing-at-the-ready.")
729             .arg("--image-dir")
730             .arg(&image)
731             .arg("--work-dir")
732             .arg(&tmpdir(builder))
733             .arg("--output-dir")
734             .arg(&distdir(builder))
735             .arg(format!("--package-name={}-{}", name, target.triple))
736             .arg(format!("--component-name=rust-std-{}", target.triple))
737             .arg("--legacy-manifest-dirs=rustlib,cargo");
738
739         builder
740             .info(&format!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target));
741         let _time = timeit(builder);
742         builder.run(&mut cmd);
743         builder.remove_dir(&image);
744         archive
745     }
746 }
747
748 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
749 pub struct RustcDev {
750     pub compiler: Compiler,
751     pub target: TargetSelection,
752 }
753
754 impl Step for RustcDev {
755     type Output = PathBuf;
756     const DEFAULT: bool = true;
757     const ONLY_HOSTS: bool = true;
758
759     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
760         run.path("rustc-dev")
761     }
762
763     fn make_run(run: RunConfig<'_>) {
764         run.builder.ensure(RustcDev {
765             compiler: run.builder.compiler_for(
766                 run.builder.top_stage,
767                 run.builder.config.build,
768                 run.target,
769             ),
770             target: run.target,
771         });
772     }
773
774     fn run(self, builder: &Builder<'_>) -> PathBuf {
775         let compiler = self.compiler;
776         let target = self.target;
777
778         let name = pkgname(builder, "rustc-dev");
779         let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
780         if skip_host_target_lib(builder, compiler) {
781             return archive;
782         }
783
784         builder.ensure(compile::Rustc { compiler, target });
785
786         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
787         let _ = fs::remove_dir_all(&image);
788
789         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
790         let stamp = compile::librustc_stamp(builder, compiler_to_use, target);
791         copy_target_libs(builder, target, &image, &stamp);
792
793         // Copy compiler sources.
794         let dst_src = image.join("lib/rustlib/rustc-src/rust");
795         t!(fs::create_dir_all(&dst_src));
796
797         let src_files = ["Cargo.lock"];
798         // This is the reduced set of paths which will become the rustc-dev component
799         // (essentially the compiler crates and all of their path dependencies).
800         copy_src_dirs(builder, &builder.src, &["compiler"], &[], &dst_src);
801         for file in src_files.iter() {
802             builder.copy(&builder.src.join(file), &dst_src.join(file));
803         }
804
805         let mut cmd = rust_installer(builder);
806         cmd.arg("generate")
807             .arg("--product-name=Rust")
808             .arg("--rel-manifest-dir=rustlib")
809             .arg("--success-message=Rust-is-ready-to-develop.")
810             .arg("--image-dir")
811             .arg(&image)
812             .arg("--work-dir")
813             .arg(&tmpdir(builder))
814             .arg("--output-dir")
815             .arg(&distdir(builder))
816             .arg(format!("--package-name={}-{}", name, target.triple))
817             .arg(format!("--component-name=rustc-dev-{}", target.triple))
818             .arg("--legacy-manifest-dirs=rustlib,cargo");
819
820         builder.info(&format!(
821             "Dist rustc-dev stage{} ({} -> {})",
822             compiler.stage, &compiler.host, target
823         ));
824         let _time = timeit(builder);
825         builder.run(&mut cmd);
826         builder.remove_dir(&image);
827         archive
828     }
829 }
830
831 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
832 pub struct Analysis {
833     pub compiler: Compiler,
834     pub target: TargetSelection,
835 }
836
837 impl Step for Analysis {
838     type Output = PathBuf;
839     const DEFAULT: bool = true;
840
841     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
842         let builder = run.builder;
843         run.path("analysis").default_condition(builder.config.extended)
844     }
845
846     fn make_run(run: RunConfig<'_>) {
847         run.builder.ensure(Analysis {
848             // Find the actual compiler (handling the full bootstrap option) which
849             // produced the save-analysis data because that data isn't copied
850             // through the sysroot uplifting.
851             compiler: run.builder.compiler_for(
852                 run.builder.top_stage,
853                 run.builder.config.build,
854                 run.target,
855             ),
856             target: run.target,
857         });
858     }
859
860     /// Creates a tarball of save-analysis metadata, if available.
861     fn run(self, builder: &Builder<'_>) -> PathBuf {
862         let compiler = self.compiler;
863         let target = self.target;
864         assert!(builder.config.extended);
865         let name = pkgname(builder, "rust-analysis");
866
867         if compiler.host != builder.config.build {
868             return distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
869         }
870
871         builder.ensure(compile::Std { compiler, target });
872
873         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
874
875         let src = builder
876             .stage_out(compiler, Mode::Std)
877             .join(target.triple)
878             .join(builder.cargo_dir())
879             .join("deps");
880
881         let image_src = src.join("save-analysis");
882         let dst = image.join("lib/rustlib").join(target.triple).join("analysis");
883         t!(fs::create_dir_all(&dst));
884         builder.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst));
885         builder.cp_r(&image_src, &dst);
886
887         let mut cmd = rust_installer(builder);
888         cmd.arg("generate")
889             .arg("--product-name=Rust")
890             .arg("--rel-manifest-dir=rustlib")
891             .arg("--success-message=save-analysis-saved.")
892             .arg("--image-dir")
893             .arg(&image)
894             .arg("--work-dir")
895             .arg(&tmpdir(builder))
896             .arg("--output-dir")
897             .arg(&distdir(builder))
898             .arg(format!("--package-name={}-{}", name, target.triple))
899             .arg(format!("--component-name=rust-analysis-{}", target.triple))
900             .arg("--legacy-manifest-dirs=rustlib,cargo");
901
902         builder.info("Dist analysis");
903         let _time = timeit(builder);
904         builder.run(&mut cmd);
905         builder.remove_dir(&image);
906         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
907     }
908 }
909
910 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
911 /// `dst_dir`.
912 fn copy_src_dirs(
913     builder: &Builder<'_>,
914     base: &Path,
915     src_dirs: &[&str],
916     exclude_dirs: &[&str],
917     dst_dir: &Path,
918 ) {
919     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
920         let spath = match path.to_str() {
921             Some(path) => path,
922             None => return false,
923         };
924         if spath.ends_with('~') || spath.ends_with(".pyc") {
925             return false;
926         }
927
928         const LLVM_PROJECTS: &[&str] = &[
929             "llvm-project/clang",
930             "llvm-project\\clang",
931             "llvm-project/libunwind",
932             "llvm-project\\libunwind",
933             "llvm-project/lld",
934             "llvm-project\\lld",
935             "llvm-project/lldb",
936             "llvm-project\\lldb",
937             "llvm-project/llvm",
938             "llvm-project\\llvm",
939             "llvm-project/compiler-rt",
940             "llvm-project\\compiler-rt",
941         ];
942         if spath.contains("llvm-project")
943             && !spath.ends_with("llvm-project")
944             && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
945         {
946             return false;
947         }
948
949         const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
950         if LLVM_TEST.iter().any(|path| spath.contains(path))
951             && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
952         {
953             return false;
954         }
955
956         let full_path = Path::new(dir).join(path);
957         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
958             return false;
959         }
960
961         let excludes = [
962             "CVS",
963             "RCS",
964             "SCCS",
965             ".git",
966             ".gitignore",
967             ".gitmodules",
968             ".gitattributes",
969             ".cvsignore",
970             ".svn",
971             ".arch-ids",
972             "{arch}",
973             "=RELEASE-ID",
974             "=meta-update",
975             "=update",
976             ".bzr",
977             ".bzrignore",
978             ".bzrtags",
979             ".hg",
980             ".hgignore",
981             ".hgrags",
982             "_darcs",
983         ];
984         !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
985     }
986
987     // Copy the directories using our filter
988     for item in src_dirs {
989         let dst = &dst_dir.join(item);
990         t!(fs::create_dir_all(dst));
991         builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
992     }
993 }
994
995 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
996 pub struct Src;
997
998 impl Step for Src {
999     /// The output path of the src installer tarball
1000     type Output = PathBuf;
1001     const DEFAULT: bool = true;
1002     const ONLY_HOSTS: bool = true;
1003
1004     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1005         run.path("src")
1006     }
1007
1008     fn make_run(run: RunConfig<'_>) {
1009         run.builder.ensure(Src);
1010     }
1011
1012     /// Creates the `rust-src` installer component
1013     fn run(self, builder: &Builder<'_>) -> PathBuf {
1014         let name = pkgname(builder, "rust-src");
1015         let image = tmpdir(builder).join(format!("{}-image", name));
1016         let _ = fs::remove_dir_all(&image);
1017
1018         // A lot of tools expect the rust-src component to be entirely in this directory, so if you
1019         // change that (e.g. by adding another directory `lib/rustlib/src/foo` or
1020         // `lib/rustlib/src/rust/foo`), you will need to go around hunting for implicit assumptions
1021         // and fix them...
1022         //
1023         // NOTE: if you update the paths here, you also should update the "virtual" path
1024         // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
1025         let dst_src = image.join("lib/rustlib/src/rust");
1026         t!(fs::create_dir_all(&dst_src));
1027
1028         let src_files = ["Cargo.lock"];
1029         // This is the reduced set of paths which will become the rust-src component
1030         // (essentially libstd and all of its path dependencies).
1031         copy_src_dirs(
1032             builder,
1033             &builder.src,
1034             &["library", "src/llvm-project/libunwind"],
1035             &[
1036                 // not needed and contains symlinks which rustup currently
1037                 // chokes on when unpacking.
1038                 "library/backtrace/crates",
1039             ],
1040             &dst_src,
1041         );
1042         for file in src_files.iter() {
1043             builder.copy(&builder.src.join(file), &dst_src.join(file));
1044         }
1045
1046         // libtest includes std and everything else, so vendoring it
1047         // creates exactly what's needed for `cargo -Zbuild-std` or any
1048         // other analysis of the stdlib's source. Cargo also needs help
1049         // finding the lock, so we copy it to libtest temporarily.
1050         //
1051         // Note that this requires std to only have one version of each
1052         // crate. e.g. two versions of getopts won't be patchable.
1053         let dst_libtest = dst_src.join("library/test");
1054         let dst_vendor = dst_src.join("vendor");
1055         let root_lock = dst_src.join("Cargo.lock");
1056         let temp_lock = dst_libtest.join("Cargo.lock");
1057
1058         // `cargo vendor` will delete everything from the lockfile that
1059         // isn't used by libtest, so we need to not use any links!
1060         builder.really_copy(&root_lock, &temp_lock);
1061
1062         let mut cmd = Command::new(&builder.initial_cargo);
1063         cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libtest);
1064         builder.info("Dist src");
1065         let _time = timeit(builder);
1066         builder.run(&mut cmd);
1067
1068         builder.remove(&temp_lock);
1069
1070         // Create source tarball in rust-installer format
1071         let mut cmd = rust_installer(builder);
1072         cmd.arg("generate")
1073             .arg("--product-name=Rust")
1074             .arg("--rel-manifest-dir=rustlib")
1075             .arg("--success-message=Awesome-Source.")
1076             .arg("--image-dir")
1077             .arg(&image)
1078             .arg("--work-dir")
1079             .arg(&tmpdir(builder))
1080             .arg("--output-dir")
1081             .arg(&distdir(builder))
1082             .arg(format!("--package-name={}", name))
1083             .arg("--component-name=rust-src")
1084             .arg("--legacy-manifest-dirs=rustlib,cargo");
1085
1086         builder.run(&mut cmd);
1087
1088         builder.remove_dir(&image);
1089         distdir(builder).join(&format!("{}.tar.gz", name))
1090     }
1091 }
1092
1093 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1094 pub struct PlainSourceTarball;
1095
1096 impl Step for PlainSourceTarball {
1097     /// Produces the location of the tarball generated
1098     type Output = PathBuf;
1099     const DEFAULT: bool = true;
1100     const ONLY_HOSTS: bool = true;
1101
1102     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1103         let builder = run.builder;
1104         run.path("src").default_condition(builder.config.rust_dist_src)
1105     }
1106
1107     fn make_run(run: RunConfig<'_>) {
1108         run.builder.ensure(PlainSourceTarball);
1109     }
1110
1111     /// Creates the plain source tarball
1112     fn run(self, builder: &Builder<'_>) -> PathBuf {
1113         // Make sure that the root folder of tarball has the correct name
1114         let plain_name = format!("{}-src", pkgname(builder, "rustc"));
1115         let plain_dst_src = tmpdir(builder).join(&plain_name);
1116         let _ = fs::remove_dir_all(&plain_dst_src);
1117         t!(fs::create_dir_all(&plain_dst_src));
1118
1119         // This is the set of root paths which will become part of the source package
1120         let src_files = [
1121             "COPYRIGHT",
1122             "LICENSE-APACHE",
1123             "LICENSE-MIT",
1124             "CONTRIBUTING.md",
1125             "README.md",
1126             "RELEASES.md",
1127             "configure",
1128             "x.py",
1129             "config.toml.example",
1130             "Cargo.toml",
1131             "Cargo.lock",
1132         ];
1133         let src_dirs = ["src", "compiler", "library"];
1134
1135         copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
1136
1137         // Copy the files normally
1138         for item in &src_files {
1139             builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
1140         }
1141
1142         // Create the version file
1143         builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1144         if let Some(sha) = builder.rust_sha() {
1145             builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
1146         }
1147
1148         // If we're building from git sources, we need to vendor a complete distribution.
1149         if builder.rust_info.is_git() {
1150             // Vendor all Cargo dependencies
1151             let mut cmd = Command::new(&builder.initial_cargo);
1152             cmd.arg("vendor")
1153                 .arg("--sync")
1154                 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
1155                 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
1156                 .current_dir(&plain_dst_src);
1157             builder.run(&mut cmd);
1158         }
1159
1160         // Create plain source tarball
1161         let plain_name = format!("rustc-{}-src", builder.rust_package_vers());
1162         let mut tarball = distdir(builder).join(&format!("{}.tar.gz", plain_name));
1163         tarball.set_extension(""); // strip .gz
1164         tarball.set_extension(""); // strip .tar
1165         if let Some(dir) = tarball.parent() {
1166             builder.create_dir(&dir);
1167         }
1168         builder.info("running installer");
1169         let mut cmd = rust_installer(builder);
1170         cmd.arg("tarball")
1171             .arg("--input")
1172             .arg(&plain_name)
1173             .arg("--output")
1174             .arg(&tarball)
1175             .arg("--work-dir=.")
1176             .current_dir(tmpdir(builder));
1177
1178         builder.info("Create plain source tarball");
1179         let _time = timeit(builder);
1180         builder.run(&mut cmd);
1181         distdir(builder).join(&format!("{}.tar.gz", plain_name))
1182     }
1183 }
1184
1185 // We have to run a few shell scripts, which choke quite a bit on both `\`
1186 // characters and on `C:\` paths, so normalize both of them away.
1187 pub fn sanitize_sh(path: &Path) -> String {
1188     let path = path.to_str().unwrap().replace("\\", "/");
1189     return change_drive(unc_to_lfs(&path)).unwrap_or(path);
1190
1191     fn unc_to_lfs(s: &str) -> &str {
1192         s.strip_prefix("//?/").unwrap_or(s)
1193     }
1194
1195     fn change_drive(s: &str) -> Option<String> {
1196         let mut ch = s.chars();
1197         let drive = ch.next().unwrap_or('C');
1198         if ch.next() != Some(':') {
1199             return None;
1200         }
1201         if ch.next() != Some('/') {
1202             return None;
1203         }
1204         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
1205     }
1206 }
1207
1208 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1209 pub struct Cargo {
1210     pub compiler: Compiler,
1211     pub target: TargetSelection,
1212 }
1213
1214 impl Step for Cargo {
1215     type Output = PathBuf;
1216     const ONLY_HOSTS: bool = true;
1217
1218     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1219         run.path("cargo")
1220     }
1221
1222     fn make_run(run: RunConfig<'_>) {
1223         run.builder.ensure(Cargo {
1224             compiler: run.builder.compiler_for(
1225                 run.builder.top_stage,
1226                 run.builder.config.build,
1227                 run.target,
1228             ),
1229             target: run.target,
1230         });
1231     }
1232
1233     fn run(self, builder: &Builder<'_>) -> PathBuf {
1234         let compiler = self.compiler;
1235         let target = self.target;
1236
1237         let src = builder.src.join("src/tools/cargo");
1238         let etc = src.join("src/etc");
1239         let release_num = builder.release_num("cargo");
1240         let name = pkgname(builder, "cargo");
1241         let version = builder.cargo_info.version(builder, &release_num);
1242
1243         let tmp = tmpdir(builder);
1244         let image = tmp.join("cargo-image");
1245         drop(fs::remove_dir_all(&image));
1246         builder.create_dir(&image);
1247
1248         // Prepare the image directory
1249         builder.create_dir(&image.join("share/zsh/site-functions"));
1250         builder.create_dir(&image.join("etc/bash_completion.d"));
1251         let cargo = builder.ensure(tool::Cargo { compiler, target });
1252         builder.install(&cargo, &image.join("bin"), 0o755);
1253         for man in t!(etc.join("man").read_dir()) {
1254             let man = t!(man);
1255             builder.install(&man.path(), &image.join("share/man/man1"), 0o644);
1256         }
1257         builder.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
1258         builder.copy(&etc.join("cargo.bashcomp.sh"), &image.join("etc/bash_completion.d/cargo"));
1259         let doc = image.join("share/doc/cargo");
1260         builder.install(&src.join("README.md"), &doc, 0o644);
1261         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1262         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1263         builder.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
1264
1265         // Prepare the overlay
1266         let overlay = tmp.join("cargo-overlay");
1267         drop(fs::remove_dir_all(&overlay));
1268         builder.create_dir(&overlay);
1269         builder.install(&src.join("README.md"), &overlay, 0o644);
1270         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1271         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1272         builder.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
1273         builder.create(&overlay.join("version"), &version);
1274
1275         // Generate the installer tarball
1276         let mut cmd = rust_installer(builder);
1277         cmd.arg("generate")
1278             .arg("--product-name=Rust")
1279             .arg("--rel-manifest-dir=rustlib")
1280             .arg("--success-message=Rust-is-ready-to-roll.")
1281             .arg("--image-dir")
1282             .arg(&image)
1283             .arg("--work-dir")
1284             .arg(&tmpdir(builder))
1285             .arg("--output-dir")
1286             .arg(&distdir(builder))
1287             .arg("--non-installed-overlay")
1288             .arg(&overlay)
1289             .arg(format!("--package-name={}-{}", name, target.triple))
1290             .arg("--component-name=cargo")
1291             .arg("--legacy-manifest-dirs=rustlib,cargo");
1292
1293         builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target));
1294         let _time = timeit(builder);
1295         builder.run(&mut cmd);
1296         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1297     }
1298 }
1299
1300 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1301 pub struct Rls {
1302     pub compiler: Compiler,
1303     pub target: TargetSelection,
1304 }
1305
1306 impl Step for Rls {
1307     type Output = Option<PathBuf>;
1308     const ONLY_HOSTS: bool = true;
1309
1310     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1311         run.path("rls")
1312     }
1313
1314     fn make_run(run: RunConfig<'_>) {
1315         run.builder.ensure(Rls {
1316             compiler: run.builder.compiler_for(
1317                 run.builder.top_stage,
1318                 run.builder.config.build,
1319                 run.target,
1320             ),
1321             target: run.target,
1322         });
1323     }
1324
1325     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1326         let compiler = self.compiler;
1327         let target = self.target;
1328         assert!(builder.config.extended);
1329
1330         let src = builder.src.join("src/tools/rls");
1331         let release_num = builder.release_num("rls");
1332         let name = pkgname(builder, "rls");
1333         let version = builder.rls_info.version(builder, &release_num);
1334
1335         let tmp = tmpdir(builder);
1336         let image = tmp.join("rls-image");
1337         drop(fs::remove_dir_all(&image));
1338         t!(fs::create_dir_all(&image));
1339
1340         // Prepare the image directory
1341         // We expect RLS to build, because we've exited this step above if tool
1342         // state for RLS isn't testing.
1343         let rls = builder
1344             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1345             .or_else(|| {
1346                 missing_tool("RLS", builder.build.config.missing_tools);
1347                 None
1348             })?;
1349
1350         builder.install(&rls, &image.join("bin"), 0o755);
1351         let doc = image.join("share/doc/rls");
1352         builder.install(&src.join("README.md"), &doc, 0o644);
1353         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1354         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1355
1356         // Prepare the overlay
1357         let overlay = tmp.join("rls-overlay");
1358         drop(fs::remove_dir_all(&overlay));
1359         t!(fs::create_dir_all(&overlay));
1360         builder.install(&src.join("README.md"), &overlay, 0o644);
1361         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1362         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1363         builder.create(&overlay.join("version"), &version);
1364
1365         // Generate the installer tarball
1366         let mut cmd = rust_installer(builder);
1367         cmd.arg("generate")
1368             .arg("--product-name=Rust")
1369             .arg("--rel-manifest-dir=rustlib")
1370             .arg("--success-message=RLS-ready-to-serve.")
1371             .arg("--image-dir")
1372             .arg(&image)
1373             .arg("--work-dir")
1374             .arg(&tmpdir(builder))
1375             .arg("--output-dir")
1376             .arg(&distdir(builder))
1377             .arg("--non-installed-overlay")
1378             .arg(&overlay)
1379             .arg(format!("--package-name={}-{}", name, target.triple))
1380             .arg("--legacy-manifest-dirs=rustlib,cargo")
1381             .arg("--component-name=rls-preview");
1382
1383         builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target.triple));
1384         let _time = timeit(builder);
1385         builder.run(&mut cmd);
1386         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1387     }
1388 }
1389
1390 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1391 pub struct RustAnalyzer {
1392     pub compiler: Compiler,
1393     pub target: TargetSelection,
1394 }
1395
1396 impl Step for RustAnalyzer {
1397     type Output = Option<PathBuf>;
1398     const ONLY_HOSTS: bool = true;
1399
1400     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1401         run.path("rust-analyzer")
1402     }
1403
1404     fn make_run(run: RunConfig<'_>) {
1405         run.builder.ensure(RustAnalyzer {
1406             compiler: run.builder.compiler_for(
1407                 run.builder.top_stage,
1408                 run.builder.config.build,
1409                 run.target,
1410             ),
1411             target: run.target,
1412         });
1413     }
1414
1415     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1416         let compiler = self.compiler;
1417         let target = self.target;
1418         assert!(builder.config.extended);
1419
1420         if target.contains("riscv64") {
1421             // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1422             // to build. See #74813 for details.
1423             return None;
1424         }
1425
1426         let src = builder.src.join("src/tools/rust-analyzer");
1427         let release_num = builder.release_num("rust-analyzer/crates/rust-analyzer");
1428         let name = pkgname(builder, "rust-analyzer");
1429         let version = builder.rust_analyzer_info.version(builder, &release_num);
1430
1431         let tmp = tmpdir(builder);
1432         let image = tmp.join("rust-analyzer-image");
1433         drop(fs::remove_dir_all(&image));
1434         builder.create_dir(&image);
1435
1436         // Prepare the image directory
1437         // We expect rust-analyer to always build, as it doesn't depend on rustc internals
1438         // and doesn't have associated toolstate.
1439         let rust_analyzer = builder
1440             .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1441             .expect("rust-analyzer always builds");
1442
1443         builder.install(&rust_analyzer, &image.join("bin"), 0o755);
1444         let doc = image.join("share/doc/rust-analyzer");
1445         builder.install(&src.join("README.md"), &doc, 0o644);
1446         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1447         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1448
1449         // Prepare the overlay
1450         let overlay = tmp.join("rust-analyzer-overlay");
1451         drop(fs::remove_dir_all(&overlay));
1452         t!(fs::create_dir_all(&overlay));
1453         builder.install(&src.join("README.md"), &overlay, 0o644);
1454         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1455         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1456         builder.create(&overlay.join("version"), &version);
1457
1458         // Generate the installer tarball
1459         let mut cmd = rust_installer(builder);
1460         cmd.arg("generate")
1461             .arg("--product-name=Rust")
1462             .arg("--rel-manifest-dir=rustlib")
1463             .arg("--success-message=rust-analyzer-ready-to-serve.")
1464             .arg("--image-dir")
1465             .arg(&image)
1466             .arg("--work-dir")
1467             .arg(&tmpdir(builder))
1468             .arg("--output-dir")
1469             .arg(&distdir(builder))
1470             .arg("--non-installed-overlay")
1471             .arg(&overlay)
1472             .arg(format!("--package-name={}-{}", name, target.triple))
1473             .arg("--legacy-manifest-dirs=rustlib,cargo")
1474             .arg("--component-name=rust-analyzer-preview");
1475
1476         builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target));
1477         let _time = timeit(builder);
1478         builder.run(&mut cmd);
1479         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1480     }
1481 }
1482
1483 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1484 pub struct Clippy {
1485     pub compiler: Compiler,
1486     pub target: TargetSelection,
1487 }
1488
1489 impl Step for Clippy {
1490     type Output = PathBuf;
1491     const ONLY_HOSTS: bool = true;
1492
1493     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1494         run.path("clippy")
1495     }
1496
1497     fn make_run(run: RunConfig<'_>) {
1498         run.builder.ensure(Clippy {
1499             compiler: run.builder.compiler_for(
1500                 run.builder.top_stage,
1501                 run.builder.config.build,
1502                 run.target,
1503             ),
1504             target: run.target,
1505         });
1506     }
1507
1508     fn run(self, builder: &Builder<'_>) -> PathBuf {
1509         let compiler = self.compiler;
1510         let target = self.target;
1511         assert!(builder.config.extended);
1512
1513         let src = builder.src.join("src/tools/clippy");
1514         let release_num = builder.release_num("clippy");
1515         let name = pkgname(builder, "clippy");
1516         let version = builder.clippy_info.version(builder, &release_num);
1517
1518         let tmp = tmpdir(builder);
1519         let image = tmp.join("clippy-image");
1520         drop(fs::remove_dir_all(&image));
1521         builder.create_dir(&image);
1522
1523         // Prepare the image directory
1524         // We expect clippy to build, because we've exited this step above if tool
1525         // state for clippy isn't testing.
1526         let clippy = builder
1527             .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1528             .expect("clippy expected to build - essential tool");
1529         let cargoclippy = builder
1530             .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1531             .expect("clippy expected to build - essential tool");
1532
1533         builder.install(&clippy, &image.join("bin"), 0o755);
1534         builder.install(&cargoclippy, &image.join("bin"), 0o755);
1535         let doc = image.join("share/doc/clippy");
1536         builder.install(&src.join("README.md"), &doc, 0o644);
1537         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1538         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1539
1540         // Prepare the overlay
1541         let overlay = tmp.join("clippy-overlay");
1542         drop(fs::remove_dir_all(&overlay));
1543         t!(fs::create_dir_all(&overlay));
1544         builder.install(&src.join("README.md"), &overlay, 0o644);
1545         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1546         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1547         builder.create(&overlay.join("version"), &version);
1548
1549         // Generate the installer tarball
1550         let mut cmd = rust_installer(builder);
1551         cmd.arg("generate")
1552             .arg("--product-name=Rust")
1553             .arg("--rel-manifest-dir=rustlib")
1554             .arg("--success-message=clippy-ready-to-serve.")
1555             .arg("--image-dir")
1556             .arg(&image)
1557             .arg("--work-dir")
1558             .arg(&tmpdir(builder))
1559             .arg("--output-dir")
1560             .arg(&distdir(builder))
1561             .arg("--non-installed-overlay")
1562             .arg(&overlay)
1563             .arg(format!("--package-name={}-{}", name, target.triple))
1564             .arg("--legacy-manifest-dirs=rustlib,cargo")
1565             .arg("--component-name=clippy-preview");
1566
1567         builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target));
1568         let _time = timeit(builder);
1569         builder.run(&mut cmd);
1570         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1571     }
1572 }
1573
1574 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1575 pub struct Miri {
1576     pub compiler: Compiler,
1577     pub target: TargetSelection,
1578 }
1579
1580 impl Step for Miri {
1581     type Output = Option<PathBuf>;
1582     const ONLY_HOSTS: bool = true;
1583
1584     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1585         run.path("miri")
1586     }
1587
1588     fn make_run(run: RunConfig<'_>) {
1589         run.builder.ensure(Miri {
1590             compiler: run.builder.compiler_for(
1591                 run.builder.top_stage,
1592                 run.builder.config.build,
1593                 run.target,
1594             ),
1595             target: run.target,
1596         });
1597     }
1598
1599     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1600         let compiler = self.compiler;
1601         let target = self.target;
1602         assert!(builder.config.extended);
1603
1604         let src = builder.src.join("src/tools/miri");
1605         let release_num = builder.release_num("miri");
1606         let name = pkgname(builder, "miri");
1607         let version = builder.miri_info.version(builder, &release_num);
1608
1609         let tmp = tmpdir(builder);
1610         let image = tmp.join("miri-image");
1611         drop(fs::remove_dir_all(&image));
1612         builder.create_dir(&image);
1613
1614         // Prepare the image directory
1615         // We expect miri to build, because we've exited this step above if tool
1616         // state for miri isn't testing.
1617         let miri = builder
1618             .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1619             .or_else(|| {
1620                 missing_tool("miri", builder.build.config.missing_tools);
1621                 None
1622             })?;
1623         let cargomiri = builder
1624             .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1625             .or_else(|| {
1626                 missing_tool("cargo miri", builder.build.config.missing_tools);
1627                 None
1628             })?;
1629
1630         builder.install(&miri, &image.join("bin"), 0o755);
1631         builder.install(&cargomiri, &image.join("bin"), 0o755);
1632         let doc = image.join("share/doc/miri");
1633         builder.install(&src.join("README.md"), &doc, 0o644);
1634         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1635         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1636
1637         // Prepare the overlay
1638         let overlay = tmp.join("miri-overlay");
1639         drop(fs::remove_dir_all(&overlay));
1640         t!(fs::create_dir_all(&overlay));
1641         builder.install(&src.join("README.md"), &overlay, 0o644);
1642         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1643         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1644         builder.create(&overlay.join("version"), &version);
1645
1646         // Generate the installer tarball
1647         let mut cmd = rust_installer(builder);
1648         cmd.arg("generate")
1649             .arg("--product-name=Rust")
1650             .arg("--rel-manifest-dir=rustlib")
1651             .arg("--success-message=miri-ready-to-serve.")
1652             .arg("--image-dir")
1653             .arg(&image)
1654             .arg("--work-dir")
1655             .arg(&tmpdir(builder))
1656             .arg("--output-dir")
1657             .arg(&distdir(builder))
1658             .arg("--non-installed-overlay")
1659             .arg(&overlay)
1660             .arg(format!("--package-name={}-{}", name, target.triple))
1661             .arg("--legacy-manifest-dirs=rustlib,cargo")
1662             .arg("--component-name=miri-preview");
1663
1664         builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target));
1665         let _time = timeit(builder);
1666         builder.run(&mut cmd);
1667         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1668     }
1669 }
1670
1671 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1672 pub struct Rustfmt {
1673     pub compiler: Compiler,
1674     pub target: TargetSelection,
1675 }
1676
1677 impl Step for Rustfmt {
1678     type Output = Option<PathBuf>;
1679     const ONLY_HOSTS: bool = true;
1680
1681     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1682         run.path("rustfmt")
1683     }
1684
1685     fn make_run(run: RunConfig<'_>) {
1686         run.builder.ensure(Rustfmt {
1687             compiler: run.builder.compiler_for(
1688                 run.builder.top_stage,
1689                 run.builder.config.build,
1690                 run.target,
1691             ),
1692             target: run.target,
1693         });
1694     }
1695
1696     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1697         let compiler = self.compiler;
1698         let target = self.target;
1699
1700         let src = builder.src.join("src/tools/rustfmt");
1701         let release_num = builder.release_num("rustfmt");
1702         let name = pkgname(builder, "rustfmt");
1703         let version = builder.rustfmt_info.version(builder, &release_num);
1704
1705         let tmp = tmpdir(builder);
1706         let image = tmp.join("rustfmt-image");
1707         drop(fs::remove_dir_all(&image));
1708         builder.create_dir(&image);
1709
1710         // Prepare the image directory
1711         let rustfmt = builder
1712             .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1713             .or_else(|| {
1714                 missing_tool("Rustfmt", builder.build.config.missing_tools);
1715                 None
1716             })?;
1717         let cargofmt = builder
1718             .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1719             .or_else(|| {
1720                 missing_tool("Cargofmt", builder.build.config.missing_tools);
1721                 None
1722             })?;
1723
1724         builder.install(&rustfmt, &image.join("bin"), 0o755);
1725         builder.install(&cargofmt, &image.join("bin"), 0o755);
1726         let doc = image.join("share/doc/rustfmt");
1727         builder.install(&src.join("README.md"), &doc, 0o644);
1728         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1729         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1730
1731         // Prepare the overlay
1732         let overlay = tmp.join("rustfmt-overlay");
1733         drop(fs::remove_dir_all(&overlay));
1734         builder.create_dir(&overlay);
1735         builder.install(&src.join("README.md"), &overlay, 0o644);
1736         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1737         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1738         builder.create(&overlay.join("version"), &version);
1739
1740         // Generate the installer tarball
1741         let mut cmd = rust_installer(builder);
1742         cmd.arg("generate")
1743             .arg("--product-name=Rust")
1744             .arg("--rel-manifest-dir=rustlib")
1745             .arg("--success-message=rustfmt-ready-to-fmt.")
1746             .arg("--image-dir")
1747             .arg(&image)
1748             .arg("--work-dir")
1749             .arg(&tmpdir(builder))
1750             .arg("--output-dir")
1751             .arg(&distdir(builder))
1752             .arg("--non-installed-overlay")
1753             .arg(&overlay)
1754             .arg(format!("--package-name={}-{}", name, target.triple))
1755             .arg("--legacy-manifest-dirs=rustlib,cargo")
1756             .arg("--component-name=rustfmt-preview");
1757
1758         builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target));
1759         let _time = timeit(builder);
1760         builder.run(&mut cmd);
1761         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1762     }
1763 }
1764
1765 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1766 pub struct Extended {
1767     stage: u32,
1768     host: TargetSelection,
1769     target: TargetSelection,
1770 }
1771
1772 impl Step for Extended {
1773     type Output = ();
1774     const DEFAULT: bool = true;
1775     const ONLY_HOSTS: bool = true;
1776
1777     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1778         let builder = run.builder;
1779         run.path("extended").default_condition(builder.config.extended)
1780     }
1781
1782     fn make_run(run: RunConfig<'_>) {
1783         run.builder.ensure(Extended {
1784             stage: run.builder.top_stage,
1785             host: run.builder.config.build,
1786             target: run.target,
1787         });
1788     }
1789
1790     /// Creates a combined installer for the specified target in the provided stage.
1791     fn run(self, builder: &Builder<'_>) {
1792         let target = self.target;
1793         let stage = self.stage;
1794         let compiler = builder.compiler_for(self.stage, self.host, self.target);
1795
1796         builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1797
1798         let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
1799         let cargo_installer = builder.ensure(Cargo { compiler, target });
1800         let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1801         let rls_installer = builder.ensure(Rls { compiler, target });
1802         let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
1803         let llvm_tools_installer = builder.ensure(LlvmTools { target });
1804         let clippy_installer = builder.ensure(Clippy { compiler, target });
1805         let miri_installer = builder.ensure(Miri { compiler, target });
1806         let mingw_installer = builder.ensure(Mingw { host: target });
1807         let analysis_installer = builder.ensure(Analysis { compiler, target });
1808
1809         let docs_installer = builder.ensure(Docs { host: target });
1810         let std_installer =
1811             builder.ensure(Std { compiler: builder.compiler(stage, target), target });
1812
1813         let tmp = tmpdir(builder);
1814         let overlay = tmp.join("extended-overlay");
1815         let etc = builder.src.join("src/etc/installer");
1816         let work = tmp.join("work");
1817
1818         let _ = fs::remove_dir_all(&overlay);
1819         builder.install(&builder.src.join("COPYRIGHT"), &overlay, 0o644);
1820         builder.install(&builder.src.join("LICENSE-APACHE"), &overlay, 0o644);
1821         builder.install(&builder.src.join("LICENSE-MIT"), &overlay, 0o644);
1822         let version = builder.rust_version();
1823         builder.create(&overlay.join("version"), &version);
1824         if let Some(sha) = builder.rust_sha() {
1825             builder.create(&overlay.join("git-commit-hash"), &sha);
1826         }
1827         builder.install(&etc.join("README.md"), &overlay, 0o644);
1828
1829         // When rust-std package split from rustc, we needed to ensure that during
1830         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1831         // the std files during uninstall. To do this ensure that rustc comes
1832         // before rust-std in the list below.
1833         let mut tarballs = Vec::new();
1834         tarballs.push(rustc_installer);
1835         tarballs.push(cargo_installer);
1836         tarballs.extend(rls_installer.clone());
1837         tarballs.extend(rust_analyzer_installer.clone());
1838         tarballs.push(clippy_installer);
1839         tarballs.extend(miri_installer.clone());
1840         tarballs.extend(rustfmt_installer.clone());
1841         tarballs.extend(llvm_tools_installer);
1842         tarballs.push(analysis_installer);
1843         tarballs.push(std_installer);
1844         if builder.config.docs {
1845             tarballs.push(docs_installer);
1846         }
1847         if target.contains("pc-windows-gnu") {
1848             tarballs.push(mingw_installer.unwrap());
1849         }
1850         let mut input_tarballs = tarballs[0].as_os_str().to_owned();
1851         for tarball in &tarballs[1..] {
1852             input_tarballs.push(",");
1853             input_tarballs.push(tarball);
1854         }
1855
1856         builder.info("building combined installer");
1857         let mut cmd = rust_installer(builder);
1858         cmd.arg("combine")
1859             .arg("--product-name=Rust")
1860             .arg("--rel-manifest-dir=rustlib")
1861             .arg("--success-message=Rust-is-ready-to-roll.")
1862             .arg("--work-dir")
1863             .arg(&work)
1864             .arg("--output-dir")
1865             .arg(&distdir(builder))
1866             .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target.triple))
1867             .arg("--legacy-manifest-dirs=rustlib,cargo")
1868             .arg("--input-tarballs")
1869             .arg(input_tarballs)
1870             .arg("--non-installed-overlay")
1871             .arg(&overlay);
1872         let time = timeit(&builder);
1873         builder.run(&mut cmd);
1874         drop(time);
1875
1876         let mut license = String::new();
1877         license += &builder.read(&builder.src.join("COPYRIGHT"));
1878         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1879         license += &builder.read(&builder.src.join("LICENSE-MIT"));
1880         license.push_str("\n");
1881         license.push_str("\n");
1882
1883         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1884         let mut rtf = rtf.to_string();
1885         rtf.push_str("\n");
1886         for line in license.lines() {
1887             rtf.push_str(line);
1888             rtf.push_str("\\line ");
1889         }
1890         rtf.push_str("}");
1891
1892         fn filter(contents: &str, marker: &str) -> String {
1893             let start = format!("tool-{}-start", marker);
1894             let end = format!("tool-{}-end", marker);
1895             let mut lines = Vec::new();
1896             let mut omitted = false;
1897             for line in contents.lines() {
1898                 if line.contains(&start) {
1899                     omitted = true;
1900                 } else if line.contains(&end) {
1901                     omitted = false;
1902                 } else if !omitted {
1903                     lines.push(line);
1904                 }
1905             }
1906
1907             lines.join("\n")
1908         }
1909
1910         let xform = |p: &Path| {
1911             let mut contents = t!(fs::read_to_string(p));
1912             if rls_installer.is_none() {
1913                 contents = filter(&contents, "rls");
1914             }
1915             if rust_analyzer_installer.is_none() {
1916                 contents = filter(&contents, "rust-analyzer");
1917             }
1918             if miri_installer.is_none() {
1919                 contents = filter(&contents, "miri");
1920             }
1921             if rustfmt_installer.is_none() {
1922                 contents = filter(&contents, "rustfmt");
1923             }
1924             let ret = tmp.join(p.file_name().unwrap());
1925             t!(fs::write(&ret, &contents));
1926             ret
1927         };
1928
1929         if target.contains("apple-darwin") {
1930             builder.info("building pkg installer");
1931             let pkg = tmp.join("pkg");
1932             let _ = fs::remove_dir_all(&pkg);
1933
1934             let pkgbuild = |component: &str| {
1935                 let mut cmd = Command::new("pkgbuild");
1936                 cmd.arg("--identifier")
1937                     .arg(format!("org.rust-lang.{}", component))
1938                     .arg("--scripts")
1939                     .arg(pkg.join(component))
1940                     .arg("--nopayload")
1941                     .arg(pkg.join(component).with_extension("pkg"));
1942                 builder.run(&mut cmd);
1943             };
1944
1945             let prepare = |name: &str| {
1946                 builder.create_dir(&pkg.join(name));
1947                 builder.cp_r(
1948                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1949                     &pkg.join(name),
1950                 );
1951                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1952                 pkgbuild(name);
1953             };
1954             prepare("rustc");
1955             prepare("cargo");
1956             prepare("rust-docs");
1957             prepare("rust-std");
1958             prepare("rust-analysis");
1959             prepare("clippy");
1960
1961             if rls_installer.is_some() {
1962                 prepare("rls");
1963             }
1964             if rust_analyzer_installer.is_some() {
1965                 prepare("rust-analyzer");
1966             }
1967             if miri_installer.is_some() {
1968                 prepare("miri");
1969             }
1970
1971             // create an 'uninstall' package
1972             builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1973             pkgbuild("uninstall");
1974
1975             builder.create_dir(&pkg.join("res"));
1976             builder.create(&pkg.join("res/LICENSE.txt"), &license);
1977             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1978             let mut cmd = Command::new("productbuild");
1979             cmd.arg("--distribution")
1980                 .arg(xform(&etc.join("pkg/Distribution.xml")))
1981                 .arg("--resources")
1982                 .arg(pkg.join("res"))
1983                 .arg(distdir(builder).join(format!(
1984                     "{}-{}.pkg",
1985                     pkgname(builder, "rust"),
1986                     target.triple
1987                 )))
1988                 .arg("--package-path")
1989                 .arg(&pkg);
1990             let _time = timeit(builder);
1991             builder.run(&mut cmd);
1992         }
1993
1994         if target.contains("windows") {
1995             let exe = tmp.join("exe");
1996             let _ = fs::remove_dir_all(&exe);
1997
1998             let prepare = |name: &str| {
1999                 builder.create_dir(&exe.join(name));
2000                 let dir = if name == "rust-std" || name == "rust-analysis" {
2001                     format!("{}-{}", name, target.triple)
2002                 } else if name == "rls" {
2003                     "rls-preview".to_string()
2004                 } else if name == "rust-analyzer" {
2005                     "rust-analyzer-preview".to_string()
2006                 } else if name == "clippy" {
2007                     "clippy-preview".to_string()
2008                 } else if name == "miri" {
2009                     "miri-preview".to_string()
2010                 } else {
2011                     name.to_string()
2012                 };
2013                 builder.cp_r(
2014                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2015                     &exe.join(name),
2016                 );
2017                 builder.remove(&exe.join(name).join("manifest.in"));
2018             };
2019             prepare("rustc");
2020             prepare("cargo");
2021             prepare("rust-analysis");
2022             prepare("rust-docs");
2023             prepare("rust-std");
2024             prepare("clippy");
2025             if rls_installer.is_some() {
2026                 prepare("rls");
2027             }
2028             if rust_analyzer_installer.is_some() {
2029                 prepare("rust-analyzer");
2030             }
2031             if miri_installer.is_some() {
2032                 prepare("miri");
2033             }
2034             if target.contains("windows-gnu") {
2035                 prepare("rust-mingw");
2036             }
2037
2038             builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
2039
2040             // Generate msi installer
2041             let wix = PathBuf::from(env::var_os("WIX").unwrap());
2042             let heat = wix.join("bin/heat.exe");
2043             let candle = wix.join("bin/candle.exe");
2044             let light = wix.join("bin/light.exe");
2045
2046             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2047             builder.run(
2048                 Command::new(&heat)
2049                     .current_dir(&exe)
2050                     .arg("dir")
2051                     .arg("rustc")
2052                     .args(&heat_flags)
2053                     .arg("-cg")
2054                     .arg("RustcGroup")
2055                     .arg("-dr")
2056                     .arg("Rustc")
2057                     .arg("-var")
2058                     .arg("var.RustcDir")
2059                     .arg("-out")
2060                     .arg(exe.join("RustcGroup.wxs")),
2061             );
2062             builder.run(
2063                 Command::new(&heat)
2064                     .current_dir(&exe)
2065                     .arg("dir")
2066                     .arg("rust-docs")
2067                     .args(&heat_flags)
2068                     .arg("-cg")
2069                     .arg("DocsGroup")
2070                     .arg("-dr")
2071                     .arg("Docs")
2072                     .arg("-var")
2073                     .arg("var.DocsDir")
2074                     .arg("-out")
2075                     .arg(exe.join("DocsGroup.wxs"))
2076                     .arg("-t")
2077                     .arg(etc.join("msi/squash-components.xsl")),
2078             );
2079             builder.run(
2080                 Command::new(&heat)
2081                     .current_dir(&exe)
2082                     .arg("dir")
2083                     .arg("cargo")
2084                     .args(&heat_flags)
2085                     .arg("-cg")
2086                     .arg("CargoGroup")
2087                     .arg("-dr")
2088                     .arg("Cargo")
2089                     .arg("-var")
2090                     .arg("var.CargoDir")
2091                     .arg("-out")
2092                     .arg(exe.join("CargoGroup.wxs"))
2093                     .arg("-t")
2094                     .arg(etc.join("msi/remove-duplicates.xsl")),
2095             );
2096             builder.run(
2097                 Command::new(&heat)
2098                     .current_dir(&exe)
2099                     .arg("dir")
2100                     .arg("rust-std")
2101                     .args(&heat_flags)
2102                     .arg("-cg")
2103                     .arg("StdGroup")
2104                     .arg("-dr")
2105                     .arg("Std")
2106                     .arg("-var")
2107                     .arg("var.StdDir")
2108                     .arg("-out")
2109                     .arg(exe.join("StdGroup.wxs")),
2110             );
2111             if rls_installer.is_some() {
2112                 builder.run(
2113                     Command::new(&heat)
2114                         .current_dir(&exe)
2115                         .arg("dir")
2116                         .arg("rls")
2117                         .args(&heat_flags)
2118                         .arg("-cg")
2119                         .arg("RlsGroup")
2120                         .arg("-dr")
2121                         .arg("Rls")
2122                         .arg("-var")
2123                         .arg("var.RlsDir")
2124                         .arg("-out")
2125                         .arg(exe.join("RlsGroup.wxs"))
2126                         .arg("-t")
2127                         .arg(etc.join("msi/remove-duplicates.xsl")),
2128                 );
2129             }
2130             if rust_analyzer_installer.is_some() {
2131                 builder.run(
2132                     Command::new(&heat)
2133                         .current_dir(&exe)
2134                         .arg("dir")
2135                         .arg("rust-analyzer")
2136                         .args(&heat_flags)
2137                         .arg("-cg")
2138                         .arg("RustAnalyzerGroup")
2139                         .arg("-dr")
2140                         .arg("RustAnalyzer")
2141                         .arg("-var")
2142                         .arg("var.RustAnalyzerDir")
2143                         .arg("-out")
2144                         .arg(exe.join("RustAnalyzerGroup.wxs"))
2145                         .arg("-t")
2146                         .arg(etc.join("msi/remove-duplicates.xsl")),
2147                 );
2148             }
2149             builder.run(
2150                 Command::new(&heat)
2151                     .current_dir(&exe)
2152                     .arg("dir")
2153                     .arg("clippy")
2154                     .args(&heat_flags)
2155                     .arg("-cg")
2156                     .arg("ClippyGroup")
2157                     .arg("-dr")
2158                     .arg("Clippy")
2159                     .arg("-var")
2160                     .arg("var.ClippyDir")
2161                     .arg("-out")
2162                     .arg(exe.join("ClippyGroup.wxs"))
2163                     .arg("-t")
2164                     .arg(etc.join("msi/remove-duplicates.xsl")),
2165             );
2166             if miri_installer.is_some() {
2167                 builder.run(
2168                     Command::new(&heat)
2169                         .current_dir(&exe)
2170                         .arg("dir")
2171                         .arg("miri")
2172                         .args(&heat_flags)
2173                         .arg("-cg")
2174                         .arg("MiriGroup")
2175                         .arg("-dr")
2176                         .arg("Miri")
2177                         .arg("-var")
2178                         .arg("var.MiriDir")
2179                         .arg("-out")
2180                         .arg(exe.join("MiriGroup.wxs"))
2181                         .arg("-t")
2182                         .arg(etc.join("msi/remove-duplicates.xsl")),
2183                 );
2184             }
2185             builder.run(
2186                 Command::new(&heat)
2187                     .current_dir(&exe)
2188                     .arg("dir")
2189                     .arg("rust-analysis")
2190                     .args(&heat_flags)
2191                     .arg("-cg")
2192                     .arg("AnalysisGroup")
2193                     .arg("-dr")
2194                     .arg("Analysis")
2195                     .arg("-var")
2196                     .arg("var.AnalysisDir")
2197                     .arg("-out")
2198                     .arg(exe.join("AnalysisGroup.wxs"))
2199                     .arg("-t")
2200                     .arg(etc.join("msi/remove-duplicates.xsl")),
2201             );
2202             if target.contains("windows-gnu") {
2203                 builder.run(
2204                     Command::new(&heat)
2205                         .current_dir(&exe)
2206                         .arg("dir")
2207                         .arg("rust-mingw")
2208                         .args(&heat_flags)
2209                         .arg("-cg")
2210                         .arg("GccGroup")
2211                         .arg("-dr")
2212                         .arg("Gcc")
2213                         .arg("-var")
2214                         .arg("var.GccDir")
2215                         .arg("-out")
2216                         .arg(exe.join("GccGroup.wxs")),
2217                 );
2218             }
2219
2220             let candle = |input: &Path| {
2221                 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2222                 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2223                 let mut cmd = Command::new(&candle);
2224                 cmd.current_dir(&exe)
2225                     .arg("-nologo")
2226                     .arg("-dRustcDir=rustc")
2227                     .arg("-dDocsDir=rust-docs")
2228                     .arg("-dCargoDir=cargo")
2229                     .arg("-dStdDir=rust-std")
2230                     .arg("-dAnalysisDir=rust-analysis")
2231                     .arg("-dClippyDir=clippy")
2232                     .arg("-arch")
2233                     .arg(&arch)
2234                     .arg("-out")
2235                     .arg(&output)
2236                     .arg(&input);
2237                 add_env(builder, &mut cmd, target);
2238
2239                 if rls_installer.is_some() {
2240                     cmd.arg("-dRlsDir=rls");
2241                 }
2242                 if rust_analyzer_installer.is_some() {
2243                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2244                 }
2245                 if miri_installer.is_some() {
2246                     cmd.arg("-dMiriDir=miri");
2247                 }
2248                 if target.contains("windows-gnu") {
2249                     cmd.arg("-dGccDir=rust-mingw");
2250                 }
2251                 builder.run(&mut cmd);
2252             };
2253             candle(&xform(&etc.join("msi/rust.wxs")));
2254             candle(&etc.join("msi/ui.wxs"));
2255             candle(&etc.join("msi/rustwelcomedlg.wxs"));
2256             candle("RustcGroup.wxs".as_ref());
2257             candle("DocsGroup.wxs".as_ref());
2258             candle("CargoGroup.wxs".as_ref());
2259             candle("StdGroup.wxs".as_ref());
2260             candle("ClippyGroup.wxs".as_ref());
2261             if rls_installer.is_some() {
2262                 candle("RlsGroup.wxs".as_ref());
2263             }
2264             if rust_analyzer_installer.is_some() {
2265                 candle("RustAnalyzerGroup.wxs".as_ref());
2266             }
2267             if miri_installer.is_some() {
2268                 candle("MiriGroup.wxs".as_ref());
2269             }
2270             candle("AnalysisGroup.wxs".as_ref());
2271
2272             if target.contains("windows-gnu") {
2273                 candle("GccGroup.wxs".as_ref());
2274             }
2275
2276             builder.create(&exe.join("LICENSE.rtf"), &rtf);
2277             builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
2278             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
2279
2280             builder.info(&format!("building `msi` installer with {:?}", light));
2281             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2282             let mut cmd = Command::new(&light);
2283             cmd.arg("-nologo")
2284                 .arg("-ext")
2285                 .arg("WixUIExtension")
2286                 .arg("-ext")
2287                 .arg("WixUtilExtension")
2288                 .arg("-out")
2289                 .arg(exe.join(&filename))
2290                 .arg("rust.wixobj")
2291                 .arg("ui.wixobj")
2292                 .arg("rustwelcomedlg.wixobj")
2293                 .arg("RustcGroup.wixobj")
2294                 .arg("DocsGroup.wixobj")
2295                 .arg("CargoGroup.wixobj")
2296                 .arg("StdGroup.wixobj")
2297                 .arg("AnalysisGroup.wixobj")
2298                 .arg("ClippyGroup.wixobj")
2299                 .current_dir(&exe);
2300
2301             if rls_installer.is_some() {
2302                 cmd.arg("RlsGroup.wixobj");
2303             }
2304             if rust_analyzer_installer.is_some() {
2305                 cmd.arg("RustAnalyzerGroup.wixobj");
2306             }
2307             if miri_installer.is_some() {
2308                 cmd.arg("MiriGroup.wixobj");
2309             }
2310
2311             if target.contains("windows-gnu") {
2312                 cmd.arg("GccGroup.wixobj");
2313             }
2314             // ICE57 wrongly complains about the shortcuts
2315             cmd.arg("-sice:ICE57");
2316
2317             let _time = timeit(builder);
2318             builder.run(&mut cmd);
2319
2320             if !builder.config.dry_run {
2321                 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
2322             }
2323         }
2324     }
2325 }
2326
2327 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
2328     let mut parts = builder.version.split('.');
2329     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2330         .env("CFG_RELEASE_NUM", &builder.version)
2331         .env("CFG_RELEASE", builder.rust_release())
2332         .env("CFG_VER_MAJOR", parts.next().unwrap())
2333         .env("CFG_VER_MINOR", parts.next().unwrap())
2334         .env("CFG_VER_PATCH", parts.next().unwrap())
2335         .env("CFG_VER_BUILD", "0") // just needed to build
2336         .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2337         .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2338         .env("CFG_BUILD", target.triple)
2339         .env("CFG_CHANNEL", &builder.config.channel);
2340
2341     if target.contains("windows-gnu") {
2342         cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2343     } else {
2344         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2345     }
2346
2347     if target.contains("x86_64") {
2348         cmd.env("CFG_PLATFORM", "x64");
2349     } else {
2350         cmd.env("CFG_PLATFORM", "x86");
2351     }
2352 }
2353
2354 /// Maybe add libLLVM.so to the given destination lib-dir. It will only have
2355 /// been built if LLVM tools are linked dynamically.
2356 ///
2357 /// Note: This function does not yet support Windows, but we also don't support
2358 ///       linking LLVM tools dynamically on Windows yet.
2359 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) {
2360     if !builder.config.llvm_link_shared {
2361         // We do not need to copy LLVM files into the sysroot if it is not
2362         // dynamically linked; it is already included into librustc_llvm
2363         // statically.
2364         return;
2365     }
2366
2367     if let Some(config) = builder.config.target_config.get(&target) {
2368         if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
2369             // If the LLVM was externally provided, then we don't currently copy
2370             // artifacts into the sysroot. This is not necessarily the right
2371             // choice (in particular, it will require the LLVM dylib to be in
2372             // the linker's load path at runtime), but the common use case for
2373             // external LLVMs is distribution provided LLVMs, and in that case
2374             // they're usually in the standard search path (e.g., /usr/lib) and
2375             // copying them here is going to cause problems as we may end up
2376             // with the wrong files and isn't what distributions want.
2377             //
2378             // This behavior may be revisited in the future though.
2379             //
2380             // If the LLVM is coming from ourselves (just from CI) though, we
2381             // still want to install it, as it otherwise won't be available.
2382             return;
2383         }
2384     }
2385
2386     // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
2387     // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
2388     // clear why this is the case, though. llvm-config will emit the versioned
2389     // paths and we don't want those in the sysroot (as we're expecting
2390     // unversioned paths).
2391     if target.contains("apple-darwin") {
2392         let src_libdir = builder.llvm_out(target).join("lib");
2393         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2394         if llvm_dylib_path.exists() {
2395             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
2396         }
2397     } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
2398         let files = output(Command::new(llvm_config).arg("--libfiles"));
2399         for file in files.lines() {
2400             builder.install(Path::new(file), dst_libdir, 0o644);
2401         }
2402     }
2403 }
2404
2405 /// Maybe add libLLVM.so to the target lib-dir for linking.
2406 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2407     let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
2408     maybe_install_llvm(builder, target, &dst_libdir);
2409 }
2410
2411 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
2412 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2413     let dst_libdir =
2414         sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
2415     maybe_install_llvm(builder, target, &dst_libdir);
2416 }
2417
2418 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2419 pub struct LlvmTools {
2420     pub target: TargetSelection,
2421 }
2422
2423 impl Step for LlvmTools {
2424     type Output = Option<PathBuf>;
2425     const ONLY_HOSTS: bool = true;
2426
2427     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2428         run.path("llvm-tools")
2429     }
2430
2431     fn make_run(run: RunConfig<'_>) {
2432         run.builder.ensure(LlvmTools { target: run.target });
2433     }
2434
2435     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
2436         let target = self.target;
2437         assert!(builder.config.extended);
2438
2439         /* run only if llvm-config isn't used */
2440         if let Some(config) = builder.config.target_config.get(&target) {
2441             if let Some(ref _s) = config.llvm_config {
2442                 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
2443                 return None;
2444             }
2445         }
2446
2447         builder.info(&format!("Dist LlvmTools ({})", target));
2448         let _time = timeit(builder);
2449         let src = builder.src.join("src/llvm-project/llvm");
2450         let name = pkgname(builder, "llvm-tools");
2451
2452         let tmp = tmpdir(builder);
2453         let image = tmp.join("llvm-tools-image");
2454         drop(fs::remove_dir_all(&image));
2455
2456         // Prepare the image directory
2457         let src_bindir = builder.llvm_out(target).join("bin");
2458         let dst_bindir = image.join("lib/rustlib").join(&*target.triple).join("bin");
2459         t!(fs::create_dir_all(&dst_bindir));
2460         for tool in LLVM_TOOLS {
2461             let exe = src_bindir.join(exe(tool, target));
2462             builder.install(&exe, &dst_bindir, 0o755);
2463         }
2464
2465         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2466         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2467         // of `rustc-dev` to support the inherited `-lLLVM` when using the
2468         // compiler libraries.
2469         maybe_install_llvm_target(builder, target, &image);
2470
2471         // Prepare the overlay
2472         let overlay = tmp.join("llvm-tools-overlay");
2473         drop(fs::remove_dir_all(&overlay));
2474         builder.create_dir(&overlay);
2475         builder.install(&src.join("README.txt"), &overlay, 0o644);
2476         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
2477         builder.create(&overlay.join("version"), &builder.llvm_tools_vers());
2478
2479         // Generate the installer tarball
2480         let mut cmd = rust_installer(builder);
2481         cmd.arg("generate")
2482             .arg("--product-name=Rust")
2483             .arg("--rel-manifest-dir=rustlib")
2484             .arg("--success-message=llvm-tools-installed.")
2485             .arg("--image-dir")
2486             .arg(&image)
2487             .arg("--work-dir")
2488             .arg(&tmpdir(builder))
2489             .arg("--output-dir")
2490             .arg(&distdir(builder))
2491             .arg("--non-installed-overlay")
2492             .arg(&overlay)
2493             .arg(format!("--package-name={}-{}", name, target.triple))
2494             .arg("--legacy-manifest-dirs=rustlib,cargo")
2495             .arg("--component-name=llvm-tools-preview");
2496
2497         builder.run(&mut cmd);
2498         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
2499     }
2500 }
2501
2502 // Tarball intended for internal consumption to ease rustc/std development.
2503 //
2504 // Should not be considered stable by end users.
2505 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2506 pub struct RustDev {
2507     pub target: TargetSelection,
2508 }
2509
2510 impl Step for RustDev {
2511     type Output = Option<PathBuf>;
2512     const DEFAULT: bool = true;
2513     const ONLY_HOSTS: bool = true;
2514
2515     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2516         run.path("rust-dev")
2517     }
2518
2519     fn make_run(run: RunConfig<'_>) {
2520         run.builder.ensure(RustDev { target: run.target });
2521     }
2522
2523     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
2524         let target = self.target;
2525
2526         /* run only if llvm-config isn't used */
2527         if let Some(config) = builder.config.target_config.get(&target) {
2528             if let Some(ref _s) = config.llvm_config {
2529                 builder.info(&format!("Skipping RustDev ({}): external LLVM", target));
2530                 return None;
2531             }
2532         }
2533
2534         builder.info(&format!("Dist RustDev ({})", target));
2535         let _time = timeit(builder);
2536         let src = builder.src.join("src/llvm-project/llvm");
2537         let name = pkgname(builder, "rust-dev");
2538
2539         let tmp = tmpdir(builder);
2540         let image = tmp.join("rust-dev-image");
2541         drop(fs::remove_dir_all(&image));
2542
2543         // Prepare the image directory
2544         let dst_bindir = image.join("bin");
2545         t!(fs::create_dir_all(&dst_bindir));
2546
2547         let src_bindir = builder.llvm_out(target).join("bin");
2548         let install_bin =
2549             |name| builder.install(&src_bindir.join(exe(name, target)), &dst_bindir, 0o755);
2550         install_bin("llvm-config");
2551         install_bin("llvm-ar");
2552         install_bin("llvm-objdump");
2553         install_bin("llvm-profdata");
2554         install_bin("llvm-bcanalyzer");
2555         install_bin("llvm-cov");
2556         install_bin("llvm-dwp");
2557         builder.install(&builder.llvm_filecheck(target), &dst_bindir, 0o755);
2558
2559         // Copy the include directory as well; needed mostly to build
2560         // librustc_llvm properly (e.g., llvm-config.h is in here). But also
2561         // just broadly useful to be able to link against the bundled LLVM.
2562         builder.cp_r(&builder.llvm_out(target).join("include"), &image.join("include"));
2563
2564         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2565         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2566         // of `rustc-dev` to support the inherited `-lLLVM` when using the
2567         // compiler libraries.
2568         maybe_install_llvm(builder, target, &image.join("lib"));
2569
2570         // Prepare the overlay
2571         let overlay = tmp.join("rust-dev-overlay");
2572         drop(fs::remove_dir_all(&overlay));
2573         builder.create_dir(&overlay);
2574         builder.install(&src.join("README.txt"), &overlay, 0o644);
2575         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
2576         builder.create(&overlay.join("version"), &builder.rust_version());
2577
2578         // Generate the installer tarball
2579         let mut cmd = rust_installer(builder);
2580         cmd.arg("generate")
2581             .arg("--product-name=Rust")
2582             .arg("--rel-manifest-dir=rustlib")
2583             .arg("--success-message=rust-dev-installed.")
2584             .arg("--image-dir")
2585             .arg(&image)
2586             .arg("--work-dir")
2587             .arg(&tmpdir(builder))
2588             .arg("--output-dir")
2589             .arg(&distdir(builder))
2590             .arg("--non-installed-overlay")
2591             .arg(&overlay)
2592             .arg(format!("--package-name={}-{}", name, target.triple))
2593             .arg("--legacy-manifest-dirs=rustlib,cargo")
2594             .arg("--component-name=rust-dev");
2595
2596         builder.run(&mut cmd);
2597         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
2598     }
2599 }
2600
2601 /// Tarball containing a prebuilt version of the build-manifest tool, intented to be used by the
2602 /// release process to avoid cloning the monorepo and building stuff.
2603 ///
2604 /// Should not be considered stable by end users.
2605 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2606 pub struct BuildManifest {
2607     pub target: TargetSelection,
2608 }
2609
2610 impl Step for BuildManifest {
2611     type Output = PathBuf;
2612     const DEFAULT: bool = false;
2613     const ONLY_HOSTS: bool = true;
2614
2615     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2616         run.path("src/tools/build-manifest")
2617     }
2618
2619     fn make_run(run: RunConfig<'_>) {
2620         run.builder.ensure(BuildManifest { target: run.target });
2621     }
2622
2623     fn run(self, builder: &Builder<'_>) -> PathBuf {
2624         let build_manifest = builder.tool_exe(Tool::BuildManifest);
2625
2626         let name = pkgname(builder, "build-manifest");
2627         let tmp = tmpdir(builder);
2628
2629         // Prepare the image.
2630         let image = tmp.join("build-manifest-image");
2631         let image_bin = image.join("bin");
2632         let _ = fs::remove_dir_all(&image);
2633         t!(fs::create_dir_all(&image_bin));
2634         builder.install(&build_manifest, &image_bin, 0o755);
2635
2636         // Prepare the overlay.
2637         let overlay = tmp.join("build-manifest-overlay");
2638         let _ = fs::remove_dir_all(&overlay);
2639         builder.create_dir(&overlay);
2640         builder.create(&overlay.join("version"), &builder.rust_version());
2641         for file in &["COPYRIGHT", "LICENSE-APACHE", "LICENSE-MIT", "README.md"] {
2642             builder.install(&builder.src.join(file), &overlay, 0o644);
2643         }
2644
2645         // Create the final tarball.
2646         let mut cmd = rust_installer(builder);
2647         cmd.arg("generate")
2648             .arg("--product-name=Rust")
2649             .arg("--rel-manifest-dir=rustlib")
2650             .arg("--success-message=build-manifest installed.")
2651             .arg("--image-dir")
2652             .arg(&image)
2653             .arg("--work-dir")
2654             .arg(&tmpdir(builder))
2655             .arg("--output-dir")
2656             .arg(&distdir(builder))
2657             .arg("--non-installed-overlay")
2658             .arg(&overlay)
2659             .arg(format!("--package-name={}-{}", name, self.target.triple))
2660             .arg("--legacy-manifest-dirs=rustlib,cargo")
2661             .arg("--component-name=build-manifest");
2662
2663         builder.run(&mut cmd);
2664         distdir(builder).join(format!("{}-{}.tar.gz", name, self.target.triple))
2665     }
2666 }