]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Rollup merge of #78969 - tmiasko:normalize, r=davidtwco
[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         // libtest includes std and everything else, so vendoring it
1044         // creates exactly what's needed for `cargo -Zbuild-std` or any
1045         // other analysis of the stdlib's source. Cargo also needs help
1046         // finding the lock, so we copy it to libtest temporarily.
1047         //
1048         // Note that this requires std to only have one version of each
1049         // crate. e.g. two versions of getopts won't be patchable.
1050         let dst_libtest = dst_src.join("library/test");
1051         let dst_vendor = dst_src.join("vendor");
1052         let root_lock = dst_src.join("Cargo.lock");
1053         let temp_lock = dst_libtest.join("Cargo.lock");
1054
1055         // `cargo vendor` will delete everything from the lockfile that
1056         // isn't used by libtest, so we need to not use any links!
1057         builder.really_copy(&root_lock, &temp_lock);
1058
1059         let mut cmd = Command::new(&builder.initial_cargo);
1060         cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libtest);
1061         builder.info("Dist src");
1062         let _time = timeit(builder);
1063         builder.run(&mut cmd);
1064
1065         builder.remove(&temp_lock);
1066
1067         // Create source tarball in rust-installer format
1068         let mut cmd = rust_installer(builder);
1069         cmd.arg("generate")
1070             .arg("--product-name=Rust")
1071             .arg("--rel-manifest-dir=rustlib")
1072             .arg("--success-message=Awesome-Source.")
1073             .arg("--image-dir")
1074             .arg(&image)
1075             .arg("--work-dir")
1076             .arg(&tmpdir(builder))
1077             .arg("--output-dir")
1078             .arg(&distdir(builder))
1079             .arg(format!("--package-name={}", name))
1080             .arg("--component-name=rust-src")
1081             .arg("--legacy-manifest-dirs=rustlib,cargo");
1082
1083         builder.run(&mut cmd);
1084
1085         builder.remove_dir(&image);
1086         distdir(builder).join(&format!("{}.tar.gz", name))
1087     }
1088 }
1089
1090 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1091 pub struct PlainSourceTarball;
1092
1093 impl Step for PlainSourceTarball {
1094     /// Produces the location of the tarball generated
1095     type Output = PathBuf;
1096     const DEFAULT: bool = true;
1097     const ONLY_HOSTS: bool = true;
1098
1099     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1100         let builder = run.builder;
1101         run.path("src").default_condition(builder.config.rust_dist_src)
1102     }
1103
1104     fn make_run(run: RunConfig<'_>) {
1105         run.builder.ensure(PlainSourceTarball);
1106     }
1107
1108     /// Creates the plain source tarball
1109     fn run(self, builder: &Builder<'_>) -> PathBuf {
1110         // Make sure that the root folder of tarball has the correct name
1111         let plain_name = format!("{}-src", pkgname(builder, "rustc"));
1112         let plain_dst_src = tmpdir(builder).join(&plain_name);
1113         let _ = fs::remove_dir_all(&plain_dst_src);
1114         t!(fs::create_dir_all(&plain_dst_src));
1115
1116         // This is the set of root paths which will become part of the source package
1117         let src_files = [
1118             "COPYRIGHT",
1119             "LICENSE-APACHE",
1120             "LICENSE-MIT",
1121             "CONTRIBUTING.md",
1122             "README.md",
1123             "RELEASES.md",
1124             "configure",
1125             "x.py",
1126             "config.toml.example",
1127             "Cargo.toml",
1128             "Cargo.lock",
1129         ];
1130         let src_dirs = ["src", "compiler", "library"];
1131
1132         copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
1133
1134         // Copy the files normally
1135         for item in &src_files {
1136             builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
1137         }
1138
1139         // Create the version file
1140         builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1141         if let Some(sha) = builder.rust_sha() {
1142             builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
1143         }
1144
1145         // If we're building from git sources, we need to vendor a complete distribution.
1146         if builder.rust_info.is_git() {
1147             // Vendor all Cargo dependencies
1148             let mut cmd = Command::new(&builder.initial_cargo);
1149             cmd.arg("vendor")
1150                 .arg("--sync")
1151                 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
1152                 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
1153                 .current_dir(&plain_dst_src);
1154             builder.run(&mut cmd);
1155         }
1156
1157         // Create plain source tarball
1158         let plain_name = format!("rustc-{}-src", builder.rust_package_vers());
1159         let mut tarball = distdir(builder).join(&format!("{}.tar.gz", plain_name));
1160         tarball.set_extension(""); // strip .gz
1161         tarball.set_extension(""); // strip .tar
1162         if let Some(dir) = tarball.parent() {
1163             builder.create_dir(&dir);
1164         }
1165         builder.info("running installer");
1166         let mut cmd = rust_installer(builder);
1167         cmd.arg("tarball")
1168             .arg("--input")
1169             .arg(&plain_name)
1170             .arg("--output")
1171             .arg(&tarball)
1172             .arg("--work-dir=.")
1173             .current_dir(tmpdir(builder));
1174
1175         builder.info("Create plain source tarball");
1176         let _time = timeit(builder);
1177         builder.run(&mut cmd);
1178         distdir(builder).join(&format!("{}.tar.gz", plain_name))
1179     }
1180 }
1181
1182 // We have to run a few shell scripts, which choke quite a bit on both `\`
1183 // characters and on `C:\` paths, so normalize both of them away.
1184 pub fn sanitize_sh(path: &Path) -> String {
1185     let path = path.to_str().unwrap().replace("\\", "/");
1186     return change_drive(&path).unwrap_or(path);
1187
1188     fn change_drive(s: &str) -> Option<String> {
1189         let mut ch = s.chars();
1190         let drive = ch.next().unwrap_or('C');
1191         if ch.next() != Some(':') {
1192             return None;
1193         }
1194         if ch.next() != Some('/') {
1195             return None;
1196         }
1197         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
1198     }
1199 }
1200
1201 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1202 pub struct Cargo {
1203     pub compiler: Compiler,
1204     pub target: TargetSelection,
1205 }
1206
1207 impl Step for Cargo {
1208     type Output = PathBuf;
1209     const ONLY_HOSTS: bool = true;
1210
1211     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1212         run.path("cargo")
1213     }
1214
1215     fn make_run(run: RunConfig<'_>) {
1216         run.builder.ensure(Cargo {
1217             compiler: run.builder.compiler_for(
1218                 run.builder.top_stage,
1219                 run.builder.config.build,
1220                 run.target,
1221             ),
1222             target: run.target,
1223         });
1224     }
1225
1226     fn run(self, builder: &Builder<'_>) -> PathBuf {
1227         let compiler = self.compiler;
1228         let target = self.target;
1229
1230         let src = builder.src.join("src/tools/cargo");
1231         let etc = src.join("src/etc");
1232         let release_num = builder.release_num("cargo");
1233         let name = pkgname(builder, "cargo");
1234         let version = builder.cargo_info.version(builder, &release_num);
1235
1236         let tmp = tmpdir(builder);
1237         let image = tmp.join("cargo-image");
1238         drop(fs::remove_dir_all(&image));
1239         builder.create_dir(&image);
1240
1241         // Prepare the image directory
1242         builder.create_dir(&image.join("share/zsh/site-functions"));
1243         builder.create_dir(&image.join("etc/bash_completion.d"));
1244         let cargo = builder.ensure(tool::Cargo { compiler, target });
1245         builder.install(&cargo, &image.join("bin"), 0o755);
1246         for man in t!(etc.join("man").read_dir()) {
1247             let man = t!(man);
1248             builder.install(&man.path(), &image.join("share/man/man1"), 0o644);
1249         }
1250         builder.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
1251         builder.copy(&etc.join("cargo.bashcomp.sh"), &image.join("etc/bash_completion.d/cargo"));
1252         let doc = image.join("share/doc/cargo");
1253         builder.install(&src.join("README.md"), &doc, 0o644);
1254         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1255         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1256         builder.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
1257
1258         // Prepare the overlay
1259         let overlay = tmp.join("cargo-overlay");
1260         drop(fs::remove_dir_all(&overlay));
1261         builder.create_dir(&overlay);
1262         builder.install(&src.join("README.md"), &overlay, 0o644);
1263         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1264         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1265         builder.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
1266         builder.create(&overlay.join("version"), &version);
1267
1268         // Generate the installer tarball
1269         let mut cmd = rust_installer(builder);
1270         cmd.arg("generate")
1271             .arg("--product-name=Rust")
1272             .arg("--rel-manifest-dir=rustlib")
1273             .arg("--success-message=Rust-is-ready-to-roll.")
1274             .arg("--image-dir")
1275             .arg(&image)
1276             .arg("--work-dir")
1277             .arg(&tmpdir(builder))
1278             .arg("--output-dir")
1279             .arg(&distdir(builder))
1280             .arg("--non-installed-overlay")
1281             .arg(&overlay)
1282             .arg(format!("--package-name={}-{}", name, target.triple))
1283             .arg("--component-name=cargo")
1284             .arg("--legacy-manifest-dirs=rustlib,cargo");
1285
1286         builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target));
1287         let _time = timeit(builder);
1288         builder.run(&mut cmd);
1289         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1290     }
1291 }
1292
1293 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1294 pub struct Rls {
1295     pub compiler: Compiler,
1296     pub target: TargetSelection,
1297 }
1298
1299 impl Step for Rls {
1300     type Output = Option<PathBuf>;
1301     const ONLY_HOSTS: bool = true;
1302
1303     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1304         run.path("rls")
1305     }
1306
1307     fn make_run(run: RunConfig<'_>) {
1308         run.builder.ensure(Rls {
1309             compiler: run.builder.compiler_for(
1310                 run.builder.top_stage,
1311                 run.builder.config.build,
1312                 run.target,
1313             ),
1314             target: run.target,
1315         });
1316     }
1317
1318     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1319         let compiler = self.compiler;
1320         let target = self.target;
1321         assert!(builder.config.extended);
1322
1323         let src = builder.src.join("src/tools/rls");
1324         let release_num = builder.release_num("rls");
1325         let name = pkgname(builder, "rls");
1326         let version = builder.rls_info.version(builder, &release_num);
1327
1328         let tmp = tmpdir(builder);
1329         let image = tmp.join("rls-image");
1330         drop(fs::remove_dir_all(&image));
1331         t!(fs::create_dir_all(&image));
1332
1333         // Prepare the image directory
1334         // We expect RLS to build, because we've exited this step above if tool
1335         // state for RLS isn't testing.
1336         let rls = builder
1337             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1338             .or_else(|| {
1339                 missing_tool("RLS", builder.build.config.missing_tools);
1340                 None
1341             })?;
1342
1343         builder.install(&rls, &image.join("bin"), 0o755);
1344         let doc = image.join("share/doc/rls");
1345         builder.install(&src.join("README.md"), &doc, 0o644);
1346         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1347         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1348
1349         // Prepare the overlay
1350         let overlay = tmp.join("rls-overlay");
1351         drop(fs::remove_dir_all(&overlay));
1352         t!(fs::create_dir_all(&overlay));
1353         builder.install(&src.join("README.md"), &overlay, 0o644);
1354         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1355         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1356         builder.create(&overlay.join("version"), &version);
1357
1358         // Generate the installer tarball
1359         let mut cmd = rust_installer(builder);
1360         cmd.arg("generate")
1361             .arg("--product-name=Rust")
1362             .arg("--rel-manifest-dir=rustlib")
1363             .arg("--success-message=RLS-ready-to-serve.")
1364             .arg("--image-dir")
1365             .arg(&image)
1366             .arg("--work-dir")
1367             .arg(&tmpdir(builder))
1368             .arg("--output-dir")
1369             .arg(&distdir(builder))
1370             .arg("--non-installed-overlay")
1371             .arg(&overlay)
1372             .arg(format!("--package-name={}-{}", name, target.triple))
1373             .arg("--legacy-manifest-dirs=rustlib,cargo")
1374             .arg("--component-name=rls-preview");
1375
1376         builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target.triple));
1377         let _time = timeit(builder);
1378         builder.run(&mut cmd);
1379         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1380     }
1381 }
1382
1383 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1384 pub struct RustAnalyzer {
1385     pub compiler: Compiler,
1386     pub target: TargetSelection,
1387 }
1388
1389 impl Step for RustAnalyzer {
1390     type Output = Option<PathBuf>;
1391     const ONLY_HOSTS: bool = true;
1392
1393     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1394         run.path("rust-analyzer")
1395     }
1396
1397     fn make_run(run: RunConfig<'_>) {
1398         run.builder.ensure(RustAnalyzer {
1399             compiler: run.builder.compiler_for(
1400                 run.builder.top_stage,
1401                 run.builder.config.build,
1402                 run.target,
1403             ),
1404             target: run.target,
1405         });
1406     }
1407
1408     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1409         let compiler = self.compiler;
1410         let target = self.target;
1411         assert!(builder.config.extended);
1412
1413         if target.contains("riscv64") {
1414             // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1415             // to build. See #74813 for details.
1416             return None;
1417         }
1418
1419         let src = builder.src.join("src/tools/rust-analyzer");
1420         let release_num = builder.release_num("rust-analyzer/crates/rust-analyzer");
1421         let name = pkgname(builder, "rust-analyzer");
1422         let version = builder.rust_analyzer_info.version(builder, &release_num);
1423
1424         let tmp = tmpdir(builder);
1425         let image = tmp.join("rust-analyzer-image");
1426         drop(fs::remove_dir_all(&image));
1427         builder.create_dir(&image);
1428
1429         // Prepare the image directory
1430         // We expect rust-analyer to always build, as it doesn't depend on rustc internals
1431         // and doesn't have associated toolstate.
1432         let rust_analyzer = builder
1433             .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1434             .expect("rust-analyzer always builds");
1435
1436         builder.install(&rust_analyzer, &image.join("bin"), 0o755);
1437         let doc = image.join("share/doc/rust-analyzer");
1438         builder.install(&src.join("README.md"), &doc, 0o644);
1439         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1440         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1441
1442         // Prepare the overlay
1443         let overlay = tmp.join("rust-analyzer-overlay");
1444         drop(fs::remove_dir_all(&overlay));
1445         t!(fs::create_dir_all(&overlay));
1446         builder.install(&src.join("README.md"), &overlay, 0o644);
1447         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1448         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1449         builder.create(&overlay.join("version"), &version);
1450
1451         // Generate the installer tarball
1452         let mut cmd = rust_installer(builder);
1453         cmd.arg("generate")
1454             .arg("--product-name=Rust")
1455             .arg("--rel-manifest-dir=rustlib")
1456             .arg("--success-message=rust-analyzer-ready-to-serve.")
1457             .arg("--image-dir")
1458             .arg(&image)
1459             .arg("--work-dir")
1460             .arg(&tmpdir(builder))
1461             .arg("--output-dir")
1462             .arg(&distdir(builder))
1463             .arg("--non-installed-overlay")
1464             .arg(&overlay)
1465             .arg(format!("--package-name={}-{}", name, target.triple))
1466             .arg("--legacy-manifest-dirs=rustlib,cargo")
1467             .arg("--component-name=rust-analyzer-preview");
1468
1469         builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target));
1470         let _time = timeit(builder);
1471         builder.run(&mut cmd);
1472         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1473     }
1474 }
1475
1476 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1477 pub struct Clippy {
1478     pub compiler: Compiler,
1479     pub target: TargetSelection,
1480 }
1481
1482 impl Step for Clippy {
1483     type Output = PathBuf;
1484     const ONLY_HOSTS: bool = true;
1485
1486     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1487         run.path("clippy")
1488     }
1489
1490     fn make_run(run: RunConfig<'_>) {
1491         run.builder.ensure(Clippy {
1492             compiler: run.builder.compiler_for(
1493                 run.builder.top_stage,
1494                 run.builder.config.build,
1495                 run.target,
1496             ),
1497             target: run.target,
1498         });
1499     }
1500
1501     fn run(self, builder: &Builder<'_>) -> PathBuf {
1502         let compiler = self.compiler;
1503         let target = self.target;
1504         assert!(builder.config.extended);
1505
1506         let src = builder.src.join("src/tools/clippy");
1507         let release_num = builder.release_num("clippy");
1508         let name = pkgname(builder, "clippy");
1509         let version = builder.clippy_info.version(builder, &release_num);
1510
1511         let tmp = tmpdir(builder);
1512         let image = tmp.join("clippy-image");
1513         drop(fs::remove_dir_all(&image));
1514         builder.create_dir(&image);
1515
1516         // Prepare the image directory
1517         // We expect clippy to build, because we've exited this step above if tool
1518         // state for clippy isn't testing.
1519         let clippy = builder
1520             .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1521             .expect("clippy expected to build - essential tool");
1522         let cargoclippy = builder
1523             .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1524             .expect("clippy expected to build - essential tool");
1525
1526         builder.install(&clippy, &image.join("bin"), 0o755);
1527         builder.install(&cargoclippy, &image.join("bin"), 0o755);
1528         let doc = image.join("share/doc/clippy");
1529         builder.install(&src.join("README.md"), &doc, 0o644);
1530         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1531         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1532
1533         // Prepare the overlay
1534         let overlay = tmp.join("clippy-overlay");
1535         drop(fs::remove_dir_all(&overlay));
1536         t!(fs::create_dir_all(&overlay));
1537         builder.install(&src.join("README.md"), &overlay, 0o644);
1538         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1539         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1540         builder.create(&overlay.join("version"), &version);
1541
1542         // Generate the installer tarball
1543         let mut cmd = rust_installer(builder);
1544         cmd.arg("generate")
1545             .arg("--product-name=Rust")
1546             .arg("--rel-manifest-dir=rustlib")
1547             .arg("--success-message=clippy-ready-to-serve.")
1548             .arg("--image-dir")
1549             .arg(&image)
1550             .arg("--work-dir")
1551             .arg(&tmpdir(builder))
1552             .arg("--output-dir")
1553             .arg(&distdir(builder))
1554             .arg("--non-installed-overlay")
1555             .arg(&overlay)
1556             .arg(format!("--package-name={}-{}", name, target.triple))
1557             .arg("--legacy-manifest-dirs=rustlib,cargo")
1558             .arg("--component-name=clippy-preview");
1559
1560         builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target));
1561         let _time = timeit(builder);
1562         builder.run(&mut cmd);
1563         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1564     }
1565 }
1566
1567 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1568 pub struct Miri {
1569     pub compiler: Compiler,
1570     pub target: TargetSelection,
1571 }
1572
1573 impl Step for Miri {
1574     type Output = Option<PathBuf>;
1575     const ONLY_HOSTS: bool = true;
1576
1577     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1578         run.path("miri")
1579     }
1580
1581     fn make_run(run: RunConfig<'_>) {
1582         run.builder.ensure(Miri {
1583             compiler: run.builder.compiler_for(
1584                 run.builder.top_stage,
1585                 run.builder.config.build,
1586                 run.target,
1587             ),
1588             target: run.target,
1589         });
1590     }
1591
1592     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1593         let compiler = self.compiler;
1594         let target = self.target;
1595         assert!(builder.config.extended);
1596
1597         let src = builder.src.join("src/tools/miri");
1598         let release_num = builder.release_num("miri");
1599         let name = pkgname(builder, "miri");
1600         let version = builder.miri_info.version(builder, &release_num);
1601
1602         let tmp = tmpdir(builder);
1603         let image = tmp.join("miri-image");
1604         drop(fs::remove_dir_all(&image));
1605         builder.create_dir(&image);
1606
1607         // Prepare the image directory
1608         // We expect miri to build, because we've exited this step above if tool
1609         // state for miri isn't testing.
1610         let miri = builder
1611             .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1612             .or_else(|| {
1613                 missing_tool("miri", builder.build.config.missing_tools);
1614                 None
1615             })?;
1616         let cargomiri = builder
1617             .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1618             .or_else(|| {
1619                 missing_tool("cargo miri", builder.build.config.missing_tools);
1620                 None
1621             })?;
1622
1623         builder.install(&miri, &image.join("bin"), 0o755);
1624         builder.install(&cargomiri, &image.join("bin"), 0o755);
1625         let doc = image.join("share/doc/miri");
1626         builder.install(&src.join("README.md"), &doc, 0o644);
1627         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1628         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1629
1630         // Prepare the overlay
1631         let overlay = tmp.join("miri-overlay");
1632         drop(fs::remove_dir_all(&overlay));
1633         t!(fs::create_dir_all(&overlay));
1634         builder.install(&src.join("README.md"), &overlay, 0o644);
1635         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1636         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1637         builder.create(&overlay.join("version"), &version);
1638
1639         // Generate the installer tarball
1640         let mut cmd = rust_installer(builder);
1641         cmd.arg("generate")
1642             .arg("--product-name=Rust")
1643             .arg("--rel-manifest-dir=rustlib")
1644             .arg("--success-message=miri-ready-to-serve.")
1645             .arg("--image-dir")
1646             .arg(&image)
1647             .arg("--work-dir")
1648             .arg(&tmpdir(builder))
1649             .arg("--output-dir")
1650             .arg(&distdir(builder))
1651             .arg("--non-installed-overlay")
1652             .arg(&overlay)
1653             .arg(format!("--package-name={}-{}", name, target.triple))
1654             .arg("--legacy-manifest-dirs=rustlib,cargo")
1655             .arg("--component-name=miri-preview");
1656
1657         builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target));
1658         let _time = timeit(builder);
1659         builder.run(&mut cmd);
1660         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1661     }
1662 }
1663
1664 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1665 pub struct Rustfmt {
1666     pub compiler: Compiler,
1667     pub target: TargetSelection,
1668 }
1669
1670 impl Step for Rustfmt {
1671     type Output = Option<PathBuf>;
1672     const ONLY_HOSTS: bool = true;
1673
1674     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1675         run.path("rustfmt")
1676     }
1677
1678     fn make_run(run: RunConfig<'_>) {
1679         run.builder.ensure(Rustfmt {
1680             compiler: run.builder.compiler_for(
1681                 run.builder.top_stage,
1682                 run.builder.config.build,
1683                 run.target,
1684             ),
1685             target: run.target,
1686         });
1687     }
1688
1689     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1690         let compiler = self.compiler;
1691         let target = self.target;
1692
1693         let src = builder.src.join("src/tools/rustfmt");
1694         let release_num = builder.release_num("rustfmt");
1695         let name = pkgname(builder, "rustfmt");
1696         let version = builder.rustfmt_info.version(builder, &release_num);
1697
1698         let tmp = tmpdir(builder);
1699         let image = tmp.join("rustfmt-image");
1700         drop(fs::remove_dir_all(&image));
1701         builder.create_dir(&image);
1702
1703         // Prepare the image directory
1704         let rustfmt = builder
1705             .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1706             .or_else(|| {
1707                 missing_tool("Rustfmt", builder.build.config.missing_tools);
1708                 None
1709             })?;
1710         let cargofmt = builder
1711             .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1712             .or_else(|| {
1713                 missing_tool("Cargofmt", builder.build.config.missing_tools);
1714                 None
1715             })?;
1716
1717         builder.install(&rustfmt, &image.join("bin"), 0o755);
1718         builder.install(&cargofmt, &image.join("bin"), 0o755);
1719         let doc = image.join("share/doc/rustfmt");
1720         builder.install(&src.join("README.md"), &doc, 0o644);
1721         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1722         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1723
1724         // Prepare the overlay
1725         let overlay = tmp.join("rustfmt-overlay");
1726         drop(fs::remove_dir_all(&overlay));
1727         builder.create_dir(&overlay);
1728         builder.install(&src.join("README.md"), &overlay, 0o644);
1729         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1730         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1731         builder.create(&overlay.join("version"), &version);
1732
1733         // Generate the installer tarball
1734         let mut cmd = rust_installer(builder);
1735         cmd.arg("generate")
1736             .arg("--product-name=Rust")
1737             .arg("--rel-manifest-dir=rustlib")
1738             .arg("--success-message=rustfmt-ready-to-fmt.")
1739             .arg("--image-dir")
1740             .arg(&image)
1741             .arg("--work-dir")
1742             .arg(&tmpdir(builder))
1743             .arg("--output-dir")
1744             .arg(&distdir(builder))
1745             .arg("--non-installed-overlay")
1746             .arg(&overlay)
1747             .arg(format!("--package-name={}-{}", name, target.triple))
1748             .arg("--legacy-manifest-dirs=rustlib,cargo")
1749             .arg("--component-name=rustfmt-preview");
1750
1751         builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target));
1752         let _time = timeit(builder);
1753         builder.run(&mut cmd);
1754         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1755     }
1756 }
1757
1758 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1759 pub struct Extended {
1760     stage: u32,
1761     host: TargetSelection,
1762     target: TargetSelection,
1763 }
1764
1765 impl Step for Extended {
1766     type Output = ();
1767     const DEFAULT: bool = true;
1768     const ONLY_HOSTS: bool = true;
1769
1770     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1771         let builder = run.builder;
1772         run.path("extended").default_condition(builder.config.extended)
1773     }
1774
1775     fn make_run(run: RunConfig<'_>) {
1776         run.builder.ensure(Extended {
1777             stage: run.builder.top_stage,
1778             host: run.builder.config.build,
1779             target: run.target,
1780         });
1781     }
1782
1783     /// Creates a combined installer for the specified target in the provided stage.
1784     fn run(self, builder: &Builder<'_>) {
1785         let target = self.target;
1786         let stage = self.stage;
1787         let compiler = builder.compiler_for(self.stage, self.host, self.target);
1788
1789         builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1790
1791         let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
1792         let cargo_installer = builder.ensure(Cargo { compiler, target });
1793         let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1794         let rls_installer = builder.ensure(Rls { compiler, target });
1795         let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
1796         let llvm_tools_installer = builder.ensure(LlvmTools { target });
1797         let clippy_installer = builder.ensure(Clippy { compiler, target });
1798         let miri_installer = builder.ensure(Miri { compiler, target });
1799         let mingw_installer = builder.ensure(Mingw { host: target });
1800         let analysis_installer = builder.ensure(Analysis { compiler, target });
1801
1802         let docs_installer = builder.ensure(Docs { host: target });
1803         let std_installer =
1804             builder.ensure(Std { compiler: builder.compiler(stage, target), target });
1805
1806         let tmp = tmpdir(builder);
1807         let overlay = tmp.join("extended-overlay");
1808         let etc = builder.src.join("src/etc/installer");
1809         let work = tmp.join("work");
1810
1811         let _ = fs::remove_dir_all(&overlay);
1812         builder.install(&builder.src.join("COPYRIGHT"), &overlay, 0o644);
1813         builder.install(&builder.src.join("LICENSE-APACHE"), &overlay, 0o644);
1814         builder.install(&builder.src.join("LICENSE-MIT"), &overlay, 0o644);
1815         let version = builder.rust_version();
1816         builder.create(&overlay.join("version"), &version);
1817         if let Some(sha) = builder.rust_sha() {
1818             builder.create(&overlay.join("git-commit-hash"), &sha);
1819         }
1820         builder.install(&etc.join("README.md"), &overlay, 0o644);
1821
1822         // When rust-std package split from rustc, we needed to ensure that during
1823         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1824         // the std files during uninstall. To do this ensure that rustc comes
1825         // before rust-std in the list below.
1826         let mut tarballs = Vec::new();
1827         tarballs.push(rustc_installer);
1828         tarballs.push(cargo_installer);
1829         tarballs.extend(rls_installer.clone());
1830         tarballs.extend(rust_analyzer_installer.clone());
1831         tarballs.push(clippy_installer);
1832         tarballs.extend(miri_installer.clone());
1833         tarballs.extend(rustfmt_installer.clone());
1834         tarballs.extend(llvm_tools_installer);
1835         tarballs.push(analysis_installer);
1836         tarballs.push(std_installer);
1837         if builder.config.docs {
1838             tarballs.push(docs_installer);
1839         }
1840         if target.contains("pc-windows-gnu") {
1841             tarballs.push(mingw_installer.unwrap());
1842         }
1843         let mut input_tarballs = tarballs[0].as_os_str().to_owned();
1844         for tarball in &tarballs[1..] {
1845             input_tarballs.push(",");
1846             input_tarballs.push(tarball);
1847         }
1848
1849         builder.info("building combined installer");
1850         let mut cmd = rust_installer(builder);
1851         cmd.arg("combine")
1852             .arg("--product-name=Rust")
1853             .arg("--rel-manifest-dir=rustlib")
1854             .arg("--success-message=Rust-is-ready-to-roll.")
1855             .arg("--work-dir")
1856             .arg(&work)
1857             .arg("--output-dir")
1858             .arg(&distdir(builder))
1859             .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target.triple))
1860             .arg("--legacy-manifest-dirs=rustlib,cargo")
1861             .arg("--input-tarballs")
1862             .arg(input_tarballs)
1863             .arg("--non-installed-overlay")
1864             .arg(&overlay);
1865         let time = timeit(&builder);
1866         builder.run(&mut cmd);
1867         drop(time);
1868
1869         let mut license = String::new();
1870         license += &builder.read(&builder.src.join("COPYRIGHT"));
1871         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1872         license += &builder.read(&builder.src.join("LICENSE-MIT"));
1873         license.push_str("\n");
1874         license.push_str("\n");
1875
1876         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1877         let mut rtf = rtf.to_string();
1878         rtf.push_str("\n");
1879         for line in license.lines() {
1880             rtf.push_str(line);
1881             rtf.push_str("\\line ");
1882         }
1883         rtf.push_str("}");
1884
1885         fn filter(contents: &str, marker: &str) -> String {
1886             let start = format!("tool-{}-start", marker);
1887             let end = format!("tool-{}-end", marker);
1888             let mut lines = Vec::new();
1889             let mut omitted = false;
1890             for line in contents.lines() {
1891                 if line.contains(&start) {
1892                     omitted = true;
1893                 } else if line.contains(&end) {
1894                     omitted = false;
1895                 } else if !omitted {
1896                     lines.push(line);
1897                 }
1898             }
1899
1900             lines.join("\n")
1901         }
1902
1903         let xform = |p: &Path| {
1904             let mut contents = t!(fs::read_to_string(p));
1905             if rls_installer.is_none() {
1906                 contents = filter(&contents, "rls");
1907             }
1908             if rust_analyzer_installer.is_none() {
1909                 contents = filter(&contents, "rust-analyzer");
1910             }
1911             if miri_installer.is_none() {
1912                 contents = filter(&contents, "miri");
1913             }
1914             if rustfmt_installer.is_none() {
1915                 contents = filter(&contents, "rustfmt");
1916             }
1917             let ret = tmp.join(p.file_name().unwrap());
1918             t!(fs::write(&ret, &contents));
1919             ret
1920         };
1921
1922         if target.contains("apple-darwin") {
1923             builder.info("building pkg installer");
1924             let pkg = tmp.join("pkg");
1925             let _ = fs::remove_dir_all(&pkg);
1926
1927             let pkgbuild = |component: &str| {
1928                 let mut cmd = Command::new("pkgbuild");
1929                 cmd.arg("--identifier")
1930                     .arg(format!("org.rust-lang.{}", component))
1931                     .arg("--scripts")
1932                     .arg(pkg.join(component))
1933                     .arg("--nopayload")
1934                     .arg(pkg.join(component).with_extension("pkg"));
1935                 builder.run(&mut cmd);
1936             };
1937
1938             let prepare = |name: &str| {
1939                 builder.create_dir(&pkg.join(name));
1940                 builder.cp_r(
1941                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1942                     &pkg.join(name),
1943                 );
1944                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1945                 pkgbuild(name);
1946             };
1947             prepare("rustc");
1948             prepare("cargo");
1949             prepare("rust-docs");
1950             prepare("rust-std");
1951             prepare("rust-analysis");
1952             prepare("clippy");
1953
1954             if rls_installer.is_some() {
1955                 prepare("rls");
1956             }
1957             if rust_analyzer_installer.is_some() {
1958                 prepare("rust-analyzer");
1959             }
1960             if miri_installer.is_some() {
1961                 prepare("miri");
1962             }
1963
1964             // create an 'uninstall' package
1965             builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1966             pkgbuild("uninstall");
1967
1968             builder.create_dir(&pkg.join("res"));
1969             builder.create(&pkg.join("res/LICENSE.txt"), &license);
1970             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1971             let mut cmd = Command::new("productbuild");
1972             cmd.arg("--distribution")
1973                 .arg(xform(&etc.join("pkg/Distribution.xml")))
1974                 .arg("--resources")
1975                 .arg(pkg.join("res"))
1976                 .arg(distdir(builder).join(format!(
1977                     "{}-{}.pkg",
1978                     pkgname(builder, "rust"),
1979                     target.triple
1980                 )))
1981                 .arg("--package-path")
1982                 .arg(&pkg);
1983             let _time = timeit(builder);
1984             builder.run(&mut cmd);
1985         }
1986
1987         if target.contains("windows") {
1988             let exe = tmp.join("exe");
1989             let _ = fs::remove_dir_all(&exe);
1990
1991             let prepare = |name: &str| {
1992                 builder.create_dir(&exe.join(name));
1993                 let dir = if name == "rust-std" || name == "rust-analysis" {
1994                     format!("{}-{}", name, target.triple)
1995                 } else if name == "rls" {
1996                     "rls-preview".to_string()
1997                 } else if name == "rust-analyzer" {
1998                     "rust-analyzer-preview".to_string()
1999                 } else if name == "clippy" {
2000                     "clippy-preview".to_string()
2001                 } else if name == "miri" {
2002                     "miri-preview".to_string()
2003                 } else {
2004                     name.to_string()
2005                 };
2006                 builder.cp_r(
2007                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2008                     &exe.join(name),
2009                 );
2010                 builder.remove(&exe.join(name).join("manifest.in"));
2011             };
2012             prepare("rustc");
2013             prepare("cargo");
2014             prepare("rust-analysis");
2015             prepare("rust-docs");
2016             prepare("rust-std");
2017             prepare("clippy");
2018             if rls_installer.is_some() {
2019                 prepare("rls");
2020             }
2021             if rust_analyzer_installer.is_some() {
2022                 prepare("rust-analyzer");
2023             }
2024             if miri_installer.is_some() {
2025                 prepare("miri");
2026             }
2027             if target.contains("windows-gnu") {
2028                 prepare("rust-mingw");
2029             }
2030
2031             builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
2032
2033             // Generate msi installer
2034             let wix = PathBuf::from(env::var_os("WIX").unwrap());
2035             let heat = wix.join("bin/heat.exe");
2036             let candle = wix.join("bin/candle.exe");
2037             let light = wix.join("bin/light.exe");
2038
2039             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2040             builder.run(
2041                 Command::new(&heat)
2042                     .current_dir(&exe)
2043                     .arg("dir")
2044                     .arg("rustc")
2045                     .args(&heat_flags)
2046                     .arg("-cg")
2047                     .arg("RustcGroup")
2048                     .arg("-dr")
2049                     .arg("Rustc")
2050                     .arg("-var")
2051                     .arg("var.RustcDir")
2052                     .arg("-out")
2053                     .arg(exe.join("RustcGroup.wxs")),
2054             );
2055             builder.run(
2056                 Command::new(&heat)
2057                     .current_dir(&exe)
2058                     .arg("dir")
2059                     .arg("rust-docs")
2060                     .args(&heat_flags)
2061                     .arg("-cg")
2062                     .arg("DocsGroup")
2063                     .arg("-dr")
2064                     .arg("Docs")
2065                     .arg("-var")
2066                     .arg("var.DocsDir")
2067                     .arg("-out")
2068                     .arg(exe.join("DocsGroup.wxs"))
2069                     .arg("-t")
2070                     .arg(etc.join("msi/squash-components.xsl")),
2071             );
2072             builder.run(
2073                 Command::new(&heat)
2074                     .current_dir(&exe)
2075                     .arg("dir")
2076                     .arg("cargo")
2077                     .args(&heat_flags)
2078                     .arg("-cg")
2079                     .arg("CargoGroup")
2080                     .arg("-dr")
2081                     .arg("Cargo")
2082                     .arg("-var")
2083                     .arg("var.CargoDir")
2084                     .arg("-out")
2085                     .arg(exe.join("CargoGroup.wxs"))
2086                     .arg("-t")
2087                     .arg(etc.join("msi/remove-duplicates.xsl")),
2088             );
2089             builder.run(
2090                 Command::new(&heat)
2091                     .current_dir(&exe)
2092                     .arg("dir")
2093                     .arg("rust-std")
2094                     .args(&heat_flags)
2095                     .arg("-cg")
2096                     .arg("StdGroup")
2097                     .arg("-dr")
2098                     .arg("Std")
2099                     .arg("-var")
2100                     .arg("var.StdDir")
2101                     .arg("-out")
2102                     .arg(exe.join("StdGroup.wxs")),
2103             );
2104             if rls_installer.is_some() {
2105                 builder.run(
2106                     Command::new(&heat)
2107                         .current_dir(&exe)
2108                         .arg("dir")
2109                         .arg("rls")
2110                         .args(&heat_flags)
2111                         .arg("-cg")
2112                         .arg("RlsGroup")
2113                         .arg("-dr")
2114                         .arg("Rls")
2115                         .arg("-var")
2116                         .arg("var.RlsDir")
2117                         .arg("-out")
2118                         .arg(exe.join("RlsGroup.wxs"))
2119                         .arg("-t")
2120                         .arg(etc.join("msi/remove-duplicates.xsl")),
2121                 );
2122             }
2123             if rust_analyzer_installer.is_some() {
2124                 builder.run(
2125                     Command::new(&heat)
2126                         .current_dir(&exe)
2127                         .arg("dir")
2128                         .arg("rust-analyzer")
2129                         .args(&heat_flags)
2130                         .arg("-cg")
2131                         .arg("RustAnalyzerGroup")
2132                         .arg("-dr")
2133                         .arg("RustAnalyzer")
2134                         .arg("-var")
2135                         .arg("var.RustAnalyzerDir")
2136                         .arg("-out")
2137                         .arg(exe.join("RustAnalyzerGroup.wxs"))
2138                         .arg("-t")
2139                         .arg(etc.join("msi/remove-duplicates.xsl")),
2140                 );
2141             }
2142             builder.run(
2143                 Command::new(&heat)
2144                     .current_dir(&exe)
2145                     .arg("dir")
2146                     .arg("clippy")
2147                     .args(&heat_flags)
2148                     .arg("-cg")
2149                     .arg("ClippyGroup")
2150                     .arg("-dr")
2151                     .arg("Clippy")
2152                     .arg("-var")
2153                     .arg("var.ClippyDir")
2154                     .arg("-out")
2155                     .arg(exe.join("ClippyGroup.wxs"))
2156                     .arg("-t")
2157                     .arg(etc.join("msi/remove-duplicates.xsl")),
2158             );
2159             if miri_installer.is_some() {
2160                 builder.run(
2161                     Command::new(&heat)
2162                         .current_dir(&exe)
2163                         .arg("dir")
2164                         .arg("miri")
2165                         .args(&heat_flags)
2166                         .arg("-cg")
2167                         .arg("MiriGroup")
2168                         .arg("-dr")
2169                         .arg("Miri")
2170                         .arg("-var")
2171                         .arg("var.MiriDir")
2172                         .arg("-out")
2173                         .arg(exe.join("MiriGroup.wxs"))
2174                         .arg("-t")
2175                         .arg(etc.join("msi/remove-duplicates.xsl")),
2176                 );
2177             }
2178             builder.run(
2179                 Command::new(&heat)
2180                     .current_dir(&exe)
2181                     .arg("dir")
2182                     .arg("rust-analysis")
2183                     .args(&heat_flags)
2184                     .arg("-cg")
2185                     .arg("AnalysisGroup")
2186                     .arg("-dr")
2187                     .arg("Analysis")
2188                     .arg("-var")
2189                     .arg("var.AnalysisDir")
2190                     .arg("-out")
2191                     .arg(exe.join("AnalysisGroup.wxs"))
2192                     .arg("-t")
2193                     .arg(etc.join("msi/remove-duplicates.xsl")),
2194             );
2195             if target.contains("windows-gnu") {
2196                 builder.run(
2197                     Command::new(&heat)
2198                         .current_dir(&exe)
2199                         .arg("dir")
2200                         .arg("rust-mingw")
2201                         .args(&heat_flags)
2202                         .arg("-cg")
2203                         .arg("GccGroup")
2204                         .arg("-dr")
2205                         .arg("Gcc")
2206                         .arg("-var")
2207                         .arg("var.GccDir")
2208                         .arg("-out")
2209                         .arg(exe.join("GccGroup.wxs")),
2210                 );
2211             }
2212
2213             let candle = |input: &Path| {
2214                 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2215                 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2216                 let mut cmd = Command::new(&candle);
2217                 cmd.current_dir(&exe)
2218                     .arg("-nologo")
2219                     .arg("-dRustcDir=rustc")
2220                     .arg("-dDocsDir=rust-docs")
2221                     .arg("-dCargoDir=cargo")
2222                     .arg("-dStdDir=rust-std")
2223                     .arg("-dAnalysisDir=rust-analysis")
2224                     .arg("-dClippyDir=clippy")
2225                     .arg("-arch")
2226                     .arg(&arch)
2227                     .arg("-out")
2228                     .arg(&output)
2229                     .arg(&input);
2230                 add_env(builder, &mut cmd, target);
2231
2232                 if rls_installer.is_some() {
2233                     cmd.arg("-dRlsDir=rls");
2234                 }
2235                 if rust_analyzer_installer.is_some() {
2236                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2237                 }
2238                 if miri_installer.is_some() {
2239                     cmd.arg("-dMiriDir=miri");
2240                 }
2241                 if target.contains("windows-gnu") {
2242                     cmd.arg("-dGccDir=rust-mingw");
2243                 }
2244                 builder.run(&mut cmd);
2245             };
2246             candle(&xform(&etc.join("msi/rust.wxs")));
2247             candle(&etc.join("msi/ui.wxs"));
2248             candle(&etc.join("msi/rustwelcomedlg.wxs"));
2249             candle("RustcGroup.wxs".as_ref());
2250             candle("DocsGroup.wxs".as_ref());
2251             candle("CargoGroup.wxs".as_ref());
2252             candle("StdGroup.wxs".as_ref());
2253             candle("ClippyGroup.wxs".as_ref());
2254             if rls_installer.is_some() {
2255                 candle("RlsGroup.wxs".as_ref());
2256             }
2257             if rust_analyzer_installer.is_some() {
2258                 candle("RustAnalyzerGroup.wxs".as_ref());
2259             }
2260             if miri_installer.is_some() {
2261                 candle("MiriGroup.wxs".as_ref());
2262             }
2263             candle("AnalysisGroup.wxs".as_ref());
2264
2265             if target.contains("windows-gnu") {
2266                 candle("GccGroup.wxs".as_ref());
2267             }
2268
2269             builder.create(&exe.join("LICENSE.rtf"), &rtf);
2270             builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
2271             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
2272
2273             builder.info(&format!("building `msi` installer with {:?}", light));
2274             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2275             let mut cmd = Command::new(&light);
2276             cmd.arg("-nologo")
2277                 .arg("-ext")
2278                 .arg("WixUIExtension")
2279                 .arg("-ext")
2280                 .arg("WixUtilExtension")
2281                 .arg("-out")
2282                 .arg(exe.join(&filename))
2283                 .arg("rust.wixobj")
2284                 .arg("ui.wixobj")
2285                 .arg("rustwelcomedlg.wixobj")
2286                 .arg("RustcGroup.wixobj")
2287                 .arg("DocsGroup.wixobj")
2288                 .arg("CargoGroup.wixobj")
2289                 .arg("StdGroup.wixobj")
2290                 .arg("AnalysisGroup.wixobj")
2291                 .arg("ClippyGroup.wixobj")
2292                 .current_dir(&exe);
2293
2294             if rls_installer.is_some() {
2295                 cmd.arg("RlsGroup.wixobj");
2296             }
2297             if rust_analyzer_installer.is_some() {
2298                 cmd.arg("RustAnalyzerGroup.wixobj");
2299             }
2300             if miri_installer.is_some() {
2301                 cmd.arg("MiriGroup.wixobj");
2302             }
2303
2304             if target.contains("windows-gnu") {
2305                 cmd.arg("GccGroup.wixobj");
2306             }
2307             // ICE57 wrongly complains about the shortcuts
2308             cmd.arg("-sice:ICE57");
2309
2310             let _time = timeit(builder);
2311             builder.run(&mut cmd);
2312
2313             if !builder.config.dry_run {
2314                 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
2315             }
2316         }
2317     }
2318 }
2319
2320 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
2321     let mut parts = builder.version.split('.');
2322     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2323         .env("CFG_RELEASE_NUM", &builder.version)
2324         .env("CFG_RELEASE", builder.rust_release())
2325         .env("CFG_VER_MAJOR", parts.next().unwrap())
2326         .env("CFG_VER_MINOR", parts.next().unwrap())
2327         .env("CFG_VER_PATCH", parts.next().unwrap())
2328         .env("CFG_VER_BUILD", "0") // just needed to build
2329         .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2330         .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2331         .env("CFG_BUILD", target.triple)
2332         .env("CFG_CHANNEL", &builder.config.channel);
2333
2334     if target.contains("windows-gnu") {
2335         cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2336     } else {
2337         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2338     }
2339
2340     if target.contains("x86_64") {
2341         cmd.env("CFG_PLATFORM", "x64");
2342     } else {
2343         cmd.env("CFG_PLATFORM", "x86");
2344     }
2345 }
2346
2347 /// Maybe add libLLVM.so to the given destination lib-dir. It will only have
2348 /// been built if LLVM tools are linked dynamically.
2349 ///
2350 /// Note: This function does not yet support Windows, but we also don't support
2351 ///       linking LLVM tools dynamically on Windows yet.
2352 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) {
2353     if !builder.config.llvm_link_shared {
2354         // We do not need to copy LLVM files into the sysroot if it is not
2355         // dynamically linked; it is already included into librustc_llvm
2356         // statically.
2357         return;
2358     }
2359
2360     // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
2361     // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
2362     // clear why this is the case, though. llvm-config will emit the versioned
2363     // paths and we don't want those in the sysroot (as we're expecting
2364     // unversioned paths).
2365     if target.contains("apple-darwin") {
2366         let src_libdir = builder.llvm_out(target).join("lib");
2367         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2368         if llvm_dylib_path.exists() {
2369             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
2370         }
2371     } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
2372         let files = output(Command::new(llvm_config).arg("--libfiles"));
2373         for file in files.lines() {
2374             builder.install(Path::new(file), dst_libdir, 0o644);
2375         }
2376     }
2377 }
2378
2379 /// Maybe add libLLVM.so to the target lib-dir for linking.
2380 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2381     let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
2382     maybe_install_llvm(builder, target, &dst_libdir);
2383 }
2384
2385 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
2386 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2387     let dst_libdir =
2388         sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
2389     maybe_install_llvm(builder, target, &dst_libdir);
2390 }
2391
2392 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2393 pub struct LlvmTools {
2394     pub target: TargetSelection,
2395 }
2396
2397 impl Step for LlvmTools {
2398     type Output = Option<PathBuf>;
2399     const ONLY_HOSTS: bool = true;
2400
2401     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2402         run.path("llvm-tools")
2403     }
2404
2405     fn make_run(run: RunConfig<'_>) {
2406         run.builder.ensure(LlvmTools { target: run.target });
2407     }
2408
2409     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
2410         let target = self.target;
2411         assert!(builder.config.extended);
2412
2413         /* run only if llvm-config isn't used */
2414         if let Some(config) = builder.config.target_config.get(&target) {
2415             if let Some(ref _s) = config.llvm_config {
2416                 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
2417                 return None;
2418             }
2419         }
2420
2421         builder.info(&format!("Dist LlvmTools ({})", target));
2422         let _time = timeit(builder);
2423         let src = builder.src.join("src/llvm-project/llvm");
2424         let name = pkgname(builder, "llvm-tools");
2425
2426         let tmp = tmpdir(builder);
2427         let image = tmp.join("llvm-tools-image");
2428         drop(fs::remove_dir_all(&image));
2429
2430         // Prepare the image directory
2431         let src_bindir = builder.llvm_out(target).join("bin");
2432         let dst_bindir = image.join("lib/rustlib").join(&*target.triple).join("bin");
2433         t!(fs::create_dir_all(&dst_bindir));
2434         for tool in LLVM_TOOLS {
2435             let exe = src_bindir.join(exe(tool, target));
2436             builder.install(&exe, &dst_bindir, 0o755);
2437         }
2438
2439         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2440         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2441         // of `rustc-dev` to support the inherited `-lLLVM` when using the
2442         // compiler libraries.
2443         maybe_install_llvm_target(builder, target, &image);
2444
2445         // Prepare the overlay
2446         let overlay = tmp.join("llvm-tools-overlay");
2447         drop(fs::remove_dir_all(&overlay));
2448         builder.create_dir(&overlay);
2449         builder.install(&src.join("README.txt"), &overlay, 0o644);
2450         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
2451         builder.create(&overlay.join("version"), &builder.llvm_tools_vers());
2452
2453         // Generate the installer tarball
2454         let mut cmd = rust_installer(builder);
2455         cmd.arg("generate")
2456             .arg("--product-name=Rust")
2457             .arg("--rel-manifest-dir=rustlib")
2458             .arg("--success-message=llvm-tools-installed.")
2459             .arg("--image-dir")
2460             .arg(&image)
2461             .arg("--work-dir")
2462             .arg(&tmpdir(builder))
2463             .arg("--output-dir")
2464             .arg(&distdir(builder))
2465             .arg("--non-installed-overlay")
2466             .arg(&overlay)
2467             .arg(format!("--package-name={}-{}", name, target.triple))
2468             .arg("--legacy-manifest-dirs=rustlib,cargo")
2469             .arg("--component-name=llvm-tools-preview");
2470
2471         builder.run(&mut cmd);
2472         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
2473     }
2474 }
2475
2476 // Tarball intended for internal consumption to ease rustc/std development.
2477 //
2478 // Should not be considered stable by end users.
2479 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2480 pub struct RustDev {
2481     pub target: TargetSelection,
2482 }
2483
2484 impl Step for RustDev {
2485     type Output = Option<PathBuf>;
2486     const DEFAULT: bool = true;
2487     const ONLY_HOSTS: bool = true;
2488
2489     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2490         run.path("rust-dev")
2491     }
2492
2493     fn make_run(run: RunConfig<'_>) {
2494         run.builder.ensure(RustDev { target: run.target });
2495     }
2496
2497     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
2498         let target = self.target;
2499
2500         /* run only if llvm-config isn't used */
2501         if let Some(config) = builder.config.target_config.get(&target) {
2502             if let Some(ref _s) = config.llvm_config {
2503                 builder.info(&format!("Skipping RustDev ({}): external LLVM", target));
2504                 return None;
2505             }
2506         }
2507
2508         builder.info(&format!("Dist RustDev ({})", target));
2509         let _time = timeit(builder);
2510         let src = builder.src.join("src/llvm-project/llvm");
2511         let name = pkgname(builder, "rust-dev");
2512
2513         let tmp = tmpdir(builder);
2514         let image = tmp.join("rust-dev-image");
2515         drop(fs::remove_dir_all(&image));
2516
2517         // Prepare the image directory
2518         let dst_bindir = image.join("bin");
2519         t!(fs::create_dir_all(&dst_bindir));
2520
2521         let src_bindir = builder.llvm_out(target).join("bin");
2522         let install_bin =
2523             |name| builder.install(&src_bindir.join(exe(name, target)), &dst_bindir, 0o755);
2524         install_bin("llvm-config");
2525         install_bin("llvm-ar");
2526         install_bin("llvm-objdump");
2527         install_bin("llvm-profdata");
2528         install_bin("llvm-bcanalyzer");
2529         install_bin("llvm-cov");
2530         builder.install(&builder.llvm_filecheck(target), &dst_bindir, 0o755);
2531
2532         // Copy the include directory as well; needed mostly to build
2533         // librustc_llvm properly (e.g., llvm-config.h is in here). But also
2534         // just broadly useful to be able to link against the bundled LLVM.
2535         builder.cp_r(&builder.llvm_out(target).join("include"), &image.join("include"));
2536
2537         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2538         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2539         // of `rustc-dev` to support the inherited `-lLLVM` when using the
2540         // compiler libraries.
2541         maybe_install_llvm(builder, target, &image.join("lib"));
2542
2543         // Prepare the overlay
2544         let overlay = tmp.join("rust-dev-overlay");
2545         drop(fs::remove_dir_all(&overlay));
2546         builder.create_dir(&overlay);
2547         builder.install(&src.join("README.txt"), &overlay, 0o644);
2548         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
2549         builder.create(&overlay.join("version"), &builder.rust_version());
2550
2551         // Generate the installer tarball
2552         let mut cmd = rust_installer(builder);
2553         cmd.arg("generate")
2554             .arg("--product-name=Rust")
2555             .arg("--rel-manifest-dir=rustlib")
2556             .arg("--success-message=rust-dev-installed.")
2557             .arg("--image-dir")
2558             .arg(&image)
2559             .arg("--work-dir")
2560             .arg(&tmpdir(builder))
2561             .arg("--output-dir")
2562             .arg(&distdir(builder))
2563             .arg("--non-installed-overlay")
2564             .arg(&overlay)
2565             .arg(format!("--package-name={}-{}", name, target.triple))
2566             .arg("--legacy-manifest-dirs=rustlib,cargo")
2567             .arg("--component-name=rust-dev");
2568
2569         builder.run(&mut cmd);
2570         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
2571     }
2572 }
2573
2574 /// Tarball containing a prebuilt version of the build-manifest tool, intented to be used by the
2575 /// release process to avoid cloning the monorepo and building stuff.
2576 ///
2577 /// Should not be considered stable by end users.
2578 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2579 pub struct BuildManifest {
2580     pub target: TargetSelection,
2581 }
2582
2583 impl Step for BuildManifest {
2584     type Output = PathBuf;
2585     const DEFAULT: bool = false;
2586     const ONLY_HOSTS: bool = true;
2587
2588     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2589         run.path("src/tools/build-manifest")
2590     }
2591
2592     fn make_run(run: RunConfig<'_>) {
2593         run.builder.ensure(BuildManifest { target: run.target });
2594     }
2595
2596     fn run(self, builder: &Builder<'_>) -> PathBuf {
2597         let build_manifest = builder.tool_exe(Tool::BuildManifest);
2598
2599         let name = pkgname(builder, "build-manifest");
2600         let tmp = tmpdir(builder);
2601
2602         // Prepare the image.
2603         let image = tmp.join("build-manifest-image");
2604         let image_bin = image.join("bin");
2605         let _ = fs::remove_dir_all(&image);
2606         t!(fs::create_dir_all(&image_bin));
2607         builder.install(&build_manifest, &image_bin, 0o755);
2608
2609         // Prepare the overlay.
2610         let overlay = tmp.join("build-manifest-overlay");
2611         let _ = fs::remove_dir_all(&overlay);
2612         builder.create_dir(&overlay);
2613         builder.create(&overlay.join("version"), &builder.rust_version());
2614         for file in &["COPYRIGHT", "LICENSE-APACHE", "LICENSE-MIT", "README.md"] {
2615             builder.install(&builder.src.join(file), &overlay, 0o644);
2616         }
2617
2618         // Create the final tarball.
2619         let mut cmd = rust_installer(builder);
2620         cmd.arg("generate")
2621             .arg("--product-name=Rust")
2622             .arg("--rel-manifest-dir=rustlib")
2623             .arg("--success-message=build-manifest installed.")
2624             .arg("--image-dir")
2625             .arg(&image)
2626             .arg("--work-dir")
2627             .arg(&tmpdir(builder))
2628             .arg("--output-dir")
2629             .arg(&distdir(builder))
2630             .arg("--non-installed-overlay")
2631             .arg(&overlay)
2632             .arg(format!("--package-name={}-{}", name, self.target.triple))
2633             .arg("--legacy-manifest-dirs=rustlib,cargo")
2634             .arg("--component-name=build-manifest");
2635
2636         builder.run(&mut cmd);
2637         distdir(builder).join(format!("{}-{}.tar.gz", name, self.target.triple))
2638     }
2639 }