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 compiler the standard library, libtest, and
6 //! compiler. This module is also responsible for assembling the sysroot as it
7 //! goes along from the output of the previous stage.
12 use std
::io
::prelude
::*;
13 use std
::io
::BufReader
;
14 use std
::path
::{Path, PathBuf}
;
15 use std
::process
::{exit, Command, Stdio}
;
18 use build_helper
::{output, t, up_to_date}
;
19 use filetime
::FileTime
;
20 use serde
::Deserialize
;
22 use crate::builder
::Cargo
;
23 use crate::builder
::{Builder, Kind, RunConfig, ShouldRun, Step}
;
24 use crate::cache
::{Interned, INTERNER}
;
25 use crate::config
::TargetSelection
;
28 use crate::tool
::SourceType
;
29 use crate::util
::{exe, is_dylib, symlink_dir}
;
30 use crate::{Compiler, DependencyType, GitRepo, Mode}
;
32 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
34 pub target
: TargetSelection
,
35 pub compiler
: Compiler
,
40 const DEFAULT
: bool
= true;
42 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
43 run
.all_krates("test")
46 fn make_run(run
: RunConfig
<'_
>) {
47 run
.builder
.ensure(Std
{
48 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.host
),
53 /// Builds the standard library.
55 /// This will build the standard library for a particular stage of the build
56 /// using the `compiler` targeting the `target` architecture. The artifacts
57 /// created will also be linked into the sysroot directory.
58 fn run(self, builder
: &Builder
<'_
>) {
59 let target
= self.target
;
60 let compiler
= self.compiler
;
62 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
63 builder
.info("Warning: Using a potentially old libstd. This may not behave well.");
64 builder
.ensure(StdLink { compiler, target_compiler: compiler, target }
);
68 let mut target_deps
= builder
.ensure(StartupObjects { compiler, target }
);
70 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
71 if compiler_to_use
!= compiler
{
72 builder
.ensure(Std { compiler: compiler_to_use, target }
);
73 builder
.info(&format
!("Uplifting stage1 std ({} -> {})", compiler_to_use
.host
, target
));
75 // Even if we're not building std this stage, the new sysroot must
76 // still contain the third party objects needed by various targets.
77 copy_third_party_objects(builder
, &compiler
, target
);
78 copy_self_contained_objects(builder
, &compiler
, target
);
80 builder
.ensure(StdLink
{
81 compiler
: compiler_to_use
,
82 target_compiler
: compiler
,
88 target_deps
.extend(copy_third_party_objects(builder
, &compiler
, target
));
89 target_deps
.extend(copy_self_contained_objects(builder
, &compiler
, target
));
91 let mut cargo
= builder
.cargo(compiler
, Mode
::Std
, SourceType
::InTree
, target
, "build");
92 std_cargo(builder
, target
, compiler
.stage
, &mut cargo
);
94 builder
.info(&format
!(
95 "Building stage{} std artifacts ({} -> {})",
96 compiler
.stage
, &compiler
.host
, target
102 &libstd_stamp(builder
, compiler
, target
),
107 builder
.ensure(StdLink
{
108 compiler
: builder
.compiler(compiler
.stage
, builder
.config
.build
),
109 target_compiler
: compiler
,
116 builder
: &Builder
<'_
>,
120 target_deps
: &mut Vec
<(PathBuf
, DependencyType
)>,
121 dependency_type
: DependencyType
,
123 let target
= libdir
.join(name
);
124 builder
.copy(&sourcedir
.join(name
), &target
);
126 target_deps
.push((target
, dependency_type
));
129 /// Copies third party objects needed by various targets.
130 fn copy_third_party_objects(
131 builder
: &Builder
<'_
>,
133 target
: TargetSelection
,
134 ) -> Vec
<(PathBuf
, DependencyType
)> {
135 let mut target_deps
= vec
![];
137 // FIXME: remove this in 2021
138 if target
== "x86_64-fortanix-unknown-sgx" {
139 if env
::var_os("X86_FORTANIX_SGX_LIBS").is_some() {
140 builder
.info("Warning: X86_FORTANIX_SGX_LIBS environment variable is ignored, libunwind is now compiled as part of rustbuild");
144 if builder
.config
.sanitizers
&& compiler
.stage
!= 0 {
145 // The sanitizers are only copied in stage1 or above,
146 // to avoid creating dependency on LLVM.
148 copy_sanitizers(builder
, &compiler
, target
)
150 .map(|d
| (d
, DependencyType
::Target
)),
157 /// Copies third party objects needed by various targets for self-contained linkage.
158 fn copy_self_contained_objects(
159 builder
: &Builder
<'_
>,
161 target
: TargetSelection
,
162 ) -> Vec
<(PathBuf
, DependencyType
)> {
163 let libdir_self_contained
= builder
.sysroot_libdir(*compiler
, target
).join("self-contained");
164 t
!(fs
::create_dir_all(&libdir_self_contained
));
165 let mut target_deps
= vec
![];
167 // Copies the CRT objects.
169 // rustc historically provides a more self-contained installation for musl targets
170 // not requiring the presence of a native musl toolchain. For example, it can fall back
171 // to using gcc from a glibc-targeting toolchain for linking.
172 // To do that we have to distribute musl startup objects as a part of Rust toolchain
173 // and link with them manually in the self-contained mode.
174 if target
.contains("musl") {
175 let srcdir
= builder
.musl_libdir(target
).unwrap();
176 for &obj
in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
179 &libdir_self_contained
,
183 DependencyType
::TargetSelfContained
,
186 } else if target
.ends_with("-wasi") {
187 let srcdir
= builder
.wasi_root(target
).unwrap().join("lib/wasm32-wasi");
190 &libdir_self_contained
,
194 DependencyType
::TargetSelfContained
,
196 } else if target
.contains("windows-gnu") {
197 for obj
in ["crt2.o", "dllcrt2.o"].iter() {
198 let src
= compiler_file(builder
, builder
.cc(target
), target
, obj
);
199 let target
= libdir_self_contained
.join(obj
);
200 builder
.copy(&src
, &target
);
201 target_deps
.push((target
, DependencyType
::TargetSelfContained
));
208 /// Configure cargo to compile the standard library, adding appropriate env vars
210 pub fn std_cargo(builder
: &Builder
<'_
>, target
: TargetSelection
, stage
: u32, cargo
: &mut Cargo
) {
211 if let Some(target
) = env
::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
212 cargo
.env("MACOSX_DEPLOYMENT_TARGET", target
);
215 // Determine if we're going to compile in optimized C intrinsics to
216 // the `compiler-builtins` crate. These intrinsics live in LLVM's
217 // `compiler-rt` repository, but our `src/llvm-project` submodule isn't
218 // always checked out, so we need to conditionally look for this. (e.g. if
219 // an external LLVM is used we skip the LLVM submodule checkout).
221 // Note that this shouldn't affect the correctness of `compiler-builtins`,
222 // but only its speed. Some intrinsics in C haven't been translated to Rust
223 // yet but that's pretty rare. Other intrinsics have optimized
224 // implementations in C which have only had slower versions ported to Rust,
225 // so we favor the C version where we can, but it's not critical.
227 // If `compiler-rt` is available ensure that the `c` feature of the
228 // `compiler-builtins` crate is enabled and it's configured to learn where
229 // `compiler-rt` is located.
230 let compiler_builtins_root
= builder
.src
.join("src/llvm-project/compiler-rt");
231 let compiler_builtins_c_feature
= if compiler_builtins_root
.exists() {
232 // Note that `libprofiler_builtins/build.rs` also computes this so if
233 // you're changing something here please also change that.
234 cargo
.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root
);
235 " compiler-builtins-c".to_string()
240 if builder
.no_std(target
) == Some(true) {
241 let mut features
= "compiler-builtins-mem".to_string();
242 features
.push_str(&compiler_builtins_c_feature
);
244 // for no-std targets we only compile a few no_std crates
246 .args(&["-p", "alloc"])
247 .arg("--manifest-path")
248 .arg(builder
.src
.join("library/alloc/Cargo.toml"))
250 .arg("compiler-builtins-mem compiler-builtins-c");
252 let mut features
= builder
.std_features();
253 features
.push_str(&compiler_builtins_c_feature
);
258 .arg("--manifest-path")
259 .arg(builder
.src
.join("library/test/Cargo.toml"));
261 // Help the libc crate compile by assisting it in finding various
262 // sysroot native libraries.
263 if target
.contains("musl") {
264 if let Some(p
) = builder
.musl_libdir(target
) {
265 let root
= format
!("native={}", p
.to_str().unwrap());
266 cargo
.rustflag("-L").rustflag(&root
);
270 if target
.ends_with("-wasi") {
271 if let Some(p
) = builder
.wasi_root(target
) {
272 let root
= format
!("native={}/lib/wasm32-wasi", p
.to_str().unwrap());
273 cargo
.rustflag("-L").rustflag(&root
);
278 // By default, rustc uses `-Cembed-bitcode=yes`, and Cargo overrides that
279 // with `-Cembed-bitcode=no` for non-LTO builds. However, libstd must be
280 // built with bitcode so that the produced rlibs can be used for both LTO
281 // builds (which use bitcode) and non-LTO builds (which use object code).
282 // So we override the override here!
284 // But we don't bother for the stage 0 compiler because it's never used
287 cargo
.rustflag("-Cembed-bitcode=yes");
290 // By default, rustc does not include unwind tables unless they are required
291 // for a particular target. They are not required by RISC-V targets, but
292 // compiling the standard library with them means that users can get
293 // backtraces without having to recompile the standard library themselves.
295 // This choice was discussed in https://github.com/rust-lang/rust/pull/69890
296 if target
.contains("riscv") {
297 cargo
.rustflag("-Cforce-unwind-tables=yes");
301 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
303 pub compiler
: Compiler
,
304 pub target_compiler
: Compiler
,
305 pub target
: TargetSelection
,
308 impl Step
for StdLink
{
311 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
315 /// Link all libstd rlibs/dylibs into the sysroot location.
317 /// Links those artifacts generated by `compiler` to the `stage` compiler's
318 /// sysroot for the specified `host` and `target`.
320 /// Note that this assumes that `compiler` has already generated the libstd
321 /// libraries for `target`, and this method will find them in the relevant
322 /// output directory.
323 fn run(self, builder
: &Builder
<'_
>) {
324 let compiler
= self.compiler
;
325 let target_compiler
= self.target_compiler
;
326 let target
= self.target
;
327 builder
.info(&format
!(
328 "Copying stage{} std from stage{} ({} -> {} / {})",
329 target_compiler
.stage
, compiler
.stage
, &compiler
.host
, target_compiler
.host
, target
331 let libdir
= builder
.sysroot_libdir(target_compiler
, target
);
332 let hostdir
= builder
.sysroot_libdir(target_compiler
, compiler
.host
);
333 add_to_sysroot(builder
, &libdir
, &hostdir
, &libstd_stamp(builder
, compiler
, target
));
337 /// Copies sanitizer runtime libraries into target libdir.
339 builder
: &Builder
<'_
>,
341 target
: TargetSelection
,
343 let runtimes
: Vec
<native
::SanitizerRuntime
> = builder
.ensure(native
::Sanitizers { target }
);
345 if builder
.config
.dry_run
{
349 let mut target_deps
= Vec
::new();
350 let libdir
= builder
.sysroot_libdir(*compiler
, target
);
352 for runtime
in &runtimes
{
353 let dst
= libdir
.join(&runtime
.name
);
354 builder
.copy(&runtime
.path
, &dst
);
356 if target
== "x86_64-apple-darwin" {
357 // Update the library install name reflect the fact it has been renamed.
358 let status
= Command
::new("install_name_tool")
360 .arg(format
!("@rpath/{}", runtime
.name
))
363 .expect("failed to execute `install_name_tool`");
364 assert
!(status
.success());
367 target_deps
.push(dst
);
373 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
374 pub struct StartupObjects
{
375 pub compiler
: Compiler
,
376 pub target
: TargetSelection
,
379 impl Step
for StartupObjects
{
380 type Output
= Vec
<(PathBuf
, DependencyType
)>;
382 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
383 run
.path("library/rtstartup")
386 fn make_run(run
: RunConfig
<'_
>) {
387 run
.builder
.ensure(StartupObjects
{
388 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.host
),
393 /// Builds and prepare startup objects like rsbegin.o and rsend.o
395 /// These are primarily used on Windows right now for linking executables/dlls.
396 /// They don't require any library support as they're just plain old object
397 /// files, so we just use the nightly snapshot compiler to always build them (as
398 /// no other compilers are guaranteed to be available).
399 fn run(self, builder
: &Builder
<'_
>) -> Vec
<(PathBuf
, DependencyType
)> {
400 let for_compiler
= self.compiler
;
401 let target
= self.target
;
402 if !target
.contains("windows-gnu") {
406 let mut target_deps
= vec
![];
408 let src_dir
= &builder
.src
.join("library").join("rtstartup");
409 let dst_dir
= &builder
.native_dir(target
).join("rtstartup");
410 let sysroot_dir
= &builder
.sysroot_libdir(for_compiler
, target
);
411 t
!(fs
::create_dir_all(dst_dir
));
413 for file
in &["rsbegin", "rsend"] {
414 let src_file
= &src_dir
.join(file
.to_string() + ".rs");
415 let dst_file
= &dst_dir
.join(file
.to_string() + ".o");
416 if !up_to_date(src_file
, dst_file
) {
417 let mut cmd
= Command
::new(&builder
.initial_rustc
);
419 cmd
.env("RUSTC_BOOTSTRAP", "1")
423 .arg(target
.rustc_target_arg())
431 let target
= sysroot_dir
.join((*file
).to_string() + ".o");
432 builder
.copy(dst_file
, &target
);
433 target_deps
.push((target
, DependencyType
::Target
));
440 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
442 pub target
: TargetSelection
,
443 pub compiler
: Compiler
,
446 impl Step
for Rustc
{
448 const ONLY_HOSTS
: bool
= true;
449 const DEFAULT
: bool
= false;
451 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
452 run
.path("src/rustc")
455 fn make_run(run
: RunConfig
<'_
>) {
456 run
.builder
.ensure(Rustc
{
457 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.host
),
462 /// Builds the compiler.
464 /// This will build the compiler for a particular stage of the build using
465 /// the `compiler` targeting the `target` architecture. The artifacts
466 /// created will also be linked into the sysroot directory.
467 fn run(self, builder
: &Builder
<'_
>) {
468 let compiler
= self.compiler
;
469 let target
= self.target
;
471 builder
.ensure(Std { compiler, target }
);
473 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
474 builder
.info("Warning: Using a potentially old librustc. This may not behave well.");
475 builder
.ensure(RustcLink { compiler, target_compiler: compiler, target }
);
479 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
480 if compiler_to_use
!= compiler
{
481 builder
.ensure(Rustc { compiler: compiler_to_use, target }
);
483 .info(&format
!("Uplifting stage1 rustc ({} -> {})", builder
.config
.build
, target
));
484 builder
.ensure(RustcLink
{
485 compiler
: compiler_to_use
,
486 target_compiler
: compiler
,
492 // Ensure that build scripts and proc macros have a std / libproc_macro to link against.
494 compiler
: builder
.compiler(self.compiler
.stage
, builder
.config
.build
),
495 target
: builder
.config
.build
,
498 let mut cargo
= builder
.cargo(compiler
, Mode
::Rustc
, SourceType
::InTree
, target
, "build");
499 rustc_cargo(builder
, &mut cargo
, target
);
501 builder
.info(&format
!(
502 "Building stage{} compiler artifacts ({} -> {})",
503 compiler
.stage
, &compiler
.host
, target
509 &librustc_stamp(builder
, compiler
, target
),
514 builder
.ensure(RustcLink
{
515 compiler
: builder
.compiler(compiler
.stage
, builder
.config
.build
),
516 target_compiler
: compiler
,
522 pub fn rustc_cargo(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: TargetSelection
) {
525 .arg(builder
.rustc_features())
526 .arg("--manifest-path")
527 .arg(builder
.src
.join("src/rustc/Cargo.toml"));
528 rustc_cargo_env(builder
, cargo
, target
);
531 pub fn rustc_cargo_env(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: TargetSelection
) {
532 // Set some configuration variables picked up by build scripts and
533 // the compiler alike
535 .env("CFG_RELEASE", builder
.rust_release())
536 .env("CFG_RELEASE_CHANNEL", &builder
.config
.channel
)
537 .env("CFG_VERSION", builder
.rust_version())
538 .env("CFG_PREFIX", builder
.config
.prefix
.clone().unwrap_or_default());
540 let libdir_relative
= builder
.config
.libdir_relative().unwrap_or_else(|| Path
::new("lib"));
541 cargo
.env("CFG_LIBDIR_RELATIVE", libdir_relative
);
543 if let Some(ref ver_date
) = builder
.rust_info
.commit_date() {
544 cargo
.env("CFG_VER_DATE", ver_date
);
546 if let Some(ref ver_hash
) = builder
.rust_info
.sha() {
547 cargo
.env("CFG_VER_HASH", ver_hash
);
549 if !builder
.unstable_features() {
550 cargo
.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
552 if let Some(ref s
) = builder
.config
.rustc_default_linker
{
553 cargo
.env("CFG_DEFAULT_LINKER", s
);
555 if builder
.config
.rustc_parallel
{
556 cargo
.rustflag("--cfg=parallel_compiler");
558 if builder
.config
.rust_verify_llvm_ir
{
559 cargo
.env("RUSTC_VERIFY_LLVM_IR", "1");
562 // Pass down configuration from the LLVM build into the build of
563 // librustc_llvm and librustc_codegen_llvm.
565 // Note that this is disabled if LLVM itself is disabled or we're in a check
566 // build. If we are in a check build we still go ahead here presuming we've
567 // detected that LLVM is alreay built and good to go which helps prevent
568 // busting caches (e.g. like #71152).
569 if builder
.config
.llvm_enabled()
570 && (builder
.kind
!= Kind
::Check
571 || crate::native
::prebuilt_llvm_config(builder
, target
).is_ok())
573 if builder
.is_rust_llvm(target
) {
574 cargo
.env("LLVM_RUSTLLVM", "1");
576 let llvm_config
= builder
.ensure(native
::Llvm { target }
);
577 cargo
.env("LLVM_CONFIG", &llvm_config
);
578 let target_config
= builder
.config
.target_config
.get(&target
);
579 if let Some(s
) = target_config
.and_then(|c
| c
.llvm_config
.as_ref()) {
580 cargo
.env("CFG_LLVM_ROOT", s
);
582 // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm.
583 if let Some(ref s
) = builder
.config
.llvm_ldflags
{
584 cargo
.env("LLVM_LINKER_FLAGS", s
);
586 // Building with a static libstdc++ is only supported on linux right now,
587 // not for MSVC or macOS
588 if builder
.config
.llvm_static_stdcpp
589 && !target
.contains("freebsd")
590 && !target
.contains("msvc")
591 && !target
.contains("apple")
593 let file
= compiler_file(builder
, builder
.cxx(target
).unwrap(), target
, "libstdc++.a");
594 cargo
.env("LLVM_STATIC_STDCPP", file
);
596 if builder
.config
.llvm_link_shared
|| builder
.config
.llvm_thin_lto
{
597 cargo
.env("LLVM_LINK_SHARED", "1");
599 if builder
.config
.llvm_use_libcxx
{
600 cargo
.env("LLVM_USE_LIBCXX", "1");
602 if builder
.config
.llvm_optimize
&& !builder
.config
.llvm_release_debuginfo
{
603 cargo
.env("LLVM_NDEBUG", "1");
608 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
610 pub compiler
: Compiler
,
611 pub target_compiler
: Compiler
,
612 pub target
: TargetSelection
,
615 impl Step
for RustcLink
{
618 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
622 /// Same as `std_link`, only for librustc
623 fn run(self, builder
: &Builder
<'_
>) {
624 let compiler
= self.compiler
;
625 let target_compiler
= self.target_compiler
;
626 let target
= self.target
;
627 builder
.info(&format
!(
628 "Copying stage{} rustc from stage{} ({} -> {} / {})",
629 target_compiler
.stage
, compiler
.stage
, &compiler
.host
, target_compiler
.host
, target
633 &builder
.sysroot_libdir(target_compiler
, target
),
634 &builder
.sysroot_libdir(target_compiler
, compiler
.host
),
635 &librustc_stamp(builder
, compiler
, target
),
640 /// Cargo's output path for the standard library in a given stage, compiled
641 /// by a particular compiler for the specified target.
642 pub fn libstd_stamp(builder
: &Builder
<'_
>, compiler
: Compiler
, target
: TargetSelection
) -> PathBuf
{
643 builder
.cargo_out(compiler
, Mode
::Std
, target
).join(".libstd.stamp")
646 /// Cargo's output path for librustc in a given stage, compiled by a particular
647 /// compiler for the specified target.
648 pub fn librustc_stamp(
649 builder
: &Builder
<'_
>,
651 target
: TargetSelection
,
653 builder
.cargo_out(compiler
, Mode
::Rustc
, target
).join(".librustc.stamp")
656 pub fn compiler_file(
657 builder
: &Builder
<'_
>,
659 target
: TargetSelection
,
662 let mut cmd
= Command
::new(compiler
);
663 cmd
.args(builder
.cflags(target
, GitRepo
::Rustc
));
664 cmd
.arg(format
!("-print-file-name={}", file
));
665 let out
= output(&mut cmd
);
666 PathBuf
::from(out
.trim())
669 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
671 pub compiler
: Compiler
,
674 impl Step
for Sysroot
{
675 type Output
= Interned
<PathBuf
>;
677 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
681 /// Returns the sysroot for the `compiler` specified that *this build system
684 /// That is, the sysroot for the stage0 compiler is not what the compiler
685 /// thinks it is by default, but it's the same as the default for stages
687 fn run(self, builder
: &Builder
<'_
>) -> Interned
<PathBuf
> {
688 let compiler
= self.compiler
;
689 let sysroot
= if compiler
.stage
== 0 {
690 builder
.out
.join(&compiler
.host
.triple
).join("stage0-sysroot")
692 builder
.out
.join(&compiler
.host
.triple
).join(format
!("stage{}", compiler
.stage
))
694 let _
= fs
::remove_dir_all(&sysroot
);
695 t
!(fs
::create_dir_all(&sysroot
));
697 // Symlink the source root into the same location inside the sysroot,
698 // where `rust-src` component would go (`$sysroot/lib/rustlib/src/rust`),
699 // so that any tools relying on `rust-src` also work for local builds,
700 // and also for translating the virtual `/rustc/$hash` back to the real
701 // directory (for running tests with `rust.remap-debuginfo = true`).
702 let sysroot_lib_rustlib_src
= sysroot
.join("lib/rustlib/src");
703 t
!(fs
::create_dir_all(&sysroot_lib_rustlib_src
));
704 let sysroot_lib_rustlib_src_rust
= sysroot_lib_rustlib_src
.join("rust");
705 if let Err(e
) = symlink_dir(&builder
.config
, &builder
.src
, &sysroot_lib_rustlib_src_rust
) {
707 "warning: creating symbolic link `{}` to `{}` failed with {}",
708 sysroot_lib_rustlib_src_rust
.display(),
709 builder
.src
.display(),
712 if builder
.config
.rust_remap_debuginfo
{
714 "warning: some `src/test/ui` tests will fail when lacking `{}`",
715 sysroot_lib_rustlib_src_rust
.display(),
720 INTERNER
.intern_path(sysroot
)
724 #[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
725 pub struct Assemble
{
726 /// The compiler which we will produce in this step. Assemble itself will
727 /// take care of ensuring that the necessary prerequisites to do so exist,
728 /// that is, this target can be a stage2 compiler and Assemble will build
729 /// previous stages for you.
730 pub target_compiler
: Compiler
,
733 impl Step
for Assemble
{
734 type Output
= Compiler
;
736 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
740 /// Prepare a new compiler from the artifacts in `stage`
742 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
743 /// must have been previously produced by the `stage - 1` builder.build
745 fn run(self, builder
: &Builder
<'_
>) -> Compiler
{
746 let target_compiler
= self.target_compiler
;
748 if target_compiler
.stage
== 0 {
750 builder
.config
.build
, target_compiler
.host
,
751 "Cannot obtain compiler for non-native build triple at stage 0"
753 // The stage 0 compiler for the build triple is always pre-built.
754 return target_compiler
;
757 // Get the compiler that we'll use to bootstrap ourselves.
759 // Note that this is where the recursive nature of the bootstrap
760 // happens, as this will request the previous stage's compiler on
761 // downwards to stage 0.
763 // Also note that we're building a compiler for the host platform. We
764 // only assume that we can run `build` artifacts, which means that to
765 // produce some other architecture compiler we need to start from
766 // `build` to get there.
768 // FIXME: Perhaps we should download those libraries?
769 // It would make builds faster...
771 // FIXME: It may be faster if we build just a stage 1 compiler and then
772 // use that to bootstrap this compiler forward.
773 let build_compiler
= builder
.compiler(target_compiler
.stage
- 1, builder
.config
.build
);
775 // Build the libraries for this compiler to link to (i.e., the libraries
776 // it uses at runtime). NOTE: Crates the target compiler compiles don't
777 // link to these. (FIXME: Is that correct? It seems to be correct most
778 // of the time but I think we do link to these for stage2/bin compilers
779 // when not performing a full bootstrap).
780 builder
.ensure(Rustc { compiler: build_compiler, target: target_compiler.host }
);
782 let lld_install
= if builder
.config
.lld_enabled
{
783 Some(builder
.ensure(native
::Lld { target: target_compiler.host }
))
788 let stage
= target_compiler
.stage
;
789 let host
= target_compiler
.host
;
790 builder
.info(&format
!("Assembling stage{} compiler ({})", stage
, host
));
792 // Link in all dylibs to the libdir
793 let sysroot
= builder
.sysroot(target_compiler
);
794 let rustc_libdir
= builder
.rustc_libdir(target_compiler
);
795 t
!(fs
::create_dir_all(&rustc_libdir
));
796 let src_libdir
= builder
.sysroot_libdir(build_compiler
, host
);
797 for f
in builder
.read_dir(&src_libdir
) {
798 let filename
= f
.file_name().into_string().unwrap();
799 if is_dylib(&filename
) {
800 builder
.copy(&f
.path(), &rustc_libdir
.join(&filename
));
804 let libdir
= builder
.sysroot_libdir(target_compiler
, target_compiler
.host
);
805 if let Some(lld_install
) = lld_install
{
806 let src_exe
= exe("lld", target_compiler
.host
);
807 let dst_exe
= exe("rust-lld", target_compiler
.host
);
808 // we prepend this bin directory to the user PATH when linking Rust binaries. To
809 // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
810 let dst
= libdir
.parent().unwrap().join("bin");
811 t
!(fs
::create_dir_all(&dst
));
812 builder
.copy(&lld_install
.join("bin").join(&src_exe
), &dst
.join(&dst_exe
));
815 // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
816 // so that it can be found when the newly built `rustc` is run.
817 dist
::maybe_install_llvm_runtime(builder
, target_compiler
.host
, &sysroot
);
818 dist
::maybe_install_llvm_target(builder
, target_compiler
.host
, &sysroot
);
820 // Link the compiler binary itself into place
821 let out_dir
= builder
.cargo_out(build_compiler
, Mode
::Rustc
, host
);
822 let rustc
= out_dir
.join(exe("rustc_binary", host
));
823 let bindir
= sysroot
.join("bin");
824 t
!(fs
::create_dir_all(&bindir
));
825 let compiler
= builder
.rustc(target_compiler
);
826 builder
.copy(&rustc
, &compiler
);
832 /// Link some files into a rustc sysroot.
834 /// For a particular stage this will link the file listed in `stamp` into the
835 /// `sysroot_dst` provided.
836 pub fn add_to_sysroot(
837 builder
: &Builder
<'_
>,
839 sysroot_host_dst
: &Path
,
842 let self_contained_dst
= &sysroot_dst
.join("self-contained");
843 t
!(fs
::create_dir_all(&sysroot_dst
));
844 t
!(fs
::create_dir_all(&sysroot_host_dst
));
845 t
!(fs
::create_dir_all(&self_contained_dst
));
846 for (path
, dependency_type
) in builder
.read_stamp_file(stamp
) {
847 let dst
= match dependency_type
{
848 DependencyType
::Host
=> sysroot_host_dst
,
849 DependencyType
::Target
=> sysroot_dst
,
850 DependencyType
::TargetSelfContained
=> self_contained_dst
,
852 builder
.copy(&path
, &dst
.join(path
.file_name().unwrap()));
857 builder
: &Builder
<'_
>,
859 tail_args
: Vec
<String
>,
861 additional_target_deps
: Vec
<(PathBuf
, DependencyType
)>,
864 if builder
.config
.dry_run
{
868 // `target_root_dir` looks like $dir/$target/release
869 let target_root_dir
= stamp
.parent().unwrap();
870 // `target_deps_dir` looks like $dir/$target/release/deps
871 let target_deps_dir
= target_root_dir
.join("deps");
872 // `host_root_dir` looks like $dir/release
873 let host_root_dir
= target_root_dir
875 .unwrap() // chop off `release`
877 .unwrap() // chop off `$target`
878 .join(target_root_dir
.file_name().unwrap());
880 // Spawn Cargo slurping up its JSON output. We'll start building up the
881 // `deps` array of all files it generated along with a `toplevel` array of
882 // files we need to probe for later.
883 let mut deps
= Vec
::new();
884 let mut toplevel
= Vec
::new();
885 let ok
= stream_cargo(builder
, cargo
, tail_args
, &mut |msg
| {
886 let (filenames
, crate_types
) = match msg
{
887 CargoMessage
::CompilerArtifact
{
889 target
: CargoTarget { crate_types }
,
891 } => (filenames
, crate_types
),
894 for filename
in filenames
{
895 // Skip files like executables
896 if !(filename
.ends_with(".rlib")
897 || filename
.ends_with(".lib")
898 || filename
.ends_with(".a")
899 || is_dylib(&filename
)
900 || (is_check
&& filename
.ends_with(".rmeta")))
905 let filename
= Path
::new(&*filename
);
907 // If this was an output file in the "host dir" we don't actually
908 // worry about it, it's not relevant for us
909 if filename
.starts_with(&host_root_dir
) {
910 // Unless it's a proc macro used in the compiler
911 if crate_types
.iter().any(|t
| t
== "proc-macro") {
912 deps
.push((filename
.to_path_buf(), DependencyType
::Host
));
917 // If this was output in the `deps` dir then this is a precise file
918 // name (hash included) so we start tracking it.
919 if filename
.starts_with(&target_deps_dir
) {
920 deps
.push((filename
.to_path_buf(), DependencyType
::Target
));
924 // Otherwise this was a "top level artifact" which right now doesn't
925 // have a hash in the name, but there's a version of this file in
926 // the `deps` folder which *does* have a hash in the name. That's
927 // the one we'll want to we'll probe for it later.
929 // We do not use `Path::file_stem` or `Path::extension` here,
930 // because some generated files may have multiple extensions e.g.
931 // `std-<hash>.dll.lib` on Windows. The aforementioned methods only
932 // split the file name by the last extension (`.lib`) while we need
933 // to split by all extensions (`.dll.lib`).
934 let expected_len
= t
!(filename
.metadata()).len();
935 let filename
= filename
.file_name().unwrap().to_str().unwrap();
936 let mut parts
= filename
.splitn(2, '
.'
);
937 let file_stem
= parts
.next().unwrap().to_owned();
938 let extension
= parts
.next().unwrap().to_owned();
940 toplevel
.push((file_stem
, extension
, expected_len
));
948 // Ok now we need to actually find all the files listed in `toplevel`. We've
949 // got a list of prefix/extensions and we basically just need to find the
950 // most recent file in the `deps` folder corresponding to each one.
951 let contents
= t
!(target_deps_dir
.read_dir())
953 .map(|e
| (e
.path(), e
.file_name().into_string().unwrap(), t
!(e
.metadata())))
954 .collect
::<Vec
<_
>>();
955 for (prefix
, extension
, expected_len
) in toplevel
{
956 let candidates
= contents
.iter().filter(|&&(_
, ref filename
, ref meta
)| {
957 meta
.len() == expected_len
959 .strip_prefix(&prefix
[..])
960 .map(|s
| s
.starts_with('
-'
) && s
.ends_with(&extension
[..]))
964 .max_by_key(|&&(_
, _
, ref metadata
)| FileTime
::from_last_modification_time(metadata
));
965 let path_to_add
= match max
{
966 Some(triple
) => triple
.0.to_str().unwrap(),
967 None
=> panic
!("no output generated for {:?} {:?}", prefix
, extension
),
969 if is_dylib(path_to_add
) {
970 let candidate
= format
!("{}.lib", path_to_add
);
971 let candidate
= PathBuf
::from(candidate
);
972 if candidate
.exists() {
973 deps
.push((candidate
, DependencyType
::Target
));
976 deps
.push((path_to_add
.into(), DependencyType
::Target
));
979 deps
.extend(additional_target_deps
);
981 let mut new_contents
= Vec
::new();
982 for (dep
, dependency_type
) in deps
.iter() {
983 new_contents
.extend(match *dependency_type
{
984 DependencyType
::Host
=> b
"h",
985 DependencyType
::Target
=> b
"t",
986 DependencyType
::TargetSelfContained
=> b
"s",
988 new_contents
.extend(dep
.to_str().unwrap().as_bytes());
989 new_contents
.extend(b
"\0");
991 t
!(fs
::write(&stamp
, &new_contents
));
992 deps
.into_iter().map(|(d
, _
)| d
).collect()
996 builder
: &Builder
<'_
>,
998 tail_args
: Vec
<String
>,
999 cb
: &mut dyn FnMut(CargoMessage
<'_
>),
1001 let mut cargo
= Command
::from(cargo
);
1002 if builder
.config
.dry_run
{
1005 // Instruct Cargo to give us json messages on stdout, critically leaving
1006 // stderr as piped so we can get those pretty colors.
1007 let mut message_format
= if builder
.config
.json_output
{
1008 String
::from("json")
1010 String
::from("json-render-diagnostics")
1012 if let Some(s
) = &builder
.config
.rustc_error_format
{
1013 message_format
.push_str(",json-diagnostic-");
1014 message_format
.push_str(s
);
1016 cargo
.arg("--message-format").arg(message_format
).stdout(Stdio
::piped());
1018 for arg
in tail_args
{
1022 builder
.verbose(&format
!("running: {:?}", cargo
));
1023 let mut child
= match cargo
.spawn() {
1025 Err(e
) => panic
!("failed to execute command: {:?}\nerror: {}", cargo
, e
),
1028 // Spawn Cargo slurping up its JSON output. We'll start building up the
1029 // `deps` array of all files it generated along with a `toplevel` array of
1030 // files we need to probe for later.
1031 let stdout
= BufReader
::new(child
.stdout
.take().unwrap());
1032 for line
in stdout
.lines() {
1033 let line
= t
!(line
);
1034 match serde_json
::from_str
::<CargoMessage
<'_
>>(&line
) {
1036 if builder
.config
.json_output
{
1037 // Forward JSON to stdout.
1038 println
!("{}", line
);
1042 // If this was informational, just print it out and continue
1043 Err(_
) => println
!("{}", line
),
1047 // Make sure Cargo actually succeeded after we read all of its stdout.
1048 let status
= t
!(child
.wait());
1049 if !status
.success() {
1051 "command did not execute successfully: {:?}\n\
1052 expected success, got: {}",
1059 #[derive(Deserialize)]
1060 pub struct CargoTarget
<'a
> {
1061 crate_types
: Vec
<Cow
<'a
, str>>,
1064 #[derive(Deserialize)]
1065 #[serde(tag = "reason", rename_all = "kebab-case")]
1066 pub enum CargoMessage
<'a
> {
1068 package_id
: Cow
<'a
, str>,
1069 features
: Vec
<Cow
<'a
, str>>,
1070 filenames
: Vec
<Cow
<'a
, str>>,
1071 target
: CargoTarget
<'a
>,
1073 BuildScriptExecuted
{
1074 package_id
: Cow
<'a
, str>,