]> git.proxmox.com Git - rustc.git/blob - src/bootstrap/compile.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / src / bootstrap / compile.rs
1 //! Implementation of compiling various phases of the compiler and standard
2 //! library.
3 //!
4 //! This module contains some of the real meat in the rustbuild build system
5 //! which is where Cargo is used to compile the standard library, libtest, and
6 //! the compiler. This module is also responsible for assembling the sysroot as it
7 //! goes along from the output of the previous stage.
8
9 use std::borrow::Cow;
10 use std::collections::HashSet;
11 use std::env;
12 use std::fs;
13 use std::io::prelude::*;
14 use std::io::BufReader;
15 use std::path::{Path, PathBuf};
16 use std::process::{Command, Stdio};
17 use std::str;
18
19 use serde_derive::Deserialize;
20
21 use crate::builder::crate_description;
22 use crate::builder::Cargo;
23 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
24 use crate::cache::{Interned, INTERNER};
25 use crate::config::{LlvmLibunwind, RustcLto, TargetSelection};
26 use crate::dist;
27 use crate::native;
28 use crate::tool::SourceType;
29 use crate::util::get_clang_cl_resource_dir;
30 use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date};
31 use crate::LLVM_TOOLS;
32 use crate::{CLang, Compiler, DependencyType, GitRepo, Mode};
33
34 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35 pub struct Std {
36 pub target: TargetSelection,
37 pub compiler: Compiler,
38 /// Whether to build only a subset of crates in the standard library.
39 ///
40 /// This shouldn't be used from other steps; see the comment on [`Rustc`].
41 crates: Interned<Vec<String>>,
42 }
43
44 impl Std {
45 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
46 Self { target, compiler, crates: Default::default() }
47 }
48 }
49
50 impl Step for Std {
51 type Output = ();
52 const DEFAULT: bool = true;
53
54 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
55 // When downloading stage1, the standard library has already been copied to the sysroot, so
56 // there's no need to rebuild it.
57 let builder = run.builder;
58 run.crate_or_deps("test")
59 .path("library")
60 .lazy_default_condition(Box::new(|| !builder.download_rustc()))
61 }
62
63 fn make_run(run: RunConfig<'_>) {
64 // Normally, people will pass *just* library if they pass it.
65 // But it's possible (although strange) to pass something like `library std core`.
66 // Build all crates anyway, as if they hadn't passed the other args.
67 let has_library =
68 run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
69 let crates = if has_library { Default::default() } else { run.cargo_crates_in_set() };
70 run.builder.ensure(Std {
71 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
72 target: run.target,
73 crates,
74 });
75 }
76
77 /// Builds the standard library.
78 ///
79 /// This will build the standard library for a particular stage of the build
80 /// using the `compiler` targeting the `target` architecture. The artifacts
81 /// created will also be linked into the sysroot directory.
82 fn run(self, builder: &Builder<'_>) {
83 let target = self.target;
84 let compiler = self.compiler;
85
86 // These artifacts were already copied (in `impl Step for Sysroot`).
87 // Don't recompile them.
88 // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
89 // so its artifacts can't be reused.
90 if builder.download_rustc() && compiler.stage != 0 {
91 return;
92 }
93
94 if builder.config.keep_stage.contains(&compiler.stage)
95 || builder.config.keep_stage_std.contains(&compiler.stage)
96 {
97 builder.info("Warning: Using a potentially old libstd. This may not behave well.");
98 builder.ensure(StdLink::from_std(self, compiler));
99 return;
100 }
101
102 builder.update_submodule(&Path::new("library").join("stdarch"));
103
104 // Profiler information requires LLVM's compiler-rt
105 if builder.config.profiler {
106 builder.update_submodule(&Path::new("src/llvm-project"));
107 }
108
109 let mut target_deps = builder.ensure(StartupObjects { compiler, target });
110
111 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
112 if compiler_to_use != compiler {
113 builder.ensure(Std::new(compiler_to_use, target));
114 let msg = if compiler_to_use.host == target {
115 format!(
116 "Uplifting library (stage{} -> stage{})",
117 compiler_to_use.stage, compiler.stage
118 )
119 } else {
120 format!(
121 "Uplifting library (stage{}:{} -> stage{}:{})",
122 compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
123 )
124 };
125 builder.info(&msg);
126
127 // Even if we're not building std this stage, the new sysroot must
128 // still contain the third party objects needed by various targets.
129 copy_third_party_objects(builder, &compiler, target);
130 copy_self_contained_objects(builder, &compiler, target);
131
132 builder.ensure(StdLink::from_std(self, compiler_to_use));
133 return;
134 }
135
136 target_deps.extend(copy_third_party_objects(builder, &compiler, target));
137 target_deps.extend(copy_self_contained_objects(builder, &compiler, target));
138
139 let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build");
140 std_cargo(builder, target, compiler.stage, &mut cargo);
141 for krate in &*self.crates {
142 cargo.arg("-p").arg(krate);
143 }
144
145 let msg = if compiler.host == target {
146 format!(
147 "Building{} stage{} library artifacts ({}) ",
148 crate_description(&self.crates),
149 compiler.stage,
150 compiler.host
151 )
152 } else {
153 format!(
154 "Building{} stage{} library artifacts ({} -> {})",
155 crate_description(&self.crates),
156 compiler.stage,
157 compiler.host,
158 target,
159 )
160 };
161 builder.info(&msg);
162 run_cargo(
163 builder,
164 cargo,
165 vec![],
166 &libstd_stamp(builder, compiler, target),
167 target_deps,
168 false,
169 false,
170 );
171
172 builder.ensure(StdLink::from_std(
173 self,
174 builder.compiler(compiler.stage, builder.config.build),
175 ));
176 }
177 }
178
179 fn copy_and_stamp(
180 builder: &Builder<'_>,
181 libdir: &Path,
182 sourcedir: &Path,
183 name: &str,
184 target_deps: &mut Vec<(PathBuf, DependencyType)>,
185 dependency_type: DependencyType,
186 ) {
187 let target = libdir.join(name);
188 builder.copy(&sourcedir.join(name), &target);
189
190 target_deps.push((target, dependency_type));
191 }
192
193 fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
194 let libunwind_path = builder.ensure(native::Libunwind { target });
195 let libunwind_source = libunwind_path.join("libunwind.a");
196 let libunwind_target = libdir.join("libunwind.a");
197 builder.copy(&libunwind_source, &libunwind_target);
198 libunwind_target
199 }
200
201 /// Copies third party objects needed by various targets.
202 fn copy_third_party_objects(
203 builder: &Builder<'_>,
204 compiler: &Compiler,
205 target: TargetSelection,
206 ) -> Vec<(PathBuf, DependencyType)> {
207 let mut target_deps = vec![];
208
209 // FIXME: remove this in 2021
210 if target == "x86_64-fortanix-unknown-sgx" {
211 if env::var_os("X86_FORTANIX_SGX_LIBS").is_some() {
212 builder.info("Warning: X86_FORTANIX_SGX_LIBS environment variable is ignored, libunwind is now compiled as part of rustbuild");
213 }
214 }
215
216 if builder.config.sanitizers_enabled(target) && compiler.stage != 0 {
217 // The sanitizers are only copied in stage1 or above,
218 // to avoid creating dependency on LLVM.
219 target_deps.extend(
220 copy_sanitizers(builder, &compiler, target)
221 .into_iter()
222 .map(|d| (d, DependencyType::Target)),
223 );
224 }
225
226 if target == "x86_64-fortanix-unknown-sgx"
227 || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
228 && (target.contains("linux") || target.contains("fuchsia"))
229 {
230 let libunwind_path =
231 copy_llvm_libunwind(builder, target, &builder.sysroot_libdir(*compiler, target));
232 target_deps.push((libunwind_path, DependencyType::Target));
233 }
234
235 target_deps
236 }
237
238 /// Copies third party objects needed by various targets for self-contained linkage.
239 fn copy_self_contained_objects(
240 builder: &Builder<'_>,
241 compiler: &Compiler,
242 target: TargetSelection,
243 ) -> Vec<(PathBuf, DependencyType)> {
244 let libdir_self_contained = builder.sysroot_libdir(*compiler, target).join("self-contained");
245 t!(fs::create_dir_all(&libdir_self_contained));
246 let mut target_deps = vec![];
247
248 // Copies the libc and CRT objects.
249 //
250 // rustc historically provides a more self-contained installation for musl targets
251 // not requiring the presence of a native musl toolchain. For example, it can fall back
252 // to using gcc from a glibc-targeting toolchain for linking.
253 // To do that we have to distribute musl startup objects as a part of Rust toolchain
254 // and link with them manually in the self-contained mode.
255 if target.contains("musl") {
256 let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
257 panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
258 });
259 for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
260 copy_and_stamp(
261 builder,
262 &libdir_self_contained,
263 &srcdir,
264 obj,
265 &mut target_deps,
266 DependencyType::TargetSelfContained,
267 );
268 }
269 let crt_path = builder.ensure(native::CrtBeginEnd { target });
270 for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
271 let src = crt_path.join(obj);
272 let target = libdir_self_contained.join(obj);
273 builder.copy(&src, &target);
274 target_deps.push((target, DependencyType::TargetSelfContained));
275 }
276
277 if !target.starts_with("s390x") {
278 let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
279 target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
280 }
281 } else if target.ends_with("-wasi") {
282 let srcdir = builder
283 .wasi_root(target)
284 .unwrap_or_else(|| {
285 panic!("Target {:?} does not have a \"wasi-root\" key", target.triple)
286 })
287 .join("lib/wasm32-wasi");
288 for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
289 copy_and_stamp(
290 builder,
291 &libdir_self_contained,
292 &srcdir,
293 obj,
294 &mut target_deps,
295 DependencyType::TargetSelfContained,
296 );
297 }
298 } else if target.ends_with("windows-gnu") {
299 for obj in ["crt2.o", "dllcrt2.o"].iter() {
300 let src = compiler_file(builder, builder.cc(target), target, CLang::C, obj);
301 let target = libdir_self_contained.join(obj);
302 builder.copy(&src, &target);
303 target_deps.push((target, DependencyType::TargetSelfContained));
304 }
305 }
306
307 target_deps
308 }
309
310 /// Configure cargo to compile the standard library, adding appropriate env vars
311 /// and such.
312 pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
313 if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
314 cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
315 }
316
317 // Determine if we're going to compile in optimized C intrinsics to
318 // the `compiler-builtins` crate. These intrinsics live in LLVM's
319 // `compiler-rt` repository, but our `src/llvm-project` submodule isn't
320 // always checked out, so we need to conditionally look for this. (e.g. if
321 // an external LLVM is used we skip the LLVM submodule checkout).
322 //
323 // Note that this shouldn't affect the correctness of `compiler-builtins`,
324 // but only its speed. Some intrinsics in C haven't been translated to Rust
325 // yet but that's pretty rare. Other intrinsics have optimized
326 // implementations in C which have only had slower versions ported to Rust,
327 // so we favor the C version where we can, but it's not critical.
328 //
329 // If `compiler-rt` is available ensure that the `c` feature of the
330 // `compiler-builtins` crate is enabled and it's configured to learn where
331 // `compiler-rt` is located.
332 let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
333 let compiler_builtins_c_feature = if compiler_builtins_root.exists() {
334 // Note that `libprofiler_builtins/build.rs` also computes this so if
335 // you're changing something here please also change that.
336 cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
337 " compiler-builtins-c"
338 } else {
339 ""
340 };
341
342 let mut features = String::new();
343
344 // Cranelift doesn't support `asm`.
345 if stage != 0 && builder.config.default_codegen_backend().unwrap_or_default() == "cranelift" {
346 features += " compiler-builtins-no-asm";
347 }
348
349 if builder.no_std(target) == Some(true) {
350 features += " compiler-builtins-mem";
351 if !target.starts_with("bpf") {
352 features.push_str(compiler_builtins_c_feature);
353 }
354
355 // for no-std targets we only compile a few no_std crates
356 cargo
357 .args(&["-p", "alloc"])
358 .arg("--manifest-path")
359 .arg(builder.src.join("library/alloc/Cargo.toml"))
360 .arg("--features")
361 .arg(features);
362 } else {
363 features += &builder.std_features(target);
364 features.push_str(compiler_builtins_c_feature);
365
366 cargo
367 .arg("--features")
368 .arg(features)
369 .arg("--manifest-path")
370 .arg(builder.src.join("library/test/Cargo.toml"));
371
372 // Help the libc crate compile by assisting it in finding various
373 // sysroot native libraries.
374 if target.contains("musl") {
375 if let Some(p) = builder.musl_libdir(target) {
376 let root = format!("native={}", p.to_str().unwrap());
377 cargo.rustflag("-L").rustflag(&root);
378 }
379 }
380
381 if target.ends_with("-wasi") {
382 if let Some(p) = builder.wasi_root(target) {
383 let root = format!("native={}/lib/wasm32-wasi", p.to_str().unwrap());
384 cargo.rustflag("-L").rustflag(&root);
385 }
386 }
387 }
388
389 // By default, rustc uses `-Cembed-bitcode=yes`, and Cargo overrides that
390 // with `-Cembed-bitcode=no` for non-LTO builds. However, libstd must be
391 // built with bitcode so that the produced rlibs can be used for both LTO
392 // builds (which use bitcode) and non-LTO builds (which use object code).
393 // So we override the override here!
394 //
395 // But we don't bother for the stage 0 compiler because it's never used
396 // with LTO.
397 if stage >= 1 {
398 cargo.rustflag("-Cembed-bitcode=yes");
399 }
400 if builder.config.rust_lto == RustcLto::Off {
401 cargo.rustflag("-Clto=off");
402 }
403
404 // By default, rustc does not include unwind tables unless they are required
405 // for a particular target. They are not required by RISC-V targets, but
406 // compiling the standard library with them means that users can get
407 // backtraces without having to recompile the standard library themselves.
408 //
409 // This choice was discussed in https://github.com/rust-lang/rust/pull/69890
410 if target.contains("riscv") {
411 cargo.rustflag("-Cforce-unwind-tables=yes");
412 }
413
414 let html_root =
415 format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
416 cargo.rustflag(&html_root);
417 cargo.rustdocflag(&html_root);
418 }
419
420 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
421 struct StdLink {
422 pub compiler: Compiler,
423 pub target_compiler: Compiler,
424 pub target: TargetSelection,
425 /// Not actually used; only present to make sure the cache invalidation is correct.
426 crates: Interned<Vec<String>>,
427 }
428
429 impl StdLink {
430 fn from_std(std: Std, host_compiler: Compiler) -> Self {
431 Self {
432 compiler: host_compiler,
433 target_compiler: std.compiler,
434 target: std.target,
435 crates: std.crates,
436 }
437 }
438 }
439
440 impl Step for StdLink {
441 type Output = ();
442
443 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
444 run.never()
445 }
446
447 /// Link all libstd rlibs/dylibs into the sysroot location.
448 ///
449 /// Links those artifacts generated by `compiler` to the `stage` compiler's
450 /// sysroot for the specified `host` and `target`.
451 ///
452 /// Note that this assumes that `compiler` has already generated the libstd
453 /// libraries for `target`, and this method will find them in the relevant
454 /// output directory.
455 fn run(self, builder: &Builder<'_>) {
456 let compiler = self.compiler;
457 let target_compiler = self.target_compiler;
458 let target = self.target;
459 let libdir = builder.sysroot_libdir(target_compiler, target);
460 let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
461 add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
462 }
463 }
464
465 /// Copies sanitizer runtime libraries into target libdir.
466 fn copy_sanitizers(
467 builder: &Builder<'_>,
468 compiler: &Compiler,
469 target: TargetSelection,
470 ) -> Vec<PathBuf> {
471 let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
472
473 if builder.config.dry_run() {
474 return Vec::new();
475 }
476
477 let mut target_deps = Vec::new();
478 let libdir = builder.sysroot_libdir(*compiler, target);
479
480 for runtime in &runtimes {
481 let dst = libdir.join(&runtime.name);
482 builder.copy(&runtime.path, &dst);
483
484 if target == "x86_64-apple-darwin"
485 || target == "aarch64-apple-darwin"
486 || target == "aarch64-apple-ios"
487 || target == "aarch64-apple-ios-sim"
488 || target == "x86_64-apple-ios"
489 {
490 // Update the library’s install name to reflect that it has been renamed.
491 apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name));
492 // Upon renaming the install name, the code signature of the file will invalidate,
493 // so we will sign it again.
494 apple_darwin_sign_file(&dst);
495 }
496
497 target_deps.push(dst);
498 }
499
500 target_deps
501 }
502
503 fn apple_darwin_update_library_name(library_path: &Path, new_name: &str) {
504 let status = Command::new("install_name_tool")
505 .arg("-id")
506 .arg(new_name)
507 .arg(library_path)
508 .status()
509 .expect("failed to execute `install_name_tool`");
510 assert!(status.success());
511 }
512
513 fn apple_darwin_sign_file(file_path: &Path) {
514 let status = Command::new("codesign")
515 .arg("-f") // Force to rewrite the existing signature
516 .arg("-s")
517 .arg("-")
518 .arg(file_path)
519 .status()
520 .expect("failed to execute `codesign`");
521 assert!(status.success());
522 }
523
524 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
525 pub struct StartupObjects {
526 pub compiler: Compiler,
527 pub target: TargetSelection,
528 }
529
530 impl Step for StartupObjects {
531 type Output = Vec<(PathBuf, DependencyType)>;
532
533 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
534 run.path("library/rtstartup")
535 }
536
537 fn make_run(run: RunConfig<'_>) {
538 run.builder.ensure(StartupObjects {
539 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
540 target: run.target,
541 });
542 }
543
544 /// Builds and prepare startup objects like rsbegin.o and rsend.o
545 ///
546 /// These are primarily used on Windows right now for linking executables/dlls.
547 /// They don't require any library support as they're just plain old object
548 /// files, so we just use the nightly snapshot compiler to always build them (as
549 /// no other compilers are guaranteed to be available).
550 fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
551 let for_compiler = self.compiler;
552 let target = self.target;
553 if !target.ends_with("windows-gnu") {
554 return vec![];
555 }
556
557 let mut target_deps = vec![];
558
559 let src_dir = &builder.src.join("library").join("rtstartup");
560 let dst_dir = &builder.native_dir(target).join("rtstartup");
561 let sysroot_dir = &builder.sysroot_libdir(for_compiler, target);
562 t!(fs::create_dir_all(dst_dir));
563
564 for file in &["rsbegin", "rsend"] {
565 let src_file = &src_dir.join(file.to_string() + ".rs");
566 let dst_file = &dst_dir.join(file.to_string() + ".o");
567 if !up_to_date(src_file, dst_file) {
568 let mut cmd = Command::new(&builder.initial_rustc);
569 cmd.env("RUSTC_BOOTSTRAP", "1");
570 if !builder.local_rebuild {
571 // a local_rebuild compiler already has stage1 features
572 cmd.arg("--cfg").arg("bootstrap");
573 }
574 builder.run(
575 cmd.arg("--target")
576 .arg(target.rustc_target_arg())
577 .arg("--emit=obj")
578 .arg("-o")
579 .arg(dst_file)
580 .arg(src_file),
581 );
582 }
583
584 let target = sysroot_dir.join((*file).to_string() + ".o");
585 builder.copy(dst_file, &target);
586 target_deps.push((target, DependencyType::Target));
587 }
588
589 target_deps
590 }
591 }
592
593 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
594 pub struct Rustc {
595 pub target: TargetSelection,
596 pub compiler: Compiler,
597 /// Whether to build a subset of crates, rather than the whole compiler.
598 ///
599 /// This should only be requested by the user, not used within rustbuild itself.
600 /// Using it within rustbuild can lead to confusing situation where lints are replayed
601 /// in two different steps.
602 crates: Interned<Vec<String>>,
603 }
604
605 impl Rustc {
606 pub fn new(compiler: Compiler, target: TargetSelection) -> Self {
607 Self { target, compiler, crates: Default::default() }
608 }
609 }
610
611 impl Step for Rustc {
612 type Output = ();
613 const ONLY_HOSTS: bool = true;
614 const DEFAULT: bool = false;
615
616 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
617 let mut crates = run.builder.in_tree_crates("rustc-main", None);
618 for (i, krate) in crates.iter().enumerate() {
619 if krate.name == "rustc-main" {
620 crates.swap_remove(i);
621 break;
622 }
623 }
624 run.crates(crates)
625 }
626
627 fn make_run(run: RunConfig<'_>) {
628 let crates = run.cargo_crates_in_set();
629 run.builder.ensure(Rustc {
630 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
631 target: run.target,
632 crates,
633 });
634 }
635
636 /// Builds the compiler.
637 ///
638 /// This will build the compiler for a particular stage of the build using
639 /// the `compiler` targeting the `target` architecture. The artifacts
640 /// created will also be linked into the sysroot directory.
641 fn run(self, builder: &Builder<'_>) {
642 let compiler = self.compiler;
643 let target = self.target;
644
645 // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
646 // so its artifacts can't be reused.
647 if builder.download_rustc() && compiler.stage != 0 {
648 // Copy the existing artifacts instead of rebuilding them.
649 // NOTE: this path is only taken for tools linking to rustc-dev.
650 builder.ensure(Sysroot { compiler });
651 return;
652 }
653
654 builder.ensure(Std::new(compiler, target));
655
656 if builder.config.keep_stage.contains(&compiler.stage) {
657 builder.info("Warning: Using a potentially old librustc. This may not behave well.");
658 builder.info("Warning: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
659 builder.ensure(RustcLink::from_rustc(self, compiler));
660 return;
661 }
662
663 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
664 if compiler_to_use != compiler {
665 builder.ensure(Rustc::new(compiler_to_use, target));
666 let msg = if compiler_to_use.host == target {
667 format!(
668 "Uplifting rustc (stage{} -> stage{})",
669 compiler_to_use.stage,
670 compiler.stage + 1
671 )
672 } else {
673 format!(
674 "Uplifting rustc (stage{}:{} -> stage{}:{})",
675 compiler_to_use.stage,
676 compiler_to_use.host,
677 compiler.stage + 1,
678 target
679 )
680 };
681 builder.info(&msg);
682 builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
683 return;
684 }
685
686 // Ensure that build scripts and proc macros have a std / libproc_macro to link against.
687 builder.ensure(Std::new(
688 builder.compiler(self.compiler.stage, builder.config.build),
689 builder.config.build,
690 ));
691
692 let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "build");
693 rustc_cargo(builder, &mut cargo, target);
694
695 if builder.config.rust_profile_use.is_some()
696 && builder.config.rust_profile_generate.is_some()
697 {
698 panic!("Cannot use and generate PGO profiles at the same time");
699 }
700
701 // With LLD, we can use ICF (identical code folding) to reduce the executable size
702 // of librustc_driver/rustc and to improve i-cache utilization.
703 //
704 // -Wl,[link options] doesn't work on MSVC. However, /OPT:ICF (technically /OPT:REF,ICF)
705 // is already on by default in MSVC optimized builds, which is interpreted as --icf=all:
706 // https://github.com/llvm/llvm-project/blob/3329cec2f79185bafd678f310fafadba2a8c76d2/lld/COFF/Driver.cpp#L1746
707 // https://github.com/rust-lang/rust/blob/f22819bcce4abaff7d1246a56eec493418f9f4ee/compiler/rustc_codegen_ssa/src/back/linker.rs#L827
708 if builder.config.use_lld && !compiler.host.contains("msvc") {
709 cargo.rustflag("-Clink-args=-Wl,--icf=all");
710 }
711
712 let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
713 if compiler.stage == 1 {
714 cargo.rustflag(&format!("-Cprofile-generate={}", path));
715 // Apparently necessary to avoid overflowing the counters during
716 // a Cargo build profile
717 cargo.rustflag("-Cllvm-args=-vp-counters-per-site=4");
718 true
719 } else {
720 false
721 }
722 } else if let Some(path) = &builder.config.rust_profile_use {
723 if compiler.stage == 1 {
724 cargo.rustflag(&format!("-Cprofile-use={}", path));
725 cargo.rustflag("-Cllvm-args=-pgo-warn-missing-function");
726 true
727 } else {
728 false
729 }
730 } else {
731 false
732 };
733 if is_collecting {
734 // Ensure paths to Rust sources are relative, not absolute.
735 cargo.rustflag(&format!(
736 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
737 builder.config.src.components().count()
738 ));
739 }
740
741 // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary
742 // and may just be a time sink.
743 if compiler.stage != 0 {
744 match builder.config.rust_lto {
745 RustcLto::Thin | RustcLto::Fat => {
746 // Since using LTO for optimizing dylibs is currently experimental,
747 // we need to pass -Zdylib-lto.
748 cargo.rustflag("-Zdylib-lto");
749 // Cargo by default passes `-Cembed-bitcode=no` and doesn't pass `-Clto` when
750 // compiling dylibs (and their dependencies), even when LTO is enabled for the
751 // crate. Therefore, we need to override `-Clto` and `-Cembed-bitcode` here.
752 let lto_type = match builder.config.rust_lto {
753 RustcLto::Thin => "thin",
754 RustcLto::Fat => "fat",
755 _ => unreachable!(),
756 };
757 cargo.rustflag(&format!("-Clto={}", lto_type));
758 cargo.rustflag("-Cembed-bitcode=yes");
759 }
760 RustcLto::ThinLocal => { /* Do nothing, this is the default */ }
761 RustcLto::Off => {
762 cargo.rustflag("-Clto=off");
763 }
764 }
765 } else {
766 if builder.config.rust_lto == RustcLto::Off {
767 cargo.rustflag("-Clto=off");
768 }
769 }
770
771 for krate in &*self.crates {
772 cargo.arg("-p").arg(krate);
773 }
774
775 let msg = if compiler.host == target {
776 format!(
777 "Building{} compiler artifacts (stage{} -> stage{})",
778 crate_description(&self.crates),
779 compiler.stage,
780 compiler.stage + 1
781 )
782 } else {
783 format!(
784 "Building{} compiler artifacts (stage{}:{} -> stage{}:{})",
785 crate_description(&self.crates),
786 compiler.stage,
787 compiler.host,
788 compiler.stage + 1,
789 target,
790 )
791 };
792 builder.info(&msg);
793 run_cargo(
794 builder,
795 cargo,
796 vec![],
797 &librustc_stamp(builder, compiler, target),
798 vec![],
799 false,
800 true, // Only ship rustc_driver.so and .rmeta files, not all intermediate .rlib files.
801 );
802
803 builder.ensure(RustcLink::from_rustc(
804 self,
805 builder.compiler(compiler.stage, builder.config.build),
806 ));
807 }
808 }
809
810 pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
811 cargo
812 .arg("--features")
813 .arg(builder.rustc_features(builder.kind))
814 .arg("--manifest-path")
815 .arg(builder.src.join("compiler/rustc/Cargo.toml"));
816 rustc_cargo_env(builder, cargo, target);
817 }
818
819 pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
820 // Set some configuration variables picked up by build scripts and
821 // the compiler alike
822 cargo
823 .env("CFG_RELEASE", builder.rust_release())
824 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
825 .env("CFG_VERSION", builder.rust_version());
826
827 if let Some(backend) = builder.config.default_codegen_backend() {
828 cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
829 }
830
831 let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
832 let target_config = builder.config.target_config.get(&target);
833
834 cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
835
836 if let Some(ref ver_date) = builder.rust_info().commit_date() {
837 cargo.env("CFG_VER_DATE", ver_date);
838 }
839 if let Some(ref ver_hash) = builder.rust_info().sha() {
840 cargo.env("CFG_VER_HASH", ver_hash);
841 }
842 if !builder.unstable_features() {
843 cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
844 }
845
846 // Prefer the current target's own default_linker, else a globally
847 // specified one.
848 if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) {
849 cargo.env("CFG_DEFAULT_LINKER", s);
850 } else if let Some(ref s) = builder.config.rustc_default_linker {
851 cargo.env("CFG_DEFAULT_LINKER", s);
852 }
853
854 if builder.config.rustc_parallel {
855 // keep in sync with `bootstrap/lib.rs:Build::rustc_features`
856 // `cfg` option for rustc, `features` option for cargo, for conditional compilation
857 cargo.rustflag("--cfg=parallel_compiler");
858 cargo.rustdocflag("--cfg=parallel_compiler");
859 }
860 if builder.config.rust_verify_llvm_ir {
861 cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
862 }
863
864 // Pass down configuration from the LLVM build into the build of
865 // rustc_llvm and rustc_codegen_llvm.
866 //
867 // Note that this is disabled if LLVM itself is disabled or we're in a check
868 // build. If we are in a check build we still go ahead here presuming we've
869 // detected that LLVM is already built and good to go which helps prevent
870 // busting caches (e.g. like #71152).
871 if builder.config.llvm_enabled()
872 && (builder.kind != Kind::Check
873 || crate::native::prebuilt_llvm_config(builder, target).is_ok())
874 {
875 if builder.is_rust_llvm(target) {
876 cargo.env("LLVM_RUSTLLVM", "1");
877 }
878 let native::LlvmResult { llvm_config, .. } = builder.ensure(native::Llvm { target });
879 cargo.env("LLVM_CONFIG", &llvm_config);
880 if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
881 cargo.env("CFG_LLVM_ROOT", s);
882 }
883
884 // Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script
885 // expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by
886 // whitespace.
887 //
888 // For example:
889 // - on windows, when `clang-cl` is used with instrumentation, we need to manually add
890 // clang's runtime library resource directory so that the profiler runtime library can be
891 // found. This is to avoid the linker errors about undefined references to
892 // `__llvm_profile_instrument_memop` when linking `rustc_driver`.
893 let mut llvm_linker_flags = String::new();
894 if builder.config.llvm_profile_generate && target.contains("msvc") {
895 if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
896 // Add clang's runtime library directory to the search path
897 let clang_rt_dir = get_clang_cl_resource_dir(clang_cl_path);
898 llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
899 }
900 }
901
902 // The config can also specify its own llvm linker flags.
903 if let Some(ref s) = builder.config.llvm_ldflags {
904 if !llvm_linker_flags.is_empty() {
905 llvm_linker_flags.push_str(" ");
906 }
907 llvm_linker_flags.push_str(s);
908 }
909
910 // Set the linker flags via the env var that `rustc_llvm`'s build script will read.
911 if !llvm_linker_flags.is_empty() {
912 cargo.env("LLVM_LINKER_FLAGS", llvm_linker_flags);
913 }
914
915 // Building with a static libstdc++ is only supported on linux right now,
916 // not for MSVC or macOS
917 if builder.config.llvm_static_stdcpp
918 && !target.contains("freebsd")
919 && !target.contains("msvc")
920 && !target.contains("apple")
921 && !target.contains("solaris")
922 {
923 let file = compiler_file(
924 builder,
925 builder.cxx(target).unwrap(),
926 target,
927 CLang::Cxx,
928 "libstdc++.a",
929 );
930 cargo.env("LLVM_STATIC_STDCPP", file);
931 }
932 if builder.llvm_link_shared() {
933 cargo.env("LLVM_LINK_SHARED", "1");
934 }
935 if builder.config.llvm_use_libcxx {
936 cargo.env("LLVM_USE_LIBCXX", "1");
937 }
938 if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo {
939 cargo.env("LLVM_NDEBUG", "1");
940 }
941 }
942 }
943
944 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
945 struct RustcLink {
946 pub compiler: Compiler,
947 pub target_compiler: Compiler,
948 pub target: TargetSelection,
949 /// Not actually used; only present to make sure the cache invalidation is correct.
950 crates: Interned<Vec<String>>,
951 }
952
953 impl RustcLink {
954 fn from_rustc(rustc: Rustc, host_compiler: Compiler) -> Self {
955 Self {
956 compiler: host_compiler,
957 target_compiler: rustc.compiler,
958 target: rustc.target,
959 crates: rustc.crates,
960 }
961 }
962 }
963
964 impl Step for RustcLink {
965 type Output = ();
966
967 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
968 run.never()
969 }
970
971 /// Same as `std_link`, only for librustc
972 fn run(self, builder: &Builder<'_>) {
973 let compiler = self.compiler;
974 let target_compiler = self.target_compiler;
975 let target = self.target;
976 add_to_sysroot(
977 builder,
978 &builder.sysroot_libdir(target_compiler, target),
979 &builder.sysroot_libdir(target_compiler, compiler.host),
980 &librustc_stamp(builder, compiler, target),
981 );
982 }
983 }
984
985 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
986 pub struct CodegenBackend {
987 pub target: TargetSelection,
988 pub compiler: Compiler,
989 pub backend: Interned<String>,
990 }
991
992 impl Step for CodegenBackend {
993 type Output = ();
994 const ONLY_HOSTS: bool = true;
995 // Only the backends specified in the `codegen-backends` entry of `config.toml` are built.
996 const DEFAULT: bool = true;
997
998 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
999 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1000 }
1001
1002 fn make_run(run: RunConfig<'_>) {
1003 for &backend in &run.builder.config.rust_codegen_backends {
1004 if backend == "llvm" {
1005 continue; // Already built as part of rustc
1006 }
1007
1008 run.builder.ensure(CodegenBackend {
1009 target: run.target,
1010 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
1011 backend,
1012 });
1013 }
1014 }
1015
1016 fn run(self, builder: &Builder<'_>) {
1017 let compiler = self.compiler;
1018 let target = self.target;
1019 let backend = self.backend;
1020
1021 builder.ensure(Rustc::new(compiler, target));
1022
1023 if builder.config.keep_stage.contains(&compiler.stage) {
1024 builder.info(
1025 "Warning: Using a potentially old codegen backend. \
1026 This may not behave well.",
1027 );
1028 // Codegen backends are linked separately from this step today, so we don't do
1029 // anything here.
1030 return;
1031 }
1032
1033 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
1034 if compiler_to_use != compiler {
1035 builder.ensure(CodegenBackend { compiler: compiler_to_use, target, backend });
1036 return;
1037 }
1038
1039 let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
1040
1041 let mut cargo = builder.cargo(compiler, Mode::Codegen, SourceType::InTree, target, "build");
1042 cargo
1043 .arg("--manifest-path")
1044 .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
1045 rustc_cargo_env(builder, &mut cargo, target);
1046
1047 let tmp_stamp = out_dir.join(".tmp.stamp");
1048
1049 let msg = if compiler.host == target {
1050 format!("Building stage{} codegen backend {}", compiler.stage, backend)
1051 } else {
1052 format!(
1053 "Building stage{} codegen backend {} ({} -> {})",
1054 compiler.stage, backend, compiler.host, target
1055 )
1056 };
1057 builder.info(&msg);
1058 let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
1059 if builder.config.dry_run() {
1060 return;
1061 }
1062 let mut files = files.into_iter().filter(|f| {
1063 let filename = f.file_name().unwrap().to_str().unwrap();
1064 is_dylib(filename) && filename.contains("rustc_codegen_")
1065 });
1066 let codegen_backend = match files.next() {
1067 Some(f) => f,
1068 None => panic!("no dylibs built for codegen backend?"),
1069 };
1070 if let Some(f) = files.next() {
1071 panic!(
1072 "codegen backend built two dylibs:\n{}\n{}",
1073 codegen_backend.display(),
1074 f.display()
1075 );
1076 }
1077 let stamp = codegen_backend_stamp(builder, compiler, target, backend);
1078 let codegen_backend = codegen_backend.to_str().unwrap();
1079 t!(fs::write(&stamp, &codegen_backend));
1080 }
1081 }
1082
1083 /// Creates the `codegen-backends` folder for a compiler that's about to be
1084 /// assembled as a complete compiler.
1085 ///
1086 /// This will take the codegen artifacts produced by `compiler` and link them
1087 /// into an appropriate location for `target_compiler` to be a functional
1088 /// compiler.
1089 fn copy_codegen_backends_to_sysroot(
1090 builder: &Builder<'_>,
1091 compiler: Compiler,
1092 target_compiler: Compiler,
1093 ) {
1094 let target = target_compiler.host;
1095
1096 // Note that this step is different than all the other `*Link` steps in
1097 // that it's not assembling a bunch of libraries but rather is primarily
1098 // moving the codegen backend into place. The codegen backend of rustc is
1099 // not linked into the main compiler by default but is rather dynamically
1100 // selected at runtime for inclusion.
1101 //
1102 // Here we're looking for the output dylib of the `CodegenBackend` step and
1103 // we're copying that into the `codegen-backends` folder.
1104 let dst = builder.sysroot_codegen_backends(target_compiler);
1105 t!(fs::create_dir_all(&dst), dst);
1106
1107 if builder.config.dry_run() {
1108 return;
1109 }
1110
1111 for backend in builder.config.rust_codegen_backends.iter() {
1112 if backend == "llvm" {
1113 continue; // Already built as part of rustc
1114 }
1115
1116 let stamp = codegen_backend_stamp(builder, compiler, target, *backend);
1117 let dylib = t!(fs::read_to_string(&stamp));
1118 let file = Path::new(&dylib);
1119 let filename = file.file_name().unwrap().to_str().unwrap();
1120 // change `librustc_codegen_cranelift-xxxxxx.so` to
1121 // `librustc_codegen_cranelift-release.so`
1122 let target_filename = {
1123 let dash = filename.find('-').unwrap();
1124 let dot = filename.find('.').unwrap();
1125 format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
1126 };
1127 builder.copy(&file, &dst.join(target_filename));
1128 }
1129 }
1130
1131 /// Cargo's output path for the standard library in a given stage, compiled
1132 /// by a particular compiler for the specified target.
1133 pub fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
1134 builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp")
1135 }
1136
1137 /// Cargo's output path for librustc in a given stage, compiled by a particular
1138 /// compiler for the specified target.
1139 pub fn librustc_stamp(
1140 builder: &Builder<'_>,
1141 compiler: Compiler,
1142 target: TargetSelection,
1143 ) -> PathBuf {
1144 builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp")
1145 }
1146
1147 /// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
1148 /// compiler for the specified target and backend.
1149 fn codegen_backend_stamp(
1150 builder: &Builder<'_>,
1151 compiler: Compiler,
1152 target: TargetSelection,
1153 backend: Interned<String>,
1154 ) -> PathBuf {
1155 builder
1156 .cargo_out(compiler, Mode::Codegen, target)
1157 .join(format!(".librustc_codegen_{}.stamp", backend))
1158 }
1159
1160 pub fn compiler_file(
1161 builder: &Builder<'_>,
1162 compiler: &Path,
1163 target: TargetSelection,
1164 c: CLang,
1165 file: &str,
1166 ) -> PathBuf {
1167 let mut cmd = Command::new(compiler);
1168 cmd.args(builder.cflags(target, GitRepo::Rustc, c));
1169 cmd.arg(format!("-print-file-name={}", file));
1170 let out = output(&mut cmd);
1171 PathBuf::from(out.trim())
1172 }
1173
1174 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1175 pub struct Sysroot {
1176 pub compiler: Compiler,
1177 }
1178
1179 impl Step for Sysroot {
1180 type Output = Interned<PathBuf>;
1181
1182 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1183 run.never()
1184 }
1185
1186 /// Returns the sysroot for the `compiler` specified that *this build system
1187 /// generates*.
1188 ///
1189 /// That is, the sysroot for the stage0 compiler is not what the compiler
1190 /// thinks it is by default, but it's the same as the default for stages
1191 /// 1-3.
1192 fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
1193 let compiler = self.compiler;
1194 let host_dir = builder.out.join(&compiler.host.triple);
1195
1196 let sysroot_dir = |stage| {
1197 if stage == 0 {
1198 host_dir.join("stage0-sysroot")
1199 } else if builder.download_rustc() && compiler.stage != builder.top_stage {
1200 host_dir.join("ci-rustc-sysroot")
1201 } else {
1202 host_dir.join(format!("stage{}", stage))
1203 }
1204 };
1205 let sysroot = sysroot_dir(compiler.stage);
1206
1207 let _ = fs::remove_dir_all(&sysroot);
1208 t!(fs::create_dir_all(&sysroot));
1209
1210 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1211 if builder.download_rustc() && compiler.stage != 0 {
1212 assert_eq!(
1213 builder.config.build, compiler.host,
1214 "Cross-compiling is not yet supported with `download-rustc`",
1215 );
1216
1217 // #102002, cleanup old toolchain folders when using download-rustc so people don't use them by accident.
1218 for stage in 0..=2 {
1219 if stage != compiler.stage {
1220 let dir = sysroot_dir(stage);
1221 if !dir.ends_with("ci-rustc-sysroot") {
1222 let _ = fs::remove_dir_all(dir);
1223 }
1224 }
1225 }
1226
1227 // Copy the compiler into the correct sysroot.
1228 let ci_rustc_dir =
1229 builder.config.out.join(&*builder.config.build.triple).join("ci-rustc");
1230 builder.cp_r(&ci_rustc_dir, &sysroot);
1231 return INTERNER.intern_path(sysroot);
1232 }
1233
1234 // Symlink the source root into the same location inside the sysroot,
1235 // where `rust-src` component would go (`$sysroot/lib/rustlib/src/rust`),
1236 // so that any tools relying on `rust-src` also work for local builds,
1237 // and also for translating the virtual `/rustc/$hash` back to the real
1238 // directory (for running tests with `rust.remap-debuginfo = true`).
1239 let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
1240 t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
1241 let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
1242 if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
1243 eprintln!(
1244 "warning: creating symbolic link `{}` to `{}` failed with {}",
1245 sysroot_lib_rustlib_src_rust.display(),
1246 builder.src.display(),
1247 e,
1248 );
1249 if builder.config.rust_remap_debuginfo {
1250 eprintln!(
1251 "warning: some `tests/ui` tests will fail when lacking `{}`",
1252 sysroot_lib_rustlib_src_rust.display(),
1253 );
1254 }
1255 }
1256 // Same for the rustc-src component.
1257 let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
1258 t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
1259 let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
1260 if let Err(e) =
1261 symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
1262 {
1263 eprintln!(
1264 "warning: creating symbolic link `{}` to `{}` failed with {}",
1265 sysroot_lib_rustlib_rustcsrc_rust.display(),
1266 builder.src.display(),
1267 e,
1268 );
1269 }
1270
1271 INTERNER.intern_path(sysroot)
1272 }
1273 }
1274
1275 #[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1276 pub struct Assemble {
1277 /// The compiler which we will produce in this step. Assemble itself will
1278 /// take care of ensuring that the necessary prerequisites to do so exist,
1279 /// that is, this target can be a stage2 compiler and Assemble will build
1280 /// previous stages for you.
1281 pub target_compiler: Compiler,
1282 }
1283
1284 impl Step for Assemble {
1285 type Output = Compiler;
1286 const ONLY_HOSTS: bool = true;
1287
1288 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1289 run.path("compiler/rustc").path("compiler")
1290 }
1291
1292 fn make_run(run: RunConfig<'_>) {
1293 run.builder.ensure(Assemble {
1294 target_compiler: run.builder.compiler(run.builder.top_stage + 1, run.target),
1295 });
1296 }
1297
1298 /// Prepare a new compiler from the artifacts in `stage`
1299 ///
1300 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
1301 /// must have been previously produced by the `stage - 1` builder.build
1302 /// compiler.
1303 fn run(self, builder: &Builder<'_>) -> Compiler {
1304 let target_compiler = self.target_compiler;
1305
1306 if target_compiler.stage == 0 {
1307 assert_eq!(
1308 builder.config.build, target_compiler.host,
1309 "Cannot obtain compiler for non-native build triple at stage 0"
1310 );
1311 // The stage 0 compiler for the build triple is always pre-built.
1312 return target_compiler;
1313 }
1314
1315 // Get the compiler that we'll use to bootstrap ourselves.
1316 //
1317 // Note that this is where the recursive nature of the bootstrap
1318 // happens, as this will request the previous stage's compiler on
1319 // downwards to stage 0.
1320 //
1321 // Also note that we're building a compiler for the host platform. We
1322 // only assume that we can run `build` artifacts, which means that to
1323 // produce some other architecture compiler we need to start from
1324 // `build` to get there.
1325 //
1326 // FIXME: It may be faster if we build just a stage 1 compiler and then
1327 // use that to bootstrap this compiler forward.
1328 let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
1329
1330 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1331 if builder.download_rustc() {
1332 builder.ensure(Sysroot { compiler: target_compiler });
1333 return target_compiler;
1334 }
1335
1336 // Build the libraries for this compiler to link to (i.e., the libraries
1337 // it uses at runtime). NOTE: Crates the target compiler compiles don't
1338 // link to these. (FIXME: Is that correct? It seems to be correct most
1339 // of the time but I think we do link to these for stage2/bin compilers
1340 // when not performing a full bootstrap).
1341 builder.ensure(Rustc::new(build_compiler, target_compiler.host));
1342
1343 for &backend in builder.config.rust_codegen_backends.iter() {
1344 if backend == "llvm" {
1345 continue; // Already built as part of rustc
1346 }
1347
1348 builder.ensure(CodegenBackend {
1349 compiler: build_compiler,
1350 target: target_compiler.host,
1351 backend,
1352 });
1353 }
1354
1355 let lld_install = if builder.config.lld_enabled {
1356 Some(builder.ensure(native::Lld { target: target_compiler.host }))
1357 } else {
1358 None
1359 };
1360
1361 let stage = target_compiler.stage;
1362 let host = target_compiler.host;
1363 let msg = if build_compiler.host == host {
1364 format!("Assembling stage{} compiler", stage)
1365 } else {
1366 format!("Assembling stage{} compiler ({})", stage, host)
1367 };
1368 builder.info(&msg);
1369
1370 // Link in all dylibs to the libdir
1371 let stamp = librustc_stamp(builder, build_compiler, target_compiler.host);
1372 let proc_macros = builder
1373 .read_stamp_file(&stamp)
1374 .into_iter()
1375 .filter_map(|(path, dependency_type)| {
1376 if dependency_type == DependencyType::Host {
1377 Some(path.file_name().unwrap().to_owned().into_string().unwrap())
1378 } else {
1379 None
1380 }
1381 })
1382 .collect::<HashSet<_>>();
1383
1384 let sysroot = builder.sysroot(target_compiler);
1385 let rustc_libdir = builder.rustc_libdir(target_compiler);
1386 t!(fs::create_dir_all(&rustc_libdir));
1387 let src_libdir = builder.sysroot_libdir(build_compiler, host);
1388 for f in builder.read_dir(&src_libdir) {
1389 let filename = f.file_name().into_string().unwrap();
1390 if (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename)
1391 {
1392 builder.copy(&f.path(), &rustc_libdir.join(&filename));
1393 }
1394 }
1395
1396 copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
1397
1398 // We prepend this bin directory to the user PATH when linking Rust binaries. To
1399 // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
1400 let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host);
1401 let libdir_bin = libdir.parent().unwrap().join("bin");
1402 t!(fs::create_dir_all(&libdir_bin));
1403 if let Some(lld_install) = lld_install {
1404 let src_exe = exe("lld", target_compiler.host);
1405 let dst_exe = exe("rust-lld", target_compiler.host);
1406 builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe));
1407 // for `-Z gcc-ld=lld`
1408 let gcc_ld_dir = libdir_bin.join("gcc-ld");
1409 t!(fs::create_dir(&gcc_ld_dir));
1410 let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper {
1411 compiler: build_compiler,
1412 target: target_compiler.host,
1413 });
1414 for name in crate::LLD_FILE_NAMES {
1415 builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(name, target_compiler.host)));
1416 }
1417 }
1418
1419 if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
1420 let native::LlvmResult { llvm_config, .. } =
1421 builder.ensure(native::Llvm { target: target_compiler.host });
1422 if !builder.config.dry_run() {
1423 let llvm_bin_dir = output(Command::new(llvm_config).arg("--bindir"));
1424 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
1425
1426 // Since we've already built the LLVM tools, install them to the sysroot.
1427 // This is the equivalent of installing the `llvm-tools-preview` component via
1428 // rustup, and lets developers use a locally built toolchain to
1429 // build projects that expect llvm tools to be present in the sysroot
1430 // (e.g. the `bootimage` crate).
1431 for tool in LLVM_TOOLS {
1432 let tool_exe = exe(tool, target_compiler.host);
1433 let src_path = llvm_bin_dir.join(&tool_exe);
1434 // When using `download-ci-llvm`, some of the tools
1435 // may not exist, so skip trying to copy them.
1436 if src_path.exists() {
1437 builder.copy(&src_path, &libdir_bin.join(&tool_exe));
1438 }
1439 }
1440 }
1441 }
1442
1443 // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
1444 // so that it can be found when the newly built `rustc` is run.
1445 dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
1446 dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
1447
1448 // Link the compiler binary itself into place
1449 let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
1450 let rustc = out_dir.join(exe("rustc-main", host));
1451 let bindir = sysroot.join("bin");
1452 t!(fs::create_dir_all(&bindir));
1453 let compiler = builder.rustc(target_compiler);
1454 builder.copy(&rustc, &compiler);
1455
1456 target_compiler
1457 }
1458 }
1459
1460 /// Link some files into a rustc sysroot.
1461 ///
1462 /// For a particular stage this will link the file listed in `stamp` into the
1463 /// `sysroot_dst` provided.
1464 pub fn add_to_sysroot(
1465 builder: &Builder<'_>,
1466 sysroot_dst: &Path,
1467 sysroot_host_dst: &Path,
1468 stamp: &Path,
1469 ) {
1470 let self_contained_dst = &sysroot_dst.join("self-contained");
1471 t!(fs::create_dir_all(&sysroot_dst));
1472 t!(fs::create_dir_all(&sysroot_host_dst));
1473 t!(fs::create_dir_all(&self_contained_dst));
1474 for (path, dependency_type) in builder.read_stamp_file(stamp) {
1475 let dst = match dependency_type {
1476 DependencyType::Host => sysroot_host_dst,
1477 DependencyType::Target => sysroot_dst,
1478 DependencyType::TargetSelfContained => self_contained_dst,
1479 };
1480 builder.copy(&path, &dst.join(path.file_name().unwrap()));
1481 }
1482 }
1483
1484 pub fn run_cargo(
1485 builder: &Builder<'_>,
1486 cargo: Cargo,
1487 tail_args: Vec<String>,
1488 stamp: &Path,
1489 additional_target_deps: Vec<(PathBuf, DependencyType)>,
1490 is_check: bool,
1491 rlib_only_metadata: bool,
1492 ) -> Vec<PathBuf> {
1493 if builder.config.dry_run() {
1494 return Vec::new();
1495 }
1496
1497 // `target_root_dir` looks like $dir/$target/release
1498 let target_root_dir = stamp.parent().unwrap();
1499 // `target_deps_dir` looks like $dir/$target/release/deps
1500 let target_deps_dir = target_root_dir.join("deps");
1501 // `host_root_dir` looks like $dir/release
1502 let host_root_dir = target_root_dir
1503 .parent()
1504 .unwrap() // chop off `release`
1505 .parent()
1506 .unwrap() // chop off `$target`
1507 .join(target_root_dir.file_name().unwrap());
1508
1509 // Spawn Cargo slurping up its JSON output. We'll start building up the
1510 // `deps` array of all files it generated along with a `toplevel` array of
1511 // files we need to probe for later.
1512 let mut deps = Vec::new();
1513 let mut toplevel = Vec::new();
1514 let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| {
1515 let (filenames, crate_types) = match msg {
1516 CargoMessage::CompilerArtifact {
1517 filenames,
1518 target: CargoTarget { crate_types },
1519 ..
1520 } => (filenames, crate_types),
1521 _ => return,
1522 };
1523 for filename in filenames {
1524 // Skip files like executables
1525 let mut keep = false;
1526 if filename.ends_with(".lib")
1527 || filename.ends_with(".a")
1528 || is_debug_info(&filename)
1529 || is_dylib(&filename)
1530 {
1531 // Always keep native libraries, rust dylibs and debuginfo
1532 keep = true;
1533 }
1534 if is_check && filename.ends_with(".rmeta") {
1535 // During check builds we need to keep crate metadata
1536 keep = true;
1537 } else if rlib_only_metadata {
1538 if filename.contains("jemalloc_sys") || filename.contains("rustc_smir") {
1539 // jemalloc_sys and rustc_smir are not linked into librustc_driver.so,
1540 // so we need to distribute them as rlib to be able to use them.
1541 keep |= filename.ends_with(".rlib");
1542 } else {
1543 // Distribute the rest of the rustc crates as rmeta files only to reduce
1544 // the tarball sizes by about 50%. The object files are linked into
1545 // librustc_driver.so, so it is still possible to link against them.
1546 keep |= filename.ends_with(".rmeta");
1547 }
1548 } else {
1549 // In all other cases keep all rlibs
1550 keep |= filename.ends_with(".rlib");
1551 }
1552
1553 if !keep {
1554 continue;
1555 }
1556
1557 let filename = Path::new(&*filename);
1558
1559 // If this was an output file in the "host dir" we don't actually
1560 // worry about it, it's not relevant for us
1561 if filename.starts_with(&host_root_dir) {
1562 // Unless it's a proc macro used in the compiler
1563 if crate_types.iter().any(|t| t == "proc-macro") {
1564 deps.push((filename.to_path_buf(), DependencyType::Host));
1565 }
1566 continue;
1567 }
1568
1569 // If this was output in the `deps` dir then this is a precise file
1570 // name (hash included) so we start tracking it.
1571 if filename.starts_with(&target_deps_dir) {
1572 deps.push((filename.to_path_buf(), DependencyType::Target));
1573 continue;
1574 }
1575
1576 // Otherwise this was a "top level artifact" which right now doesn't
1577 // have a hash in the name, but there's a version of this file in
1578 // the `deps` folder which *does* have a hash in the name. That's
1579 // the one we'll want to we'll probe for it later.
1580 //
1581 // We do not use `Path::file_stem` or `Path::extension` here,
1582 // because some generated files may have multiple extensions e.g.
1583 // `std-<hash>.dll.lib` on Windows. The aforementioned methods only
1584 // split the file name by the last extension (`.lib`) while we need
1585 // to split by all extensions (`.dll.lib`).
1586 let expected_len = t!(filename.metadata()).len();
1587 let filename = filename.file_name().unwrap().to_str().unwrap();
1588 let mut parts = filename.splitn(2, '.');
1589 let file_stem = parts.next().unwrap().to_owned();
1590 let extension = parts.next().unwrap().to_owned();
1591
1592 toplevel.push((file_stem, extension, expected_len));
1593 }
1594 });
1595
1596 if !ok {
1597 crate::detail_exit(1);
1598 }
1599
1600 // Ok now we need to actually find all the files listed in `toplevel`. We've
1601 // got a list of prefix/extensions and we basically just need to find the
1602 // most recent file in the `deps` folder corresponding to each one.
1603 let contents = t!(target_deps_dir.read_dir())
1604 .map(|e| t!(e))
1605 .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata())))
1606 .collect::<Vec<_>>();
1607 for (prefix, extension, expected_len) in toplevel {
1608 let candidates = contents.iter().filter(|&&(_, ref filename, ref meta)| {
1609 meta.len() == expected_len
1610 && filename
1611 .strip_prefix(&prefix[..])
1612 .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
1613 .unwrap_or(false)
1614 });
1615 let max = candidates.max_by_key(|&&(_, _, ref metadata)| {
1616 metadata.modified().expect("mtime should be available on all relevant OSes")
1617 });
1618 let path_to_add = match max {
1619 Some(triple) => triple.0.to_str().unwrap(),
1620 None => panic!("no output generated for {:?} {:?}", prefix, extension),
1621 };
1622 if is_dylib(path_to_add) {
1623 let candidate = format!("{}.lib", path_to_add);
1624 let candidate = PathBuf::from(candidate);
1625 if candidate.exists() {
1626 deps.push((candidate, DependencyType::Target));
1627 }
1628 }
1629 deps.push((path_to_add.into(), DependencyType::Target));
1630 }
1631
1632 deps.extend(additional_target_deps);
1633 deps.sort();
1634 let mut new_contents = Vec::new();
1635 for (dep, dependency_type) in deps.iter() {
1636 new_contents.extend(match *dependency_type {
1637 DependencyType::Host => b"h",
1638 DependencyType::Target => b"t",
1639 DependencyType::TargetSelfContained => b"s",
1640 });
1641 new_contents.extend(dep.to_str().unwrap().as_bytes());
1642 new_contents.extend(b"\0");
1643 }
1644 t!(fs::write(&stamp, &new_contents));
1645 deps.into_iter().map(|(d, _)| d).collect()
1646 }
1647
1648 pub fn stream_cargo(
1649 builder: &Builder<'_>,
1650 cargo: Cargo,
1651 tail_args: Vec<String>,
1652 cb: &mut dyn FnMut(CargoMessage<'_>),
1653 ) -> bool {
1654 let mut cargo = Command::from(cargo);
1655 if builder.config.dry_run() {
1656 return true;
1657 }
1658 // Instruct Cargo to give us json messages on stdout, critically leaving
1659 // stderr as piped so we can get those pretty colors.
1660 let mut message_format = if builder.config.json_output {
1661 String::from("json")
1662 } else {
1663 String::from("json-render-diagnostics")
1664 };
1665 if let Some(s) = &builder.config.rustc_error_format {
1666 message_format.push_str(",json-diagnostic-");
1667 message_format.push_str(s);
1668 }
1669 cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped());
1670
1671 for arg in tail_args {
1672 cargo.arg(arg);
1673 }
1674
1675 builder.verbose(&format!("running: {:?}", cargo));
1676 let mut child = match cargo.spawn() {
1677 Ok(child) => child,
1678 Err(e) => panic!("failed to execute command: {:?}\nerror: {}", cargo, e),
1679 };
1680
1681 // Spawn Cargo slurping up its JSON output. We'll start building up the
1682 // `deps` array of all files it generated along with a `toplevel` array of
1683 // files we need to probe for later.
1684 let stdout = BufReader::new(child.stdout.take().unwrap());
1685 for line in stdout.lines() {
1686 let line = t!(line);
1687 match serde_json::from_str::<CargoMessage<'_>>(&line) {
1688 Ok(msg) => {
1689 if builder.config.json_output {
1690 // Forward JSON to stdout.
1691 println!("{}", line);
1692 }
1693 cb(msg)
1694 }
1695 // If this was informational, just print it out and continue
1696 Err(_) => println!("{}", line),
1697 }
1698 }
1699
1700 // Make sure Cargo actually succeeded after we read all of its stdout.
1701 let status = t!(child.wait());
1702 if builder.is_verbose() && !status.success() {
1703 eprintln!(
1704 "command did not execute successfully: {:?}\n\
1705 expected success, got: {}",
1706 cargo, status
1707 );
1708 }
1709 status.success()
1710 }
1711
1712 #[derive(Deserialize)]
1713 pub struct CargoTarget<'a> {
1714 crate_types: Vec<Cow<'a, str>>,
1715 }
1716
1717 #[derive(Deserialize)]
1718 #[serde(tag = "reason", rename_all = "kebab-case")]
1719 pub enum CargoMessage<'a> {
1720 CompilerArtifact {
1721 package_id: Cow<'a, str>,
1722 features: Vec<Cow<'a, str>>,
1723 filenames: Vec<Cow<'a, str>>,
1724 target: CargoTarget<'a>,
1725 },
1726 BuildScriptExecuted {
1727 package_id: Cow<'a, str>,
1728 },
1729 BuildFinished {
1730 success: bool,
1731 },
1732 }