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