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