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