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