]> git.proxmox.com Git - rustc.git/blob - src/bootstrap/dist.rs
New upstream version 1.54.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(&[]);
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_bulk_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(&[]);
107
108 let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
109 tarball.set_product_name("Rustc Documentation");
110 tarball.add_bulk_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 // for `-Z gcc-ld=lld`
406 let gcc_lld_dir = dst_dir.join("gcc-ld");
407 t!(fs::create_dir(&gcc_lld_dir));
408 builder.copy(&src_dir.join(&exe), &gcc_lld_dir.join(&exe));
409 }
410
411 // Copy over llvm-dwp if it's there
412 let exe = exe("rust-llvm-dwp", compiler.host);
413 builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
414
415 // Man pages
416 t!(fs::create_dir_all(image.join("share/man/man1")));
417 let man_src = builder.src.join("src/doc/man");
418 let man_dst = image.join("share/man/man1");
419
420 // Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time.
421 let time = env::var("SOURCE_DATE_EPOCH")
422 .map(|timestamp| {
423 let epoch = timestamp
424 .parse()
425 .map_err(|err| format!("could not parse SOURCE_DATE_EPOCH: {}", err))
426 .unwrap();
427
428 time::at(Timespec::new(epoch, 0))
429 })
430 .unwrap_or_else(|_| time::now());
431
432 let month_year = t!(time::strftime("%B %Y", &time));
433 // don't use our `bootstrap::util::{copy, cp_r}`, because those try
434 // to hardlink, and we don't want to edit the source templates
435 for file_entry in builder.read_dir(&man_src) {
436 let page_src = file_entry.path();
437 let page_dst = man_dst.join(file_entry.file_name());
438 t!(fs::copy(&page_src, &page_dst));
439 // template in month/year and version number
440 builder.replace_in_file(
441 &page_dst,
442 &[
443 ("<INSERT DATE HERE>", &month_year),
444 ("<INSERT VERSION HERE>", &builder.version),
445 ],
446 );
447 }
448
449 // Debugger scripts
450 builder
451 .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host });
452
453 // Misc license info
454 let cp = |file: &str| {
455 builder.install(&builder.src.join(file), &image.join("share/doc/rust"), 0o644);
456 };
457 cp("COPYRIGHT");
458 cp("LICENSE-APACHE");
459 cp("LICENSE-MIT");
460 cp("README.md");
461 }
462 }
463 }
464
465 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
466 pub struct DebuggerScripts {
467 pub sysroot: Interned<PathBuf>,
468 pub host: TargetSelection,
469 }
470
471 impl Step for DebuggerScripts {
472 type Output = ();
473
474 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
475 run.path("src/lldb_batchmode.py")
476 }
477
478 fn make_run(run: RunConfig<'_>) {
479 run.builder.ensure(DebuggerScripts {
480 sysroot: run
481 .builder
482 .sysroot(run.builder.compiler(run.builder.top_stage, run.build_triple())),
483 host: run.target,
484 });
485 }
486
487 /// Copies debugger scripts for `target` into the `sysroot` specified.
488 fn run(self, builder: &Builder<'_>) {
489 let host = self.host;
490 let sysroot = self.sysroot;
491 let dst = sysroot.join("lib/rustlib/etc");
492 t!(fs::create_dir_all(&dst));
493 let cp_debugger_script = |file: &str| {
494 builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
495 };
496 if host.contains("windows-msvc") {
497 // windbg debugger scripts
498 builder.install(
499 &builder.src.join("src/etc/rust-windbg.cmd"),
500 &sysroot.join("bin"),
501 0o755,
502 );
503
504 cp_debugger_script("natvis/intrinsic.natvis");
505 cp_debugger_script("natvis/liballoc.natvis");
506 cp_debugger_script("natvis/libcore.natvis");
507 cp_debugger_script("natvis/libstd.natvis");
508 } else {
509 cp_debugger_script("rust_types.py");
510
511 // gdb debugger scripts
512 builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
513 builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
514
515 cp_debugger_script("gdb_load_rust_pretty_printers.py");
516 cp_debugger_script("gdb_lookup.py");
517 cp_debugger_script("gdb_providers.py");
518
519 // lldb debugger scripts
520 builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
521
522 cp_debugger_script("lldb_lookup.py");
523 cp_debugger_script("lldb_providers.py");
524 cp_debugger_script("lldb_commands")
525 }
526 }
527 }
528
529 fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
530 // The only true set of target libraries came from the build triple, so
531 // let's reduce redundant work by only producing archives from that host.
532 if compiler.host != builder.config.build {
533 builder.info("\tskipping, not a build host");
534 true
535 } else {
536 false
537 }
538 }
539
540 /// Copy stamped files into an image's `target/lib` directory.
541 fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
542 let dst = image.join("lib/rustlib").join(target.triple).join("lib");
543 let self_contained_dst = dst.join("self-contained");
544 t!(fs::create_dir_all(&dst));
545 t!(fs::create_dir_all(&self_contained_dst));
546 for (path, dependency_type) in builder.read_stamp_file(stamp) {
547 if dependency_type == DependencyType::TargetSelfContained {
548 builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
549 } else if dependency_type == DependencyType::Target || builder.config.build == target {
550 builder.copy(&path, &dst.join(path.file_name().unwrap()));
551 }
552 }
553 }
554
555 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
556 pub struct Std {
557 pub compiler: Compiler,
558 pub target: TargetSelection,
559 }
560
561 impl Step for Std {
562 type Output = Option<GeneratedTarball>;
563 const DEFAULT: bool = true;
564
565 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
566 run.path("library/std")
567 }
568
569 fn make_run(run: RunConfig<'_>) {
570 run.builder.ensure(Std {
571 compiler: run.builder.compiler_for(
572 run.builder.top_stage,
573 run.builder.config.build,
574 run.target,
575 ),
576 target: run.target,
577 });
578 }
579
580 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
581 let compiler = self.compiler;
582 let target = self.target;
583
584 if skip_host_target_lib(builder, compiler) {
585 return None;
586 }
587
588 builder.ensure(compile::Std { compiler, target });
589
590 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
591 tarball.include_target_in_component_name(true);
592
593 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
594 let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
595 copy_target_libs(builder, target, &tarball.image_dir(), &stamp);
596
597 Some(tarball.generate())
598 }
599 }
600
601 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
602 pub struct RustcDev {
603 pub compiler: Compiler,
604 pub target: TargetSelection,
605 }
606
607 impl Step for RustcDev {
608 type Output = Option<GeneratedTarball>;
609 const DEFAULT: bool = true;
610 const ONLY_HOSTS: bool = true;
611
612 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
613 run.path("rustc-dev")
614 }
615
616 fn make_run(run: RunConfig<'_>) {
617 run.builder.ensure(RustcDev {
618 compiler: run.builder.compiler_for(
619 run.builder.top_stage,
620 run.builder.config.build,
621 run.target,
622 ),
623 target: run.target,
624 });
625 }
626
627 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
628 let compiler = self.compiler;
629 let target = self.target;
630 if skip_host_target_lib(builder, compiler) {
631 return None;
632 }
633
634 builder.ensure(compile::Rustc { compiler, target });
635
636 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
637
638 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
639 let stamp = compile::librustc_stamp(builder, compiler_to_use, target);
640 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
641
642 let src_files = &["Cargo.lock"];
643 // This is the reduced set of paths which will become the rustc-dev component
644 // (essentially the compiler crates and all of their path dependencies).
645 copy_src_dirs(
646 builder,
647 &builder.src,
648 &["compiler"],
649 &[],
650 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
651 );
652 // This particular crate is used as a build dependency of the above.
653 copy_src_dirs(
654 builder,
655 &builder.src,
656 &["src/build_helper"],
657 &[],
658 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
659 );
660 for file in src_files {
661 tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
662 }
663
664 Some(tarball.generate())
665 }
666 }
667
668 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
669 pub struct Analysis {
670 pub compiler: Compiler,
671 pub target: TargetSelection,
672 }
673
674 impl Step for Analysis {
675 type Output = Option<GeneratedTarball>;
676 const DEFAULT: bool = true;
677
678 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
679 let builder = run.builder;
680 run.path("analysis").default_condition(builder.config.extended)
681 }
682
683 fn make_run(run: RunConfig<'_>) {
684 run.builder.ensure(Analysis {
685 // Find the actual compiler (handling the full bootstrap option) which
686 // produced the save-analysis data because that data isn't copied
687 // through the sysroot uplifting.
688 compiler: run.builder.compiler_for(
689 run.builder.top_stage,
690 run.builder.config.build,
691 run.target,
692 ),
693 target: run.target,
694 });
695 }
696
697 /// Creates a tarball of save-analysis metadata, if available.
698 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
699 let compiler = self.compiler;
700 let target = self.target;
701 assert!(builder.config.extended);
702 if compiler.host != builder.config.build {
703 return None;
704 }
705
706 builder.ensure(compile::Std { compiler, target });
707 let src = builder
708 .stage_out(compiler, Mode::Std)
709 .join(target.triple)
710 .join(builder.cargo_dir())
711 .join("deps")
712 .join("save-analysis");
713
714 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
715 tarball.include_target_in_component_name(true);
716 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
717 Some(tarball.generate())
718 }
719 }
720
721 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
722 /// `dst_dir`.
723 fn copy_src_dirs(
724 builder: &Builder<'_>,
725 base: &Path,
726 src_dirs: &[&str],
727 exclude_dirs: &[&str],
728 dst_dir: &Path,
729 ) {
730 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
731 let spath = match path.to_str() {
732 Some(path) => path,
733 None => return false,
734 };
735 if spath.ends_with('~') || spath.ends_with(".pyc") {
736 return false;
737 }
738
739 const LLVM_PROJECTS: &[&str] = &[
740 "llvm-project/clang",
741 "llvm-project\\clang",
742 "llvm-project/libunwind",
743 "llvm-project\\libunwind",
744 "llvm-project/lld",
745 "llvm-project\\lld",
746 "llvm-project/lldb",
747 "llvm-project\\lldb",
748 "llvm-project/llvm",
749 "llvm-project\\llvm",
750 "llvm-project/compiler-rt",
751 "llvm-project\\compiler-rt",
752 ];
753 if spath.contains("llvm-project")
754 && !spath.ends_with("llvm-project")
755 && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
756 {
757 return false;
758 }
759
760 const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
761 if LLVM_TEST.iter().any(|path| spath.contains(path))
762 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
763 {
764 return false;
765 }
766
767 let full_path = Path::new(dir).join(path);
768 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
769 return false;
770 }
771
772 let excludes = [
773 "CVS",
774 "RCS",
775 "SCCS",
776 ".git",
777 ".gitignore",
778 ".gitmodules",
779 ".gitattributes",
780 ".cvsignore",
781 ".svn",
782 ".arch-ids",
783 "{arch}",
784 "=RELEASE-ID",
785 "=meta-update",
786 "=update",
787 ".bzr",
788 ".bzrignore",
789 ".bzrtags",
790 ".hg",
791 ".hgignore",
792 ".hgrags",
793 "_darcs",
794 ];
795 !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
796 }
797
798 // Copy the directories using our filter
799 for item in src_dirs {
800 let dst = &dst_dir.join(item);
801 t!(fs::create_dir_all(dst));
802 builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
803 }
804 }
805
806 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
807 pub struct Src;
808
809 impl Step for Src {
810 /// The output path of the src installer tarball
811 type Output = GeneratedTarball;
812 const DEFAULT: bool = true;
813 const ONLY_HOSTS: bool = true;
814
815 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
816 run.path("src")
817 }
818
819 fn make_run(run: RunConfig<'_>) {
820 run.builder.ensure(Src);
821 }
822
823 /// Creates the `rust-src` installer component
824 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
825 let tarball = Tarball::new_targetless(builder, "rust-src");
826
827 // A lot of tools expect the rust-src component to be entirely in this directory, so if you
828 // change that (e.g. by adding another directory `lib/rustlib/src/foo` or
829 // `lib/rustlib/src/rust/foo`), you will need to go around hunting for implicit assumptions
830 // and fix them...
831 //
832 // NOTE: if you update the paths here, you also should update the "virtual" path
833 // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
834 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
835
836 let src_files = ["Cargo.lock"];
837 // This is the reduced set of paths which will become the rust-src component
838 // (essentially libstd and all of its path dependencies).
839 copy_src_dirs(
840 builder,
841 &builder.src,
842 &["library", "src/llvm-project/libunwind"],
843 &[
844 // not needed and contains symlinks which rustup currently
845 // chokes on when unpacking.
846 "library/backtrace/crates",
847 ],
848 &dst_src,
849 );
850 for file in src_files.iter() {
851 builder.copy(&builder.src.join(file), &dst_src.join(file));
852 }
853
854 tarball.generate()
855 }
856 }
857
858 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
859 pub struct PlainSourceTarball;
860
861 impl Step for PlainSourceTarball {
862 /// Produces the location of the tarball generated
863 type Output = GeneratedTarball;
864 const DEFAULT: bool = true;
865 const ONLY_HOSTS: bool = true;
866
867 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
868 let builder = run.builder;
869 run.path("src").default_condition(builder.config.rust_dist_src)
870 }
871
872 fn make_run(run: RunConfig<'_>) {
873 run.builder.ensure(PlainSourceTarball);
874 }
875
876 /// Creates the plain source tarball
877 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
878 let tarball = Tarball::new(builder, "rustc", "src");
879 let plain_dst_src = tarball.image_dir();
880
881 // This is the set of root paths which will become part of the source package
882 let src_files = [
883 "COPYRIGHT",
884 "LICENSE-APACHE",
885 "LICENSE-MIT",
886 "CONTRIBUTING.md",
887 "README.md",
888 "RELEASES.md",
889 "configure",
890 "x.py",
891 "config.toml.example",
892 "Cargo.toml",
893 "Cargo.lock",
894 ];
895 let src_dirs = ["src", "compiler", "library"];
896
897 copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
898
899 // Copy the files normally
900 for item in &src_files {
901 builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
902 }
903
904 // Create the version file
905 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
906 if let Some(sha) = builder.rust_sha() {
907 builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
908 }
909
910 // If we're building from git sources, we need to vendor a complete distribution.
911 if builder.rust_info.is_git() {
912 // Vendor all Cargo dependencies
913 let mut cmd = Command::new(&builder.initial_cargo);
914 cmd.arg("vendor")
915 .arg("--sync")
916 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
917 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
918 .current_dir(&plain_dst_src);
919 builder.run(&mut cmd);
920 }
921
922 tarball.bare()
923 }
924 }
925
926 // We have to run a few shell scripts, which choke quite a bit on both `\`
927 // characters and on `C:\` paths, so normalize both of them away.
928 pub fn sanitize_sh(path: &Path) -> String {
929 let path = path.to_str().unwrap().replace("\\", "/");
930 return change_drive(unc_to_lfs(&path)).unwrap_or(path);
931
932 fn unc_to_lfs(s: &str) -> &str {
933 s.strip_prefix("//?/").unwrap_or(s)
934 }
935
936 fn change_drive(s: &str) -> Option<String> {
937 let mut ch = s.chars();
938 let drive = ch.next().unwrap_or('C');
939 if ch.next() != Some(':') {
940 return None;
941 }
942 if ch.next() != Some('/') {
943 return None;
944 }
945 Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
946 }
947 }
948
949 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
950 pub struct Cargo {
951 pub compiler: Compiler,
952 pub target: TargetSelection,
953 }
954
955 impl Step for Cargo {
956 type Output = GeneratedTarball;
957 const ONLY_HOSTS: bool = true;
958
959 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
960 run.path("cargo")
961 }
962
963 fn make_run(run: RunConfig<'_>) {
964 run.builder.ensure(Cargo {
965 compiler: run.builder.compiler_for(
966 run.builder.top_stage,
967 run.builder.config.build,
968 run.target,
969 ),
970 target: run.target,
971 });
972 }
973
974 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
975 let compiler = self.compiler;
976 let target = self.target;
977
978 let cargo = builder.ensure(tool::Cargo { compiler, target });
979 let src = builder.src.join("src/tools/cargo");
980 let etc = src.join("src/etc");
981
982 // Prepare the image directory
983 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
984 tarball.set_overlay(OverlayKind::Cargo);
985
986 tarball.add_file(&cargo, "bin", 0o755);
987 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
988 tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
989 tarball.add_dir(etc.join("man"), "share/man/man1");
990 tarball.add_legal_and_readme_to("share/doc/cargo");
991
992 for dirent in fs::read_dir(cargo.parent().unwrap()).expect("read_dir") {
993 let dirent = dirent.expect("read dir entry");
994 if dirent.file_name().to_str().expect("utf8").starts_with("cargo-credential-") {
995 tarball.add_file(&dirent.path(), "libexec", 0o755);
996 }
997 }
998
999 tarball.generate()
1000 }
1001 }
1002
1003 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1004 pub struct Rls {
1005 pub compiler: Compiler,
1006 pub target: TargetSelection,
1007 }
1008
1009 impl Step for Rls {
1010 type Output = Option<GeneratedTarball>;
1011 const ONLY_HOSTS: bool = true;
1012
1013 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1014 run.path("rls")
1015 }
1016
1017 fn make_run(run: RunConfig<'_>) {
1018 run.builder.ensure(Rls {
1019 compiler: run.builder.compiler_for(
1020 run.builder.top_stage,
1021 run.builder.config.build,
1022 run.target,
1023 ),
1024 target: run.target,
1025 });
1026 }
1027
1028 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1029 let compiler = self.compiler;
1030 let target = self.target;
1031 assert!(builder.config.extended);
1032
1033 let rls = builder
1034 .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1035 .or_else(|| {
1036 // We ignore failure on aarch64 Windows because RLS currently
1037 // fails to build, due to winapi 0.2 not supporting aarch64.
1038 missing_tool(
1039 "RLS",
1040 builder.build.config.missing_tools
1041 || (target.triple.contains("aarch64") && target.triple.contains("windows")),
1042 );
1043 None
1044 })?;
1045
1046 let mut tarball = Tarball::new(builder, "rls", &target.triple);
1047 tarball.set_overlay(OverlayKind::RLS);
1048 tarball.is_preview(true);
1049 tarball.add_file(rls, "bin", 0o755);
1050 tarball.add_legal_and_readme_to("share/doc/rls");
1051 Some(tarball.generate())
1052 }
1053 }
1054
1055 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1056 pub struct RustAnalyzer {
1057 pub compiler: Compiler,
1058 pub target: TargetSelection,
1059 }
1060
1061 impl Step for RustAnalyzer {
1062 type Output = Option<GeneratedTarball>;
1063 const ONLY_HOSTS: bool = true;
1064
1065 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1066 run.path("rust-analyzer")
1067 }
1068
1069 fn make_run(run: RunConfig<'_>) {
1070 run.builder.ensure(RustAnalyzer {
1071 compiler: run.builder.compiler_for(
1072 run.builder.top_stage,
1073 run.builder.config.build,
1074 run.target,
1075 ),
1076 target: run.target,
1077 });
1078 }
1079
1080 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1081 // This prevents rust-analyzer from being built for "dist" or "install"
1082 // on the stable/beta channels. It is a nightly-only tool and should
1083 // not be included.
1084 if !builder.build.unstable_features() {
1085 return None;
1086 }
1087 let compiler = self.compiler;
1088 let target = self.target;
1089 assert!(builder.config.extended);
1090
1091 if target.contains("riscv64") {
1092 // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1093 // to build. See #74813 for details.
1094 return None;
1095 }
1096
1097 let rust_analyzer = builder
1098 .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1099 .expect("rust-analyzer always builds");
1100
1101 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1102 tarball.set_overlay(OverlayKind::RustAnalyzer);
1103 tarball.is_preview(true);
1104 tarball.add_file(rust_analyzer, "bin", 0o755);
1105 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1106 Some(tarball.generate())
1107 }
1108 }
1109
1110 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1111 pub struct Clippy {
1112 pub compiler: Compiler,
1113 pub target: TargetSelection,
1114 }
1115
1116 impl Step for Clippy {
1117 type Output = GeneratedTarball;
1118 const ONLY_HOSTS: bool = true;
1119
1120 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1121 run.path("clippy")
1122 }
1123
1124 fn make_run(run: RunConfig<'_>) {
1125 run.builder.ensure(Clippy {
1126 compiler: run.builder.compiler_for(
1127 run.builder.top_stage,
1128 run.builder.config.build,
1129 run.target,
1130 ),
1131 target: run.target,
1132 });
1133 }
1134
1135 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1136 let compiler = self.compiler;
1137 let target = self.target;
1138 assert!(builder.config.extended);
1139
1140 // Prepare the image directory
1141 // We expect clippy to build, because we've exited this step above if tool
1142 // state for clippy isn't testing.
1143 let clippy = builder
1144 .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1145 .expect("clippy expected to build - essential tool");
1146 let cargoclippy = builder
1147 .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1148 .expect("clippy expected to build - essential tool");
1149
1150 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1151 tarball.set_overlay(OverlayKind::Clippy);
1152 tarball.is_preview(true);
1153 tarball.add_file(clippy, "bin", 0o755);
1154 tarball.add_file(cargoclippy, "bin", 0o755);
1155 tarball.add_legal_and_readme_to("share/doc/clippy");
1156 tarball.generate()
1157 }
1158 }
1159
1160 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1161 pub struct Miri {
1162 pub compiler: Compiler,
1163 pub target: TargetSelection,
1164 }
1165
1166 impl Step for Miri {
1167 type Output = Option<GeneratedTarball>;
1168 const ONLY_HOSTS: bool = true;
1169
1170 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1171 run.path("miri")
1172 }
1173
1174 fn make_run(run: RunConfig<'_>) {
1175 run.builder.ensure(Miri {
1176 compiler: run.builder.compiler_for(
1177 run.builder.top_stage,
1178 run.builder.config.build,
1179 run.target,
1180 ),
1181 target: run.target,
1182 });
1183 }
1184
1185 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1186 // This prevents miri from being built for "dist" or "install"
1187 // on the stable/beta channels. It is a nightly-only tool and should
1188 // not be included.
1189 if !builder.build.unstable_features() {
1190 return None;
1191 }
1192 let compiler = self.compiler;
1193 let target = self.target;
1194 assert!(builder.config.extended);
1195
1196 let miri = builder
1197 .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1198 .or_else(|| {
1199 missing_tool("miri", builder.build.config.missing_tools);
1200 None
1201 })?;
1202 let cargomiri = builder
1203 .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1204 .or_else(|| {
1205 missing_tool("cargo miri", builder.build.config.missing_tools);
1206 None
1207 })?;
1208
1209 let mut tarball = Tarball::new(builder, "miri", &target.triple);
1210 tarball.set_overlay(OverlayKind::Miri);
1211 tarball.is_preview(true);
1212 tarball.add_file(miri, "bin", 0o755);
1213 tarball.add_file(cargomiri, "bin", 0o755);
1214 tarball.add_legal_and_readme_to("share/doc/miri");
1215 Some(tarball.generate())
1216 }
1217 }
1218
1219 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1220 pub struct Rustfmt {
1221 pub compiler: Compiler,
1222 pub target: TargetSelection,
1223 }
1224
1225 impl Step for Rustfmt {
1226 type Output = Option<GeneratedTarball>;
1227 const ONLY_HOSTS: bool = true;
1228
1229 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1230 run.path("rustfmt")
1231 }
1232
1233 fn make_run(run: RunConfig<'_>) {
1234 run.builder.ensure(Rustfmt {
1235 compiler: run.builder.compiler_for(
1236 run.builder.top_stage,
1237 run.builder.config.build,
1238 run.target,
1239 ),
1240 target: run.target,
1241 });
1242 }
1243
1244 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1245 let compiler = self.compiler;
1246 let target = self.target;
1247
1248 let rustfmt = builder
1249 .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1250 .or_else(|| {
1251 missing_tool("Rustfmt", builder.build.config.missing_tools);
1252 None
1253 })?;
1254 let cargofmt = builder
1255 .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1256 .or_else(|| {
1257 missing_tool("Cargofmt", builder.build.config.missing_tools);
1258 None
1259 })?;
1260
1261 let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
1262 tarball.set_overlay(OverlayKind::Rustfmt);
1263 tarball.is_preview(true);
1264 tarball.add_file(rustfmt, "bin", 0o755);
1265 tarball.add_file(cargofmt, "bin", 0o755);
1266 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1267 Some(tarball.generate())
1268 }
1269 }
1270
1271 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1272 pub struct RustDemangler {
1273 pub compiler: Compiler,
1274 pub target: TargetSelection,
1275 }
1276
1277 impl Step for RustDemangler {
1278 type Output = Option<GeneratedTarball>;
1279 const ONLY_HOSTS: bool = true;
1280
1281 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1282 run.path("rust-demangler")
1283 }
1284
1285 fn make_run(run: RunConfig<'_>) {
1286 run.builder.ensure(RustDemangler {
1287 compiler: run.builder.compiler_for(
1288 run.builder.top_stage,
1289 run.builder.config.build,
1290 run.target,
1291 ),
1292 target: run.target,
1293 });
1294 }
1295
1296 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1297 let compiler = self.compiler;
1298 let target = self.target;
1299 assert!(builder.config.extended);
1300
1301 // Only build this extended tool if explicitly included in `tools`, or if `profiler = true`
1302 let profiler = builder.config.profiler_enabled(target);
1303 if !builder.config.tools.as_ref().map_or(profiler, |t| t.contains("rust-demangler")) {
1304 return None;
1305 }
1306
1307 let rust_demangler = builder
1308 .ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() })
1309 .expect("rust-demangler expected to build - in-tree tool");
1310
1311 // Prepare the image directory
1312 let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple);
1313 tarball.set_overlay(OverlayKind::RustDemangler);
1314 tarball.is_preview(true);
1315 tarball.add_file(&rust_demangler, "bin", 0o755);
1316 tarball.add_legal_and_readme_to("share/doc/rust-demangler");
1317 Some(tarball.generate())
1318 }
1319 }
1320
1321 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1322 pub struct Extended {
1323 stage: u32,
1324 host: TargetSelection,
1325 target: TargetSelection,
1326 }
1327
1328 impl Step for Extended {
1329 type Output = ();
1330 const DEFAULT: bool = true;
1331 const ONLY_HOSTS: bool = true;
1332
1333 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1334 let builder = run.builder;
1335 run.path("extended").default_condition(builder.config.extended)
1336 }
1337
1338 fn make_run(run: RunConfig<'_>) {
1339 run.builder.ensure(Extended {
1340 stage: run.builder.top_stage,
1341 host: run.builder.config.build,
1342 target: run.target,
1343 });
1344 }
1345
1346 /// Creates a combined installer for the specified target in the provided stage.
1347 fn run(self, builder: &Builder<'_>) {
1348 let target = self.target;
1349 let stage = self.stage;
1350 let compiler = builder.compiler_for(self.stage, self.host, self.target);
1351
1352 builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1353
1354 let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
1355 let cargo_installer = builder.ensure(Cargo { compiler, target });
1356 let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1357 let rust_demangler_installer = builder.ensure(RustDemangler { compiler, target });
1358 let rls_installer = builder.ensure(Rls { compiler, target });
1359 let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
1360 let llvm_tools_installer = builder.ensure(LlvmTools { target });
1361 let clippy_installer = builder.ensure(Clippy { compiler, target });
1362 let miri_installer = builder.ensure(Miri { compiler, target });
1363 let mingw_installer = builder.ensure(Mingw { host: target });
1364 let analysis_installer = builder.ensure(Analysis { compiler, target });
1365
1366 let docs_installer = builder.ensure(Docs { host: target });
1367 let std_installer = builder.ensure(Std { compiler, target });
1368
1369 let etc = builder.src.join("src/etc/installer");
1370
1371 // Avoid producing tarballs during a dry run.
1372 if builder.config.dry_run {
1373 return;
1374 }
1375
1376 // When rust-std package split from rustc, we needed to ensure that during
1377 // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1378 // the std files during uninstall. To do this ensure that rustc comes
1379 // before rust-std in the list below.
1380 let mut tarballs = Vec::new();
1381 tarballs.push(rustc_installer);
1382 tarballs.push(cargo_installer);
1383 tarballs.push(clippy_installer);
1384 tarballs.extend(rust_demangler_installer.clone());
1385 tarballs.extend(rls_installer.clone());
1386 tarballs.extend(rust_analyzer_installer.clone());
1387 tarballs.extend(miri_installer.clone());
1388 tarballs.extend(rustfmt_installer.clone());
1389 tarballs.extend(llvm_tools_installer);
1390 if let Some(analysis_installer) = analysis_installer {
1391 tarballs.push(analysis_installer);
1392 }
1393 tarballs.push(std_installer.expect("missing std"));
1394 if let Some(docs_installer) = docs_installer {
1395 tarballs.push(docs_installer);
1396 }
1397 if target.contains("pc-windows-gnu") {
1398 tarballs.push(mingw_installer.unwrap());
1399 }
1400
1401 let tarball = Tarball::new(builder, "rust", &target.triple);
1402 let generated = tarball.combine(&tarballs);
1403
1404 let tmp = tmpdir(builder).join("combined-tarball");
1405 let work = generated.work_dir();
1406
1407 let mut license = String::new();
1408 license += &builder.read(&builder.src.join("COPYRIGHT"));
1409 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1410 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1411 license.push('\n');
1412 license.push('\n');
1413
1414 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1415 let mut rtf = rtf.to_string();
1416 rtf.push('\n');
1417 for line in license.lines() {
1418 rtf.push_str(line);
1419 rtf.push_str("\\line ");
1420 }
1421 rtf.push('}');
1422
1423 fn filter(contents: &str, marker: &str) -> String {
1424 let start = format!("tool-{}-start", marker);
1425 let end = format!("tool-{}-end", marker);
1426 let mut lines = Vec::new();
1427 let mut omitted = false;
1428 for line in contents.lines() {
1429 if line.contains(&start) {
1430 omitted = true;
1431 } else if line.contains(&end) {
1432 omitted = false;
1433 } else if !omitted {
1434 lines.push(line);
1435 }
1436 }
1437
1438 lines.join("\n")
1439 }
1440
1441 let xform = |p: &Path| {
1442 let mut contents = t!(fs::read_to_string(p));
1443 if rust_demangler_installer.is_none() {
1444 contents = filter(&contents, "rust-demangler");
1445 }
1446 if rls_installer.is_none() {
1447 contents = filter(&contents, "rls");
1448 }
1449 if rust_analyzer_installer.is_none() {
1450 contents = filter(&contents, "rust-analyzer");
1451 }
1452 if miri_installer.is_none() {
1453 contents = filter(&contents, "miri");
1454 }
1455 if rustfmt_installer.is_none() {
1456 contents = filter(&contents, "rustfmt");
1457 }
1458 let ret = tmp.join(p.file_name().unwrap());
1459 t!(fs::write(&ret, &contents));
1460 ret
1461 };
1462
1463 if target.contains("apple-darwin") {
1464 builder.info("building pkg installer");
1465 let pkg = tmp.join("pkg");
1466 let _ = fs::remove_dir_all(&pkg);
1467
1468 let pkgbuild = |component: &str| {
1469 let mut cmd = Command::new("pkgbuild");
1470 cmd.arg("--identifier")
1471 .arg(format!("org.rust-lang.{}", component))
1472 .arg("--scripts")
1473 .arg(pkg.join(component))
1474 .arg("--nopayload")
1475 .arg(pkg.join(component).with_extension("pkg"));
1476 builder.run(&mut cmd);
1477 };
1478
1479 let prepare = |name: &str| {
1480 builder.create_dir(&pkg.join(name));
1481 builder.cp_r(
1482 &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1483 &pkg.join(name),
1484 );
1485 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1486 pkgbuild(name);
1487 };
1488 prepare("rustc");
1489 prepare("cargo");
1490 prepare("rust-docs");
1491 prepare("rust-std");
1492 prepare("rust-analysis");
1493 prepare("clippy");
1494 if rust_demangler_installer.is_some() {
1495 prepare("rust-demangler");
1496 }
1497 if rls_installer.is_some() {
1498 prepare("rls");
1499 }
1500 if rust_analyzer_installer.is_some() {
1501 prepare("rust-analyzer");
1502 }
1503 if miri_installer.is_some() {
1504 prepare("miri");
1505 }
1506
1507 // create an 'uninstall' package
1508 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1509 pkgbuild("uninstall");
1510
1511 builder.create_dir(&pkg.join("res"));
1512 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1513 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1514 let mut cmd = Command::new("productbuild");
1515 cmd.arg("--distribution")
1516 .arg(xform(&etc.join("pkg/Distribution.xml")))
1517 .arg("--resources")
1518 .arg(pkg.join("res"))
1519 .arg(distdir(builder).join(format!(
1520 "{}-{}.pkg",
1521 pkgname(builder, "rust"),
1522 target.triple
1523 )))
1524 .arg("--package-path")
1525 .arg(&pkg);
1526 let _time = timeit(builder);
1527 builder.run(&mut cmd);
1528 }
1529
1530 if target.contains("windows") {
1531 let exe = tmp.join("exe");
1532 let _ = fs::remove_dir_all(&exe);
1533
1534 let prepare = |name: &str| {
1535 builder.create_dir(&exe.join(name));
1536 let dir = if name == "rust-std" || name == "rust-analysis" {
1537 format!("{}-{}", name, target.triple)
1538 } else if name == "rls" {
1539 "rls-preview".to_string()
1540 } else if name == "rust-analyzer" {
1541 "rust-analyzer-preview".to_string()
1542 } else if name == "clippy" {
1543 "clippy-preview".to_string()
1544 } else if name == "rust-demangler" {
1545 "rust-demangler-preview".to_string()
1546 } else if name == "miri" {
1547 "miri-preview".to_string()
1548 } else {
1549 name.to_string()
1550 };
1551 builder.cp_r(
1552 &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1553 &exe.join(name),
1554 );
1555 builder.remove(&exe.join(name).join("manifest.in"));
1556 };
1557 prepare("rustc");
1558 prepare("cargo");
1559 prepare("rust-analysis");
1560 prepare("rust-docs");
1561 prepare("rust-std");
1562 prepare("clippy");
1563 if rust_demangler_installer.is_some() {
1564 prepare("rust-demangler");
1565 }
1566 if rls_installer.is_some() {
1567 prepare("rls");
1568 }
1569 if rust_analyzer_installer.is_some() {
1570 prepare("rust-analyzer");
1571 }
1572 if miri_installer.is_some() {
1573 prepare("miri");
1574 }
1575 if target.contains("windows-gnu") {
1576 prepare("rust-mingw");
1577 }
1578
1579 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1580
1581 // Generate msi installer
1582 let wix = PathBuf::from(env::var_os("WIX").unwrap());
1583 let heat = wix.join("bin/heat.exe");
1584 let candle = wix.join("bin/candle.exe");
1585 let light = wix.join("bin/light.exe");
1586
1587 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1588 builder.run(
1589 Command::new(&heat)
1590 .current_dir(&exe)
1591 .arg("dir")
1592 .arg("rustc")
1593 .args(&heat_flags)
1594 .arg("-cg")
1595 .arg("RustcGroup")
1596 .arg("-dr")
1597 .arg("Rustc")
1598 .arg("-var")
1599 .arg("var.RustcDir")
1600 .arg("-out")
1601 .arg(exe.join("RustcGroup.wxs")),
1602 );
1603 builder.run(
1604 Command::new(&heat)
1605 .current_dir(&exe)
1606 .arg("dir")
1607 .arg("rust-docs")
1608 .args(&heat_flags)
1609 .arg("-cg")
1610 .arg("DocsGroup")
1611 .arg("-dr")
1612 .arg("Docs")
1613 .arg("-var")
1614 .arg("var.DocsDir")
1615 .arg("-out")
1616 .arg(exe.join("DocsGroup.wxs"))
1617 .arg("-t")
1618 .arg(etc.join("msi/squash-components.xsl")),
1619 );
1620 builder.run(
1621 Command::new(&heat)
1622 .current_dir(&exe)
1623 .arg("dir")
1624 .arg("cargo")
1625 .args(&heat_flags)
1626 .arg("-cg")
1627 .arg("CargoGroup")
1628 .arg("-dr")
1629 .arg("Cargo")
1630 .arg("-var")
1631 .arg("var.CargoDir")
1632 .arg("-out")
1633 .arg(exe.join("CargoGroup.wxs"))
1634 .arg("-t")
1635 .arg(etc.join("msi/remove-duplicates.xsl")),
1636 );
1637 builder.run(
1638 Command::new(&heat)
1639 .current_dir(&exe)
1640 .arg("dir")
1641 .arg("rust-std")
1642 .args(&heat_flags)
1643 .arg("-cg")
1644 .arg("StdGroup")
1645 .arg("-dr")
1646 .arg("Std")
1647 .arg("-var")
1648 .arg("var.StdDir")
1649 .arg("-out")
1650 .arg(exe.join("StdGroup.wxs")),
1651 );
1652 if rls_installer.is_some() {
1653 builder.run(
1654 Command::new(&heat)
1655 .current_dir(&exe)
1656 .arg("dir")
1657 .arg("rls")
1658 .args(&heat_flags)
1659 .arg("-cg")
1660 .arg("RlsGroup")
1661 .arg("-dr")
1662 .arg("Rls")
1663 .arg("-var")
1664 .arg("var.RlsDir")
1665 .arg("-out")
1666 .arg(exe.join("RlsGroup.wxs"))
1667 .arg("-t")
1668 .arg(etc.join("msi/remove-duplicates.xsl")),
1669 );
1670 }
1671 if rust_analyzer_installer.is_some() {
1672 builder.run(
1673 Command::new(&heat)
1674 .current_dir(&exe)
1675 .arg("dir")
1676 .arg("rust-analyzer")
1677 .args(&heat_flags)
1678 .arg("-cg")
1679 .arg("RustAnalyzerGroup")
1680 .arg("-dr")
1681 .arg("RustAnalyzer")
1682 .arg("-var")
1683 .arg("var.RustAnalyzerDir")
1684 .arg("-out")
1685 .arg(exe.join("RustAnalyzerGroup.wxs"))
1686 .arg("-t")
1687 .arg(etc.join("msi/remove-duplicates.xsl")),
1688 );
1689 }
1690 builder.run(
1691 Command::new(&heat)
1692 .current_dir(&exe)
1693 .arg("dir")
1694 .arg("clippy")
1695 .args(&heat_flags)
1696 .arg("-cg")
1697 .arg("ClippyGroup")
1698 .arg("-dr")
1699 .arg("Clippy")
1700 .arg("-var")
1701 .arg("var.ClippyDir")
1702 .arg("-out")
1703 .arg(exe.join("ClippyGroup.wxs"))
1704 .arg("-t")
1705 .arg(etc.join("msi/remove-duplicates.xsl")),
1706 );
1707 if rust_demangler_installer.is_some() {
1708 builder.run(
1709 Command::new(&heat)
1710 .current_dir(&exe)
1711 .arg("dir")
1712 .arg("rust-demangler")
1713 .args(&heat_flags)
1714 .arg("-cg")
1715 .arg("RustDemanglerGroup")
1716 .arg("-dr")
1717 .arg("RustDemangler")
1718 .arg("-var")
1719 .arg("var.RustDemanglerDir")
1720 .arg("-out")
1721 .arg(exe.join("RustDemanglerGroup.wxs"))
1722 .arg("-t")
1723 .arg(etc.join("msi/remove-duplicates.xsl")),
1724 );
1725 }
1726 if miri_installer.is_some() {
1727 builder.run(
1728 Command::new(&heat)
1729 .current_dir(&exe)
1730 .arg("dir")
1731 .arg("miri")
1732 .args(&heat_flags)
1733 .arg("-cg")
1734 .arg("MiriGroup")
1735 .arg("-dr")
1736 .arg("Miri")
1737 .arg("-var")
1738 .arg("var.MiriDir")
1739 .arg("-out")
1740 .arg(exe.join("MiriGroup.wxs"))
1741 .arg("-t")
1742 .arg(etc.join("msi/remove-duplicates.xsl")),
1743 );
1744 }
1745 builder.run(
1746 Command::new(&heat)
1747 .current_dir(&exe)
1748 .arg("dir")
1749 .arg("rust-analysis")
1750 .args(&heat_flags)
1751 .arg("-cg")
1752 .arg("AnalysisGroup")
1753 .arg("-dr")
1754 .arg("Analysis")
1755 .arg("-var")
1756 .arg("var.AnalysisDir")
1757 .arg("-out")
1758 .arg(exe.join("AnalysisGroup.wxs"))
1759 .arg("-t")
1760 .arg(etc.join("msi/remove-duplicates.xsl")),
1761 );
1762 if target.contains("windows-gnu") {
1763 builder.run(
1764 Command::new(&heat)
1765 .current_dir(&exe)
1766 .arg("dir")
1767 .arg("rust-mingw")
1768 .args(&heat_flags)
1769 .arg("-cg")
1770 .arg("GccGroup")
1771 .arg("-dr")
1772 .arg("Gcc")
1773 .arg("-var")
1774 .arg("var.GccDir")
1775 .arg("-out")
1776 .arg(exe.join("GccGroup.wxs")),
1777 );
1778 }
1779
1780 let candle = |input: &Path| {
1781 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1782 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1783 let mut cmd = Command::new(&candle);
1784 cmd.current_dir(&exe)
1785 .arg("-nologo")
1786 .arg("-dRustcDir=rustc")
1787 .arg("-dDocsDir=rust-docs")
1788 .arg("-dCargoDir=cargo")
1789 .arg("-dStdDir=rust-std")
1790 .arg("-dAnalysisDir=rust-analysis")
1791 .arg("-dClippyDir=clippy")
1792 .arg("-arch")
1793 .arg(&arch)
1794 .arg("-out")
1795 .arg(&output)
1796 .arg(&input);
1797 add_env(builder, &mut cmd, target);
1798
1799 if rust_demangler_installer.is_some() {
1800 cmd.arg("-dRustDemanglerDir=rust-demangler");
1801 }
1802 if rls_installer.is_some() {
1803 cmd.arg("-dRlsDir=rls");
1804 }
1805 if rust_analyzer_installer.is_some() {
1806 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1807 }
1808 if miri_installer.is_some() {
1809 cmd.arg("-dMiriDir=miri");
1810 }
1811 if target.contains("windows-gnu") {
1812 cmd.arg("-dGccDir=rust-mingw");
1813 }
1814 builder.run(&mut cmd);
1815 };
1816 candle(&xform(&etc.join("msi/rust.wxs")));
1817 candle(&etc.join("msi/ui.wxs"));
1818 candle(&etc.join("msi/rustwelcomedlg.wxs"));
1819 candle("RustcGroup.wxs".as_ref());
1820 candle("DocsGroup.wxs".as_ref());
1821 candle("CargoGroup.wxs".as_ref());
1822 candle("StdGroup.wxs".as_ref());
1823 candle("ClippyGroup.wxs".as_ref());
1824 if rust_demangler_installer.is_some() {
1825 candle("RustDemanglerGroup.wxs".as_ref());
1826 }
1827 if rls_installer.is_some() {
1828 candle("RlsGroup.wxs".as_ref());
1829 }
1830 if rust_analyzer_installer.is_some() {
1831 candle("RustAnalyzerGroup.wxs".as_ref());
1832 }
1833 if miri_installer.is_some() {
1834 candle("MiriGroup.wxs".as_ref());
1835 }
1836 candle("AnalysisGroup.wxs".as_ref());
1837
1838 if target.contains("windows-gnu") {
1839 candle("GccGroup.wxs".as_ref());
1840 }
1841
1842 builder.create(&exe.join("LICENSE.rtf"), &rtf);
1843 builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1844 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1845
1846 builder.info(&format!("building `msi` installer with {:?}", light));
1847 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1848 let mut cmd = Command::new(&light);
1849 cmd.arg("-nologo")
1850 .arg("-ext")
1851 .arg("WixUIExtension")
1852 .arg("-ext")
1853 .arg("WixUtilExtension")
1854 .arg("-out")
1855 .arg(exe.join(&filename))
1856 .arg("rust.wixobj")
1857 .arg("ui.wixobj")
1858 .arg("rustwelcomedlg.wixobj")
1859 .arg("RustcGroup.wixobj")
1860 .arg("DocsGroup.wixobj")
1861 .arg("CargoGroup.wixobj")
1862 .arg("StdGroup.wixobj")
1863 .arg("AnalysisGroup.wixobj")
1864 .arg("ClippyGroup.wixobj")
1865 .current_dir(&exe);
1866
1867 if rls_installer.is_some() {
1868 cmd.arg("RlsGroup.wixobj");
1869 }
1870 if rust_analyzer_installer.is_some() {
1871 cmd.arg("RustAnalyzerGroup.wixobj");
1872 }
1873 if rust_demangler_installer.is_some() {
1874 cmd.arg("RustDemanglerGroup.wixobj");
1875 }
1876 if miri_installer.is_some() {
1877 cmd.arg("MiriGroup.wixobj");
1878 }
1879
1880 if target.contains("windows-gnu") {
1881 cmd.arg("GccGroup.wixobj");
1882 }
1883 // ICE57 wrongly complains about the shortcuts
1884 cmd.arg("-sice:ICE57");
1885
1886 let _time = timeit(builder);
1887 builder.run(&mut cmd);
1888
1889 if !builder.config.dry_run {
1890 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
1891 }
1892 }
1893 }
1894 }
1895
1896 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
1897 let mut parts = builder.version.split('.');
1898 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
1899 .env("CFG_RELEASE_NUM", &builder.version)
1900 .env("CFG_RELEASE", builder.rust_release())
1901 .env("CFG_VER_MAJOR", parts.next().unwrap())
1902 .env("CFG_VER_MINOR", parts.next().unwrap())
1903 .env("CFG_VER_PATCH", parts.next().unwrap())
1904 .env("CFG_VER_BUILD", "0") // just needed to build
1905 .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
1906 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
1907 .env("CFG_BUILD", target.triple)
1908 .env("CFG_CHANNEL", &builder.config.channel);
1909
1910 if target.contains("windows-gnu") {
1911 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
1912 } else {
1913 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
1914 }
1915
1916 if target.contains("x86_64") {
1917 cmd.env("CFG_PLATFORM", "x64");
1918 } else {
1919 cmd.env("CFG_PLATFORM", "x86");
1920 }
1921 }
1922
1923 /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
1924 ///
1925
1926 /// Returns whether the files were actually copied.
1927 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
1928 if let Some(config) = builder.config.target_config.get(&target) {
1929 if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
1930 // If the LLVM was externally provided, then we don't currently copy
1931 // artifacts into the sysroot. This is not necessarily the right
1932 // choice (in particular, it will require the LLVM dylib to be in
1933 // the linker's load path at runtime), but the common use case for
1934 // external LLVMs is distribution provided LLVMs, and in that case
1935 // they're usually in the standard search path (e.g., /usr/lib) and
1936 // copying them here is going to cause problems as we may end up
1937 // with the wrong files and isn't what distributions want.
1938 //
1939 // This behavior may be revisited in the future though.
1940 //
1941 // If the LLVM is coming from ourselves (just from CI) though, we
1942 // still want to install it, as it otherwise won't be available.
1943 return false;
1944 }
1945 }
1946
1947 // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
1948 // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
1949 // clear why this is the case, though. llvm-config will emit the versioned
1950 // paths and we don't want those in the sysroot (as we're expecting
1951 // unversioned paths).
1952 if target.contains("apple-darwin") && builder.config.llvm_link_shared {
1953 let src_libdir = builder.llvm_out(target).join("lib");
1954 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
1955 if llvm_dylib_path.exists() {
1956 builder.install(&llvm_dylib_path, dst_libdir, 0o644);
1957 }
1958 !builder.config.dry_run
1959 } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
1960 let mut cmd = Command::new(llvm_config);
1961 cmd.arg("--libfiles");
1962 builder.verbose(&format!("running {:?}", cmd));
1963 let files = output(&mut cmd);
1964 for file in files.trim_end().split(' ') {
1965 builder.install(Path::new(file), dst_libdir, 0o644);
1966 }
1967 !builder.config.dry_run
1968 } else {
1969 false
1970 }
1971 }
1972
1973 /// Maybe add libLLVM.so to the target lib-dir for linking.
1974 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1975 let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
1976 // We do not need to copy LLVM files into the sysroot if it is not
1977 // dynamically linked; it is already included into librustc_llvm
1978 // statically.
1979 if builder.config.llvm_link_shared {
1980 maybe_install_llvm(builder, target, &dst_libdir);
1981 }
1982 }
1983
1984 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
1985 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1986 let dst_libdir =
1987 sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
1988 // We do not need to copy LLVM files into the sysroot if it is not
1989 // dynamically linked; it is already included into librustc_llvm
1990 // statically.
1991 if builder.config.llvm_link_shared {
1992 maybe_install_llvm(builder, target, &dst_libdir);
1993 }
1994 }
1995
1996 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1997 pub struct LlvmTools {
1998 pub target: TargetSelection,
1999 }
2000
2001 impl Step for LlvmTools {
2002 type Output = Option<GeneratedTarball>;
2003 const ONLY_HOSTS: bool = true;
2004
2005 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2006 run.path("llvm-tools")
2007 }
2008
2009 fn make_run(run: RunConfig<'_>) {
2010 run.builder.ensure(LlvmTools { target: run.target });
2011 }
2012
2013 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2014 let target = self.target;
2015 assert!(builder.config.extended);
2016
2017 /* run only if llvm-config isn't used */
2018 if let Some(config) = builder.config.target_config.get(&target) {
2019 if let Some(ref _s) = config.llvm_config {
2020 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
2021 return None;
2022 }
2023 }
2024
2025 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2026 tarball.set_overlay(OverlayKind::LLVM);
2027 tarball.is_preview(true);
2028
2029 // Prepare the image directory
2030 let src_bindir = builder.llvm_out(target).join("bin");
2031 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2032 for tool in LLVM_TOOLS {
2033 let exe = src_bindir.join(exe(tool, target));
2034 tarball.add_file(&exe, &dst_bindir, 0o755);
2035 }
2036
2037 // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2038 // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2039 // of `rustc-dev` to support the inherited `-lLLVM` when using the
2040 // compiler libraries.
2041 maybe_install_llvm_target(builder, target, tarball.image_dir());
2042
2043 Some(tarball.generate())
2044 }
2045 }
2046
2047 // Tarball intended for internal consumption to ease rustc/std development.
2048 //
2049 // Should not be considered stable by end users.
2050 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2051 pub struct RustDev {
2052 pub target: TargetSelection,
2053 }
2054
2055 impl Step for RustDev {
2056 type Output = Option<GeneratedTarball>;
2057 const DEFAULT: bool = true;
2058 const ONLY_HOSTS: bool = true;
2059
2060 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2061 run.path("rust-dev")
2062 }
2063
2064 fn make_run(run: RunConfig<'_>) {
2065 run.builder.ensure(RustDev { target: run.target });
2066 }
2067
2068 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2069 let target = self.target;
2070
2071 /* run only if llvm-config isn't used */
2072 if let Some(config) = builder.config.target_config.get(&target) {
2073 if let Some(ref _s) = config.llvm_config {
2074 builder.info(&format!("Skipping RustDev ({}): external LLVM", target));
2075 return None;
2076 }
2077 }
2078
2079 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2080 tarball.set_overlay(OverlayKind::LLVM);
2081
2082 let src_bindir = builder.llvm_out(target).join("bin");
2083 for bin in &[
2084 "llvm-config",
2085 "llvm-ar",
2086 "llvm-objdump",
2087 "llvm-profdata",
2088 "llvm-bcanalyzer",
2089 "llvm-cov",
2090 "llvm-dwp",
2091 ] {
2092 tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
2093 }
2094 tarball.add_file(&builder.llvm_filecheck(target), "bin", 0o755);
2095
2096 // Copy the include directory as well; needed mostly to build
2097 // librustc_llvm properly (e.g., llvm-config.h is in here). But also
2098 // just broadly useful to be able to link against the bundled LLVM.
2099 tarball.add_dir(&builder.llvm_out(target).join("include"), "include");
2100
2101 // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2102 // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2103 // of `rustc-dev` to support the inherited `-lLLVM` when using the
2104 // compiler libraries.
2105 let dst_libdir = tarball.image_dir().join("lib");
2106 maybe_install_llvm(builder, target, &dst_libdir);
2107 let link_type = if builder.config.llvm_link_shared { "dynamic" } else { "static" };
2108 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2109
2110 Some(tarball.generate())
2111 }
2112 }
2113
2114 /// Tarball containing a prebuilt version of the build-manifest tool, intented to be used by the
2115 /// release process to avoid cloning the monorepo and building stuff.
2116 ///
2117 /// Should not be considered stable by end users.
2118 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2119 pub struct BuildManifest {
2120 pub target: TargetSelection,
2121 }
2122
2123 impl Step for BuildManifest {
2124 type Output = GeneratedTarball;
2125 const DEFAULT: bool = false;
2126 const ONLY_HOSTS: bool = true;
2127
2128 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2129 run.path("src/tools/build-manifest")
2130 }
2131
2132 fn make_run(run: RunConfig<'_>) {
2133 run.builder.ensure(BuildManifest { target: run.target });
2134 }
2135
2136 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2137 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2138
2139 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2140 tarball.add_file(&build_manifest, "bin", 0o755);
2141 tarball.generate()
2142 }
2143 }
2144
2145 /// Tarball containing artifacts necessary to reproduce the build of rustc.
2146 ///
2147 /// Currently this is the PGO profile data.
2148 ///
2149 /// Should not be considered stable by end users.
2150 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2151 pub struct ReproducibleArtifacts {
2152 pub target: TargetSelection,
2153 }
2154
2155 impl Step for ReproducibleArtifacts {
2156 type Output = Option<GeneratedTarball>;
2157 const DEFAULT: bool = true;
2158 const ONLY_HOSTS: bool = true;
2159
2160 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2161 run.path("reproducible")
2162 }
2163
2164 fn make_run(run: RunConfig<'_>) {
2165 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2166 }
2167
2168 fn run(self, builder: &Builder<'_>) -> Self::Output {
2169 let path = builder.config.rust_profile_use.as_ref()?;
2170
2171 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2172 tarball.add_file(path, ".", 0o644);
2173 Some(tarball.generate())
2174 }
2175 }