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