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