]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
ci: build docs for aarch64-unknown-linux-gnu
[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             // Copy over lld if it's there
527             if builder.config.lld_enabled {
528                 let exe = exe("rust-lld", compiler.host);
529                 let src =
530                     builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin").join(&exe);
531                 // for the rationale about this rename check `compile::copy_lld_to_sysroot`
532                 let dst = image.join("lib/rustlib").join(&*host.triple).join("bin").join(&exe);
533                 t!(fs::create_dir_all(&dst.parent().unwrap()));
534                 builder.copy(&src, &dst);
535             }
536
537             // Man pages
538             t!(fs::create_dir_all(image.join("share/man/man1")));
539             let man_src = builder.src.join("src/doc/man");
540             let man_dst = image.join("share/man/man1");
541
542             // Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time.
543             let time = env::var("SOURCE_DATE_EPOCH")
544                 .map(|timestamp| {
545                     let epoch = timestamp
546                         .parse()
547                         .map_err(|err| format!("could not parse SOURCE_DATE_EPOCH: {}", err))
548                         .unwrap();
549
550                     time::at(Timespec::new(epoch, 0))
551                 })
552                 .unwrap_or_else(|_| time::now());
553
554             let month_year = t!(time::strftime("%B %Y", &time));
555             // don't use our `bootstrap::util::{copy, cp_r}`, because those try
556             // to hardlink, and we don't want to edit the source templates
557             for file_entry in builder.read_dir(&man_src) {
558                 let page_src = file_entry.path();
559                 let page_dst = man_dst.join(file_entry.file_name());
560                 t!(fs::copy(&page_src, &page_dst));
561                 // template in month/year and version number
562                 builder.replace_in_file(
563                     &page_dst,
564                     &[
565                         ("<INSERT DATE HERE>", &month_year),
566                         ("<INSERT VERSION HERE>", &builder.version),
567                     ],
568                 );
569             }
570
571             // Debugger scripts
572             builder
573                 .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host });
574
575             // Misc license info
576             let cp = |file: &str| {
577                 builder.install(&builder.src.join(file), &image.join("share/doc/rust"), 0o644);
578             };
579             cp("COPYRIGHT");
580             cp("LICENSE-APACHE");
581             cp("LICENSE-MIT");
582             cp("README.md");
583         }
584     }
585 }
586
587 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
588 pub struct DebuggerScripts {
589     pub sysroot: Interned<PathBuf>,
590     pub host: TargetSelection,
591 }
592
593 impl Step for DebuggerScripts {
594     type Output = ();
595
596     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
597         run.path("src/lldb_batchmode.py")
598     }
599
600     fn make_run(run: RunConfig<'_>) {
601         run.builder.ensure(DebuggerScripts {
602             sysroot: run
603                 .builder
604                 .sysroot(run.builder.compiler(run.builder.top_stage, run.build_triple())),
605             host: run.target,
606         });
607     }
608
609     /// Copies debugger scripts for `target` into the `sysroot` specified.
610     fn run(self, builder: &Builder<'_>) {
611         let host = self.host;
612         let sysroot = self.sysroot;
613         let dst = sysroot.join("lib/rustlib/etc");
614         t!(fs::create_dir_all(&dst));
615         let cp_debugger_script = |file: &str| {
616             builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
617         };
618         if host.contains("windows-msvc") {
619             // windbg debugger scripts
620             builder.install(
621                 &builder.src.join("src/etc/rust-windbg.cmd"),
622                 &sysroot.join("bin"),
623                 0o755,
624             );
625
626             cp_debugger_script("natvis/intrinsic.natvis");
627             cp_debugger_script("natvis/liballoc.natvis");
628             cp_debugger_script("natvis/libcore.natvis");
629             cp_debugger_script("natvis/libstd.natvis");
630         } else {
631             cp_debugger_script("rust_types.py");
632
633             // gdb debugger scripts
634             builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
635             builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
636
637             cp_debugger_script("gdb_load_rust_pretty_printers.py");
638             cp_debugger_script("gdb_lookup.py");
639             cp_debugger_script("gdb_providers.py");
640
641             // lldb debugger scripts
642             builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
643
644             cp_debugger_script("lldb_lookup.py");
645             cp_debugger_script("lldb_providers.py");
646             cp_debugger_script("lldb_commands")
647         }
648     }
649 }
650
651 fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
652     // The only true set of target libraries came from the build triple, so
653     // let's reduce redundant work by only producing archives from that host.
654     if compiler.host != builder.config.build {
655         builder.info("\tskipping, not a build host");
656         true
657     } else {
658         false
659     }
660 }
661
662 /// Copy stamped files into an image's `target/lib` directory.
663 fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
664     let dst = image.join("lib/rustlib").join(target.triple).join("lib");
665     let self_contained_dst = dst.join("self-contained");
666     t!(fs::create_dir_all(&dst));
667     t!(fs::create_dir_all(&self_contained_dst));
668     for (path, dependency_type) in builder.read_stamp_file(stamp) {
669         if dependency_type == DependencyType::TargetSelfContained {
670             builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
671         } else if dependency_type == DependencyType::Target || builder.config.build == target {
672             builder.copy(&path, &dst.join(path.file_name().unwrap()));
673         }
674     }
675 }
676
677 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
678 pub struct Std {
679     pub compiler: Compiler,
680     pub target: TargetSelection,
681 }
682
683 impl Step for Std {
684     type Output = PathBuf;
685     const DEFAULT: bool = true;
686
687     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
688         run.path("library/std")
689     }
690
691     fn make_run(run: RunConfig<'_>) {
692         run.builder.ensure(Std {
693             compiler: run.builder.compiler_for(
694                 run.builder.top_stage,
695                 run.builder.config.build,
696                 run.target,
697             ),
698             target: run.target,
699         });
700     }
701
702     fn run(self, builder: &Builder<'_>) -> PathBuf {
703         let compiler = self.compiler;
704         let target = self.target;
705
706         let name = pkgname(builder, "rust-std");
707         let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
708         if skip_host_target_lib(builder, compiler) {
709             return archive;
710         }
711
712         builder.ensure(compile::Std { compiler, target });
713
714         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
715         let _ = fs::remove_dir_all(&image);
716
717         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
718         let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
719         copy_target_libs(builder, target, &image, &stamp);
720
721         let mut cmd = rust_installer(builder);
722         cmd.arg("generate")
723             .arg("--product-name=Rust")
724             .arg("--rel-manifest-dir=rustlib")
725             .arg("--success-message=std-is-standing-at-the-ready.")
726             .arg("--image-dir")
727             .arg(&image)
728             .arg("--work-dir")
729             .arg(&tmpdir(builder))
730             .arg("--output-dir")
731             .arg(&distdir(builder))
732             .arg(format!("--package-name={}-{}", name, target.triple))
733             .arg(format!("--component-name=rust-std-{}", target.triple))
734             .arg("--legacy-manifest-dirs=rustlib,cargo");
735
736         builder
737             .info(&format!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target));
738         let _time = timeit(builder);
739         builder.run(&mut cmd);
740         builder.remove_dir(&image);
741         archive
742     }
743 }
744
745 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
746 pub struct RustcDev {
747     pub compiler: Compiler,
748     pub target: TargetSelection,
749 }
750
751 impl Step for RustcDev {
752     type Output = PathBuf;
753     const DEFAULT: bool = true;
754     const ONLY_HOSTS: bool = true;
755
756     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
757         run.path("rustc-dev")
758     }
759
760     fn make_run(run: RunConfig<'_>) {
761         run.builder.ensure(RustcDev {
762             compiler: run.builder.compiler_for(
763                 run.builder.top_stage,
764                 run.builder.config.build,
765                 run.target,
766             ),
767             target: run.target,
768         });
769     }
770
771     fn run(self, builder: &Builder<'_>) -> PathBuf {
772         let compiler = self.compiler;
773         let target = self.target;
774
775         let name = pkgname(builder, "rustc-dev");
776         let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
777         if skip_host_target_lib(builder, compiler) {
778             return archive;
779         }
780
781         builder.ensure(compile::Rustc { compiler, target });
782
783         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
784         let _ = fs::remove_dir_all(&image);
785
786         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
787         let stamp = compile::librustc_stamp(builder, compiler_to_use, target);
788         copy_target_libs(builder, target, &image, &stamp);
789
790         // Copy compiler sources.
791         let dst_src = image.join("lib/rustlib/rustc-src/rust");
792         t!(fs::create_dir_all(&dst_src));
793
794         let src_files = ["Cargo.lock"];
795         // This is the reduced set of paths which will become the rustc-dev component
796         // (essentially the compiler crates and all of their path dependencies).
797         copy_src_dirs(builder, &builder.src, &["compiler"], &[], &dst_src);
798         for file in src_files.iter() {
799             builder.copy(&builder.src.join(file), &dst_src.join(file));
800         }
801
802         let mut cmd = rust_installer(builder);
803         cmd.arg("generate")
804             .arg("--product-name=Rust")
805             .arg("--rel-manifest-dir=rustlib")
806             .arg("--success-message=Rust-is-ready-to-develop.")
807             .arg("--image-dir")
808             .arg(&image)
809             .arg("--work-dir")
810             .arg(&tmpdir(builder))
811             .arg("--output-dir")
812             .arg(&distdir(builder))
813             .arg(format!("--package-name={}-{}", name, target.triple))
814             .arg(format!("--component-name=rustc-dev-{}", target.triple))
815             .arg("--legacy-manifest-dirs=rustlib,cargo");
816
817         builder.info(&format!(
818             "Dist rustc-dev stage{} ({} -> {})",
819             compiler.stage, &compiler.host, target
820         ));
821         let _time = timeit(builder);
822         builder.run(&mut cmd);
823         builder.remove_dir(&image);
824         archive
825     }
826 }
827
828 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
829 pub struct Analysis {
830     pub compiler: Compiler,
831     pub target: TargetSelection,
832 }
833
834 impl Step for Analysis {
835     type Output = PathBuf;
836     const DEFAULT: bool = true;
837
838     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
839         let builder = run.builder;
840         run.path("analysis").default_condition(builder.config.extended)
841     }
842
843     fn make_run(run: RunConfig<'_>) {
844         run.builder.ensure(Analysis {
845             // Find the actual compiler (handling the full bootstrap option) which
846             // produced the save-analysis data because that data isn't copied
847             // through the sysroot uplifting.
848             compiler: run.builder.compiler_for(
849                 run.builder.top_stage,
850                 run.builder.config.build,
851                 run.target,
852             ),
853             target: run.target,
854         });
855     }
856
857     /// Creates a tarball of save-analysis metadata, if available.
858     fn run(self, builder: &Builder<'_>) -> PathBuf {
859         let compiler = self.compiler;
860         let target = self.target;
861         assert!(builder.config.extended);
862         let name = pkgname(builder, "rust-analysis");
863
864         if compiler.host != builder.config.build {
865             return distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
866         }
867
868         builder.ensure(compile::Std { compiler, target });
869
870         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
871
872         let src = builder
873             .stage_out(compiler, Mode::Std)
874             .join(target.triple)
875             .join(builder.cargo_dir())
876             .join("deps");
877
878         let image_src = src.join("save-analysis");
879         let dst = image.join("lib/rustlib").join(target.triple).join("analysis");
880         t!(fs::create_dir_all(&dst));
881         builder.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst));
882         builder.cp_r(&image_src, &dst);
883
884         let mut cmd = rust_installer(builder);
885         cmd.arg("generate")
886             .arg("--product-name=Rust")
887             .arg("--rel-manifest-dir=rustlib")
888             .arg("--success-message=save-analysis-saved.")
889             .arg("--image-dir")
890             .arg(&image)
891             .arg("--work-dir")
892             .arg(&tmpdir(builder))
893             .arg("--output-dir")
894             .arg(&distdir(builder))
895             .arg(format!("--package-name={}-{}", name, target.triple))
896             .arg(format!("--component-name=rust-analysis-{}", target.triple))
897             .arg("--legacy-manifest-dirs=rustlib,cargo");
898
899         builder.info("Dist analysis");
900         let _time = timeit(builder);
901         builder.run(&mut cmd);
902         builder.remove_dir(&image);
903         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
904     }
905 }
906
907 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
908 /// `dst_dir`.
909 fn copy_src_dirs(
910     builder: &Builder<'_>,
911     base: &Path,
912     src_dirs: &[&str],
913     exclude_dirs: &[&str],
914     dst_dir: &Path,
915 ) {
916     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
917         let spath = match path.to_str() {
918             Some(path) => path,
919             None => return false,
920         };
921         if spath.ends_with('~') || spath.ends_with(".pyc") {
922             return false;
923         }
924
925         const LLVM_PROJECTS: &[&str] = &[
926             "llvm-project/clang",
927             "llvm-project\\clang",
928             "llvm-project/libunwind",
929             "llvm-project\\libunwind",
930             "llvm-project/lld",
931             "llvm-project\\lld",
932             "llvm-project/lldb",
933             "llvm-project\\lldb",
934             "llvm-project/llvm",
935             "llvm-project\\llvm",
936             "llvm-project/compiler-rt",
937             "llvm-project\\compiler-rt",
938         ];
939         if spath.contains("llvm-project")
940             && !spath.ends_with("llvm-project")
941             && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
942         {
943             return false;
944         }
945
946         const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
947         if LLVM_TEST.iter().any(|path| spath.contains(path))
948             && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
949         {
950             return false;
951         }
952
953         let full_path = Path::new(dir).join(path);
954         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
955             return false;
956         }
957
958         let excludes = [
959             "CVS",
960             "RCS",
961             "SCCS",
962             ".git",
963             ".gitignore",
964             ".gitmodules",
965             ".gitattributes",
966             ".cvsignore",
967             ".svn",
968             ".arch-ids",
969             "{arch}",
970             "=RELEASE-ID",
971             "=meta-update",
972             "=update",
973             ".bzr",
974             ".bzrignore",
975             ".bzrtags",
976             ".hg",
977             ".hgignore",
978             ".hgrags",
979             "_darcs",
980         ];
981         !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
982     }
983
984     // Copy the directories using our filter
985     for item in src_dirs {
986         let dst = &dst_dir.join(item);
987         t!(fs::create_dir_all(dst));
988         builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
989     }
990 }
991
992 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
993 pub struct Src;
994
995 impl Step for Src {
996     /// The output path of the src installer tarball
997     type Output = PathBuf;
998     const DEFAULT: bool = true;
999     const ONLY_HOSTS: bool = true;
1000
1001     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1002         run.path("src")
1003     }
1004
1005     fn make_run(run: RunConfig<'_>) {
1006         run.builder.ensure(Src);
1007     }
1008
1009     /// Creates the `rust-src` installer component
1010     fn run(self, builder: &Builder<'_>) -> PathBuf {
1011         let name = pkgname(builder, "rust-src");
1012         let image = tmpdir(builder).join(format!("{}-image", name));
1013         let _ = fs::remove_dir_all(&image);
1014
1015         // A lot of tools expect the rust-src component to be entirely in this directory, so if you
1016         // change that (e.g. by adding another directory `lib/rustlib/src/foo` or
1017         // `lib/rustlib/src/rust/foo`), you will need to go around hunting for implicit assumptions
1018         // and fix them...
1019         //
1020         // NOTE: if you update the paths here, you also should update the "virtual" path
1021         // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
1022         let dst_src = image.join("lib/rustlib/src/rust");
1023         t!(fs::create_dir_all(&dst_src));
1024
1025         let src_files = ["Cargo.lock"];
1026         // This is the reduced set of paths which will become the rust-src component
1027         // (essentially libstd and all of its path dependencies).
1028         copy_src_dirs(
1029             builder,
1030             &builder.src,
1031             &["library", "src/llvm-project/libunwind"],
1032             &[
1033                 // not needed and contains symlinks which rustup currently
1034                 // chokes on when unpacking.
1035                 "library/backtrace/crates",
1036             ],
1037             &dst_src,
1038         );
1039         for file in src_files.iter() {
1040             builder.copy(&builder.src.join(file), &dst_src.join(file));
1041         }
1042
1043         // Create source tarball in rust-installer format
1044         let mut cmd = rust_installer(builder);
1045         cmd.arg("generate")
1046             .arg("--product-name=Rust")
1047             .arg("--rel-manifest-dir=rustlib")
1048             .arg("--success-message=Awesome-Source.")
1049             .arg("--image-dir")
1050             .arg(&image)
1051             .arg("--work-dir")
1052             .arg(&tmpdir(builder))
1053             .arg("--output-dir")
1054             .arg(&distdir(builder))
1055             .arg(format!("--package-name={}", name))
1056             .arg("--component-name=rust-src")
1057             .arg("--legacy-manifest-dirs=rustlib,cargo");
1058
1059         builder.info("Dist src");
1060         let _time = timeit(builder);
1061         builder.run(&mut cmd);
1062
1063         builder.remove_dir(&image);
1064         distdir(builder).join(&format!("{}.tar.gz", name))
1065     }
1066 }
1067
1068 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1069 pub struct PlainSourceTarball;
1070
1071 impl Step for PlainSourceTarball {
1072     /// Produces the location of the tarball generated
1073     type Output = PathBuf;
1074     const DEFAULT: bool = true;
1075     const ONLY_HOSTS: bool = true;
1076
1077     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1078         let builder = run.builder;
1079         run.path("src").default_condition(builder.config.rust_dist_src)
1080     }
1081
1082     fn make_run(run: RunConfig<'_>) {
1083         run.builder.ensure(PlainSourceTarball);
1084     }
1085
1086     /// Creates the plain source tarball
1087     fn run(self, builder: &Builder<'_>) -> PathBuf {
1088         // Make sure that the root folder of tarball has the correct name
1089         let plain_name = format!("{}-src", pkgname(builder, "rustc"));
1090         let plain_dst_src = tmpdir(builder).join(&plain_name);
1091         let _ = fs::remove_dir_all(&plain_dst_src);
1092         t!(fs::create_dir_all(&plain_dst_src));
1093
1094         // This is the set of root paths which will become part of the source package
1095         let src_files = [
1096             "COPYRIGHT",
1097             "LICENSE-APACHE",
1098             "LICENSE-MIT",
1099             "CONTRIBUTING.md",
1100             "README.md",
1101             "RELEASES.md",
1102             "configure",
1103             "x.py",
1104             "config.toml.example",
1105             "Cargo.toml",
1106             "Cargo.lock",
1107         ];
1108         let src_dirs = ["src", "compiler", "library"];
1109
1110         copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
1111
1112         // Copy the files normally
1113         for item in &src_files {
1114             builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
1115         }
1116
1117         // Create the version file
1118         builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1119         if let Some(sha) = builder.rust_sha() {
1120             builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
1121         }
1122
1123         // If we're building from git sources, we need to vendor a complete distribution.
1124         if builder.rust_info.is_git() {
1125             // Vendor all Cargo dependencies
1126             let mut cmd = Command::new(&builder.initial_cargo);
1127             cmd.arg("vendor")
1128                 .arg("--sync")
1129                 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
1130                 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
1131                 .current_dir(&plain_dst_src);
1132             builder.run(&mut cmd);
1133         }
1134
1135         // Create plain source tarball
1136         let plain_name = format!("rustc-{}-src", builder.rust_package_vers());
1137         let mut tarball = distdir(builder).join(&format!("{}.tar.gz", plain_name));
1138         tarball.set_extension(""); // strip .gz
1139         tarball.set_extension(""); // strip .tar
1140         if let Some(dir) = tarball.parent() {
1141             builder.create_dir(&dir);
1142         }
1143         builder.info("running installer");
1144         let mut cmd = rust_installer(builder);
1145         cmd.arg("tarball")
1146             .arg("--input")
1147             .arg(&plain_name)
1148             .arg("--output")
1149             .arg(&tarball)
1150             .arg("--work-dir=.")
1151             .current_dir(tmpdir(builder));
1152
1153         builder.info("Create plain source tarball");
1154         let _time = timeit(builder);
1155         builder.run(&mut cmd);
1156         distdir(builder).join(&format!("{}.tar.gz", plain_name))
1157     }
1158 }
1159
1160 // We have to run a few shell scripts, which choke quite a bit on both `\`
1161 // characters and on `C:\` paths, so normalize both of them away.
1162 pub fn sanitize_sh(path: &Path) -> String {
1163     let path = path.to_str().unwrap().replace("\\", "/");
1164     return change_drive(&path).unwrap_or(path);
1165
1166     fn change_drive(s: &str) -> Option<String> {
1167         let mut ch = s.chars();
1168         let drive = ch.next().unwrap_or('C');
1169         if ch.next() != Some(':') {
1170             return None;
1171         }
1172         if ch.next() != Some('/') {
1173             return None;
1174         }
1175         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
1176     }
1177 }
1178
1179 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1180 pub struct Cargo {
1181     pub compiler: Compiler,
1182     pub target: TargetSelection,
1183 }
1184
1185 impl Step for Cargo {
1186     type Output = PathBuf;
1187     const ONLY_HOSTS: bool = true;
1188
1189     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1190         run.path("cargo")
1191     }
1192
1193     fn make_run(run: RunConfig<'_>) {
1194         run.builder.ensure(Cargo {
1195             compiler: run.builder.compiler_for(
1196                 run.builder.top_stage,
1197                 run.builder.config.build,
1198                 run.target,
1199             ),
1200             target: run.target,
1201         });
1202     }
1203
1204     fn run(self, builder: &Builder<'_>) -> PathBuf {
1205         let compiler = self.compiler;
1206         let target = self.target;
1207
1208         let src = builder.src.join("src/tools/cargo");
1209         let etc = src.join("src/etc");
1210         let release_num = builder.release_num("cargo");
1211         let name = pkgname(builder, "cargo");
1212         let version = builder.cargo_info.version(builder, &release_num);
1213
1214         let tmp = tmpdir(builder);
1215         let image = tmp.join("cargo-image");
1216         drop(fs::remove_dir_all(&image));
1217         builder.create_dir(&image);
1218
1219         // Prepare the image directory
1220         builder.create_dir(&image.join("share/zsh/site-functions"));
1221         builder.create_dir(&image.join("etc/bash_completion.d"));
1222         let cargo = builder.ensure(tool::Cargo { compiler, target });
1223         builder.install(&cargo, &image.join("bin"), 0o755);
1224         for man in t!(etc.join("man").read_dir()) {
1225             let man = t!(man);
1226             builder.install(&man.path(), &image.join("share/man/man1"), 0o644);
1227         }
1228         builder.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
1229         builder.copy(&etc.join("cargo.bashcomp.sh"), &image.join("etc/bash_completion.d/cargo"));
1230         let doc = image.join("share/doc/cargo");
1231         builder.install(&src.join("README.md"), &doc, 0o644);
1232         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1233         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1234         builder.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
1235
1236         // Prepare the overlay
1237         let overlay = tmp.join("cargo-overlay");
1238         drop(fs::remove_dir_all(&overlay));
1239         builder.create_dir(&overlay);
1240         builder.install(&src.join("README.md"), &overlay, 0o644);
1241         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1242         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1243         builder.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
1244         builder.create(&overlay.join("version"), &version);
1245
1246         // Generate the installer tarball
1247         let mut cmd = rust_installer(builder);
1248         cmd.arg("generate")
1249             .arg("--product-name=Rust")
1250             .arg("--rel-manifest-dir=rustlib")
1251             .arg("--success-message=Rust-is-ready-to-roll.")
1252             .arg("--image-dir")
1253             .arg(&image)
1254             .arg("--work-dir")
1255             .arg(&tmpdir(builder))
1256             .arg("--output-dir")
1257             .arg(&distdir(builder))
1258             .arg("--non-installed-overlay")
1259             .arg(&overlay)
1260             .arg(format!("--package-name={}-{}", name, target.triple))
1261             .arg("--component-name=cargo")
1262             .arg("--legacy-manifest-dirs=rustlib,cargo");
1263
1264         builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target));
1265         let _time = timeit(builder);
1266         builder.run(&mut cmd);
1267         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1268     }
1269 }
1270
1271 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1272 pub struct Rls {
1273     pub compiler: Compiler,
1274     pub target: TargetSelection,
1275 }
1276
1277 impl Step for Rls {
1278     type Output = Option<PathBuf>;
1279     const ONLY_HOSTS: bool = true;
1280
1281     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1282         run.path("rls")
1283     }
1284
1285     fn make_run(run: RunConfig<'_>) {
1286         run.builder.ensure(Rls {
1287             compiler: run.builder.compiler_for(
1288                 run.builder.top_stage,
1289                 run.builder.config.build,
1290                 run.target,
1291             ),
1292             target: run.target,
1293         });
1294     }
1295
1296     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1297         let compiler = self.compiler;
1298         let target = self.target;
1299         assert!(builder.config.extended);
1300
1301         let src = builder.src.join("src/tools/rls");
1302         let release_num = builder.release_num("rls");
1303         let name = pkgname(builder, "rls");
1304         let version = builder.rls_info.version(builder, &release_num);
1305
1306         let tmp = tmpdir(builder);
1307         let image = tmp.join("rls-image");
1308         drop(fs::remove_dir_all(&image));
1309         t!(fs::create_dir_all(&image));
1310
1311         // Prepare the image directory
1312         // We expect RLS to build, because we've exited this step above if tool
1313         // state for RLS isn't testing.
1314         let rls = builder
1315             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1316             .or_else(|| {
1317                 missing_tool("RLS", builder.build.config.missing_tools);
1318                 None
1319             })?;
1320
1321         builder.install(&rls, &image.join("bin"), 0o755);
1322         let doc = image.join("share/doc/rls");
1323         builder.install(&src.join("README.md"), &doc, 0o644);
1324         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1325         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1326
1327         // Prepare the overlay
1328         let overlay = tmp.join("rls-overlay");
1329         drop(fs::remove_dir_all(&overlay));
1330         t!(fs::create_dir_all(&overlay));
1331         builder.install(&src.join("README.md"), &overlay, 0o644);
1332         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1333         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1334         builder.create(&overlay.join("version"), &version);
1335
1336         // Generate the installer tarball
1337         let mut cmd = rust_installer(builder);
1338         cmd.arg("generate")
1339             .arg("--product-name=Rust")
1340             .arg("--rel-manifest-dir=rustlib")
1341             .arg("--success-message=RLS-ready-to-serve.")
1342             .arg("--image-dir")
1343             .arg(&image)
1344             .arg("--work-dir")
1345             .arg(&tmpdir(builder))
1346             .arg("--output-dir")
1347             .arg(&distdir(builder))
1348             .arg("--non-installed-overlay")
1349             .arg(&overlay)
1350             .arg(format!("--package-name={}-{}", name, target.triple))
1351             .arg("--legacy-manifest-dirs=rustlib,cargo")
1352             .arg("--component-name=rls-preview");
1353
1354         builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target.triple));
1355         let _time = timeit(builder);
1356         builder.run(&mut cmd);
1357         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1358     }
1359 }
1360
1361 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1362 pub struct RustAnalyzer {
1363     pub compiler: Compiler,
1364     pub target: TargetSelection,
1365 }
1366
1367 impl Step for RustAnalyzer {
1368     type Output = Option<PathBuf>;
1369     const ONLY_HOSTS: bool = true;
1370
1371     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1372         run.path("rust-analyzer")
1373     }
1374
1375     fn make_run(run: RunConfig<'_>) {
1376         run.builder.ensure(RustAnalyzer {
1377             compiler: run.builder.compiler_for(
1378                 run.builder.top_stage,
1379                 run.builder.config.build,
1380                 run.target,
1381             ),
1382             target: run.target,
1383         });
1384     }
1385
1386     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1387         let compiler = self.compiler;
1388         let target = self.target;
1389         assert!(builder.config.extended);
1390
1391         if target.contains("riscv64") {
1392             // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1393             // to build. See #74813 for details.
1394             return None;
1395         }
1396
1397         let src = builder.src.join("src/tools/rust-analyzer");
1398         let release_num = builder.release_num("rust-analyzer/crates/rust-analyzer");
1399         let name = pkgname(builder, "rust-analyzer");
1400         let version = builder.rust_analyzer_info.version(builder, &release_num);
1401
1402         let tmp = tmpdir(builder);
1403         let image = tmp.join("rust-analyzer-image");
1404         drop(fs::remove_dir_all(&image));
1405         builder.create_dir(&image);
1406
1407         // Prepare the image directory
1408         // We expect rust-analyer to always build, as it doesn't depend on rustc internals
1409         // and doesn't have associated toolstate.
1410         let rust_analyzer = builder
1411             .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1412             .expect("rust-analyzer always builds");
1413
1414         builder.install(&rust_analyzer, &image.join("bin"), 0o755);
1415         let doc = image.join("share/doc/rust-analyzer");
1416         builder.install(&src.join("README.md"), &doc, 0o644);
1417         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1418         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1419
1420         // Prepare the overlay
1421         let overlay = tmp.join("rust-analyzer-overlay");
1422         drop(fs::remove_dir_all(&overlay));
1423         t!(fs::create_dir_all(&overlay));
1424         builder.install(&src.join("README.md"), &overlay, 0o644);
1425         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1426         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1427         builder.create(&overlay.join("version"), &version);
1428
1429         // Generate the installer tarball
1430         let mut cmd = rust_installer(builder);
1431         cmd.arg("generate")
1432             .arg("--product-name=Rust")
1433             .arg("--rel-manifest-dir=rustlib")
1434             .arg("--success-message=rust-analyzer-ready-to-serve.")
1435             .arg("--image-dir")
1436             .arg(&image)
1437             .arg("--work-dir")
1438             .arg(&tmpdir(builder))
1439             .arg("--output-dir")
1440             .arg(&distdir(builder))
1441             .arg("--non-installed-overlay")
1442             .arg(&overlay)
1443             .arg(format!("--package-name={}-{}", name, target.triple))
1444             .arg("--legacy-manifest-dirs=rustlib,cargo")
1445             .arg("--component-name=rust-analyzer-preview");
1446
1447         builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target));
1448         let _time = timeit(builder);
1449         builder.run(&mut cmd);
1450         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1451     }
1452 }
1453
1454 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1455 pub struct Clippy {
1456     pub compiler: Compiler,
1457     pub target: TargetSelection,
1458 }
1459
1460 impl Step for Clippy {
1461     type Output = PathBuf;
1462     const ONLY_HOSTS: bool = true;
1463
1464     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1465         run.path("clippy")
1466     }
1467
1468     fn make_run(run: RunConfig<'_>) {
1469         run.builder.ensure(Clippy {
1470             compiler: run.builder.compiler_for(
1471                 run.builder.top_stage,
1472                 run.builder.config.build,
1473                 run.target,
1474             ),
1475             target: run.target,
1476         });
1477     }
1478
1479     fn run(self, builder: &Builder<'_>) -> PathBuf {
1480         let compiler = self.compiler;
1481         let target = self.target;
1482         assert!(builder.config.extended);
1483
1484         let src = builder.src.join("src/tools/clippy");
1485         let release_num = builder.release_num("clippy");
1486         let name = pkgname(builder, "clippy");
1487         let version = builder.clippy_info.version(builder, &release_num);
1488
1489         let tmp = tmpdir(builder);
1490         let image = tmp.join("clippy-image");
1491         drop(fs::remove_dir_all(&image));
1492         builder.create_dir(&image);
1493
1494         // Prepare the image directory
1495         // We expect clippy to build, because we've exited this step above if tool
1496         // state for clippy isn't testing.
1497         let clippy = builder
1498             .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1499             .expect("clippy expected to build - essential tool");
1500         let cargoclippy = builder
1501             .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1502             .expect("clippy expected to build - essential tool");
1503
1504         builder.install(&clippy, &image.join("bin"), 0o755);
1505         builder.install(&cargoclippy, &image.join("bin"), 0o755);
1506         let doc = image.join("share/doc/clippy");
1507         builder.install(&src.join("README.md"), &doc, 0o644);
1508         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1509         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1510
1511         // Prepare the overlay
1512         let overlay = tmp.join("clippy-overlay");
1513         drop(fs::remove_dir_all(&overlay));
1514         t!(fs::create_dir_all(&overlay));
1515         builder.install(&src.join("README.md"), &overlay, 0o644);
1516         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1517         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1518         builder.create(&overlay.join("version"), &version);
1519
1520         // Generate the installer tarball
1521         let mut cmd = rust_installer(builder);
1522         cmd.arg("generate")
1523             .arg("--product-name=Rust")
1524             .arg("--rel-manifest-dir=rustlib")
1525             .arg("--success-message=clippy-ready-to-serve.")
1526             .arg("--image-dir")
1527             .arg(&image)
1528             .arg("--work-dir")
1529             .arg(&tmpdir(builder))
1530             .arg("--output-dir")
1531             .arg(&distdir(builder))
1532             .arg("--non-installed-overlay")
1533             .arg(&overlay)
1534             .arg(format!("--package-name={}-{}", name, target.triple))
1535             .arg("--legacy-manifest-dirs=rustlib,cargo")
1536             .arg("--component-name=clippy-preview");
1537
1538         builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target));
1539         let _time = timeit(builder);
1540         builder.run(&mut cmd);
1541         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1542     }
1543 }
1544
1545 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1546 pub struct Miri {
1547     pub compiler: Compiler,
1548     pub target: TargetSelection,
1549 }
1550
1551 impl Step for Miri {
1552     type Output = Option<PathBuf>;
1553     const ONLY_HOSTS: bool = true;
1554
1555     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1556         run.path("miri")
1557     }
1558
1559     fn make_run(run: RunConfig<'_>) {
1560         run.builder.ensure(Miri {
1561             compiler: run.builder.compiler_for(
1562                 run.builder.top_stage,
1563                 run.builder.config.build,
1564                 run.target,
1565             ),
1566             target: run.target,
1567         });
1568     }
1569
1570     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1571         let compiler = self.compiler;
1572         let target = self.target;
1573         assert!(builder.config.extended);
1574
1575         let src = builder.src.join("src/tools/miri");
1576         let release_num = builder.release_num("miri");
1577         let name = pkgname(builder, "miri");
1578         let version = builder.miri_info.version(builder, &release_num);
1579
1580         let tmp = tmpdir(builder);
1581         let image = tmp.join("miri-image");
1582         drop(fs::remove_dir_all(&image));
1583         builder.create_dir(&image);
1584
1585         // Prepare the image directory
1586         // We expect miri to build, because we've exited this step above if tool
1587         // state for miri isn't testing.
1588         let miri = builder
1589             .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1590             .or_else(|| {
1591                 missing_tool("miri", builder.build.config.missing_tools);
1592                 None
1593             })?;
1594         let cargomiri = builder
1595             .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1596             .or_else(|| {
1597                 missing_tool("cargo miri", builder.build.config.missing_tools);
1598                 None
1599             })?;
1600
1601         builder.install(&miri, &image.join("bin"), 0o755);
1602         builder.install(&cargomiri, &image.join("bin"), 0o755);
1603         let doc = image.join("share/doc/miri");
1604         builder.install(&src.join("README.md"), &doc, 0o644);
1605         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1606         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1607
1608         // Prepare the overlay
1609         let overlay = tmp.join("miri-overlay");
1610         drop(fs::remove_dir_all(&overlay));
1611         t!(fs::create_dir_all(&overlay));
1612         builder.install(&src.join("README.md"), &overlay, 0o644);
1613         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1614         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1615         builder.create(&overlay.join("version"), &version);
1616
1617         // Generate the installer tarball
1618         let mut cmd = rust_installer(builder);
1619         cmd.arg("generate")
1620             .arg("--product-name=Rust")
1621             .arg("--rel-manifest-dir=rustlib")
1622             .arg("--success-message=miri-ready-to-serve.")
1623             .arg("--image-dir")
1624             .arg(&image)
1625             .arg("--work-dir")
1626             .arg(&tmpdir(builder))
1627             .arg("--output-dir")
1628             .arg(&distdir(builder))
1629             .arg("--non-installed-overlay")
1630             .arg(&overlay)
1631             .arg(format!("--package-name={}-{}", name, target.triple))
1632             .arg("--legacy-manifest-dirs=rustlib,cargo")
1633             .arg("--component-name=miri-preview");
1634
1635         builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target));
1636         let _time = timeit(builder);
1637         builder.run(&mut cmd);
1638         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1639     }
1640 }
1641
1642 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1643 pub struct Rustfmt {
1644     pub compiler: Compiler,
1645     pub target: TargetSelection,
1646 }
1647
1648 impl Step for Rustfmt {
1649     type Output = Option<PathBuf>;
1650     const ONLY_HOSTS: bool = true;
1651
1652     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1653         run.path("rustfmt")
1654     }
1655
1656     fn make_run(run: RunConfig<'_>) {
1657         run.builder.ensure(Rustfmt {
1658             compiler: run.builder.compiler_for(
1659                 run.builder.top_stage,
1660                 run.builder.config.build,
1661                 run.target,
1662             ),
1663             target: run.target,
1664         });
1665     }
1666
1667     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1668         let compiler = self.compiler;
1669         let target = self.target;
1670
1671         let src = builder.src.join("src/tools/rustfmt");
1672         let release_num = builder.release_num("rustfmt");
1673         let name = pkgname(builder, "rustfmt");
1674         let version = builder.rustfmt_info.version(builder, &release_num);
1675
1676         let tmp = tmpdir(builder);
1677         let image = tmp.join("rustfmt-image");
1678         drop(fs::remove_dir_all(&image));
1679         builder.create_dir(&image);
1680
1681         // Prepare the image directory
1682         let rustfmt = builder
1683             .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1684             .or_else(|| {
1685                 missing_tool("Rustfmt", builder.build.config.missing_tools);
1686                 None
1687             })?;
1688         let cargofmt = builder
1689             .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1690             .or_else(|| {
1691                 missing_tool("Cargofmt", builder.build.config.missing_tools);
1692                 None
1693             })?;
1694
1695         builder.install(&rustfmt, &image.join("bin"), 0o755);
1696         builder.install(&cargofmt, &image.join("bin"), 0o755);
1697         let doc = image.join("share/doc/rustfmt");
1698         builder.install(&src.join("README.md"), &doc, 0o644);
1699         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1700         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1701
1702         // Prepare the overlay
1703         let overlay = tmp.join("rustfmt-overlay");
1704         drop(fs::remove_dir_all(&overlay));
1705         builder.create_dir(&overlay);
1706         builder.install(&src.join("README.md"), &overlay, 0o644);
1707         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1708         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1709         builder.create(&overlay.join("version"), &version);
1710
1711         // Generate the installer tarball
1712         let mut cmd = rust_installer(builder);
1713         cmd.arg("generate")
1714             .arg("--product-name=Rust")
1715             .arg("--rel-manifest-dir=rustlib")
1716             .arg("--success-message=rustfmt-ready-to-fmt.")
1717             .arg("--image-dir")
1718             .arg(&image)
1719             .arg("--work-dir")
1720             .arg(&tmpdir(builder))
1721             .arg("--output-dir")
1722             .arg(&distdir(builder))
1723             .arg("--non-installed-overlay")
1724             .arg(&overlay)
1725             .arg(format!("--package-name={}-{}", name, target.triple))
1726             .arg("--legacy-manifest-dirs=rustlib,cargo")
1727             .arg("--component-name=rustfmt-preview");
1728
1729         builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target));
1730         let _time = timeit(builder);
1731         builder.run(&mut cmd);
1732         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1733     }
1734 }
1735
1736 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1737 pub struct Extended {
1738     stage: u32,
1739     host: TargetSelection,
1740     target: TargetSelection,
1741 }
1742
1743 impl Step for Extended {
1744     type Output = ();
1745     const DEFAULT: bool = true;
1746     const ONLY_HOSTS: bool = true;
1747
1748     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1749         let builder = run.builder;
1750         run.path("extended").default_condition(builder.config.extended)
1751     }
1752
1753     fn make_run(run: RunConfig<'_>) {
1754         run.builder.ensure(Extended {
1755             stage: run.builder.top_stage,
1756             host: run.builder.config.build,
1757             target: run.target,
1758         });
1759     }
1760
1761     /// Creates a combined installer for the specified target in the provided stage.
1762     fn run(self, builder: &Builder<'_>) {
1763         let target = self.target;
1764         let stage = self.stage;
1765         let compiler = builder.compiler_for(self.stage, self.host, self.target);
1766
1767         builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1768
1769         let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
1770         let cargo_installer = builder.ensure(Cargo { compiler, target });
1771         let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1772         let rls_installer = builder.ensure(Rls { compiler, target });
1773         let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
1774         let llvm_tools_installer = builder.ensure(LlvmTools { target });
1775         let clippy_installer = builder.ensure(Clippy { compiler, target });
1776         let miri_installer = builder.ensure(Miri { compiler, target });
1777         let mingw_installer = builder.ensure(Mingw { host: target });
1778         let analysis_installer = builder.ensure(Analysis { compiler, target });
1779
1780         let docs_installer = builder.ensure(Docs { host: target });
1781         let std_installer =
1782             builder.ensure(Std { compiler: builder.compiler(stage, target), target });
1783
1784         let tmp = tmpdir(builder);
1785         let overlay = tmp.join("extended-overlay");
1786         let etc = builder.src.join("src/etc/installer");
1787         let work = tmp.join("work");
1788
1789         let _ = fs::remove_dir_all(&overlay);
1790         builder.install(&builder.src.join("COPYRIGHT"), &overlay, 0o644);
1791         builder.install(&builder.src.join("LICENSE-APACHE"), &overlay, 0o644);
1792         builder.install(&builder.src.join("LICENSE-MIT"), &overlay, 0o644);
1793         let version = builder.rust_version();
1794         builder.create(&overlay.join("version"), &version);
1795         if let Some(sha) = builder.rust_sha() {
1796             builder.create(&overlay.join("git-commit-hash"), &sha);
1797         }
1798         builder.install(&etc.join("README.md"), &overlay, 0o644);
1799
1800         // When rust-std package split from rustc, we needed to ensure that during
1801         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1802         // the std files during uninstall. To do this ensure that rustc comes
1803         // before rust-std in the list below.
1804         let mut tarballs = Vec::new();
1805         tarballs.push(rustc_installer);
1806         tarballs.push(cargo_installer);
1807         tarballs.extend(rls_installer.clone());
1808         tarballs.extend(rust_analyzer_installer.clone());
1809         tarballs.push(clippy_installer);
1810         tarballs.extend(miri_installer.clone());
1811         tarballs.extend(rustfmt_installer.clone());
1812         tarballs.extend(llvm_tools_installer);
1813         tarballs.push(analysis_installer);
1814         tarballs.push(std_installer);
1815         if builder.config.docs {
1816             tarballs.push(docs_installer);
1817         }
1818         if target.contains("pc-windows-gnu") {
1819             tarballs.push(mingw_installer.unwrap());
1820         }
1821         let mut input_tarballs = tarballs[0].as_os_str().to_owned();
1822         for tarball in &tarballs[1..] {
1823             input_tarballs.push(",");
1824             input_tarballs.push(tarball);
1825         }
1826
1827         builder.info("building combined installer");
1828         let mut cmd = rust_installer(builder);
1829         cmd.arg("combine")
1830             .arg("--product-name=Rust")
1831             .arg("--rel-manifest-dir=rustlib")
1832             .arg("--success-message=Rust-is-ready-to-roll.")
1833             .arg("--work-dir")
1834             .arg(&work)
1835             .arg("--output-dir")
1836             .arg(&distdir(builder))
1837             .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target.triple))
1838             .arg("--legacy-manifest-dirs=rustlib,cargo")
1839             .arg("--input-tarballs")
1840             .arg(input_tarballs)
1841             .arg("--non-installed-overlay")
1842             .arg(&overlay);
1843         let time = timeit(&builder);
1844         builder.run(&mut cmd);
1845         drop(time);
1846
1847         let mut license = String::new();
1848         license += &builder.read(&builder.src.join("COPYRIGHT"));
1849         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1850         license += &builder.read(&builder.src.join("LICENSE-MIT"));
1851         license.push_str("\n");
1852         license.push_str("\n");
1853
1854         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1855         let mut rtf = rtf.to_string();
1856         rtf.push_str("\n");
1857         for line in license.lines() {
1858             rtf.push_str(line);
1859             rtf.push_str("\\line ");
1860         }
1861         rtf.push_str("}");
1862
1863         fn filter(contents: &str, marker: &str) -> String {
1864             let start = format!("tool-{}-start", marker);
1865             let end = format!("tool-{}-end", marker);
1866             let mut lines = Vec::new();
1867             let mut omitted = false;
1868             for line in contents.lines() {
1869                 if line.contains(&start) {
1870                     omitted = true;
1871                 } else if line.contains(&end) {
1872                     omitted = false;
1873                 } else if !omitted {
1874                     lines.push(line);
1875                 }
1876             }
1877
1878             lines.join("\n")
1879         }
1880
1881         let xform = |p: &Path| {
1882             let mut contents = t!(fs::read_to_string(p));
1883             if rls_installer.is_none() {
1884                 contents = filter(&contents, "rls");
1885             }
1886             if rust_analyzer_installer.is_none() {
1887                 contents = filter(&contents, "rust-analyzer");
1888             }
1889             if miri_installer.is_none() {
1890                 contents = filter(&contents, "miri");
1891             }
1892             if rustfmt_installer.is_none() {
1893                 contents = filter(&contents, "rustfmt");
1894             }
1895             let ret = tmp.join(p.file_name().unwrap());
1896             t!(fs::write(&ret, &contents));
1897             ret
1898         };
1899
1900         if target.contains("apple-darwin") {
1901             builder.info("building pkg installer");
1902             let pkg = tmp.join("pkg");
1903             let _ = fs::remove_dir_all(&pkg);
1904
1905             let pkgbuild = |component: &str| {
1906                 let mut cmd = Command::new("pkgbuild");
1907                 cmd.arg("--identifier")
1908                     .arg(format!("org.rust-lang.{}", component))
1909                     .arg("--scripts")
1910                     .arg(pkg.join(component))
1911                     .arg("--nopayload")
1912                     .arg(pkg.join(component).with_extension("pkg"));
1913                 builder.run(&mut cmd);
1914             };
1915
1916             let prepare = |name: &str| {
1917                 builder.create_dir(&pkg.join(name));
1918                 builder.cp_r(
1919                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1920                     &pkg.join(name),
1921                 );
1922                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1923                 pkgbuild(name);
1924             };
1925             prepare("rustc");
1926             prepare("cargo");
1927             prepare("rust-docs");
1928             prepare("rust-std");
1929             prepare("rust-analysis");
1930             prepare("clippy");
1931
1932             if rls_installer.is_some() {
1933                 prepare("rls");
1934             }
1935             if rust_analyzer_installer.is_some() {
1936                 prepare("rust-analyzer");
1937             }
1938             if miri_installer.is_some() {
1939                 prepare("miri");
1940             }
1941
1942             // create an 'uninstall' package
1943             builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1944             pkgbuild("uninstall");
1945
1946             builder.create_dir(&pkg.join("res"));
1947             builder.create(&pkg.join("res/LICENSE.txt"), &license);
1948             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1949             let mut cmd = Command::new("productbuild");
1950             cmd.arg("--distribution")
1951                 .arg(xform(&etc.join("pkg/Distribution.xml")))
1952                 .arg("--resources")
1953                 .arg(pkg.join("res"))
1954                 .arg(distdir(builder).join(format!(
1955                     "{}-{}.pkg",
1956                     pkgname(builder, "rust"),
1957                     target.triple
1958                 )))
1959                 .arg("--package-path")
1960                 .arg(&pkg);
1961             let _time = timeit(builder);
1962             builder.run(&mut cmd);
1963         }
1964
1965         if target.contains("windows") {
1966             let exe = tmp.join("exe");
1967             let _ = fs::remove_dir_all(&exe);
1968
1969             let prepare = |name: &str| {
1970                 builder.create_dir(&exe.join(name));
1971                 let dir = if name == "rust-std" || name == "rust-analysis" {
1972                     format!("{}-{}", name, target.triple)
1973                 } else if name == "rls" {
1974                     "rls-preview".to_string()
1975                 } else if name == "rust-analyzer" {
1976                     "rust-analyzer-preview".to_string()
1977                 } else if name == "clippy" {
1978                     "clippy-preview".to_string()
1979                 } else if name == "miri" {
1980                     "miri-preview".to_string()
1981                 } else {
1982                     name.to_string()
1983                 };
1984                 builder.cp_r(
1985                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1986                     &exe.join(name),
1987                 );
1988                 builder.remove(&exe.join(name).join("manifest.in"));
1989             };
1990             prepare("rustc");
1991             prepare("cargo");
1992             prepare("rust-analysis");
1993             prepare("rust-docs");
1994             prepare("rust-std");
1995             prepare("clippy");
1996             if rls_installer.is_some() {
1997                 prepare("rls");
1998             }
1999             if rust_analyzer_installer.is_some() {
2000                 prepare("rust-analyzer");
2001             }
2002             if miri_installer.is_some() {
2003                 prepare("miri");
2004             }
2005             if target.contains("windows-gnu") {
2006                 prepare("rust-mingw");
2007             }
2008
2009             builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
2010
2011             // Generate msi installer
2012             let wix = PathBuf::from(env::var_os("WIX").unwrap());
2013             let heat = wix.join("bin/heat.exe");
2014             let candle = wix.join("bin/candle.exe");
2015             let light = wix.join("bin/light.exe");
2016
2017             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2018             builder.run(
2019                 Command::new(&heat)
2020                     .current_dir(&exe)
2021                     .arg("dir")
2022                     .arg("rustc")
2023                     .args(&heat_flags)
2024                     .arg("-cg")
2025                     .arg("RustcGroup")
2026                     .arg("-dr")
2027                     .arg("Rustc")
2028                     .arg("-var")
2029                     .arg("var.RustcDir")
2030                     .arg("-out")
2031                     .arg(exe.join("RustcGroup.wxs")),
2032             );
2033             builder.run(
2034                 Command::new(&heat)
2035                     .current_dir(&exe)
2036                     .arg("dir")
2037                     .arg("rust-docs")
2038                     .args(&heat_flags)
2039                     .arg("-cg")
2040                     .arg("DocsGroup")
2041                     .arg("-dr")
2042                     .arg("Docs")
2043                     .arg("-var")
2044                     .arg("var.DocsDir")
2045                     .arg("-out")
2046                     .arg(exe.join("DocsGroup.wxs"))
2047                     .arg("-t")
2048                     .arg(etc.join("msi/squash-components.xsl")),
2049             );
2050             builder.run(
2051                 Command::new(&heat)
2052                     .current_dir(&exe)
2053                     .arg("dir")
2054                     .arg("cargo")
2055                     .args(&heat_flags)
2056                     .arg("-cg")
2057                     .arg("CargoGroup")
2058                     .arg("-dr")
2059                     .arg("Cargo")
2060                     .arg("-var")
2061                     .arg("var.CargoDir")
2062                     .arg("-out")
2063                     .arg(exe.join("CargoGroup.wxs"))
2064                     .arg("-t")
2065                     .arg(etc.join("msi/remove-duplicates.xsl")),
2066             );
2067             builder.run(
2068                 Command::new(&heat)
2069                     .current_dir(&exe)
2070                     .arg("dir")
2071                     .arg("rust-std")
2072                     .args(&heat_flags)
2073                     .arg("-cg")
2074                     .arg("StdGroup")
2075                     .arg("-dr")
2076                     .arg("Std")
2077                     .arg("-var")
2078                     .arg("var.StdDir")
2079                     .arg("-out")
2080                     .arg(exe.join("StdGroup.wxs")),
2081             );
2082             if rls_installer.is_some() {
2083                 builder.run(
2084                     Command::new(&heat)
2085                         .current_dir(&exe)
2086                         .arg("dir")
2087                         .arg("rls")
2088                         .args(&heat_flags)
2089                         .arg("-cg")
2090                         .arg("RlsGroup")
2091                         .arg("-dr")
2092                         .arg("Rls")
2093                         .arg("-var")
2094                         .arg("var.RlsDir")
2095                         .arg("-out")
2096                         .arg(exe.join("RlsGroup.wxs"))
2097                         .arg("-t")
2098                         .arg(etc.join("msi/remove-duplicates.xsl")),
2099                 );
2100             }
2101             if rust_analyzer_installer.is_some() {
2102                 builder.run(
2103                     Command::new(&heat)
2104                         .current_dir(&exe)
2105                         .arg("dir")
2106                         .arg("rust-analyzer")
2107                         .args(&heat_flags)
2108                         .arg("-cg")
2109                         .arg("RustAnalyzerGroup")
2110                         .arg("-dr")
2111                         .arg("RustAnalyzer")
2112                         .arg("-var")
2113                         .arg("var.RustAnalyzerDir")
2114                         .arg("-out")
2115                         .arg(exe.join("RustAnalyzerGroup.wxs"))
2116                         .arg("-t")
2117                         .arg(etc.join("msi/remove-duplicates.xsl")),
2118                 );
2119             }
2120             builder.run(
2121                 Command::new(&heat)
2122                     .current_dir(&exe)
2123                     .arg("dir")
2124                     .arg("clippy")
2125                     .args(&heat_flags)
2126                     .arg("-cg")
2127                     .arg("ClippyGroup")
2128                     .arg("-dr")
2129                     .arg("Clippy")
2130                     .arg("-var")
2131                     .arg("var.ClippyDir")
2132                     .arg("-out")
2133                     .arg(exe.join("ClippyGroup.wxs"))
2134                     .arg("-t")
2135                     .arg(etc.join("msi/remove-duplicates.xsl")),
2136             );
2137             if miri_installer.is_some() {
2138                 builder.run(
2139                     Command::new(&heat)
2140                         .current_dir(&exe)
2141                         .arg("dir")
2142                         .arg("miri")
2143                         .args(&heat_flags)
2144                         .arg("-cg")
2145                         .arg("MiriGroup")
2146                         .arg("-dr")
2147                         .arg("Miri")
2148                         .arg("-var")
2149                         .arg("var.MiriDir")
2150                         .arg("-out")
2151                         .arg(exe.join("MiriGroup.wxs"))
2152                         .arg("-t")
2153                         .arg(etc.join("msi/remove-duplicates.xsl")),
2154                 );
2155             }
2156             builder.run(
2157                 Command::new(&heat)
2158                     .current_dir(&exe)
2159                     .arg("dir")
2160                     .arg("rust-analysis")
2161                     .args(&heat_flags)
2162                     .arg("-cg")
2163                     .arg("AnalysisGroup")
2164                     .arg("-dr")
2165                     .arg("Analysis")
2166                     .arg("-var")
2167                     .arg("var.AnalysisDir")
2168                     .arg("-out")
2169                     .arg(exe.join("AnalysisGroup.wxs"))
2170                     .arg("-t")
2171                     .arg(etc.join("msi/remove-duplicates.xsl")),
2172             );
2173             if target.contains("windows-gnu") {
2174                 builder.run(
2175                     Command::new(&heat)
2176                         .current_dir(&exe)
2177                         .arg("dir")
2178                         .arg("rust-mingw")
2179                         .args(&heat_flags)
2180                         .arg("-cg")
2181                         .arg("GccGroup")
2182                         .arg("-dr")
2183                         .arg("Gcc")
2184                         .arg("-var")
2185                         .arg("var.GccDir")
2186                         .arg("-out")
2187                         .arg(exe.join("GccGroup.wxs")),
2188                 );
2189             }
2190
2191             let candle = |input: &Path| {
2192                 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2193                 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2194                 let mut cmd = Command::new(&candle);
2195                 cmd.current_dir(&exe)
2196                     .arg("-nologo")
2197                     .arg("-dRustcDir=rustc")
2198                     .arg("-dDocsDir=rust-docs")
2199                     .arg("-dCargoDir=cargo")
2200                     .arg("-dStdDir=rust-std")
2201                     .arg("-dAnalysisDir=rust-analysis")
2202                     .arg("-dClippyDir=clippy")
2203                     .arg("-arch")
2204                     .arg(&arch)
2205                     .arg("-out")
2206                     .arg(&output)
2207                     .arg(&input);
2208                 add_env(builder, &mut cmd, target);
2209
2210                 if rls_installer.is_some() {
2211                     cmd.arg("-dRlsDir=rls");
2212                 }
2213                 if rust_analyzer_installer.is_some() {
2214                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2215                 }
2216                 if miri_installer.is_some() {
2217                     cmd.arg("-dMiriDir=miri");
2218                 }
2219                 if target.contains("windows-gnu") {
2220                     cmd.arg("-dGccDir=rust-mingw");
2221                 }
2222                 builder.run(&mut cmd);
2223             };
2224             candle(&xform(&etc.join("msi/rust.wxs")));
2225             candle(&etc.join("msi/ui.wxs"));
2226             candle(&etc.join("msi/rustwelcomedlg.wxs"));
2227             candle("RustcGroup.wxs".as_ref());
2228             candle("DocsGroup.wxs".as_ref());
2229             candle("CargoGroup.wxs".as_ref());
2230             candle("StdGroup.wxs".as_ref());
2231             candle("ClippyGroup.wxs".as_ref());
2232             if rls_installer.is_some() {
2233                 candle("RlsGroup.wxs".as_ref());
2234             }
2235             if rust_analyzer_installer.is_some() {
2236                 candle("RustAnalyzerGroup.wxs".as_ref());
2237             }
2238             if miri_installer.is_some() {
2239                 candle("MiriGroup.wxs".as_ref());
2240             }
2241             candle("AnalysisGroup.wxs".as_ref());
2242
2243             if target.contains("windows-gnu") {
2244                 candle("GccGroup.wxs".as_ref());
2245             }
2246
2247             builder.create(&exe.join("LICENSE.rtf"), &rtf);
2248             builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
2249             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
2250
2251             builder.info(&format!("building `msi` installer with {:?}", light));
2252             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2253             let mut cmd = Command::new(&light);
2254             cmd.arg("-nologo")
2255                 .arg("-ext")
2256                 .arg("WixUIExtension")
2257                 .arg("-ext")
2258                 .arg("WixUtilExtension")
2259                 .arg("-out")
2260                 .arg(exe.join(&filename))
2261                 .arg("rust.wixobj")
2262                 .arg("ui.wixobj")
2263                 .arg("rustwelcomedlg.wixobj")
2264                 .arg("RustcGroup.wixobj")
2265                 .arg("DocsGroup.wixobj")
2266                 .arg("CargoGroup.wixobj")
2267                 .arg("StdGroup.wixobj")
2268                 .arg("AnalysisGroup.wixobj")
2269                 .arg("ClippyGroup.wixobj")
2270                 .current_dir(&exe);
2271
2272             if rls_installer.is_some() {
2273                 cmd.arg("RlsGroup.wixobj");
2274             }
2275             if rust_analyzer_installer.is_some() {
2276                 cmd.arg("RustAnalyzerGroup.wixobj");
2277             }
2278             if miri_installer.is_some() {
2279                 cmd.arg("MiriGroup.wixobj");
2280             }
2281
2282             if target.contains("windows-gnu") {
2283                 cmd.arg("GccGroup.wixobj");
2284             }
2285             // ICE57 wrongly complains about the shortcuts
2286             cmd.arg("-sice:ICE57");
2287
2288             let _time = timeit(builder);
2289             builder.run(&mut cmd);
2290
2291             if !builder.config.dry_run {
2292                 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
2293             }
2294         }
2295     }
2296 }
2297
2298 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
2299     let mut parts = builder.version.split('.');
2300     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2301         .env("CFG_RELEASE_NUM", &builder.version)
2302         .env("CFG_RELEASE", builder.rust_release())
2303         .env("CFG_VER_MAJOR", parts.next().unwrap())
2304         .env("CFG_VER_MINOR", parts.next().unwrap())
2305         .env("CFG_VER_PATCH", parts.next().unwrap())
2306         .env("CFG_VER_BUILD", "0") // just needed to build
2307         .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2308         .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2309         .env("CFG_BUILD", target.triple)
2310         .env("CFG_CHANNEL", &builder.config.channel);
2311
2312     if target.contains("windows-gnu") {
2313         cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2314     } else {
2315         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2316     }
2317
2318     if target.contains("x86_64") {
2319         cmd.env("CFG_PLATFORM", "x64");
2320     } else {
2321         cmd.env("CFG_PLATFORM", "x86");
2322     }
2323 }
2324
2325 /// Maybe add libLLVM.so to the given destination lib-dir. It will only have
2326 /// been built if LLVM tools are linked dynamically.
2327 ///
2328 /// Note: This function does not yet support Windows, but we also don't support
2329 ///       linking LLVM tools dynamically on Windows yet.
2330 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) {
2331     if !builder.config.llvm_link_shared {
2332         // We do not need to copy LLVM files into the sysroot if it is not
2333         // dynamically linked; it is already included into librustc_llvm
2334         // statically.
2335         return;
2336     }
2337
2338     // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
2339     // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
2340     // clear why this is the case, though. llvm-config will emit the versioned
2341     // paths and we don't want those in the sysroot (as we're expecting
2342     // unversioned paths).
2343     if target.contains("apple-darwin") {
2344         let src_libdir = builder.llvm_out(target).join("lib");
2345         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2346         if llvm_dylib_path.exists() {
2347             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
2348         }
2349     } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
2350         let files = output(Command::new(llvm_config).arg("--libfiles"));
2351         for file in files.lines() {
2352             builder.install(Path::new(file), dst_libdir, 0o644);
2353         }
2354     }
2355 }
2356
2357 /// Maybe add libLLVM.so to the target lib-dir for linking.
2358 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2359     let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
2360     maybe_install_llvm(builder, target, &dst_libdir);
2361 }
2362
2363 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
2364 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2365     let dst_libdir =
2366         sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
2367     maybe_install_llvm(builder, target, &dst_libdir);
2368 }
2369
2370 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2371 pub struct LlvmTools {
2372     pub target: TargetSelection,
2373 }
2374
2375 impl Step for LlvmTools {
2376     type Output = Option<PathBuf>;
2377     const ONLY_HOSTS: bool = true;
2378
2379     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2380         run.path("llvm-tools")
2381     }
2382
2383     fn make_run(run: RunConfig<'_>) {
2384         run.builder.ensure(LlvmTools { target: run.target });
2385     }
2386
2387     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
2388         let target = self.target;
2389         assert!(builder.config.extended);
2390
2391         /* run only if llvm-config isn't used */
2392         if let Some(config) = builder.config.target_config.get(&target) {
2393             if let Some(ref _s) = config.llvm_config {
2394                 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
2395                 return None;
2396             }
2397         }
2398
2399         builder.info(&format!("Dist LlvmTools ({})", target));
2400         let _time = timeit(builder);
2401         let src = builder.src.join("src/llvm-project/llvm");
2402         let name = pkgname(builder, "llvm-tools");
2403
2404         let tmp = tmpdir(builder);
2405         let image = tmp.join("llvm-tools-image");
2406         drop(fs::remove_dir_all(&image));
2407
2408         // Prepare the image directory
2409         let src_bindir = builder.llvm_out(target).join("bin");
2410         let dst_bindir = image.join("lib/rustlib").join(&*target.triple).join("bin");
2411         t!(fs::create_dir_all(&dst_bindir));
2412         for tool in LLVM_TOOLS {
2413             let exe = src_bindir.join(exe(tool, target));
2414             builder.install(&exe, &dst_bindir, 0o755);
2415         }
2416
2417         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2418         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2419         // of `rustc-dev` to support the inherited `-lLLVM` when using the
2420         // compiler libraries.
2421         maybe_install_llvm_target(builder, target, &image);
2422
2423         // Prepare the overlay
2424         let overlay = tmp.join("llvm-tools-overlay");
2425         drop(fs::remove_dir_all(&overlay));
2426         builder.create_dir(&overlay);
2427         builder.install(&src.join("README.txt"), &overlay, 0o644);
2428         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
2429         builder.create(&overlay.join("version"), &builder.llvm_tools_vers());
2430
2431         // Generate the installer tarball
2432         let mut cmd = rust_installer(builder);
2433         cmd.arg("generate")
2434             .arg("--product-name=Rust")
2435             .arg("--rel-manifest-dir=rustlib")
2436             .arg("--success-message=llvm-tools-installed.")
2437             .arg("--image-dir")
2438             .arg(&image)
2439             .arg("--work-dir")
2440             .arg(&tmpdir(builder))
2441             .arg("--output-dir")
2442             .arg(&distdir(builder))
2443             .arg("--non-installed-overlay")
2444             .arg(&overlay)
2445             .arg(format!("--package-name={}-{}", name, target.triple))
2446             .arg("--legacy-manifest-dirs=rustlib,cargo")
2447             .arg("--component-name=llvm-tools-preview");
2448
2449         builder.run(&mut cmd);
2450         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
2451     }
2452 }
2453
2454 // Tarball intended for internal consumption to ease rustc/std development.
2455 //
2456 // Should not be considered stable by end users.
2457 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2458 pub struct RustDev {
2459     pub target: TargetSelection,
2460 }
2461
2462 impl Step for RustDev {
2463     type Output = Option<PathBuf>;
2464     const DEFAULT: bool = true;
2465     const ONLY_HOSTS: bool = true;
2466
2467     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2468         run.path("rust-dev")
2469     }
2470
2471     fn make_run(run: RunConfig<'_>) {
2472         run.builder.ensure(RustDev { target: run.target });
2473     }
2474
2475     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
2476         let target = self.target;
2477
2478         /* run only if llvm-config isn't used */
2479         if let Some(config) = builder.config.target_config.get(&target) {
2480             if let Some(ref _s) = config.llvm_config {
2481                 builder.info(&format!("Skipping RustDev ({}): external LLVM", target));
2482                 return None;
2483             }
2484         }
2485
2486         builder.info(&format!("Dist RustDev ({})", target));
2487         let _time = timeit(builder);
2488         let src = builder.src.join("src/llvm-project/llvm");
2489         let name = pkgname(builder, "rust-dev");
2490
2491         let tmp = tmpdir(builder);
2492         let image = tmp.join("rust-dev-image");
2493         drop(fs::remove_dir_all(&image));
2494
2495         // Prepare the image directory
2496         let dst_bindir = image.join("bin");
2497         t!(fs::create_dir_all(&dst_bindir));
2498
2499         let src_bindir = builder.llvm_out(target).join("bin");
2500         let install_bin =
2501             |name| builder.install(&src_bindir.join(exe(name, target)), &dst_bindir, 0o755);
2502         install_bin("llvm-config");
2503         install_bin("llvm-ar");
2504         install_bin("llvm-objdump");
2505         install_bin("llvm-profdata");
2506         install_bin("llvm-bcanalyzer");
2507         install_bin("llvm-cov");
2508         builder.install(&builder.llvm_filecheck(target), &dst_bindir, 0o755);
2509
2510         // Copy the include directory as well; needed mostly to build
2511         // librustc_llvm properly (e.g., llvm-config.h is in here). But also
2512         // just broadly useful to be able to link against the bundled LLVM.
2513         builder.cp_r(&builder.llvm_out(target).join("include"), &image.join("include"));
2514
2515         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2516         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2517         // of `rustc-dev` to support the inherited `-lLLVM` when using the
2518         // compiler libraries.
2519         maybe_install_llvm(builder, target, &image.join("lib"));
2520
2521         // Prepare the overlay
2522         let overlay = tmp.join("rust-dev-overlay");
2523         drop(fs::remove_dir_all(&overlay));
2524         builder.create_dir(&overlay);
2525         builder.install(&src.join("README.txt"), &overlay, 0o644);
2526         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
2527         builder.create(&overlay.join("version"), &builder.rust_version());
2528
2529         // Generate the installer tarball
2530         let mut cmd = rust_installer(builder);
2531         cmd.arg("generate")
2532             .arg("--product-name=Rust")
2533             .arg("--rel-manifest-dir=rustlib")
2534             .arg("--success-message=rust-dev-installed.")
2535             .arg("--image-dir")
2536             .arg(&image)
2537             .arg("--work-dir")
2538             .arg(&tmpdir(builder))
2539             .arg("--output-dir")
2540             .arg(&distdir(builder))
2541             .arg("--non-installed-overlay")
2542             .arg(&overlay)
2543             .arg(format!("--package-name={}-{}", name, target.triple))
2544             .arg("--legacy-manifest-dirs=rustlib,cargo")
2545             .arg("--component-name=rust-dev");
2546
2547         builder.run(&mut cmd);
2548         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
2549     }
2550 }
2551
2552 /// Tarball containing a prebuilt version of the build-manifest tool, intented to be used by the
2553 /// release process to avoid cloning the monorepo and building stuff.
2554 ///
2555 /// Should not be considered stable by end users.
2556 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2557 pub struct BuildManifest {
2558     pub target: TargetSelection,
2559 }
2560
2561 impl Step for BuildManifest {
2562     type Output = PathBuf;
2563     const DEFAULT: bool = false;
2564     const ONLY_HOSTS: bool = true;
2565
2566     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2567         run.path("src/tools/build-manifest")
2568     }
2569
2570     fn make_run(run: RunConfig<'_>) {
2571         run.builder.ensure(BuildManifest { target: run.target });
2572     }
2573
2574     fn run(self, builder: &Builder<'_>) -> PathBuf {
2575         let build_manifest = builder.tool_exe(Tool::BuildManifest);
2576
2577         let name = pkgname(builder, "build-manifest");
2578         let tmp = tmpdir(builder);
2579
2580         // Prepare the image.
2581         let image = tmp.join("build-manifest-image");
2582         let image_bin = image.join("bin");
2583         let _ = fs::remove_dir_all(&image);
2584         t!(fs::create_dir_all(&image_bin));
2585         builder.install(&build_manifest, &image_bin, 0o755);
2586
2587         // Prepare the overlay.
2588         let overlay = tmp.join("build-manifest-overlay");
2589         let _ = fs::remove_dir_all(&overlay);
2590         builder.create_dir(&overlay);
2591         builder.create(&overlay.join("version"), &builder.rust_version());
2592         for file in &["COPYRIGHT", "LICENSE-APACHE", "LICENSE-MIT", "README.md"] {
2593             builder.install(&builder.src.join(file), &overlay, 0o644);
2594         }
2595
2596         // Create the final tarball.
2597         let mut cmd = rust_installer(builder);
2598         cmd.arg("generate")
2599             .arg("--product-name=Rust")
2600             .arg("--rel-manifest-dir=rustlib")
2601             .arg("--success-message=build-manifest installed.")
2602             .arg("--image-dir")
2603             .arg(&image)
2604             .arg("--work-dir")
2605             .arg(&tmpdir(builder))
2606             .arg("--output-dir")
2607             .arg(&distdir(builder))
2608             .arg("--non-installed-overlay")
2609             .arg(&overlay)
2610             .arg(format!("--package-name={}-{}", name, self.target.triple))
2611             .arg("--legacy-manifest-dirs=rustlib,cargo")
2612             .arg("--component-name=build-manifest");
2613
2614         builder.run(&mut cmd);
2615         distdir(builder).join(format!("{}-{}.tar.gz", name, self.target.triple))
2616     }
2617 }