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