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_derive
::Deserialize
;
21 use crate::builder
::crate_description
;
22 use crate::builder
::Cargo
;
23 use crate::builder
::{Builder, Kind, RunConfig, ShouldRun, Step}
;
24 use crate::cache
::{Interned, INTERNER}
;
25 use crate::config
::{LlvmLibunwind, RustcLto, TargetSelection}
;
28 use crate::tool
::SourceType
;
29 use crate::util
::get_clang_cl_resource_dir
;
30 use crate::util
::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date}
;
31 use crate::LLVM_TOOLS
;
32 use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}
;
34 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
36 pub target
: TargetSelection
,
37 pub compiler
: Compiler
,
38 /// Whether to build only a subset of crates in the standard library.
40 /// This shouldn't be used from other steps; see the comment on [`Rustc`].
41 crates
: Interned
<Vec
<String
>>,
45 pub fn new(compiler
: Compiler
, target
: TargetSelection
) -> Self {
46 Self { target, compiler, crates: Default::default() }
52 const DEFAULT
: bool
= true;
54 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
55 // When downloading stage1, the standard library has already been copied to the sysroot, so
56 // there's no need to rebuild it.
57 let builder
= run
.builder
;
58 run
.crate_or_deps("test")
60 .lazy_default_condition(Box
::new(|| !builder
.download_rustc()))
63 fn make_run(run
: RunConfig
<'_
>) {
64 // Normally, people will pass *just* library if they pass it.
65 // But it's possible (although strange) to pass something like `library std core`.
66 // Build all crates anyway, as if they hadn't passed the other args.
68 run
.paths
.iter().any(|set
| set
.assert_single_path().path
.ends_with("library"));
69 let crates
= if has_library { Default::default() }
else { run.cargo_crates_in_set() }
;
70 run
.builder
.ensure(Std
{
71 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
77 /// Builds the standard library.
79 /// This will build the standard library for a particular stage of the build
80 /// using the `compiler` targeting the `target` architecture. The artifacts
81 /// created will also be linked into the sysroot directory.
82 fn run(self, builder
: &Builder
<'_
>) {
83 let target
= self.target
;
84 let compiler
= self.compiler
;
86 // These artifacts were already copied (in `impl Step for Sysroot`).
87 // Don't recompile them.
88 // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
89 // so its artifacts can't be reused.
90 if builder
.download_rustc() && compiler
.stage
!= 0 {
94 if builder
.config
.keep_stage
.contains(&compiler
.stage
)
95 || builder
.config
.keep_stage_std
.contains(&compiler
.stage
)
97 builder
.info("Warning: Using a potentially old libstd. This may not behave well.");
98 builder
.ensure(StdLink
::from_std(self, compiler
));
102 builder
.update_submodule(&Path
::new("library").join("stdarch"));
104 // Profiler information requires LLVM's compiler-rt
105 if builder
.config
.profiler
{
106 builder
.update_submodule(&Path
::new("src/llvm-project"));
109 let mut target_deps
= builder
.ensure(StartupObjects { compiler, target }
);
111 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
112 if compiler_to_use
!= compiler
{
113 builder
.ensure(Std
::new(compiler_to_use
, target
));
114 let msg
= if compiler_to_use
.host
== target
{
116 "Uplifting library (stage{} -> stage{})",
117 compiler_to_use
.stage
, compiler
.stage
121 "Uplifting library (stage{}:{} -> stage{}:{})",
122 compiler_to_use
.stage
, compiler_to_use
.host
, compiler
.stage
, target
127 // Even if we're not building std this stage, the new sysroot must
128 // still contain the third party objects needed by various targets.
129 copy_third_party_objects(builder
, &compiler
, target
);
130 copy_self_contained_objects(builder
, &compiler
, target
);
132 builder
.ensure(StdLink
::from_std(self, compiler_to_use
));
136 target_deps
.extend(copy_third_party_objects(builder
, &compiler
, target
));
137 target_deps
.extend(copy_self_contained_objects(builder
, &compiler
, target
));
139 let mut cargo
= builder
.cargo(compiler
, Mode
::Std
, SourceType
::InTree
, target
, "build");
140 std_cargo(builder
, target
, compiler
.stage
, &mut cargo
);
141 for krate
in &*self.crates
{
142 cargo
.arg("-p").arg(krate
);
145 let msg
= if compiler
.host
== target
{
147 "Building{} stage{} library artifacts ({}) ",
148 crate_description(&self.crates
),
154 "Building{} stage{} library artifacts ({} -> {})",
155 crate_description(&self.crates
),
166 &libstd_stamp(builder
, compiler
, target
),
172 builder
.ensure(StdLink
::from_std(
174 builder
.compiler(compiler
.stage
, builder
.config
.build
),
180 builder
: &Builder
<'_
>,
184 target_deps
: &mut Vec
<(PathBuf
, DependencyType
)>,
185 dependency_type
: DependencyType
,
187 let target
= libdir
.join(name
);
188 builder
.copy(&sourcedir
.join(name
), &target
);
190 target_deps
.push((target
, dependency_type
));
193 fn copy_llvm_libunwind(builder
: &Builder
<'_
>, target
: TargetSelection
, libdir
: &Path
) -> PathBuf
{
194 let libunwind_path
= builder
.ensure(native
::Libunwind { target }
);
195 let libunwind_source
= libunwind_path
.join("libunwind.a");
196 let libunwind_target
= libdir
.join("libunwind.a");
197 builder
.copy(&libunwind_source
, &libunwind_target
);
201 /// Copies third party objects needed by various targets.
202 fn copy_third_party_objects(
203 builder
: &Builder
<'_
>,
205 target
: TargetSelection
,
206 ) -> Vec
<(PathBuf
, DependencyType
)> {
207 let mut target_deps
= vec
![];
209 // FIXME: remove this in 2021
210 if target
== "x86_64-fortanix-unknown-sgx" {
211 if env
::var_os("X86_FORTANIX_SGX_LIBS").is_some() {
212 builder
.info("Warning: X86_FORTANIX_SGX_LIBS environment variable is ignored, libunwind is now compiled as part of rustbuild");
216 if builder
.config
.sanitizers_enabled(target
) && compiler
.stage
!= 0 {
217 // The sanitizers are only copied in stage1 or above,
218 // to avoid creating dependency on LLVM.
220 copy_sanitizers(builder
, &compiler
, target
)
222 .map(|d
| (d
, DependencyType
::Target
)),
226 if target
== "x86_64-fortanix-unknown-sgx"
227 || builder
.config
.llvm_libunwind(target
) == LlvmLibunwind
::InTree
228 && (target
.contains("linux") || target
.contains("fuchsia"))
231 copy_llvm_libunwind(builder
, target
, &builder
.sysroot_libdir(*compiler
, target
));
232 target_deps
.push((libunwind_path
, DependencyType
::Target
));
238 /// Copies third party objects needed by various targets for self-contained linkage.
239 fn copy_self_contained_objects(
240 builder
: &Builder
<'_
>,
242 target
: TargetSelection
,
243 ) -> Vec
<(PathBuf
, DependencyType
)> {
244 let libdir_self_contained
= builder
.sysroot_libdir(*compiler
, target
).join("self-contained");
245 t
!(fs
::create_dir_all(&libdir_self_contained
));
246 let mut target_deps
= vec
![];
248 // Copies the libc and CRT objects.
250 // rustc historically provides a more self-contained installation for musl targets
251 // not requiring the presence of a native musl toolchain. For example, it can fall back
252 // to using gcc from a glibc-targeting toolchain for linking.
253 // To do that we have to distribute musl startup objects as a part of Rust toolchain
254 // and link with them manually in the self-contained mode.
255 if target
.contains("musl") {
256 let srcdir
= builder
.musl_libdir(target
).unwrap_or_else(|| {
257 panic
!("Target {:?} does not have a \"musl-libdir\" key", target
.triple
)
259 for &obj
in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
262 &libdir_self_contained
,
266 DependencyType
::TargetSelfContained
,
269 let crt_path
= builder
.ensure(native
::CrtBeginEnd { target }
);
270 for &obj
in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
271 let src
= crt_path
.join(obj
);
272 let target
= libdir_self_contained
.join(obj
);
273 builder
.copy(&src
, &target
);
274 target_deps
.push((target
, DependencyType
::TargetSelfContained
));
277 if !target
.starts_with("s390x") {
278 let libunwind_path
= copy_llvm_libunwind(builder
, target
, &libdir_self_contained
);
279 target_deps
.push((libunwind_path
, DependencyType
::TargetSelfContained
));
281 } else if target
.ends_with("-wasi") {
285 panic
!("Target {:?} does not have a \"wasi-root\" key", target
.triple
)
287 .join("lib/wasm32-wasi");
288 for &obj
in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
291 &libdir_self_contained
,
295 DependencyType
::TargetSelfContained
,
298 } else if target
.ends_with("windows-gnu") {
299 for obj
in ["crt2.o", "dllcrt2.o"].iter() {
300 let src
= compiler_file(builder
, builder
.cc(target
), target
, CLang
::C
, obj
);
301 let target
= libdir_self_contained
.join(obj
);
302 builder
.copy(&src
, &target
);
303 target_deps
.push((target
, DependencyType
::TargetSelfContained
));
310 /// Configure cargo to compile the standard library, adding appropriate env vars
312 pub fn std_cargo(builder
: &Builder
<'_
>, target
: TargetSelection
, stage
: u32, cargo
: &mut Cargo
) {
313 if let Some(target
) = env
::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
314 cargo
.env("MACOSX_DEPLOYMENT_TARGET", target
);
317 // Determine if we're going to compile in optimized C intrinsics to
318 // the `compiler-builtins` crate. These intrinsics live in LLVM's
319 // `compiler-rt` repository, but our `src/llvm-project` submodule isn't
320 // always checked out, so we need to conditionally look for this. (e.g. if
321 // an external LLVM is used we skip the LLVM submodule checkout).
323 // Note that this shouldn't affect the correctness of `compiler-builtins`,
324 // but only its speed. Some intrinsics in C haven't been translated to Rust
325 // yet but that's pretty rare. Other intrinsics have optimized
326 // implementations in C which have only had slower versions ported to Rust,
327 // so we favor the C version where we can, but it's not critical.
329 // If `compiler-rt` is available ensure that the `c` feature of the
330 // `compiler-builtins` crate is enabled and it's configured to learn where
331 // `compiler-rt` is located.
332 let compiler_builtins_root
= builder
.src
.join("src/llvm-project/compiler-rt");
333 let compiler_builtins_c_feature
= if compiler_builtins_root
.exists() {
334 // Note that `libprofiler_builtins/build.rs` also computes this so if
335 // you're changing something here please also change that.
336 cargo
.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root
);
337 " compiler-builtins-c"
342 let mut features
= String
::new();
344 // Cranelift doesn't support `asm`.
345 if stage
!= 0 && builder
.config
.default_codegen_backend().unwrap_or_default() == "cranelift" {
346 features
+= " compiler-builtins-no-asm";
349 if builder
.no_std(target
) == Some(true) {
350 features
+= " compiler-builtins-mem";
351 if !target
.starts_with("bpf") {
352 features
.push_str(compiler_builtins_c_feature
);
355 // for no-std targets we only compile a few no_std crates
357 .args(&["-p", "alloc"])
358 .arg("--manifest-path")
359 .arg(builder
.src
.join("library/alloc/Cargo.toml"))
363 features
+= &builder
.std_features(target
);
364 features
.push_str(compiler_builtins_c_feature
);
369 .arg("--manifest-path")
370 .arg(builder
.src
.join("library/test/Cargo.toml"));
372 // Help the libc crate compile by assisting it in finding various
373 // sysroot native libraries.
374 if target
.contains("musl") {
375 if let Some(p
) = builder
.musl_libdir(target
) {
376 let root
= format
!("native={}", p
.to_str().unwrap());
377 cargo
.rustflag("-L").rustflag(&root
);
381 if target
.ends_with("-wasi") {
382 if let Some(p
) = builder
.wasi_root(target
) {
383 let root
= format
!("native={}/lib/wasm32-wasi", p
.to_str().unwrap());
384 cargo
.rustflag("-L").rustflag(&root
);
389 // By default, rustc uses `-Cembed-bitcode=yes`, and Cargo overrides that
390 // with `-Cembed-bitcode=no` for non-LTO builds. However, libstd must be
391 // built with bitcode so that the produced rlibs can be used for both LTO
392 // builds (which use bitcode) and non-LTO builds (which use object code).
393 // So we override the override here!
395 // But we don't bother for the stage 0 compiler because it's never used
398 cargo
.rustflag("-Cembed-bitcode=yes");
400 if builder
.config
.rust_lto
== RustcLto
::Off
{
401 cargo
.rustflag("-Clto=off");
404 // By default, rustc does not include unwind tables unless they are required
405 // for a particular target. They are not required by RISC-V targets, but
406 // compiling the standard library with them means that users can get
407 // backtraces without having to recompile the standard library themselves.
409 // This choice was discussed in https://github.com/rust-lang/rust/pull/69890
410 if target
.contains("riscv") {
411 cargo
.rustflag("-Cforce-unwind-tables=yes");
415 format
!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder
.doc_rust_lang_org_channel(),);
416 cargo
.rustflag(&html_root
);
417 cargo
.rustdocflag(&html_root
);
420 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
422 pub compiler
: Compiler
,
423 pub target_compiler
: Compiler
,
424 pub target
: TargetSelection
,
425 /// Not actually used; only present to make sure the cache invalidation is correct.
426 crates
: Interned
<Vec
<String
>>,
430 fn from_std(std
: Std
, host_compiler
: Compiler
) -> Self {
432 compiler
: host_compiler
,
433 target_compiler
: std
.compiler
,
440 impl Step
for StdLink
{
443 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
447 /// Link all libstd rlibs/dylibs into the sysroot location.
449 /// Links those artifacts generated by `compiler` to the `stage` compiler's
450 /// sysroot for the specified `host` and `target`.
452 /// Note that this assumes that `compiler` has already generated the libstd
453 /// libraries for `target`, and this method will find them in the relevant
454 /// output directory.
455 fn run(self, builder
: &Builder
<'_
>) {
456 let compiler
= self.compiler
;
457 let target_compiler
= self.target_compiler
;
458 let target
= self.target
;
459 let libdir
= builder
.sysroot_libdir(target_compiler
, target
);
460 let hostdir
= builder
.sysroot_libdir(target_compiler
, compiler
.host
);
461 add_to_sysroot(builder
, &libdir
, &hostdir
, &libstd_stamp(builder
, compiler
, target
));
465 /// Copies sanitizer runtime libraries into target libdir.
467 builder
: &Builder
<'_
>,
469 target
: TargetSelection
,
471 let runtimes
: Vec
<native
::SanitizerRuntime
> = builder
.ensure(native
::Sanitizers { target }
);
473 if builder
.config
.dry_run() {
477 let mut target_deps
= Vec
::new();
478 let libdir
= builder
.sysroot_libdir(*compiler
, target
);
480 for runtime
in &runtimes
{
481 let dst
= libdir
.join(&runtime
.name
);
482 builder
.copy(&runtime
.path
, &dst
);
484 if target
== "x86_64-apple-darwin"
485 || target
== "aarch64-apple-darwin"
486 || target
== "aarch64-apple-ios"
487 || target
== "aarch64-apple-ios-sim"
488 || target
== "x86_64-apple-ios"
490 // Update the library’s install name to reflect that it has been renamed.
491 apple_darwin_update_library_name(&dst
, &format
!("@rpath/{}", &runtime
.name
));
492 // Upon renaming the install name, the code signature of the file will invalidate,
493 // so we will sign it again.
494 apple_darwin_sign_file(&dst
);
497 target_deps
.push(dst
);
503 fn apple_darwin_update_library_name(library_path
: &Path
, new_name
: &str) {
504 let status
= Command
::new("install_name_tool")
509 .expect("failed to execute `install_name_tool`");
510 assert
!(status
.success());
513 fn apple_darwin_sign_file(file_path
: &Path
) {
514 let status
= Command
::new("codesign")
515 .arg("-f") // Force to rewrite the existing signature
520 .expect("failed to execute `codesign`");
521 assert
!(status
.success());
524 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
525 pub struct StartupObjects
{
526 pub compiler
: Compiler
,
527 pub target
: TargetSelection
,
530 impl Step
for StartupObjects
{
531 type Output
= Vec
<(PathBuf
, DependencyType
)>;
533 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
534 run
.path("library/rtstartup")
537 fn make_run(run
: RunConfig
<'_
>) {
538 run
.builder
.ensure(StartupObjects
{
539 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
544 /// Builds and prepare startup objects like rsbegin.o and rsend.o
546 /// These are primarily used on Windows right now for linking executables/dlls.
547 /// They don't require any library support as they're just plain old object
548 /// files, so we just use the nightly snapshot compiler to always build them (as
549 /// no other compilers are guaranteed to be available).
550 fn run(self, builder
: &Builder
<'_
>) -> Vec
<(PathBuf
, DependencyType
)> {
551 let for_compiler
= self.compiler
;
552 let target
= self.target
;
553 if !target
.ends_with("windows-gnu") {
557 let mut target_deps
= vec
![];
559 let src_dir
= &builder
.src
.join("library").join("rtstartup");
560 let dst_dir
= &builder
.native_dir(target
).join("rtstartup");
561 let sysroot_dir
= &builder
.sysroot_libdir(for_compiler
, target
);
562 t
!(fs
::create_dir_all(dst_dir
));
564 for file
in &["rsbegin", "rsend"] {
565 let src_file
= &src_dir
.join(file
.to_string() + ".rs");
566 let dst_file
= &dst_dir
.join(file
.to_string() + ".o");
567 if !up_to_date(src_file
, dst_file
) {
568 let mut cmd
= Command
::new(&builder
.initial_rustc
);
569 cmd
.env("RUSTC_BOOTSTRAP", "1");
570 if !builder
.local_rebuild
{
571 // a local_rebuild compiler already has stage1 features
572 cmd
.arg("--cfg").arg("bootstrap");
576 .arg(target
.rustc_target_arg())
584 let target
= sysroot_dir
.join((*file
).to_string() + ".o");
585 builder
.copy(dst_file
, &target
);
586 target_deps
.push((target
, DependencyType
::Target
));
593 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
595 pub target
: TargetSelection
,
596 pub compiler
: Compiler
,
597 /// Whether to build a subset of crates, rather than the whole compiler.
599 /// This should only be requested by the user, not used within rustbuild itself.
600 /// Using it within rustbuild can lead to confusing situation where lints are replayed
601 /// in two different steps.
602 crates
: Interned
<Vec
<String
>>,
606 pub fn new(compiler
: Compiler
, target
: TargetSelection
) -> Self {
607 Self { target, compiler, crates: Default::default() }
611 impl Step
for Rustc
{
613 const ONLY_HOSTS
: bool
= true;
614 const DEFAULT
: bool
= false;
616 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
617 let mut crates
= run
.builder
.in_tree_crates("rustc-main", None
);
618 for (i
, krate
) in crates
.iter().enumerate() {
619 if krate
.name
== "rustc-main" {
620 crates
.swap_remove(i
);
627 fn make_run(run
: RunConfig
<'_
>) {
628 let crates
= run
.cargo_crates_in_set();
629 run
.builder
.ensure(Rustc
{
630 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
636 /// Builds the compiler.
638 /// This will build the compiler for a particular stage of the build using
639 /// the `compiler` targeting the `target` architecture. The artifacts
640 /// created will also be linked into the sysroot directory.
641 fn run(self, builder
: &Builder
<'_
>) {
642 let compiler
= self.compiler
;
643 let target
= self.target
;
645 // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
646 // so its artifacts can't be reused.
647 if builder
.download_rustc() && compiler
.stage
!= 0 {
648 // Copy the existing artifacts instead of rebuilding them.
649 // NOTE: this path is only taken for tools linking to rustc-dev.
650 builder
.ensure(Sysroot { compiler }
);
654 builder
.ensure(Std
::new(compiler
, target
));
656 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
657 builder
.info("Warning: Using a potentially old librustc. This may not behave well.");
658 builder
.info("Warning: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
659 builder
.ensure(RustcLink
::from_rustc(self, compiler
));
663 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
664 if compiler_to_use
!= compiler
{
665 builder
.ensure(Rustc
::new(compiler_to_use
, target
));
666 let msg
= if compiler_to_use
.host
== target
{
668 "Uplifting rustc (stage{} -> stage{})",
669 compiler_to_use
.stage
,
674 "Uplifting rustc (stage{}:{} -> stage{}:{})",
675 compiler_to_use
.stage
,
676 compiler_to_use
.host
,
682 builder
.ensure(RustcLink
::from_rustc(self, compiler_to_use
));
686 // Ensure that build scripts and proc macros have a std / libproc_macro to link against.
687 builder
.ensure(Std
::new(
688 builder
.compiler(self.compiler
.stage
, builder
.config
.build
),
689 builder
.config
.build
,
692 let mut cargo
= builder
.cargo(compiler
, Mode
::Rustc
, SourceType
::InTree
, target
, "build");
693 rustc_cargo(builder
, &mut cargo
, target
);
695 if builder
.config
.rust_profile_use
.is_some()
696 && builder
.config
.rust_profile_generate
.is_some()
698 panic
!("Cannot use and generate PGO profiles at the same time");
701 // With LLD, we can use ICF (identical code folding) to reduce the executable size
702 // of librustc_driver/rustc and to improve i-cache utilization.
704 // -Wl,[link options] doesn't work on MSVC. However, /OPT:ICF (technically /OPT:REF,ICF)
705 // is already on by default in MSVC optimized builds, which is interpreted as --icf=all:
706 // https://github.com/llvm/llvm-project/blob/3329cec2f79185bafd678f310fafadba2a8c76d2/lld/COFF/Driver.cpp#L1746
707 // https://github.com/rust-lang/rust/blob/f22819bcce4abaff7d1246a56eec493418f9f4ee/compiler/rustc_codegen_ssa/src/back/linker.rs#L827
708 if builder
.config
.use_lld
&& !compiler
.host
.contains("msvc") {
709 cargo
.rustflag("-Clink-args=-Wl,--icf=all");
712 let is_collecting
= if let Some(path
) = &builder
.config
.rust_profile_generate
{
713 if compiler
.stage
== 1 {
714 cargo
.rustflag(&format
!("-Cprofile-generate={}", path
));
715 // Apparently necessary to avoid overflowing the counters during
716 // a Cargo build profile
717 cargo
.rustflag("-Cllvm-args=-vp-counters-per-site=4");
722 } else if let Some(path
) = &builder
.config
.rust_profile_use
{
723 if compiler
.stage
== 1 {
724 cargo
.rustflag(&format
!("-Cprofile-use={}", path
));
725 cargo
.rustflag("-Cllvm-args=-pgo-warn-missing-function");
734 // Ensure paths to Rust sources are relative, not absolute.
735 cargo
.rustflag(&format
!(
736 "-Cllvm-args=-static-func-strip-dirname-prefix={}",
737 builder
.config
.src
.components().count()
741 // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary
742 // and may just be a time sink.
743 if compiler
.stage
!= 0 {
744 match builder
.config
.rust_lto
{
745 RustcLto
::Thin
| RustcLto
::Fat
=> {
746 // Since using LTO for optimizing dylibs is currently experimental,
747 // we need to pass -Zdylib-lto.
748 cargo
.rustflag("-Zdylib-lto");
749 // Cargo by default passes `-Cembed-bitcode=no` and doesn't pass `-Clto` when
750 // compiling dylibs (and their dependencies), even when LTO is enabled for the
751 // crate. Therefore, we need to override `-Clto` and `-Cembed-bitcode` here.
752 let lto_type
= match builder
.config
.rust_lto
{
753 RustcLto
::Thin
=> "thin",
754 RustcLto
::Fat
=> "fat",
757 cargo
.rustflag(&format
!("-Clto={}", lto_type
));
758 cargo
.rustflag("-Cembed-bitcode=yes");
760 RustcLto
::ThinLocal
=> { /* Do nothing, this is the default */ }
762 cargo
.rustflag("-Clto=off");
766 if builder
.config
.rust_lto
== RustcLto
::Off
{
767 cargo
.rustflag("-Clto=off");
771 for krate
in &*self.crates
{
772 cargo
.arg("-p").arg(krate
);
775 let msg
= if compiler
.host
== target
{
777 "Building{} compiler artifacts (stage{} -> stage{})",
778 crate_description(&self.crates
),
784 "Building{} compiler artifacts (stage{}:{} -> stage{}:{})",
785 crate_description(&self.crates
),
797 &librustc_stamp(builder
, compiler
, target
),
800 true, // Only ship rustc_driver.so and .rmeta files, not all intermediate .rlib files.
803 builder
.ensure(RustcLink
::from_rustc(
805 builder
.compiler(compiler
.stage
, builder
.config
.build
),
810 pub fn rustc_cargo(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: TargetSelection
) {
813 .arg(builder
.rustc_features(builder
.kind
))
814 .arg("--manifest-path")
815 .arg(builder
.src
.join("compiler/rustc/Cargo.toml"));
816 rustc_cargo_env(builder
, cargo
, target
);
819 pub fn rustc_cargo_env(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: TargetSelection
) {
820 // Set some configuration variables picked up by build scripts and
821 // the compiler alike
823 .env("CFG_RELEASE", builder
.rust_release())
824 .env("CFG_RELEASE_CHANNEL", &builder
.config
.channel
)
825 .env("CFG_VERSION", builder
.rust_version());
827 if let Some(backend
) = builder
.config
.default_codegen_backend() {
828 cargo
.env("CFG_DEFAULT_CODEGEN_BACKEND", backend
);
831 let libdir_relative
= builder
.config
.libdir_relative().unwrap_or_else(|| Path
::new("lib"));
832 let target_config
= builder
.config
.target_config
.get(&target
);
834 cargo
.env("CFG_LIBDIR_RELATIVE", libdir_relative
);
836 if let Some(ref ver_date
) = builder
.rust_info().commit_date() {
837 cargo
.env("CFG_VER_DATE", ver_date
);
839 if let Some(ref ver_hash
) = builder
.rust_info().sha() {
840 cargo
.env("CFG_VER_HASH", ver_hash
);
842 if !builder
.unstable_features() {
843 cargo
.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
846 // Prefer the current target's own default_linker, else a globally
848 if let Some(s
) = target_config
.and_then(|c
| c
.default_linker
.as_ref()) {
849 cargo
.env("CFG_DEFAULT_LINKER", s
);
850 } else if let Some(ref s
) = builder
.config
.rustc_default_linker
{
851 cargo
.env("CFG_DEFAULT_LINKER", s
);
854 if builder
.config
.rustc_parallel
{
855 // keep in sync with `bootstrap/lib.rs:Build::rustc_features`
856 // `cfg` option for rustc, `features` option for cargo, for conditional compilation
857 cargo
.rustflag("--cfg=parallel_compiler");
858 cargo
.rustdocflag("--cfg=parallel_compiler");
860 if builder
.config
.rust_verify_llvm_ir
{
861 cargo
.env("RUSTC_VERIFY_LLVM_IR", "1");
864 // Pass down configuration from the LLVM build into the build of
865 // rustc_llvm and rustc_codegen_llvm.
867 // Note that this is disabled if LLVM itself is disabled or we're in a check
868 // build. If we are in a check build we still go ahead here presuming we've
869 // detected that LLVM is already built and good to go which helps prevent
870 // busting caches (e.g. like #71152).
871 if builder
.config
.llvm_enabled()
872 && (builder
.kind
!= Kind
::Check
873 || crate::native
::prebuilt_llvm_config(builder
, target
).is_ok())
875 if builder
.is_rust_llvm(target
) {
876 cargo
.env("LLVM_RUSTLLVM", "1");
878 let native
::LlvmResult { llvm_config, .. }
= builder
.ensure(native
::Llvm { target }
);
879 cargo
.env("LLVM_CONFIG", &llvm_config
);
880 if let Some(s
) = target_config
.and_then(|c
| c
.llvm_config
.as_ref()) {
881 cargo
.env("CFG_LLVM_ROOT", s
);
884 // Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script
885 // expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by
889 // - on windows, when `clang-cl` is used with instrumentation, we need to manually add
890 // clang's runtime library resource directory so that the profiler runtime library can be
891 // found. This is to avoid the linker errors about undefined references to
892 // `__llvm_profile_instrument_memop` when linking `rustc_driver`.
893 let mut llvm_linker_flags
= String
::new();
894 if builder
.config
.llvm_profile_generate
&& target
.contains("msvc") {
895 if let Some(ref clang_cl_path
) = builder
.config
.llvm_clang_cl
{
896 // Add clang's runtime library directory to the search path
897 let clang_rt_dir
= get_clang_cl_resource_dir(clang_cl_path
);
898 llvm_linker_flags
.push_str(&format
!("-L{}", clang_rt_dir
.display()));
902 // The config can also specify its own llvm linker flags.
903 if let Some(ref s
) = builder
.config
.llvm_ldflags
{
904 if !llvm_linker_flags
.is_empty() {
905 llvm_linker_flags
.push_str(" ");
907 llvm_linker_flags
.push_str(s
);
910 // Set the linker flags via the env var that `rustc_llvm`'s build script will read.
911 if !llvm_linker_flags
.is_empty() {
912 cargo
.env("LLVM_LINKER_FLAGS", llvm_linker_flags
);
915 // Building with a static libstdc++ is only supported on linux right now,
916 // not for MSVC or macOS
917 if builder
.config
.llvm_static_stdcpp
918 && !target
.contains("freebsd")
919 && !target
.contains("msvc")
920 && !target
.contains("apple")
921 && !target
.contains("solaris")
923 let file
= compiler_file(
925 builder
.cxx(target
).unwrap(),
930 cargo
.env("LLVM_STATIC_STDCPP", file
);
932 if builder
.llvm_link_shared() {
933 cargo
.env("LLVM_LINK_SHARED", "1");
935 if builder
.config
.llvm_use_libcxx
{
936 cargo
.env("LLVM_USE_LIBCXX", "1");
938 if builder
.config
.llvm_optimize
&& !builder
.config
.llvm_release_debuginfo
{
939 cargo
.env("LLVM_NDEBUG", "1");
944 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
946 pub compiler
: Compiler
,
947 pub target_compiler
: Compiler
,
948 pub target
: TargetSelection
,
949 /// Not actually used; only present to make sure the cache invalidation is correct.
950 crates
: Interned
<Vec
<String
>>,
954 fn from_rustc(rustc
: Rustc
, host_compiler
: Compiler
) -> Self {
956 compiler
: host_compiler
,
957 target_compiler
: rustc
.compiler
,
958 target
: rustc
.target
,
959 crates
: rustc
.crates
,
964 impl Step
for RustcLink
{
967 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
971 /// Same as `std_link`, only for librustc
972 fn run(self, builder
: &Builder
<'_
>) {
973 let compiler
= self.compiler
;
974 let target_compiler
= self.target_compiler
;
975 let target
= self.target
;
978 &builder
.sysroot_libdir(target_compiler
, target
),
979 &builder
.sysroot_libdir(target_compiler
, compiler
.host
),
980 &librustc_stamp(builder
, compiler
, target
),
985 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
986 pub struct CodegenBackend
{
987 pub target
: TargetSelection
,
988 pub compiler
: Compiler
,
989 pub backend
: Interned
<String
>,
992 impl Step
for CodegenBackend
{
994 const ONLY_HOSTS
: bool
= true;
995 // Only the backends specified in the `codegen-backends` entry of `config.toml` are built.
996 const DEFAULT
: bool
= true;
998 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
999 run
.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
1002 fn make_run(run
: RunConfig
<'_
>) {
1003 for &backend
in &run
.builder
.config
.rust_codegen_backends
{
1004 if backend
== "llvm" {
1005 continue; // Already built as part of rustc
1008 run
.builder
.ensure(CodegenBackend
{
1010 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.build_triple()),
1016 fn run(self, builder
: &Builder
<'_
>) {
1017 let compiler
= self.compiler
;
1018 let target
= self.target
;
1019 let backend
= self.backend
;
1021 builder
.ensure(Rustc
::new(compiler
, target
));
1023 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
1025 "Warning: Using a potentially old codegen backend. \
1026 This may not behave well.",
1028 // Codegen backends are linked separately from this step today, so we don't do
1033 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
1034 if compiler_to_use
!= compiler
{
1035 builder
.ensure(CodegenBackend { compiler: compiler_to_use, target, backend }
);
1039 let out_dir
= builder
.cargo_out(compiler
, Mode
::Codegen
, target
);
1041 let mut cargo
= builder
.cargo(compiler
, Mode
::Codegen
, SourceType
::InTree
, target
, "build");
1043 .arg("--manifest-path")
1044 .arg(builder
.src
.join(format
!("compiler/rustc_codegen_{}/Cargo.toml", backend
)));
1045 rustc_cargo_env(builder
, &mut cargo
, target
);
1047 let tmp_stamp
= out_dir
.join(".tmp.stamp");
1049 let msg
= if compiler
.host
== target
{
1050 format
!("Building stage{} codegen backend {}", compiler
.stage
, backend
)
1053 "Building stage{} codegen backend {} ({} -> {})",
1054 compiler
.stage
, backend
, compiler
.host
, target
1058 let files
= run_cargo(builder
, cargo
, vec
![], &tmp_stamp
, vec
![], false, false);
1059 if builder
.config
.dry_run() {
1062 let mut files
= files
.into_iter().filter(|f
| {
1063 let filename
= f
.file_name().unwrap().to_str().unwrap();
1064 is_dylib(filename
) && filename
.contains("rustc_codegen_")
1066 let codegen_backend
= match files
.next() {
1068 None
=> panic
!("no dylibs built for codegen backend?"),
1070 if let Some(f
) = files
.next() {
1072 "codegen backend built two dylibs:\n{}\n{}",
1073 codegen_backend
.display(),
1077 let stamp
= codegen_backend_stamp(builder
, compiler
, target
, backend
);
1078 let codegen_backend
= codegen_backend
.to_str().unwrap();
1079 t
!(fs
::write(&stamp
, &codegen_backend
));
1083 /// Creates the `codegen-backends` folder for a compiler that's about to be
1084 /// assembled as a complete compiler.
1086 /// This will take the codegen artifacts produced by `compiler` and link them
1087 /// into an appropriate location for `target_compiler` to be a functional
1089 fn copy_codegen_backends_to_sysroot(
1090 builder
: &Builder
<'_
>,
1092 target_compiler
: Compiler
,
1094 let target
= target_compiler
.host
;
1096 // Note that this step is different than all the other `*Link` steps in
1097 // that it's not assembling a bunch of libraries but rather is primarily
1098 // moving the codegen backend into place. The codegen backend of rustc is
1099 // not linked into the main compiler by default but is rather dynamically
1100 // selected at runtime for inclusion.
1102 // Here we're looking for the output dylib of the `CodegenBackend` step and
1103 // we're copying that into the `codegen-backends` folder.
1104 let dst
= builder
.sysroot_codegen_backends(target_compiler
);
1105 t
!(fs
::create_dir_all(&dst
), dst
);
1107 if builder
.config
.dry_run() {
1111 for backend
in builder
.config
.rust_codegen_backends
.iter() {
1112 if backend
== "llvm" {
1113 continue; // Already built as part of rustc
1116 let stamp
= codegen_backend_stamp(builder
, compiler
, target
, *backend
);
1117 let dylib
= t
!(fs
::read_to_string(&stamp
));
1118 let file
= Path
::new(&dylib
);
1119 let filename
= file
.file_name().unwrap().to_str().unwrap();
1120 // change `librustc_codegen_cranelift-xxxxxx.so` to
1121 // `librustc_codegen_cranelift-release.so`
1122 let target_filename
= {
1123 let dash
= filename
.find('
-'
).unwrap();
1124 let dot
= filename
.find('
.'
).unwrap();
1125 format
!("{}-{}{}", &filename
[..dash
], builder
.rust_release(), &filename
[dot
..])
1127 builder
.copy(&file
, &dst
.join(target_filename
));
1131 /// Cargo's output path for the standard library in a given stage, compiled
1132 /// by a particular compiler for the specified target.
1133 pub fn libstd_stamp(builder
: &Builder
<'_
>, compiler
: Compiler
, target
: TargetSelection
) -> PathBuf
{
1134 builder
.cargo_out(compiler
, Mode
::Std
, target
).join(".libstd.stamp")
1137 /// Cargo's output path for librustc in a given stage, compiled by a particular
1138 /// compiler for the specified target.
1139 pub fn librustc_stamp(
1140 builder
: &Builder
<'_
>,
1142 target
: TargetSelection
,
1144 builder
.cargo_out(compiler
, Mode
::Rustc
, target
).join(".librustc.stamp")
1147 /// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
1148 /// compiler for the specified target and backend.
1149 fn codegen_backend_stamp(
1150 builder
: &Builder
<'_
>,
1152 target
: TargetSelection
,
1153 backend
: Interned
<String
>,
1156 .cargo_out(compiler
, Mode
::Codegen
, target
)
1157 .join(format
!(".librustc_codegen_{}.stamp", backend
))
1160 pub fn compiler_file(
1161 builder
: &Builder
<'_
>,
1163 target
: TargetSelection
,
1167 let mut cmd
= Command
::new(compiler
);
1168 cmd
.args(builder
.cflags(target
, GitRepo
::Rustc
, c
));
1169 cmd
.arg(format
!("-print-file-name={}", file
));
1170 let out
= output(&mut cmd
);
1171 PathBuf
::from(out
.trim())
1174 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1175 pub struct Sysroot
{
1176 pub compiler
: Compiler
,
1179 impl Step
for Sysroot
{
1180 type Output
= Interned
<PathBuf
>;
1182 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1186 /// Returns the sysroot for the `compiler` specified that *this build system
1189 /// That is, the sysroot for the stage0 compiler is not what the compiler
1190 /// thinks it is by default, but it's the same as the default for stages
1192 fn run(self, builder
: &Builder
<'_
>) -> Interned
<PathBuf
> {
1193 let compiler
= self.compiler
;
1194 let host_dir
= builder
.out
.join(&compiler
.host
.triple
);
1196 let sysroot_dir
= |stage
| {
1198 host_dir
.join("stage0-sysroot")
1199 } else if builder
.download_rustc() && compiler
.stage
!= builder
.top_stage
{
1200 host_dir
.join("ci-rustc-sysroot")
1202 host_dir
.join(format
!("stage{}", stage
))
1205 let sysroot
= sysroot_dir(compiler
.stage
);
1207 let _
= fs
::remove_dir_all(&sysroot
);
1208 t
!(fs
::create_dir_all(&sysroot
));
1210 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1211 if builder
.download_rustc() && compiler
.stage
!= 0 {
1213 builder
.config
.build
, compiler
.host
,
1214 "Cross-compiling is not yet supported with `download-rustc`",
1217 // #102002, cleanup old toolchain folders when using download-rustc so people don't use them by accident.
1218 for stage
in 0..=2 {
1219 if stage
!= compiler
.stage
{
1220 let dir
= sysroot_dir(stage
);
1221 if !dir
.ends_with("ci-rustc-sysroot") {
1222 let _
= fs
::remove_dir_all(dir
);
1227 // Copy the compiler into the correct sysroot.
1229 builder
.config
.out
.join(&*builder
.config
.build
.triple
).join("ci-rustc");
1230 builder
.cp_r(&ci_rustc_dir
, &sysroot
);
1231 return INTERNER
.intern_path(sysroot
);
1234 // Symlink the source root into the same location inside the sysroot,
1235 // where `rust-src` component would go (`$sysroot/lib/rustlib/src/rust`),
1236 // so that any tools relying on `rust-src` also work for local builds,
1237 // and also for translating the virtual `/rustc/$hash` back to the real
1238 // directory (for running tests with `rust.remap-debuginfo = true`).
1239 let sysroot_lib_rustlib_src
= sysroot
.join("lib/rustlib/src");
1240 t
!(fs
::create_dir_all(&sysroot_lib_rustlib_src
));
1241 let sysroot_lib_rustlib_src_rust
= sysroot_lib_rustlib_src
.join("rust");
1242 if let Err(e
) = symlink_dir(&builder
.config
, &builder
.src
, &sysroot_lib_rustlib_src_rust
) {
1244 "warning: creating symbolic link `{}` to `{}` failed with {}",
1245 sysroot_lib_rustlib_src_rust
.display(),
1246 builder
.src
.display(),
1249 if builder
.config
.rust_remap_debuginfo
{
1251 "warning: some `tests/ui` tests will fail when lacking `{}`",
1252 sysroot_lib_rustlib_src_rust
.display(),
1256 // Same for the rustc-src component.
1257 let sysroot_lib_rustlib_rustcsrc
= sysroot
.join("lib/rustlib/rustc-src");
1258 t
!(fs
::create_dir_all(&sysroot_lib_rustlib_rustcsrc
));
1259 let sysroot_lib_rustlib_rustcsrc_rust
= sysroot_lib_rustlib_rustcsrc
.join("rust");
1261 symlink_dir(&builder
.config
, &builder
.src
, &sysroot_lib_rustlib_rustcsrc_rust
)
1264 "warning: creating symbolic link `{}` to `{}` failed with {}",
1265 sysroot_lib_rustlib_rustcsrc_rust
.display(),
1266 builder
.src
.display(),
1271 INTERNER
.intern_path(sysroot
)
1275 #[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
1276 pub struct Assemble
{
1277 /// The compiler which we will produce in this step. Assemble itself will
1278 /// take care of ensuring that the necessary prerequisites to do so exist,
1279 /// that is, this target can be a stage2 compiler and Assemble will build
1280 /// previous stages for you.
1281 pub target_compiler
: Compiler
,
1284 impl Step
for Assemble
{
1285 type Output
= Compiler
;
1286 const ONLY_HOSTS
: bool
= true;
1288 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
1289 run
.path("compiler/rustc").path("compiler")
1292 fn make_run(run
: RunConfig
<'_
>) {
1293 run
.builder
.ensure(Assemble
{
1294 target_compiler
: run
.builder
.compiler(run
.builder
.top_stage
+ 1, run
.target
),
1298 /// Prepare a new compiler from the artifacts in `stage`
1300 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
1301 /// must have been previously produced by the `stage - 1` builder.build
1303 fn run(self, builder
: &Builder
<'_
>) -> Compiler
{
1304 let target_compiler
= self.target_compiler
;
1306 if target_compiler
.stage
== 0 {
1308 builder
.config
.build
, target_compiler
.host
,
1309 "Cannot obtain compiler for non-native build triple at stage 0"
1311 // The stage 0 compiler for the build triple is always pre-built.
1312 return target_compiler
;
1315 // Get the compiler that we'll use to bootstrap ourselves.
1317 // Note that this is where the recursive nature of the bootstrap
1318 // happens, as this will request the previous stage's compiler on
1319 // downwards to stage 0.
1321 // Also note that we're building a compiler for the host platform. We
1322 // only assume that we can run `build` artifacts, which means that to
1323 // produce some other architecture compiler we need to start from
1324 // `build` to get there.
1326 // FIXME: It may be faster if we build just a stage 1 compiler and then
1327 // use that to bootstrap this compiler forward.
1328 let build_compiler
= builder
.compiler(target_compiler
.stage
- 1, builder
.config
.build
);
1330 // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
1331 if builder
.download_rustc() {
1332 builder
.ensure(Sysroot { compiler: target_compiler }
);
1333 return target_compiler
;
1336 // Build the libraries for this compiler to link to (i.e., the libraries
1337 // it uses at runtime). NOTE: Crates the target compiler compiles don't
1338 // link to these. (FIXME: Is that correct? It seems to be correct most
1339 // of the time but I think we do link to these for stage2/bin compilers
1340 // when not performing a full bootstrap).
1341 builder
.ensure(Rustc
::new(build_compiler
, target_compiler
.host
));
1343 for &backend
in builder
.config
.rust_codegen_backends
.iter() {
1344 if backend
== "llvm" {
1345 continue; // Already built as part of rustc
1348 builder
.ensure(CodegenBackend
{
1349 compiler
: build_compiler
,
1350 target
: target_compiler
.host
,
1355 let lld_install
= if builder
.config
.lld_enabled
{
1356 Some(builder
.ensure(native
::Lld { target: target_compiler.host }
))
1361 let stage
= target_compiler
.stage
;
1362 let host
= target_compiler
.host
;
1363 let msg
= if build_compiler
.host
== host
{
1364 format
!("Assembling stage{} compiler", stage
)
1366 format
!("Assembling stage{} compiler ({})", stage
, host
)
1370 // Link in all dylibs to the libdir
1371 let stamp
= librustc_stamp(builder
, build_compiler
, target_compiler
.host
);
1372 let proc_macros
= builder
1373 .read_stamp_file(&stamp
)
1375 .filter_map(|(path
, dependency_type
)| {
1376 if dependency_type
== DependencyType
::Host
{
1377 Some(path
.file_name().unwrap().to_owned().into_string().unwrap())
1382 .collect
::<HashSet
<_
>>();
1384 let sysroot
= builder
.sysroot(target_compiler
);
1385 let rustc_libdir
= builder
.rustc_libdir(target_compiler
);
1386 t
!(fs
::create_dir_all(&rustc_libdir
));
1387 let src_libdir
= builder
.sysroot_libdir(build_compiler
, host
);
1388 for f
in builder
.read_dir(&src_libdir
) {
1389 let filename
= f
.file_name().into_string().unwrap();
1390 if (is_dylib(&filename
) || is_debug_info(&filename
)) && !proc_macros
.contains(&filename
)
1392 builder
.copy(&f
.path(), &rustc_libdir
.join(&filename
));
1396 copy_codegen_backends_to_sysroot(builder
, build_compiler
, target_compiler
);
1398 // We prepend this bin directory to the user PATH when linking Rust binaries. To
1399 // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
1400 let libdir
= builder
.sysroot_libdir(target_compiler
, target_compiler
.host
);
1401 let libdir_bin
= libdir
.parent().unwrap().join("bin");
1402 t
!(fs
::create_dir_all(&libdir_bin
));
1403 if let Some(lld_install
) = lld_install
{
1404 let src_exe
= exe("lld", target_compiler
.host
);
1405 let dst_exe
= exe("rust-lld", target_compiler
.host
);
1406 builder
.copy(&lld_install
.join("bin").join(&src_exe
), &libdir_bin
.join(&dst_exe
));
1407 // for `-Z gcc-ld=lld`
1408 let gcc_ld_dir
= libdir_bin
.join("gcc-ld");
1409 t
!(fs
::create_dir(&gcc_ld_dir
));
1410 let lld_wrapper_exe
= builder
.ensure(crate::tool
::LldWrapper
{
1411 compiler
: build_compiler
,
1412 target
: target_compiler
.host
,
1414 for name
in crate::LLD_FILE_NAMES
{
1415 builder
.copy(&lld_wrapper_exe
, &gcc_ld_dir
.join(exe(name
, target_compiler
.host
)));
1419 if builder
.config
.rust_codegen_backends
.contains(&INTERNER
.intern_str("llvm")) {
1420 let native
::LlvmResult { llvm_config, .. }
=
1421 builder
.ensure(native
::Llvm { target: target_compiler.host }
);
1422 if !builder
.config
.dry_run() {
1423 let llvm_bin_dir
= output(Command
::new(llvm_config
).arg("--bindir"));
1424 let llvm_bin_dir
= Path
::new(llvm_bin_dir
.trim());
1426 // Since we've already built the LLVM tools, install them to the sysroot.
1427 // This is the equivalent of installing the `llvm-tools-preview` component via
1428 // rustup, and lets developers use a locally built toolchain to
1429 // build projects that expect llvm tools to be present in the sysroot
1430 // (e.g. the `bootimage` crate).
1431 for tool
in LLVM_TOOLS
{
1432 let tool_exe
= exe(tool
, target_compiler
.host
);
1433 let src_path
= llvm_bin_dir
.join(&tool_exe
);
1434 // When using `download-ci-llvm`, some of the tools
1435 // may not exist, so skip trying to copy them.
1436 if src_path
.exists() {
1437 builder
.copy(&src_path
, &libdir_bin
.join(&tool_exe
));
1443 // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
1444 // so that it can be found when the newly built `rustc` is run.
1445 dist
::maybe_install_llvm_runtime(builder
, target_compiler
.host
, &sysroot
);
1446 dist
::maybe_install_llvm_target(builder
, target_compiler
.host
, &sysroot
);
1448 // Link the compiler binary itself into place
1449 let out_dir
= builder
.cargo_out(build_compiler
, Mode
::Rustc
, host
);
1450 let rustc
= out_dir
.join(exe("rustc-main", host
));
1451 let bindir
= sysroot
.join("bin");
1452 t
!(fs
::create_dir_all(&bindir
));
1453 let compiler
= builder
.rustc(target_compiler
);
1454 builder
.copy(&rustc
, &compiler
);
1460 /// Link some files into a rustc sysroot.
1462 /// For a particular stage this will link the file listed in `stamp` into the
1463 /// `sysroot_dst` provided.
1464 pub fn add_to_sysroot(
1465 builder
: &Builder
<'_
>,
1467 sysroot_host_dst
: &Path
,
1470 let self_contained_dst
= &sysroot_dst
.join("self-contained");
1471 t
!(fs
::create_dir_all(&sysroot_dst
));
1472 t
!(fs
::create_dir_all(&sysroot_host_dst
));
1473 t
!(fs
::create_dir_all(&self_contained_dst
));
1474 for (path
, dependency_type
) in builder
.read_stamp_file(stamp
) {
1475 let dst
= match dependency_type
{
1476 DependencyType
::Host
=> sysroot_host_dst
,
1477 DependencyType
::Target
=> sysroot_dst
,
1478 DependencyType
::TargetSelfContained
=> self_contained_dst
,
1480 builder
.copy(&path
, &dst
.join(path
.file_name().unwrap()));
1485 builder
: &Builder
<'_
>,
1487 tail_args
: Vec
<String
>,
1489 additional_target_deps
: Vec
<(PathBuf
, DependencyType
)>,
1491 rlib_only_metadata
: bool
,
1493 if builder
.config
.dry_run() {
1497 // `target_root_dir` looks like $dir/$target/release
1498 let target_root_dir
= stamp
.parent().unwrap();
1499 // `target_deps_dir` looks like $dir/$target/release/deps
1500 let target_deps_dir
= target_root_dir
.join("deps");
1501 // `host_root_dir` looks like $dir/release
1502 let host_root_dir
= target_root_dir
1504 .unwrap() // chop off `release`
1506 .unwrap() // chop off `$target`
1507 .join(target_root_dir
.file_name().unwrap());
1509 // Spawn Cargo slurping up its JSON output. We'll start building up the
1510 // `deps` array of all files it generated along with a `toplevel` array of
1511 // files we need to probe for later.
1512 let mut deps
= Vec
::new();
1513 let mut toplevel
= Vec
::new();
1514 let ok
= stream_cargo(builder
, cargo
, tail_args
, &mut |msg
| {
1515 let (filenames
, crate_types
) = match msg
{
1516 CargoMessage
::CompilerArtifact
{
1518 target
: CargoTarget { crate_types }
,
1520 } => (filenames
, crate_types
),
1523 for filename
in filenames
{
1524 // Skip files like executables
1525 let mut keep
= false;
1526 if filename
.ends_with(".lib")
1527 || filename
.ends_with(".a")
1528 || is_debug_info(&filename
)
1529 || is_dylib(&filename
)
1531 // Always keep native libraries, rust dylibs and debuginfo
1534 if is_check
&& filename
.ends_with(".rmeta") {
1535 // During check builds we need to keep crate metadata
1537 } else if rlib_only_metadata
{
1538 if filename
.contains("jemalloc_sys") || filename
.contains("rustc_smir") {
1539 // jemalloc_sys and rustc_smir are not linked into librustc_driver.so,
1540 // so we need to distribute them as rlib to be able to use them.
1541 keep
|= filename
.ends_with(".rlib");
1543 // Distribute the rest of the rustc crates as rmeta files only to reduce
1544 // the tarball sizes by about 50%. The object files are linked into
1545 // librustc_driver.so, so it is still possible to link against them.
1546 keep
|= filename
.ends_with(".rmeta");
1549 // In all other cases keep all rlibs
1550 keep
|= filename
.ends_with(".rlib");
1557 let filename
= Path
::new(&*filename
);
1559 // If this was an output file in the "host dir" we don't actually
1560 // worry about it, it's not relevant for us
1561 if filename
.starts_with(&host_root_dir
) {
1562 // Unless it's a proc macro used in the compiler
1563 if crate_types
.iter().any(|t
| t
== "proc-macro") {
1564 deps
.push((filename
.to_path_buf(), DependencyType
::Host
));
1569 // If this was output in the `deps` dir then this is a precise file
1570 // name (hash included) so we start tracking it.
1571 if filename
.starts_with(&target_deps_dir
) {
1572 deps
.push((filename
.to_path_buf(), DependencyType
::Target
));
1576 // Otherwise this was a "top level artifact" which right now doesn't
1577 // have a hash in the name, but there's a version of this file in
1578 // the `deps` folder which *does* have a hash in the name. That's
1579 // the one we'll want to we'll probe for it later.
1581 // We do not use `Path::file_stem` or `Path::extension` here,
1582 // because some generated files may have multiple extensions e.g.
1583 // `std-<hash>.dll.lib` on Windows. The aforementioned methods only
1584 // split the file name by the last extension (`.lib`) while we need
1585 // to split by all extensions (`.dll.lib`).
1586 let expected_len
= t
!(filename
.metadata()).len();
1587 let filename
= filename
.file_name().unwrap().to_str().unwrap();
1588 let mut parts
= filename
.splitn(2, '
.'
);
1589 let file_stem
= parts
.next().unwrap().to_owned();
1590 let extension
= parts
.next().unwrap().to_owned();
1592 toplevel
.push((file_stem
, extension
, expected_len
));
1597 crate::detail_exit(1);
1600 // Ok now we need to actually find all the files listed in `toplevel`. We've
1601 // got a list of prefix/extensions and we basically just need to find the
1602 // most recent file in the `deps` folder corresponding to each one.
1603 let contents
= t
!(target_deps_dir
.read_dir())
1605 .map(|e
| (e
.path(), e
.file_name().into_string().unwrap(), t
!(e
.metadata())))
1606 .collect
::<Vec
<_
>>();
1607 for (prefix
, extension
, expected_len
) in toplevel
{
1608 let candidates
= contents
.iter().filter(|&&(_
, ref filename
, ref meta
)| {
1609 meta
.len() == expected_len
1611 .strip_prefix(&prefix
[..])
1612 .map(|s
| s
.starts_with('
-'
) && s
.ends_with(&extension
[..]))
1615 let max
= candidates
.max_by_key(|&&(_
, _
, ref metadata
)| {
1616 metadata
.modified().expect("mtime should be available on all relevant OSes")
1618 let path_to_add
= match max
{
1619 Some(triple
) => triple
.0.to_str().unwrap(),
1620 None
=> panic
!("no output generated for {:?} {:?}", prefix
, extension
),
1622 if is_dylib(path_to_add
) {
1623 let candidate
= format
!("{}.lib", path_to_add
);
1624 let candidate
= PathBuf
::from(candidate
);
1625 if candidate
.exists() {
1626 deps
.push((candidate
, DependencyType
::Target
));
1629 deps
.push((path_to_add
.into(), DependencyType
::Target
));
1632 deps
.extend(additional_target_deps
);
1634 let mut new_contents
= Vec
::new();
1635 for (dep
, dependency_type
) in deps
.iter() {
1636 new_contents
.extend(match *dependency_type
{
1637 DependencyType
::Host
=> b
"h",
1638 DependencyType
::Target
=> b
"t",
1639 DependencyType
::TargetSelfContained
=> b
"s",
1641 new_contents
.extend(dep
.to_str().unwrap().as_bytes());
1642 new_contents
.extend(b
"\0");
1644 t
!(fs
::write(&stamp
, &new_contents
));
1645 deps
.into_iter().map(|(d
, _
)| d
).collect()
1648 pub fn stream_cargo(
1649 builder
: &Builder
<'_
>,
1651 tail_args
: Vec
<String
>,
1652 cb
: &mut dyn FnMut(CargoMessage
<'_
>),
1654 let mut cargo
= Command
::from(cargo
);
1655 if builder
.config
.dry_run() {
1658 // Instruct Cargo to give us json messages on stdout, critically leaving
1659 // stderr as piped so we can get those pretty colors.
1660 let mut message_format
= if builder
.config
.json_output
{
1661 String
::from("json")
1663 String
::from("json-render-diagnostics")
1665 if let Some(s
) = &builder
.config
.rustc_error_format
{
1666 message_format
.push_str(",json-diagnostic-");
1667 message_format
.push_str(s
);
1669 cargo
.arg("--message-format").arg(message_format
).stdout(Stdio
::piped());
1671 for arg
in tail_args
{
1675 builder
.verbose(&format
!("running: {:?}", cargo
));
1676 let mut child
= match cargo
.spawn() {
1678 Err(e
) => panic
!("failed to execute command: {:?}\nerror: {}", cargo
, e
),
1681 // Spawn Cargo slurping up its JSON output. We'll start building up the
1682 // `deps` array of all files it generated along with a `toplevel` array of
1683 // files we need to probe for later.
1684 let stdout
= BufReader
::new(child
.stdout
.take().unwrap());
1685 for line
in stdout
.lines() {
1686 let line
= t
!(line
);
1687 match serde_json
::from_str
::<CargoMessage
<'_
>>(&line
) {
1689 if builder
.config
.json_output
{
1690 // Forward JSON to stdout.
1691 println
!("{}", line
);
1695 // If this was informational, just print it out and continue
1696 Err(_
) => println
!("{}", line
),
1700 // Make sure Cargo actually succeeded after we read all of its stdout.
1701 let status
= t
!(child
.wait());
1702 if builder
.is_verbose() && !status
.success() {
1704 "command did not execute successfully: {:?}\n\
1705 expected success, got: {}",
1712 #[derive(Deserialize)]
1713 pub struct CargoTarget
<'a
> {
1714 crate_types
: Vec
<Cow
<'a
, str>>,
1717 #[derive(Deserialize)]
1718 #[serde(tag = "reason", rename_all = "kebab-case")]
1719 pub enum CargoMessage
<'a
> {
1721 package_id
: Cow
<'a
, str>,
1722 features
: Vec
<Cow
<'a
, str>>,
1723 filenames
: Vec
<Cow
<'a
, str>>,
1724 target
: CargoTarget
<'a
>,
1726 BuildScriptExecuted
{
1727 package_id
: Cow
<'a
, str>,