1 //! Implementation of compiling various phases of the compiler and standard
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.
10 use std
::collections
::HashSet
;
13 use std
::io
::prelude
::*;
14 use std
::io
::BufReader
;
15 use std
::path
::{Path, PathBuf}
;
16 use std
::process
::{Command, Stdio}
;
19 use serde
::Deserialize
;
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, TargetSelection}
;
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}
;
33 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35 pub target
: TargetSelection
,
36 pub compiler
: Compiler
,
37 /// Whether to build only a subset of crates in the standard library.
39 /// This shouldn't be used from other steps; see the comment on [`Rustc`].
40 crates
: Interned
<Vec
<String
>>,
44 pub fn new(compiler
: Compiler
, target
: TargetSelection
) -> Self {
45 Self { target, compiler, crates: Default::default() }
49 /// Return a `-p=x -p=y` string suitable for passing to a cargo invocation.
50 fn build_crates_in_set(run
: &RunConfig
<'_
>) -> Interned
<Vec
<String
>> {
51 let mut crates
= Vec
::new();
52 for krate
in &run
.paths
{
53 let path
= krate
.assert_single_path();
54 let crate_name
= run
.builder
.crate_paths
[&path
.path
];
55 crates
.push(format
!("-p={crate_name}"));
57 INTERNER
.intern_list(crates
)
62 const DEFAULT
: bool
= true;
64 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
65 // When downloading stage1, the standard library has already been copied to the sysroot, so
66 // there's no need to rebuild it.
67 let builder
= run
.builder
;
68 run
.crate_or_deps("test")
70 .lazy_default_condition(Box
::new(|| !builder
.download_rustc()))
73 fn make_run(run
: RunConfig
<'_
>) {
74 // Normally, people will pass *just* library if they pass it.
75 // But it's possible (although strange) to pass something like `library std core`.
76 // Build all crates anyway, as if they hadn't passed the other args.
78 run
.paths
.iter().any(|set
| set
.assert_single_path().path
.ends_with("library"));
79 let crates
= if has_library { Default::default() }
else { build_crates_in_set(&run) }
;
80 run
.builder
.ensure(Std
{
81 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
87 /// Builds the standard library.
89 /// This will build the standard library for a particular stage of the build
90 /// using the `compiler` targeting the `target` architecture. The artifacts
91 /// created will also be linked into the sysroot directory.
92 fn run(self, builder
: &Builder
<'_
>) {
93 let target
= self.target
;
94 let compiler
= self.compiler
;
96 // These artifacts were already copied (in `impl Step for Sysroot`).
97 // Don't recompile them.
98 // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
99 // so its artifacts can't be reused.
100 if builder
.download_rustc() && compiler
.stage
!= 0 {
104 if builder
.config
.keep_stage
.contains(&compiler
.stage
)
105 || builder
.config
.keep_stage_std
.contains(&compiler
.stage
)
107 builder
.info("Warning: Using a potentially old libstd. This may not behave well.");
108 builder
.ensure(StdLink
::from_std(self, compiler
));
112 builder
.update_submodule(&Path
::new("library").join("stdarch"));
114 // Profiler information requires LLVM's compiler-rt
115 if builder
.config
.profiler
{
116 builder
.update_submodule(&Path
::new("src/llvm-project"));
119 let mut target_deps
= builder
.ensure(StartupObjects { compiler, target }
);
121 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
122 if compiler_to_use
!= compiler
{
123 builder
.ensure(Std
::new(compiler_to_use
, target
));
124 builder
.info(&format
!("Uplifting stage1 std ({} -> {})", compiler_to_use
.host
, target
));
126 // Even if we're not building std this stage, the new sysroot must
127 // still contain the third party objects needed by various targets.
128 copy_third_party_objects(builder
, &compiler
, target
);
129 copy_self_contained_objects(builder
, &compiler
, target
);
131 builder
.ensure(StdLink
::from_std(self, compiler_to_use
));
135 target_deps
.extend(copy_third_party_objects(builder
, &compiler
, target
));
136 target_deps
.extend(copy_self_contained_objects(builder
, &compiler
, target
));
138 let mut cargo
= builder
.cargo(compiler
, Mode
::Std
, SourceType
::InTree
, target
, "build");
139 std_cargo(builder
, target
, compiler
.stage
, &mut cargo
);
141 builder
.info(&format
!(
142 "Building stage{} std artifacts ({} -> {})",
143 compiler
.stage
, &compiler
.host
, target
148 self.crates
.to_vec(),
149 &libstd_stamp(builder
, compiler
, target
),
154 builder
.ensure(StdLink
::from_std(
156 builder
.compiler(compiler
.stage
, builder
.config
.build
),
162 builder
: &Builder
<'_
>,
166 target_deps
: &mut Vec
<(PathBuf
, DependencyType
)>,
167 dependency_type
: DependencyType
,
169 let target
= libdir
.join(name
);
170 builder
.copy(&sourcedir
.join(name
), &target
);
172 target_deps
.push((target
, dependency_type
));
175 fn copy_llvm_libunwind(builder
: &Builder
<'_
>, target
: TargetSelection
, libdir
: &Path
) -> PathBuf
{
176 let libunwind_path
= builder
.ensure(native
::Libunwind { target }
);
177 let libunwind_source
= libunwind_path
.join("libunwind.a");
178 let libunwind_target
= libdir
.join("libunwind.a");
179 builder
.copy(&libunwind_source
, &libunwind_target
);
183 /// Copies third party objects needed by various targets.
184 fn copy_third_party_objects(
185 builder
: &Builder
<'_
>,
187 target
: TargetSelection
,
188 ) -> Vec
<(PathBuf
, DependencyType
)> {
189 let mut target_deps
= vec
![];
191 // FIXME: remove this in 2021
192 if target
== "x86_64-fortanix-unknown-sgx" {
193 if env
::var_os("X86_FORTANIX_SGX_LIBS").is_some() {
194 builder
.info("Warning: X86_FORTANIX_SGX_LIBS environment variable is ignored, libunwind is now compiled as part of rustbuild");
198 if builder
.config
.sanitizers_enabled(target
) && compiler
.stage
!= 0 {
199 // The sanitizers are only copied in stage1 or above,
200 // to avoid creating dependency on LLVM.
202 copy_sanitizers(builder
, &compiler
, target
)
204 .map(|d
| (d
, DependencyType
::Target
)),
208 if target
== "x86_64-fortanix-unknown-sgx"
209 || target
.contains("pc-windows-gnullvm")
210 || builder
.config
.llvm_libunwind(target
) == LlvmLibunwind
::InTree
211 && (target
.contains("linux") || target
.contains("fuchsia"))
214 copy_llvm_libunwind(builder
, target
, &builder
.sysroot_libdir(*compiler
, target
));
215 target_deps
.push((libunwind_path
, DependencyType
::Target
));
221 /// Copies third party objects needed by various targets for self-contained linkage.
222 fn copy_self_contained_objects(
223 builder
: &Builder
<'_
>,
225 target
: TargetSelection
,
226 ) -> Vec
<(PathBuf
, DependencyType
)> {
227 let libdir_self_contained
= builder
.sysroot_libdir(*compiler
, target
).join("self-contained");
228 t
!(fs
::create_dir_all(&libdir_self_contained
));
229 let mut target_deps
= vec
![];
231 // Copies the libc and CRT objects.
233 // rustc historically provides a more self-contained installation for musl targets
234 // not requiring the presence of a native musl toolchain. For example, it can fall back
235 // to using gcc from a glibc-targeting toolchain for linking.
236 // To do that we have to distribute musl startup objects as a part of Rust toolchain
237 // and link with them manually in the self-contained mode.
238 if target
.contains("musl") {
239 let srcdir
= builder
.musl_libdir(target
).unwrap_or_else(|| {
240 panic
!("Target {:?} does not have a \"musl-libdir\" key", target
.triple
)
242 for &obj
in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
245 &libdir_self_contained
,
249 DependencyType
::TargetSelfContained
,
252 let crt_path
= builder
.ensure(native
::CrtBeginEnd { target }
);
253 for &obj
in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
254 let src
= crt_path
.join(obj
);
255 let target
= libdir_self_contained
.join(obj
);
256 builder
.copy(&src
, &target
);
257 target_deps
.push((target
, DependencyType
::TargetSelfContained
));
260 if !target
.starts_with("s390x") {
261 let libunwind_path
= copy_llvm_libunwind(builder
, target
, &libdir_self_contained
);
262 target_deps
.push((libunwind_path
, DependencyType
::TargetSelfContained
));
264 } else if target
.ends_with("-wasi") {
268 panic
!("Target {:?} does not have a \"wasi-root\" key", target
.triple
)
270 .join("lib/wasm32-wasi");
271 for &obj
in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
274 &libdir_self_contained
,
278 DependencyType
::TargetSelfContained
,
281 } else if target
.ends_with("windows-gnu") {
282 for obj
in ["crt2.o", "dllcrt2.o"].iter() {
283 let src
= compiler_file(builder
, builder
.cc(target
), target
, CLang
::C
, obj
);
284 let target
= libdir_self_contained
.join(obj
);
285 builder
.copy(&src
, &target
);
286 target_deps
.push((target
, DependencyType
::TargetSelfContained
));
293 /// Configure cargo to compile the standard library, adding appropriate env vars
295 pub fn std_cargo(builder
: &Builder
<'_
>, target
: TargetSelection
, stage
: u32, cargo
: &mut Cargo
) {
296 if let Some(target
) = env
::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
297 cargo
.env("MACOSX_DEPLOYMENT_TARGET", target
);
300 // Determine if we're going to compile in optimized C intrinsics to
301 // the `compiler-builtins` crate. These intrinsics live in LLVM's
302 // `compiler-rt` repository, but our `src/llvm-project` submodule isn't
303 // always checked out, so we need to conditionally look for this. (e.g. if
304 // an external LLVM is used we skip the LLVM submodule checkout).
306 // Note that this shouldn't affect the correctness of `compiler-builtins`,
307 // but only its speed. Some intrinsics in C haven't been translated to Rust
308 // yet but that's pretty rare. Other intrinsics have optimized
309 // implementations in C which have only had slower versions ported to Rust,
310 // so we favor the C version where we can, but it's not critical.
312 // If `compiler-rt` is available ensure that the `c` feature of the
313 // `compiler-builtins` crate is enabled and it's configured to learn where
314 // `compiler-rt` is located.
315 let compiler_builtins_root
= builder
.src
.join("src/llvm-project/compiler-rt");
316 let compiler_builtins_c_feature
= if compiler_builtins_root
.exists() {
317 // Note that `libprofiler_builtins/build.rs` also computes this so if
318 // you're changing something here please also change that.
319 cargo
.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root
);
320 " compiler-builtins-c"
325 if builder
.no_std(target
) == Some(true) {
326 let mut features
= "compiler-builtins-mem".to_string();
327 if !target
.starts_with("bpf") {
328 features
.push_str(compiler_builtins_c_feature
);
331 // for no-std targets we only compile a few no_std crates
333 .args(&["-p", "alloc"])
334 .arg("--manifest-path")
335 .arg(builder
.src
.join("library/alloc/Cargo.toml"))
339 let mut features
= builder
.std_features(target
);
340 features
.push_str(compiler_builtins_c_feature
);
345 .arg("--manifest-path")
346 .arg(builder
.src
.join("library/test/Cargo.toml"));
348 // Help the libc crate compile by assisting it in finding various
349 // sysroot native libraries.
350 if target
.contains("musl") {
351 if let Some(p
) = builder
.musl_libdir(target
) {
352 let root
= format
!("native={}", p
.to_str().unwrap());
353 cargo
.rustflag("-L").rustflag(&root
);
357 if target
.ends_with("-wasi") {
358 if let Some(p
) = builder
.wasi_root(target
) {
359 let root
= format
!("native={}/lib/wasm32-wasi", p
.to_str().unwrap());
360 cargo
.rustflag("-L").rustflag(&root
);
365 // By default, rustc uses `-Cembed-bitcode=yes`, and Cargo overrides that
366 // with `-Cembed-bitcode=no` for non-LTO builds. However, libstd must be
367 // built with bitcode so that the produced rlibs can be used for both LTO
368 // builds (which use bitcode) and non-LTO builds (which use object code).
369 // So we override the override here!
371 // But we don't bother for the stage 0 compiler because it's never used
374 cargo
.rustflag("-Cembed-bitcode=yes");
377 // By default, rustc does not include unwind tables unless they are required
378 // for a particular target. They are not required by RISC-V targets, but
379 // compiling the standard library with them means that users can get
380 // backtraces without having to recompile the standard library themselves.
382 // This choice was discussed in https://github.com/rust-lang/rust/pull/69890
383 if target
.contains("riscv") {
384 cargo
.rustflag("-Cforce-unwind-tables=yes");
388 format
!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder
.doc_rust_lang_org_channel(),);
389 cargo
.rustflag(&html_root
);
390 cargo
.rustdocflag(&html_root
);
393 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
395 pub compiler
: Compiler
,
396 pub target_compiler
: Compiler
,
397 pub target
: TargetSelection
,
398 /// Not actually used; only present to make sure the cache invalidation is correct.
399 crates
: Interned
<Vec
<String
>>,
403 fn from_std(std
: Std
, host_compiler
: Compiler
) -> Self {
405 compiler
: host_compiler
,
406 target_compiler
: std
.compiler
,
413 impl Step
for StdLink
{
416 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
420 /// Link all libstd rlibs/dylibs into the sysroot location.
422 /// Links those artifacts generated by `compiler` to the `stage` compiler's
423 /// sysroot for the specified `host` and `target`.
425 /// Note that this assumes that `compiler` has already generated the libstd
426 /// libraries for `target`, and this method will find them in the relevant
427 /// output directory.
428 fn run(self, builder
: &Builder
<'_
>) {
429 let compiler
= self.compiler
;
430 let target_compiler
= self.target_compiler
;
431 let target
= self.target
;
432 builder
.info(&format
!(
433 "Copying stage{} std from stage{} ({} -> {} / {})",
434 target_compiler
.stage
, compiler
.stage
, &compiler
.host
, target_compiler
.host
, target
436 let libdir
= builder
.sysroot_libdir(target_compiler
, target
);
437 let hostdir
= builder
.sysroot_libdir(target_compiler
, compiler
.host
);
438 add_to_sysroot(builder
, &libdir
, &hostdir
, &libstd_stamp(builder
, compiler
, target
));
442 /// Copies sanitizer runtime libraries into target libdir.
444 builder
: &Builder
<'_
>,
446 target
: TargetSelection
,
448 let runtimes
: Vec
<native
::SanitizerRuntime
> = builder
.ensure(native
::Sanitizers { target }
);
450 if builder
.config
.dry_run
{
454 let mut target_deps
= Vec
::new();
455 let libdir
= builder
.sysroot_libdir(*compiler
, target
);
457 for runtime
in &runtimes
{
458 let dst
= libdir
.join(&runtime
.name
);
459 builder
.copy(&runtime
.path
, &dst
);
461 if target
== "x86_64-apple-darwin" || target
== "aarch64-apple-darwin" {
462 // Update the library’s install name to reflect that it has has been renamed.
463 apple_darwin_update_library_name(&dst
, &format
!("@rpath/{}", &runtime
.name
));
464 // Upon renaming the install name, the code signature of the file will invalidate,
465 // so we will sign it again.
466 apple_darwin_sign_file(&dst
);
469 target_deps
.push(dst
);
475 fn apple_darwin_update_library_name(library_path
: &Path
, new_name
: &str) {
476 let status
= Command
::new("install_name_tool")
481 .expect("failed to execute `install_name_tool`");
482 assert
!(status
.success());
485 fn apple_darwin_sign_file(file_path
: &Path
) {
486 let status
= Command
::new("codesign")
487 .arg("-f") // Force to rewrite the existing signature
492 .expect("failed to execute `codesign`");
493 assert
!(status
.success());
496 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
497 pub struct StartupObjects
{
498 pub compiler
: Compiler
,
499 pub target
: TargetSelection
,
502 impl Step
for StartupObjects
{
503 type Output
= Vec
<(PathBuf
, DependencyType
)>;
505 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
506 run
.path("library/rtstartup")
509 fn make_run(run
: RunConfig
<'_
>) {
510 run
.builder
.ensure(StartupObjects
{
511 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
516 /// Builds and prepare startup objects like rsbegin.o and rsend.o
518 /// These are primarily used on Windows right now for linking executables/dlls.
519 /// They don't require any library support as they're just plain old object
520 /// files, so we just use the nightly snapshot compiler to always build them (as
521 /// no other compilers are guaranteed to be available).
522 fn run(self, builder
: &Builder
<'_
>) -> Vec
<(PathBuf
, DependencyType
)> {
523 let for_compiler
= self.compiler
;
524 let target
= self.target
;
525 if !target
.ends_with("windows-gnu") {
529 let mut target_deps
= vec
![];
531 let src_dir
= &builder
.src
.join("library").join("rtstartup");
532 let dst_dir
= &builder
.native_dir(target
).join("rtstartup");
533 let sysroot_dir
= &builder
.sysroot_libdir(for_compiler
, target
);
534 t
!(fs
::create_dir_all(dst_dir
));
536 for file
in &["rsbegin", "rsend"] {
537 let src_file
= &src_dir
.join(file
.to_string() + ".rs");
538 let dst_file
= &dst_dir
.join(file
.to_string() + ".o");
539 if !up_to_date(src_file
, dst_file
) {
540 let mut cmd
= Command
::new(&builder
.initial_rustc
);
541 cmd
.env("RUSTC_BOOTSTRAP", "1");
542 if !builder
.local_rebuild
{
543 // a local_rebuild compiler already has stage1 features
544 cmd
.arg("--cfg").arg("bootstrap");
548 .arg(target
.rustc_target_arg())
556 let target
= sysroot_dir
.join((*file
).to_string() + ".o");
557 builder
.copy(dst_file
, &target
);
558 target_deps
.push((target
, DependencyType
::Target
));
565 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
567 pub target
: TargetSelection
,
568 pub compiler
: Compiler
,
569 /// Whether to build a subset of crates, rather than the whole compiler.
571 /// This should only be requested by the user, not used within rustbuild itself.
572 /// Using it within rustbuild can lead to confusing situation where lints are replayed
573 /// in two different steps.
574 crates
: Interned
<Vec
<String
>>,
578 pub fn new(compiler
: Compiler
, target
: TargetSelection
) -> Self {
579 Self { target, compiler, crates: Default::default() }
583 impl Step
for Rustc
{
585 const ONLY_HOSTS
: bool
= true;
586 const DEFAULT
: bool
= false;
588 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
589 let mut crates
= run
.builder
.in_tree_crates("rustc-main", None
);
590 for (i
, krate
) in crates
.iter().enumerate() {
591 if krate
.name
== "rustc-main" {
592 crates
.swap_remove(i
);
599 fn make_run(run
: RunConfig
<'_
>) {
600 let crates
= build_crates_in_set(&run
);
601 run
.builder
.ensure(Rustc
{
602 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
608 /// Builds the compiler.
610 /// This will build the compiler for a particular stage of the build using
611 /// the `compiler` targeting the `target` architecture. The artifacts
612 /// created will also be linked into the sysroot directory.
613 fn run(self, builder
: &Builder
<'_
>) {
614 let compiler
= self.compiler
;
615 let target
= self.target
;
617 // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
618 // so its artifacts can't be reused.
619 if builder
.download_rustc() && compiler
.stage
!= 0 {
620 // Copy the existing artifacts instead of rebuilding them.
621 // NOTE: this path is only taken for tools linking to rustc-dev.
622 builder
.ensure(Sysroot { compiler }
);
626 builder
.ensure(Std
::new(compiler
, target
));
628 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
629 builder
.info("Warning: Using a potentially old librustc. This may not behave well.");
630 builder
.info("Warning: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
631 builder
.ensure(RustcLink
::from_rustc(self, compiler
));
635 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
636 if compiler_to_use
!= compiler
{
637 builder
.ensure(Rustc
::new(compiler_to_use
, target
));
639 .info(&format
!("Uplifting stage1 rustc ({} -> {})", builder
.config
.build
, target
));
640 builder
.ensure(RustcLink
::from_rustc(self, compiler_to_use
));
644 // Ensure that build scripts and proc macros have a std / libproc_macro to link against.
645 builder
.ensure(Std
::new(
646 builder
.compiler(self.compiler
.stage
, builder
.config
.build
),
647 builder
.config
.build
,
650 let mut cargo
= builder
.cargo(compiler
, Mode
::Rustc
, SourceType
::InTree
, target
, "build");
651 rustc_cargo(builder
, &mut cargo
, target
);
653 if builder
.config
.rust_profile_use
.is_some()
654 && builder
.config
.rust_profile_generate
.is_some()
656 panic
!("Cannot use and generate PGO profiles at the same time");
659 // With LLD, we can use ICF (identical code folding) to reduce the executable size
660 // of librustc_driver/rustc and to improve i-cache utilization.
662 // -Wl,[link options] doesn't work on MSVC. However, /OPT:ICF (technically /OPT:REF,ICF)
663 // is already on by default in MSVC optimized builds, which is interpreted as --icf=all:
664 // https://github.com/llvm/llvm-project/blob/3329cec2f79185bafd678f310fafadba2a8c76d2/lld/COFF/Driver.cpp#L1746
665 // https://github.com/rust-lang/rust/blob/f22819bcce4abaff7d1246a56eec493418f9f4ee/compiler/rustc_codegen_ssa/src/back/linker.rs#L827
666 if builder
.config
.use_lld
&& !compiler
.host
.contains("msvc") {
667 cargo
.rustflag("-Clink-args=-Wl,--icf=all");
670 let is_collecting
= if let Some(path
) = &builder
.config
.rust_profile_generate
{
671 if compiler
.stage
== 1 {
672 cargo
.rustflag(&format
!("-Cprofile-generate={}", path
));
673 // Apparently necessary to avoid overflowing the counters during
674 // a Cargo build profile
675 cargo
.rustflag("-Cllvm-args=-vp-counters-per-site=4");
680 } else if let Some(path
) = &builder
.config
.rust_profile_use
{
681 if compiler
.stage
== 1 {
682 cargo
.rustflag(&format
!("-Cprofile-use={}", path
));
683 cargo
.rustflag("-Cllvm-args=-pgo-warn-missing-function");
692 // Ensure paths to Rust sources are relative, not absolute.
693 cargo
.rustflag(&format
!(
694 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
695 builder
.config
.src
.components().count()
699 builder
.info(&format
!(
700 "Building stage{} compiler artifacts ({} -> {})",
701 compiler
.stage
, &compiler
.host
, target
706 self.crates
.to_vec(),
707 &librustc_stamp(builder
, compiler
, target
),
712 builder
.ensure(RustcLink
::from_rustc(
714 builder
.compiler(compiler
.stage
, builder
.config
.build
),
719 pub fn rustc_cargo(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: TargetSelection
) {
722 .arg(builder
.rustc_features(builder
.kind
))
723 .arg("--manifest-path")
724 .arg(builder
.src
.join("compiler/rustc/Cargo.toml"));
725 rustc_cargo_env(builder
, cargo
, target
);
728 pub fn rustc_cargo_env(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: TargetSelection
) {
729 // Set some configuration variables picked up by build scripts and
730 // the compiler alike
732 .env("CFG_RELEASE", builder
.rust_release())
733 .env("CFG_RELEASE_CHANNEL", &builder
.config
.channel
)
734 .env("CFG_VERSION", builder
.rust_version());
736 if let Some(backend
) = builder
.config
.rust_codegen_backends
.get(0) {
737 cargo
.env("CFG_DEFAULT_CODEGEN_BACKEND", backend
);
740 let libdir_relative
= builder
.config
.libdir_relative().unwrap_or_else(|| Path
::new("lib"));
741 let target_config
= builder
.config
.target_config
.get(&target
);
743 cargo
.env("CFG_LIBDIR_RELATIVE", libdir_relative
);
745 if let Some(ref ver_date
) = builder
.rust_info
.commit_date() {
746 cargo
.env("CFG_VER_DATE", ver_date
);
748 if let Some(ref ver_hash
) = builder
.rust_info
.sha() {
749 cargo
.env("CFG_VER_HASH", ver_hash
);
751 if !builder
.unstable_features() {
752 cargo
.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
755 // Prefer the current target's own default_linker, else a globally
757 if let Some(s
) = target_config
.and_then(|c
| c
.default_linker
.as_ref()) {
758 cargo
.env("CFG_DEFAULT_LINKER", s
);
759 } else if let Some(ref s
) = builder
.config
.rustc_default_linker
{
760 cargo
.env("CFG_DEFAULT_LINKER", s
);
763 if builder
.config
.rustc_parallel
{
764 // keep in sync with `bootstrap/lib.rs:Build::rustc_features`
765 // `cfg` option for rustc, `features` option for cargo, for conditional compilation
766 cargo
.rustflag("--cfg=parallel_compiler");
767 cargo
.rustdocflag("--cfg=parallel_compiler");
769 if builder
.config
.rust_verify_llvm_ir
{
770 cargo
.env("RUSTC_VERIFY_LLVM_IR", "1");
773 // Pass down configuration from the LLVM build into the build of
774 // rustc_llvm and rustc_codegen_llvm.
776 // Note that this is disabled if LLVM itself is disabled or we're in a check
777 // build. If we are in a check build we still go ahead here presuming we've
778 // detected that LLVM is already built and good to go which helps prevent
779 // busting caches (e.g. like #71152).
780 if builder
.config
.llvm_enabled()
781 && (builder
.kind
!= Kind
::Check
782 || crate::native
::prebuilt_llvm_config(builder
, target
).is_ok())
784 if builder
.is_rust_llvm(target
) {
785 cargo
.env("LLVM_RUSTLLVM", "1");
787 let llvm_config
= builder
.ensure(native
::Llvm { target }
);
788 cargo
.env("LLVM_CONFIG", &llvm_config
);
789 if let Some(s
) = target_config
.and_then(|c
| c
.llvm_config
.as_ref()) {
790 cargo
.env("CFG_LLVM_ROOT", s
);
793 // Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script
794 // expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by
798 // - on windows, when `clang-cl` is used with instrumentation, we need to manually add
799 // clang's runtime library resource directory so that the profiler runtime library can be
800 // found. This is to avoid the linker errors about undefined references to
801 // `__llvm_profile_instrument_memop` when linking `rustc_driver`.
802 let mut llvm_linker_flags
= String
::new();
803 if builder
.config
.llvm_profile_generate
&& target
.contains("msvc") {
804 if let Some(ref clang_cl_path
) = builder
.config
.llvm_clang_cl
{
805 // Add clang's runtime library directory to the search path
806 let clang_rt_dir
= get_clang_cl_resource_dir(clang_cl_path
);
807 llvm_linker_flags
.push_str(&format
!("-L{}", clang_rt_dir
.display()));
811 // The config can also specify its own llvm linker flags.
812 if let Some(ref s
) = builder
.config
.llvm_ldflags
{
813 if !llvm_linker_flags
.is_empty() {
814 llvm_linker_flags
.push_str(" ");
816 llvm_linker_flags
.push_str(s
);
819 // Set the linker flags via the env var that `rustc_llvm`'s build script will read.
820 if !llvm_linker_flags
.is_empty() {
821 cargo
.env("LLVM_LINKER_FLAGS", llvm_linker_flags
);
824 // Building with a static libstdc++ is only supported on linux right now,
825 // not for MSVC or macOS
826 if builder
.config
.llvm_static_stdcpp
827 && !target
.contains("freebsd")
828 && !target
.contains("msvc")
829 && !target
.contains("apple")
830 && !target
.contains("solaris")
832 let file
= compiler_file(
834 builder
.cxx(target
).unwrap(),
839 cargo
.env("LLVM_STATIC_STDCPP", file
);
841 if builder
.llvm_link_shared() {
842 cargo
.env("LLVM_LINK_SHARED", "1");
844 if builder
.config
.llvm_use_libcxx
{
845 cargo
.env("LLVM_USE_LIBCXX", "1");
847 if builder
.config
.llvm_optimize
&& !builder
.config
.llvm_release_debuginfo
{
848 cargo
.env("LLVM_NDEBUG", "1");
853 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
855 pub compiler
: Compiler
,
856 pub target_compiler
: Compiler
,
857 pub target
: TargetSelection
,
858 /// Not actually used; only present to make sure the cache invalidation is correct.
859 crates
: Interned
<Vec
<String
>>,
863 fn from_rustc(rustc
: Rustc
, host_compiler
: Compiler
) -> Self {
865 compiler
: host_compiler
,
866 target_compiler
: rustc
.compiler
,
867 target
: rustc
.target
,
868 crates
: rustc
.crates
,
873 impl Step
for RustcLink
{
876 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
880 /// Same as `std_link`, only for librustc
881 fn run(self, builder
: &Builder
<'_
>) {
882 let compiler
= self.compiler
;
883 let target_compiler
= self.target_compiler
;
884 let target
= self.target
;
885 builder
.info(&format
!(
886 "Copying stage{} rustc from stage{} ({} -> {} / {})",
887 target_compiler
.stage
, compiler
.stage
, &compiler
.host
, target_compiler
.host
, target
891 &builder
.sysroot_libdir(target_compiler
, target
),
892 &builder
.sysroot_libdir(target_compiler
, compiler
.host
),
893 &librustc_stamp(builder
, compiler
, target
),
898 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
899 pub struct CodegenBackend
{
900 pub target
: TargetSelection
,
901 pub compiler
: Compiler
,
902 pub backend
: Interned
<String
>,
905 impl Step
for CodegenBackend
{
907 const ONLY_HOSTS
: bool
= true;
908 // Only the backends specified in the `codegen-backends` entry of `config.toml` are built.
909 const DEFAULT
: bool
= true;
911 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
912 run
.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
915 fn make_run(run
: RunConfig
<'_
>) {
916 for &backend
in &run
.builder
.config
.rust_codegen_backends
{
917 if backend
== "llvm" {
918 continue; // Already built as part of rustc
921 run
.builder
.ensure(CodegenBackend
{
923 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
929 fn run(self, builder
: &Builder
<'_
>) {
930 let compiler
= self.compiler
;
931 let target
= self.target
;
932 let backend
= self.backend
;
934 builder
.ensure(Rustc
::new(compiler
, target
));
936 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
938 "Warning: Using a potentially old codegen backend. \
939 This may not behave well.",
941 // Codegen backends are linked separately from this step today, so we don't do
946 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
947 if compiler_to_use
!= compiler
{
948 builder
.ensure(CodegenBackend { compiler: compiler_to_use, target, backend }
);
952 let out_dir
= builder
.cargo_out(compiler
, Mode
::Codegen
, target
);
954 let mut cargo
= builder
.cargo(compiler
, Mode
::Codegen
, SourceType
::InTree
, target
, "build");
956 .arg("--manifest-path")
957 .arg(builder
.src
.join(format
!("compiler/rustc_codegen_{}/Cargo.toml", backend
)));
958 rustc_cargo_env(builder
, &mut cargo
, target
);
960 let tmp_stamp
= out_dir
.join(".tmp.stamp");
962 builder
.info(&format
!(
963 "Building stage{} codegen backend {} ({} -> {})",
964 compiler
.stage
, backend
, &compiler
.host
, target
966 let files
= run_cargo(builder
, cargo
, vec
![], &tmp_stamp
, vec
![], false);
967 if builder
.config
.dry_run
{
970 let mut files
= files
.into_iter().filter(|f
| {
971 let filename
= f
.file_name().unwrap().to_str().unwrap();
972 is_dylib(filename
) && filename
.contains("rustc_codegen_")
974 let codegen_backend
= match files
.next() {
976 None
=> panic
!("no dylibs built for codegen backend?"),
978 if let Some(f
) = files
.next() {
980 "codegen backend built two dylibs:\n{}\n{}",
981 codegen_backend
.display(),
985 let stamp
= codegen_backend_stamp(builder
, compiler
, target
, backend
);
986 let codegen_backend
= codegen_backend
.to_str().unwrap();
987 t
!(fs
::write(&stamp
, &codegen_backend
));
991 /// Creates the `codegen-backends` folder for a compiler that's about to be
992 /// assembled as a complete compiler.
994 /// This will take the codegen artifacts produced by `compiler` and link them
995 /// into an appropriate location for `target_compiler` to be a functional
997 fn copy_codegen_backends_to_sysroot(
998 builder
: &Builder
<'_
>,
1000 target_compiler
: Compiler
,
1002 let target
= target_compiler
.host
;
1004 // Note that this step is different than all the other `*Link` steps in
1005 // that it's not assembling a bunch of libraries but rather is primarily
1006 // moving the codegen backend into place. The codegen backend of rustc is
1007 // not linked into the main compiler by default but is rather dynamically
1008 // selected at runtime for inclusion.
1010 // Here we're looking for the output dylib of the `CodegenBackend` step and
1011 // we're copying that into the `codegen-backends` folder.
1012 let dst
= builder
.sysroot_codegen_backends(target_compiler
);
1013 t
!(fs
::create_dir_all(&dst
), dst
);
1015 if builder
.config
.dry_run
{
1019 for backend
in builder
.config
.rust_codegen_backends
.iter() {
1020 if backend
== "llvm" {
1021 continue; // Already built as part of rustc
1024 let stamp
= codegen_backend_stamp(builder
, compiler
, target
, *backend
);
1025 let dylib
= t
!(fs
::read_to_string(&stamp
));
1026 let file
= Path
::new(&dylib
);
1027 let filename
= file
.file_name().unwrap().to_str().unwrap();
1028 // change `librustc_codegen_cranelift-xxxxxx.so` to
1029 // `librustc_codegen_cranelift-release.so`
1030 let target_filename
= {
1031 let dash
= filename
.find('
-'
).unwrap();
1032 let dot
= filename
.find('
.'
).unwrap();
1033 format
!("{}-{}{}", &filename
[..dash
], builder
.rust_release(), &filename
[dot
..])
1035 builder
.copy(&file
, &dst
.join(target_filename
));
1039 /// Cargo's output path for the standard library in a given stage, compiled
1040 /// by a particular compiler for the specified target.
1041 pub fn libstd_stamp(builder
: &Builder
<'_
>, compiler
: Compiler
, target
: TargetSelection
) -> PathBuf
{
1042 builder
.cargo_out(compiler
, Mode
::Std
, target
).join(".libstd.stamp")
1045 /// Cargo's output path for librustc in a given stage, compiled by a particular
1046 /// compiler for the specified target.
1047 pub fn librustc_stamp(
1048 builder
: &Builder
<'_
>,
1050 target
: TargetSelection
,
1052 builder
.cargo_out(compiler
, Mode
::Rustc
, target
).join(".librustc.stamp")
1055 /// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
1056 /// compiler for the specified target and backend.
1057 fn codegen_backend_stamp(
1058 builder
: &Builder
<'_
>,
1060 target
: TargetSelection
,
1061 backend
: Interned
<String
>,
1064 .cargo_out(compiler
, Mode
::Codegen
, target
)
1065 .join(format
!(".librustc_codegen_{}.stamp", backend
))
1068 pub fn compiler_file(
1069 builder
: &Builder
<'_
>,
1071 target
: TargetSelection
,
1075 let mut cmd
= Command
::new(compiler
);
1076 cmd
.args(builder
.cflags(target
, GitRepo
::Rustc
, c
));
1077 cmd
.arg(format
!("-print-file-name={}", file
));
1078 let out
= output(&mut cmd
);
1079 PathBuf
::from(out
.trim())
1082 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1083 pub struct Sysroot
{
1084 pub compiler
: Compiler
,
1087 impl Step
for Sysroot
{
1088 type Output
= Interned
<PathBuf
>;
1090 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1094 /// Returns the sysroot for the `compiler` specified that *this build system
1097 /// That is, the sysroot for the stage0 compiler is not what the compiler
1098 /// thinks it is by default, but it's the same as the default for stages
1100 fn run(self, builder
: &Builder
<'_
>) -> Interned
<PathBuf
> {
1101 let compiler
= self.compiler
;
1102 let sysroot
= if compiler
.stage
== 0 {
1103 builder
.out
.join(&compiler
.host
.triple
).join("stage0-sysroot")
1105 builder
.out
.join(&compiler
.host
.triple
).join(format
!("stage{}", compiler
.stage
))
1107 let _
= fs
::remove_dir_all(&sysroot
);
1108 t
!(fs
::create_dir_all(&sysroot
));
1110 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1111 if builder
.download_rustc() && compiler
.stage
!= 0 {
1113 builder
.config
.build
, compiler
.host
,
1114 "Cross-compiling is not yet supported with `download-rustc`",
1116 // Copy the compiler into the correct sysroot.
1118 builder
.config
.out
.join(&*builder
.config
.build
.triple
).join("ci-rustc");
1119 builder
.cp_r(&ci_rustc_dir
, &sysroot
);
1120 return INTERNER
.intern_path(sysroot
);
1123 // Symlink the source root into the same location inside the sysroot,
1124 // where `rust-src` component would go (`$sysroot/lib/rustlib/src/rust`),
1125 // so that any tools relying on `rust-src` also work for local builds,
1126 // and also for translating the virtual `/rustc/$hash` back to the real
1127 // directory (for running tests with `rust.remap-debuginfo = true`).
1128 let sysroot_lib_rustlib_src
= sysroot
.join("lib/rustlib/src");
1129 t
!(fs
::create_dir_all(&sysroot_lib_rustlib_src
));
1130 let sysroot_lib_rustlib_src_rust
= sysroot_lib_rustlib_src
.join("rust");
1131 if let Err(e
) = symlink_dir(&builder
.config
, &builder
.src
, &sysroot_lib_rustlib_src_rust
) {
1133 "warning: creating symbolic link `{}` to `{}` failed with {}",
1134 sysroot_lib_rustlib_src_rust
.display(),
1135 builder
.src
.display(),
1138 if builder
.config
.rust_remap_debuginfo
{
1140 "warning: some `src/test/ui` tests will fail when lacking `{}`",
1141 sysroot_lib_rustlib_src_rust
.display(),
1146 INTERNER
.intern_path(sysroot
)
1150 #[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1151 pub struct Assemble
{
1152 /// The compiler which we will produce in this step. Assemble itself will
1153 /// take care of ensuring that the necessary prerequisites to do so exist,
1154 /// that is, this target can be a stage2 compiler and Assemble will build
1155 /// previous stages for you.
1156 pub target_compiler
: Compiler
,
1159 impl Step
for Assemble
{
1160 type Output
= Compiler
;
1161 const ONLY_HOSTS
: bool
= true;
1163 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1164 run
.path("compiler/rustc").path("compiler")
1167 fn make_run(run
: RunConfig
<'_
>) {
1168 run
.builder
.ensure(Assemble
{
1169 target_compiler
: run
.builder
.compiler(run
.builder
.top_stage
+ 1, run
.target
),
1173 /// Prepare a new compiler from the artifacts in `stage`
1175 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
1176 /// must have been previously produced by the `stage - 1` builder.build
1178 fn run(self, builder
: &Builder
<'_
>) -> Compiler
{
1179 let target_compiler
= self.target_compiler
;
1181 if target_compiler
.stage
== 0 {
1183 builder
.config
.build
, target_compiler
.host
,
1184 "Cannot obtain compiler for non-native build triple at stage 0"
1186 // The stage 0 compiler for the build triple is always pre-built.
1187 return target_compiler
;
1190 // Get the compiler that we'll use to bootstrap ourselves.
1192 // Note that this is where the recursive nature of the bootstrap
1193 // happens, as this will request the previous stage's compiler on
1194 // downwards to stage 0.
1196 // Also note that we're building a compiler for the host platform. We
1197 // only assume that we can run `build` artifacts, which means that to
1198 // produce some other architecture compiler we need to start from
1199 // `build` to get there.
1201 // FIXME: It may be faster if we build just a stage 1 compiler and then
1202 // use that to bootstrap this compiler forward.
1203 let build_compiler
= builder
.compiler(target_compiler
.stage
- 1, builder
.config
.build
);
1205 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1206 if builder
.download_rustc() {
1207 builder
.ensure(Sysroot { compiler: target_compiler }
);
1208 return target_compiler
;
1211 // Build the libraries for this compiler to link to (i.e., the libraries
1212 // it uses at runtime). NOTE: Crates the target compiler compiles don't
1213 // link to these. (FIXME: Is that correct? It seems to be correct most
1214 // of the time but I think we do link to these for stage2/bin compilers
1215 // when not performing a full bootstrap).
1216 builder
.ensure(Rustc
::new(build_compiler
, target_compiler
.host
));
1218 for &backend
in builder
.config
.rust_codegen_backends
.iter() {
1219 if backend
== "llvm" {
1220 continue; // Already built as part of rustc
1223 builder
.ensure(CodegenBackend
{
1224 compiler
: build_compiler
,
1225 target
: target_compiler
.host
,
1230 let lld_install
= if builder
.config
.lld_enabled
{
1231 Some(builder
.ensure(native
::Lld { target: target_compiler.host }
))
1236 let stage
= target_compiler
.stage
;
1237 let host
= target_compiler
.host
;
1238 builder
.info(&format
!("Assembling stage{} compiler ({})", stage
, host
));
1240 // Link in all dylibs to the libdir
1241 let stamp
= librustc_stamp(builder
, build_compiler
, target_compiler
.host
);
1242 let proc_macros
= builder
1243 .read_stamp_file(&stamp
)
1245 .filter_map(|(path
, dependency_type
)| {
1246 if dependency_type
== DependencyType
::Host
{
1247 Some(path
.file_name().unwrap().to_owned().into_string().unwrap())
1252 .collect
::<HashSet
<_
>>();
1254 let sysroot
= builder
.sysroot(target_compiler
);
1255 let rustc_libdir
= builder
.rustc_libdir(target_compiler
);
1256 t
!(fs
::create_dir_all(&rustc_libdir
));
1257 let src_libdir
= builder
.sysroot_libdir(build_compiler
, host
);
1258 for f
in builder
.read_dir(&src_libdir
) {
1259 let filename
= f
.file_name().into_string().unwrap();
1260 if (is_dylib(&filename
) || is_debug_info(&filename
)) && !proc_macros
.contains(&filename
)
1262 builder
.copy(&f
.path(), &rustc_libdir
.join(&filename
));
1266 copy_codegen_backends_to_sysroot(builder
, build_compiler
, target_compiler
);
1268 // We prepend this bin directory to the user PATH when linking Rust binaries. To
1269 // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
1270 let libdir
= builder
.sysroot_libdir(target_compiler
, target_compiler
.host
);
1271 let libdir_bin
= libdir
.parent().unwrap().join("bin");
1272 t
!(fs
::create_dir_all(&libdir_bin
));
1273 if let Some(lld_install
) = lld_install
{
1274 let src_exe
= exe("lld", target_compiler
.host
);
1275 let dst_exe
= exe("rust-lld", target_compiler
.host
);
1276 builder
.copy(&lld_install
.join("bin").join(&src_exe
), &libdir_bin
.join(&dst_exe
));
1277 // for `-Z gcc-ld=lld`
1278 let gcc_ld_dir
= libdir_bin
.join("gcc-ld");
1279 t
!(fs
::create_dir(&gcc_ld_dir
));
1280 let lld_wrapper_exe
= builder
.ensure(crate::tool
::LldWrapper
{
1281 compiler
: build_compiler
,
1282 target
: target_compiler
.host
,
1284 for name
in crate::LLD_FILE_NAMES
{
1285 builder
.copy(&lld_wrapper_exe
, &gcc_ld_dir
.join(exe(name
, target_compiler
.host
)));
1289 if builder
.config
.rust_codegen_backends
.contains(&INTERNER
.intern_str("llvm")) {
1290 let llvm_config_bin
= builder
.ensure(native
::Llvm { target: target_compiler.host }
);
1291 if !builder
.config
.dry_run
{
1292 let llvm_bin_dir
= output(Command
::new(llvm_config_bin
).arg("--bindir"));
1293 let llvm_bin_dir
= Path
::new(llvm_bin_dir
.trim());
1295 // Since we've already built the LLVM tools, install them to the sysroot.
1296 // This is the equivalent of installing the `llvm-tools-preview` component via
1297 // rustup, and lets developers use a locally built toolchain to
1298 // build projects that expect llvm tools to be present in the sysroot
1299 // (e.g. the `bootimage` crate).
1300 for tool
in LLVM_TOOLS
{
1301 let tool_exe
= exe(tool
, target_compiler
.host
);
1302 let src_path
= llvm_bin_dir
.join(&tool_exe
);
1303 // When using `download-ci-llvm`, some of the tools
1304 // may not exist, so skip trying to copy them.
1305 if src_path
.exists() {
1306 builder
.copy(&src_path
, &libdir_bin
.join(&tool_exe
));
1312 // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
1313 // so that it can be found when the newly built `rustc` is run.
1314 dist
::maybe_install_llvm_runtime(builder
, target_compiler
.host
, &sysroot
);
1315 dist
::maybe_install_llvm_target(builder
, target_compiler
.host
, &sysroot
);
1317 // Link the compiler binary itself into place
1318 let out_dir
= builder
.cargo_out(build_compiler
, Mode
::Rustc
, host
);
1319 let rustc
= out_dir
.join(exe("rustc-main", host
));
1320 let bindir
= sysroot
.join("bin");
1321 t
!(fs
::create_dir_all(&bindir
));
1322 let compiler
= builder
.rustc(target_compiler
);
1323 builder
.copy(&rustc
, &compiler
);
1329 /// Link some files into a rustc sysroot.
1331 /// For a particular stage this will link the file listed in `stamp` into the
1332 /// `sysroot_dst` provided.
1333 pub fn add_to_sysroot(
1334 builder
: &Builder
<'_
>,
1336 sysroot_host_dst
: &Path
,
1339 let self_contained_dst
= &sysroot_dst
.join("self-contained");
1340 t
!(fs
::create_dir_all(&sysroot_dst
));
1341 t
!(fs
::create_dir_all(&sysroot_host_dst
));
1342 t
!(fs
::create_dir_all(&self_contained_dst
));
1343 for (path
, dependency_type
) in builder
.read_stamp_file(stamp
) {
1344 let dst
= match dependency_type
{
1345 DependencyType
::Host
=> sysroot_host_dst
,
1346 DependencyType
::Target
=> sysroot_dst
,
1347 DependencyType
::TargetSelfContained
=> self_contained_dst
,
1349 builder
.copy(&path
, &dst
.join(path
.file_name().unwrap()));
1354 builder
: &Builder
<'_
>,
1356 tail_args
: Vec
<String
>,
1358 additional_target_deps
: Vec
<(PathBuf
, DependencyType
)>,
1361 if builder
.config
.dry_run
{
1365 // `target_root_dir` looks like $dir/$target/release
1366 let target_root_dir
= stamp
.parent().unwrap();
1367 // `target_deps_dir` looks like $dir/$target/release/deps
1368 let target_deps_dir
= target_root_dir
.join("deps");
1369 // `host_root_dir` looks like $dir/release
1370 let host_root_dir
= target_root_dir
1372 .unwrap() // chop off `release`
1374 .unwrap() // chop off `$target`
1375 .join(target_root_dir
.file_name().unwrap());
1377 // Spawn Cargo slurping up its JSON output. We'll start building up the
1378 // `deps` array of all files it generated along with a `toplevel` array of
1379 // files we need to probe for later.
1380 let mut deps
= Vec
::new();
1381 let mut toplevel
= Vec
::new();
1382 let ok
= stream_cargo(builder
, cargo
, tail_args
, &mut |msg
| {
1383 let (filenames
, crate_types
) = match msg
{
1384 CargoMessage
::CompilerArtifact
{
1386 target
: CargoTarget { crate_types }
,
1388 } => (filenames
, crate_types
),
1391 for filename
in filenames
{
1392 // Skip files like executables
1393 if !(filename
.ends_with(".rlib")
1394 || filename
.ends_with(".lib")
1395 || filename
.ends_with(".a")
1396 || is_debug_info(&filename
)
1397 || is_dylib(&filename
)
1398 || (is_check
&& filename
.ends_with(".rmeta")))
1403 let filename
= Path
::new(&*filename
);
1405 // If this was an output file in the "host dir" we don't actually
1406 // worry about it, it's not relevant for us
1407 if filename
.starts_with(&host_root_dir
) {
1408 // Unless it's a proc macro used in the compiler
1409 if crate_types
.iter().any(|t
| t
== "proc-macro") {
1410 deps
.push((filename
.to_path_buf(), DependencyType
::Host
));
1415 // If this was output in the `deps` dir then this is a precise file
1416 // name (hash included) so we start tracking it.
1417 if filename
.starts_with(&target_deps_dir
) {
1418 deps
.push((filename
.to_path_buf(), DependencyType
::Target
));
1422 // Otherwise this was a "top level artifact" which right now doesn't
1423 // have a hash in the name, but there's a version of this file in
1424 // the `deps` folder which *does* have a hash in the name. That's
1425 // the one we'll want to we'll probe for it later.
1427 // We do not use `Path::file_stem` or `Path::extension` here,
1428 // because some generated files may have multiple extensions e.g.
1429 // `std-<hash>.dll.lib` on Windows. The aforementioned methods only
1430 // split the file name by the last extension (`.lib`) while we need
1431 // to split by all extensions (`.dll.lib`).
1432 let expected_len
= t
!(filename
.metadata()).len();
1433 let filename
= filename
.file_name().unwrap().to_str().unwrap();
1434 let mut parts
= filename
.splitn(2, '
.'
);
1435 let file_stem
= parts
.next().unwrap().to_owned();
1436 let extension
= parts
.next().unwrap().to_owned();
1438 toplevel
.push((file_stem
, extension
, expected_len
));
1443 crate::detail_exit(1);
1446 // Ok now we need to actually find all the files listed in `toplevel`. We've
1447 // got a list of prefix/extensions and we basically just need to find the
1448 // most recent file in the `deps` folder corresponding to each one.
1449 let contents
= t
!(target_deps_dir
.read_dir())
1451 .map(|e
| (e
.path(), e
.file_name().into_string().unwrap(), t
!(e
.metadata())))
1452 .collect
::<Vec
<_
>>();
1453 for (prefix
, extension
, expected_len
) in toplevel
{
1454 let candidates
= contents
.iter().filter(|&&(_
, ref filename
, ref meta
)| {
1455 meta
.len() == expected_len
1457 .strip_prefix(&prefix
[..])
1458 .map(|s
| s
.starts_with('
-'
) && s
.ends_with(&extension
[..]))
1461 let max
= candidates
.max_by_key(|&&(_
, _
, ref metadata
)| {
1462 metadata
.modified().expect("mtime should be available on all relevant OSes")
1464 let path_to_add
= match max
{
1465 Some(triple
) => triple
.0.to_str().unwrap(),
1466 None
=> panic
!("no output generated for {:?} {:?}", prefix
, extension
),
1468 if is_dylib(path_to_add
) {
1469 let candidate
= format
!("{}.lib", path_to_add
);
1470 let candidate
= PathBuf
::from(candidate
);
1471 if candidate
.exists() {
1472 deps
.push((candidate
, DependencyType
::Target
));
1475 deps
.push((path_to_add
.into(), DependencyType
::Target
));
1478 deps
.extend(additional_target_deps
);
1480 let mut new_contents
= Vec
::new();
1481 for (dep
, dependency_type
) in deps
.iter() {
1482 new_contents
.extend(match *dependency_type
{
1483 DependencyType
::Host
=> b
"h",
1484 DependencyType
::Target
=> b
"t",
1485 DependencyType
::TargetSelfContained
=> b
"s",
1487 new_contents
.extend(dep
.to_str().unwrap().as_bytes());
1488 new_contents
.extend(b
"\0");
1490 t
!(fs
::write(&stamp
, &new_contents
));
1491 deps
.into_iter().map(|(d
, _
)| d
).collect()
1494 pub fn stream_cargo(
1495 builder
: &Builder
<'_
>,
1497 tail_args
: Vec
<String
>,
1498 cb
: &mut dyn FnMut(CargoMessage
<'_
>),
1500 let mut cargo
= Command
::from(cargo
);
1501 if builder
.config
.dry_run
{
1504 // Instruct Cargo to give us json messages on stdout, critically leaving
1505 // stderr as piped so we can get those pretty colors.
1506 let mut message_format
= if builder
.config
.json_output
{
1507 String
::from("json")
1509 String
::from("json-render-diagnostics")
1511 if let Some(s
) = &builder
.config
.rustc_error_format
{
1512 message_format
.push_str(",json-diagnostic-");
1513 message_format
.push_str(s
);
1515 cargo
.arg("--message-format").arg(message_format
).stdout(Stdio
::piped());
1517 for arg
in tail_args
{
1521 builder
.verbose(&format
!("running: {:?}", cargo
));
1522 let mut child
= match cargo
.spawn() {
1524 Err(e
) => panic
!("failed to execute command: {:?}\nerror: {}", cargo
, e
),
1527 // Spawn Cargo slurping up its JSON output. We'll start building up the
1528 // `deps` array of all files it generated along with a `toplevel` array of
1529 // files we need to probe for later.
1530 let stdout
= BufReader
::new(child
.stdout
.take().unwrap());
1531 for line
in stdout
.lines() {
1532 let line
= t
!(line
);
1533 match serde_json
::from_str
::<CargoMessage
<'_
>>(&line
) {
1535 if builder
.config
.json_output
{
1536 // Forward JSON to stdout.
1537 println
!("{}", line
);
1541 // If this was informational, just print it out and continue
1542 Err(_
) => println
!("{}", line
),
1546 // Make sure Cargo actually succeeded after we read all of its stdout.
1547 let status
= t
!(child
.wait());
1548 if builder
.is_verbose() && !status
.success() {
1550 "command did not execute successfully: {:?}\n\
1551 expected success, got: {}",
1558 #[derive(Deserialize)]
1559 pub struct CargoTarget
<'a
> {
1560 crate_types
: Vec
<Cow
<'a
, str>>,
1563 #[derive(Deserialize)]
1564 #[serde(tag = "reason", rename_all = "kebab-case")]
1565 pub enum CargoMessage
<'a
> {
1567 package_id
: Cow
<'a
, str>,
1568 features
: Vec
<Cow
<'a
, str>>,
1569 filenames
: Vec
<Cow
<'a
, str>>,
1570 target
: CargoTarget
<'a
>,
1572 BuildScriptExecuted
{
1573 package_id
: Cow
<'a
, str>,