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