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
;
25 use crate::util
::{exe, is_dylib}
;
26 use crate::{Compiler, GitRepo, Mode}
;
28 use crate::builder
::{Builder, Kind, RunConfig, ShouldRun, Step}
;
29 use crate::cache
::{Interned, INTERNER}
;
31 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
33 pub target
: Interned
<String
>,
34 pub compiler
: Compiler
,
39 const DEFAULT
: bool
= true;
41 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
42 run
.all_krates("test")
45 fn make_run(run
: RunConfig
<'_
>) {
46 run
.builder
.ensure(Std
{
47 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.host
),
52 /// Builds the standard library.
54 /// This will build the standard library for a particular stage of the build
55 /// using the `compiler` targeting the `target` architecture. The artifacts
56 /// created will also be linked into the sysroot directory.
57 fn run(self, builder
: &Builder
<'_
>) {
58 let target
= self.target
;
59 let compiler
= self.compiler
;
61 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
62 builder
.info("Warning: Using a potentially old libstd. This may not behave well.");
63 builder
.ensure(StdLink { compiler, target_compiler: compiler, target }
);
67 let mut target_deps
= builder
.ensure(StartupObjects { compiler, target }
);
69 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
70 if compiler_to_use
!= compiler
{
71 builder
.ensure(Std { compiler: compiler_to_use, target }
);
72 builder
.info(&format
!("Uplifting stage1 std ({} -> {})", compiler_to_use
.host
, target
));
74 // Even if we're not building std this stage, the new sysroot must
75 // still contain the third party objects needed by various targets.
76 copy_third_party_objects(builder
, &compiler
, target
);
78 builder
.ensure(StdLink
{
79 compiler
: compiler_to_use
,
80 target_compiler
: compiler
,
86 target_deps
.extend(copy_third_party_objects(builder
, &compiler
, target
).into_iter());
88 let mut cargo
= builder
.cargo(compiler
, Mode
::Std
, target
, "build");
89 std_cargo(builder
, target
, &mut cargo
);
91 builder
.info(&format
!(
92 "Building stage{} std artifacts ({} -> {})",
93 compiler
.stage
, &compiler
.host
, target
99 &libstd_stamp(builder
, compiler
, target
),
104 builder
.ensure(StdLink
{
105 compiler
: builder
.compiler(compiler
.stage
, builder
.config
.build
),
106 target_compiler
: compiler
,
112 /// Copies third party objects needed by various targets.
113 fn copy_third_party_objects(
114 builder
: &Builder
<'_
>,
116 target
: Interned
<String
>,
118 let libdir
= builder
.sysroot_libdir(*compiler
, target
);
120 let mut target_deps
= vec
![];
122 let mut copy_and_stamp
= |sourcedir
: &Path
, name
: &str| {
123 let target
= libdir
.join(name
);
124 builder
.copy(&sourcedir
.join(name
), &target
);
125 target_deps
.push(target
);
128 // Copies the crt(1,i,n).o startup objects
130 // Since musl supports fully static linking, we can cross link for it even
131 // with a glibc-targeting toolchain, given we have the appropriate startup
132 // files. As those shipped with glibc won't work, copy the ones provided by
133 // musl so we have them on linux-gnu hosts.
134 if target
.contains("musl") {
135 let srcdir
= builder
.musl_root(target
).unwrap().join("lib");
136 for &obj
in &["crt1.o", "crti.o", "crtn.o"] {
137 copy_and_stamp(&srcdir
, obj
);
139 } else if target
.ends_with("-wasi") {
140 let srcdir
= builder
.wasi_root(target
).unwrap().join("lib/wasm32-wasi");
141 copy_and_stamp(&srcdir
, "crt1.o");
144 // Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
146 // This target needs to be linked to Fortanix's port of llvm's libunwind.
147 // libunwind requires support for rwlock and printing to stderr,
148 // which is provided by std for this target.
149 if target
== "x86_64-fortanix-unknown-sgx" {
150 let src_path_env
= "X86_FORTANIX_SGX_LIBS";
152 env
::var(src_path_env
).unwrap_or_else(|_
| panic
!("{} not found in env", src_path_env
));
153 copy_and_stamp(Path
::new(&src
), "libunwind.a");
156 if builder
.config
.sanitizers
&& compiler
.stage
!= 0 {
157 // The sanitizers are only copied in stage1 or above,
158 // to avoid creating dependency on LLVM.
159 target_deps
.extend(copy_sanitizers(builder
, &compiler
, target
));
165 /// Configure cargo to compile the standard library, adding appropriate env vars
167 pub fn std_cargo(builder
: &Builder
<'_
>, target
: Interned
<String
>, cargo
: &mut Cargo
) {
168 if let Some(target
) = env
::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
169 cargo
.env("MACOSX_DEPLOYMENT_TARGET", target
);
172 // Determine if we're going to compile in optimized C intrinsics to
173 // the `compiler-builtins` crate. These intrinsics live in LLVM's
174 // `compiler-rt` repository, but our `src/llvm-project` submodule isn't
175 // always checked out, so we need to conditionally look for this. (e.g. if
176 // an external LLVM is used we skip the LLVM submodule checkout).
178 // Note that this shouldn't affect the correctness of `compiler-builtins`,
179 // but only its speed. Some intrinsics in C haven't been translated to Rust
180 // yet but that's pretty rare. Other intrinsics have optimized
181 // implementations in C which have only had slower versions ported to Rust,
182 // so we favor the C version where we can, but it's not critical.
184 // If `compiler-rt` is available ensure that the `c` feature of the
185 // `compiler-builtins` crate is enabled and it's configured to learn where
186 // `compiler-rt` is located.
187 let compiler_builtins_root
= builder
.src
.join("src/llvm-project/compiler-rt");
188 let compiler_builtins_c_feature
= if compiler_builtins_root
.exists() {
189 cargo
.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root
);
190 " compiler-builtins-c".to_string()
195 if builder
.no_std(target
) == Some(true) {
196 let mut features
= "compiler-builtins-mem".to_string();
197 features
.push_str(&compiler_builtins_c_feature
);
199 // for no-std targets we only compile a few no_std crates
201 .args(&["-p", "alloc"])
202 .arg("--manifest-path")
203 .arg(builder
.src
.join("src/liballoc/Cargo.toml"))
205 .arg("compiler-builtins-mem compiler-builtins-c");
207 let mut features
= builder
.std_features();
208 features
.push_str(&compiler_builtins_c_feature
);
213 .arg("--manifest-path")
214 .arg(builder
.src
.join("src/libtest/Cargo.toml"));
216 // Help the libc crate compile by assisting it in finding various
217 // sysroot native libraries.
218 if target
.contains("musl") {
219 if let Some(p
) = builder
.musl_root(target
) {
220 let root
= format
!("native={}/lib", p
.to_str().unwrap());
221 cargo
.rustflag("-L").rustflag(&root
);
225 if target
.ends_with("-wasi") {
226 if let Some(p
) = builder
.wasi_root(target
) {
227 let root
= format
!("native={}/lib/wasm32-wasi", p
.to_str().unwrap());
228 cargo
.rustflag("-L").rustflag(&root
);
234 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
236 pub compiler
: Compiler
,
237 pub target_compiler
: Compiler
,
238 pub target
: Interned
<String
>,
241 impl Step
for StdLink
{
244 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
248 /// Link all libstd rlibs/dylibs into the sysroot location.
250 /// Links those artifacts generated by `compiler` to the `stage` compiler's
251 /// sysroot for the specified `host` and `target`.
253 /// Note that this assumes that `compiler` has already generated the libstd
254 /// libraries for `target`, and this method will find them in the relevant
255 /// output directory.
256 fn run(self, builder
: &Builder
<'_
>) {
257 let compiler
= self.compiler
;
258 let target_compiler
= self.target_compiler
;
259 let target
= self.target
;
260 builder
.info(&format
!(
261 "Copying stage{} std from stage{} ({} -> {} / {})",
262 target_compiler
.stage
, compiler
.stage
, &compiler
.host
, target_compiler
.host
, target
264 let libdir
= builder
.sysroot_libdir(target_compiler
, target
);
265 let hostdir
= builder
.sysroot_libdir(target_compiler
, compiler
.host
);
266 add_to_sysroot(builder
, &libdir
, &hostdir
, &libstd_stamp(builder
, compiler
, target
));
270 /// Copies sanitizer runtime libraries into target libdir.
272 builder
: &Builder
<'_
>,
274 target
: Interned
<String
>,
276 let runtimes
: Vec
<native
::SanitizerRuntime
> = builder
.ensure(native
::Sanitizers { target }
);
278 if builder
.config
.dry_run
{
282 let mut target_deps
= Vec
::new();
283 let libdir
= builder
.sysroot_libdir(*compiler
, target
);
285 for runtime
in &runtimes
{
286 let dst
= libdir
.join(&runtime
.name
);
287 builder
.copy(&runtime
.path
, &dst
);
289 if target
== "x86_64-apple-darwin" {
290 // Update the library install name reflect the fact it has been renamed.
291 let status
= Command
::new("install_name_tool")
293 .arg(format
!("@rpath/{}", runtime
.name
))
296 .expect("failed to execute `install_name_tool`");
297 assert
!(status
.success());
300 target_deps
.push(dst
);
306 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
307 pub struct StartupObjects
{
308 pub compiler
: Compiler
,
309 pub target
: Interned
<String
>,
312 impl Step
for StartupObjects
{
313 type Output
= Vec
<PathBuf
>;
315 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
316 run
.path("src/rtstartup")
319 fn make_run(run
: RunConfig
<'_
>) {
320 run
.builder
.ensure(StartupObjects
{
321 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.host
),
326 /// Builds and prepare startup objects like rsbegin.o and rsend.o
328 /// These are primarily used on Windows right now for linking executables/dlls.
329 /// They don't require any library support as they're just plain old object
330 /// files, so we just use the nightly snapshot compiler to always build them (as
331 /// no other compilers are guaranteed to be available).
332 fn run(self, builder
: &Builder
<'_
>) -> Vec
<PathBuf
> {
333 let for_compiler
= self.compiler
;
334 let target
= self.target
;
335 if !target
.contains("windows-gnu") {
339 let mut target_deps
= vec
![];
341 let src_dir
= &builder
.src
.join("src/rtstartup");
342 let dst_dir
= &builder
.native_dir(target
).join("rtstartup");
343 let sysroot_dir
= &builder
.sysroot_libdir(for_compiler
, target
);
344 t
!(fs
::create_dir_all(dst_dir
));
346 for file
in &["rsbegin", "rsend"] {
347 let src_file
= &src_dir
.join(file
.to_string() + ".rs");
348 let dst_file
= &dst_dir
.join(file
.to_string() + ".o");
349 if !up_to_date(src_file
, dst_file
) {
350 let mut cmd
= Command
::new(&builder
.initial_rustc
);
352 cmd
.env("RUSTC_BOOTSTRAP", "1")
364 let target
= sysroot_dir
.join((*file
).to_string() + ".o");
365 builder
.copy(dst_file
, &target
);
366 target_deps
.push(target
);
369 for obj
in ["crt2.o", "dllcrt2.o"].iter() {
370 let src
= compiler_file(builder
, builder
.cc(target
), target
, obj
);
371 let target
= sysroot_dir
.join(obj
);
372 builder
.copy(&src
, &target
);
373 target_deps
.push(target
);
380 #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
382 pub target
: Interned
<String
>,
383 pub compiler
: Compiler
,
386 impl Step
for Rustc
{
388 const ONLY_HOSTS
: bool
= true;
389 const DEFAULT
: bool
= true;
391 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
392 run
.all_krates("rustc-main")
395 fn make_run(run
: RunConfig
<'_
>) {
396 run
.builder
.ensure(Rustc
{
397 compiler
: run
.builder
.compiler(run
.builder
.top_stage
, run
.host
),
402 /// Builds the compiler.
404 /// This will build the compiler for a particular stage of the build using
405 /// the `compiler` targeting the `target` architecture. The artifacts
406 /// created will also be linked into the sysroot directory.
407 fn run(self, builder
: &Builder
<'_
>) {
408 let compiler
= self.compiler
;
409 let target
= self.target
;
411 builder
.ensure(Std { compiler, target }
);
413 if builder
.config
.keep_stage
.contains(&compiler
.stage
) {
414 builder
.info("Warning: Using a potentially old librustc. This may not behave well.");
415 builder
.ensure(RustcLink { compiler, target_compiler: compiler, target }
);
419 let compiler_to_use
= builder
.compiler_for(compiler
.stage
, compiler
.host
, target
);
420 if compiler_to_use
!= compiler
{
421 builder
.ensure(Rustc { compiler: compiler_to_use, target }
);
423 .info(&format
!("Uplifting stage1 rustc ({} -> {})", builder
.config
.build
, target
));
424 builder
.ensure(RustcLink
{
425 compiler
: compiler_to_use
,
426 target_compiler
: compiler
,
432 // Ensure that build scripts and proc macros have a std / libproc_macro to link against.
434 compiler
: builder
.compiler(self.compiler
.stage
, builder
.config
.build
),
435 target
: builder
.config
.build
,
438 let mut cargo
= builder
.cargo(compiler
, Mode
::Rustc
, target
, "build");
439 rustc_cargo(builder
, &mut cargo
, target
);
441 builder
.info(&format
!(
442 "Building stage{} compiler artifacts ({} -> {})",
443 compiler
.stage
, &compiler
.host
, target
449 &librustc_stamp(builder
, compiler
, target
),
454 // We used to build librustc_codegen_llvm as a separate step,
455 // which produced a dylib that the compiler would dlopen() at runtime.
456 // This meant that we only needed to make sure that libLLVM.so was
457 // installed by the time we went to run a tool using it - since
458 // librustc_codegen_llvm was effectively a standalone artifact,
459 // other crates were completely oblivious to its dependency
460 // on `libLLVM.so` during build time.
462 // However, librustc_codegen_llvm is now built as an ordinary
463 // crate during the same step as the rest of the compiler crates.
464 // This means that any crates depending on it will see the fact
465 // that it uses `libLLVM.so` as a native library, and will
466 // cause us to pass `-llibLLVM.so` to the linker when we link
469 // For `rustc` itself, this works out fine.
470 // During the `Assemble` step, we call `dist::maybe_install_llvm_dylib`
471 // to copy libLLVM.so into the `stage` directory. We then link
472 // the compiler binary, which will find `libLLVM.so` in the correct place.
474 // However, this is insufficient for tools that are build against stage0
475 // (e.g. stage1 rustdoc). Since `Assemble` for stage0 doesn't actually do anything,
476 // we won't have `libLLVM.so` in the stage0 sysroot. In the past, this wasn't
477 // a problem - we would copy the tool binary into its correct stage directory
478 // (e.g. stage1 for a stage1 rustdoc built against a stage0 compiler).
479 // Since libLLVM.so wasn't resolved until runtime, it was fine for it to
480 // not exist while we were building it.
482 // To ensure that we can still build stage1 tools against a stage0 compiler,
483 // we explicitly copy libLLVM.so into the stage0 sysroot when building
484 // the stage0 compiler. This ensures that tools built against stage0
485 // will see libLLVM.so at build time, making the linker happy.
486 if compiler
.stage
== 0 {
487 builder
.info(&format
!("Installing libLLVM.so to stage 0 ({})", compiler
.host
));
488 let sysroot
= builder
.sysroot(compiler
);
489 dist
::maybe_install_llvm_dylib(builder
, compiler
.host
, &sysroot
);
492 builder
.ensure(RustcLink
{
493 compiler
: builder
.compiler(compiler
.stage
, builder
.config
.build
),
494 target_compiler
: compiler
,
500 pub fn rustc_cargo(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: Interned
<String
>) {
503 .arg(builder
.rustc_features())
504 .arg("--manifest-path")
505 .arg(builder
.src
.join("src/rustc/Cargo.toml"));
506 rustc_cargo_env(builder
, cargo
, target
);
509 pub fn rustc_cargo_env(builder
: &Builder
<'_
>, cargo
: &mut Cargo
, target
: Interned
<String
>) {
510 // Set some configuration variables picked up by build scripts and
511 // the compiler alike
513 .env("CFG_RELEASE", builder
.rust_release())
514 .env("CFG_RELEASE_CHANNEL", &builder
.config
.channel
)
515 .env("CFG_VERSION", builder
.rust_version())
516 .env("CFG_PREFIX", builder
.config
.prefix
.clone().unwrap_or_default());
518 let libdir_relative
= builder
.config
.libdir_relative().unwrap_or_else(|| Path
::new("lib"));
519 cargo
.env("CFG_LIBDIR_RELATIVE", libdir_relative
);
521 if let Some(ref ver_date
) = builder
.rust_info
.commit_date() {
522 cargo
.env("CFG_VER_DATE", ver_date
);
524 if let Some(ref ver_hash
) = builder
.rust_info
.sha() {
525 cargo
.env("CFG_VER_HASH", ver_hash
);
527 if !builder
.unstable_features() {
528 cargo
.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
530 if let Some(ref s
) = builder
.config
.rustc_default_linker
{
531 cargo
.env("CFG_DEFAULT_LINKER", s
);
533 if builder
.config
.rustc_parallel
{
534 cargo
.rustflag("--cfg=parallel_compiler");
536 if builder
.config
.rust_verify_llvm_ir
{
537 cargo
.env("RUSTC_VERIFY_LLVM_IR", "1");
540 // Pass down configuration from the LLVM build into the build of
541 // librustc_llvm and librustc_codegen_llvm.
543 // Note that this is disabled if LLVM itself is disabled or we're in a check
544 // build, where if we're in a check build there's no need to build all of
546 if builder
.config
.llvm_enabled() && builder
.kind
!= Kind
::Check
{
547 if builder
.is_rust_llvm(target
) {
548 cargo
.env("LLVM_RUSTLLVM", "1");
550 let llvm_config
= builder
.ensure(native
::Llvm { target }
);
551 cargo
.env("LLVM_CONFIG", &llvm_config
);
552 let target_config
= builder
.config
.target_config
.get(&target
);
553 if let Some(s
) = target_config
.and_then(|c
| c
.llvm_config
.as_ref()) {
554 cargo
.env("CFG_LLVM_ROOT", s
);
556 // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm.
557 if let Some(ref s
) = builder
.config
.llvm_ldflags
{
558 cargo
.env("LLVM_LINKER_FLAGS", s
);
560 // Building with a static libstdc++ is only supported on linux right now,
561 // not for MSVC or macOS
562 if builder
.config
.llvm_static_stdcpp
563 && !target
.contains("freebsd")
564 && !target
.contains("msvc")
565 && !target
.contains("apple")
567 let file
= compiler_file(builder
, builder
.cxx(target
).unwrap(), target
, "libstdc++.a");
568 cargo
.env("LLVM_STATIC_STDCPP", file
);
570 if builder
.config
.llvm_link_shared
|| builder
.config
.llvm_thin_lto
{
571 cargo
.env("LLVM_LINK_SHARED", "1");
573 if builder
.config
.llvm_use_libcxx
{
574 cargo
.env("LLVM_USE_LIBCXX", "1");
576 if builder
.config
.llvm_optimize
&& !builder
.config
.llvm_release_debuginfo
{
577 cargo
.env("LLVM_NDEBUG", "1");
582 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
584 pub compiler
: Compiler
,
585 pub target_compiler
: Compiler
,
586 pub target
: Interned
<String
>,
589 impl Step
for RustcLink
{
592 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
596 /// Same as `std_link`, only for librustc
597 fn run(self, builder
: &Builder
<'_
>) {
598 let compiler
= self.compiler
;
599 let target_compiler
= self.target_compiler
;
600 let target
= self.target
;
601 builder
.info(&format
!(
602 "Copying stage{} rustc from stage{} ({} -> {} / {})",
603 target_compiler
.stage
, compiler
.stage
, &compiler
.host
, target_compiler
.host
, target
607 &builder
.sysroot_libdir(target_compiler
, target
),
608 &builder
.sysroot_libdir(target_compiler
, compiler
.host
),
609 &librustc_stamp(builder
, compiler
, target
),
614 /// Cargo's output path for the standard library in a given stage, compiled
615 /// by a particular compiler for the specified target.
617 builder
: &Builder
<'_
>,
619 target
: Interned
<String
>,
621 builder
.cargo_out(compiler
, Mode
::Std
, target
).join(".libstd.stamp")
624 /// Cargo's output path for librustc in a given stage, compiled by a particular
625 /// compiler for the specified target.
626 pub fn librustc_stamp(
627 builder
: &Builder
<'_
>,
629 target
: Interned
<String
>,
631 builder
.cargo_out(compiler
, Mode
::Rustc
, target
).join(".librustc.stamp")
634 pub fn compiler_file(
635 builder
: &Builder
<'_
>,
637 target
: Interned
<String
>,
640 let mut cmd
= Command
::new(compiler
);
641 cmd
.args(builder
.cflags(target
, GitRepo
::Rustc
));
642 cmd
.arg(format
!("-print-file-name={}", file
));
643 let out
= output(&mut cmd
);
644 PathBuf
::from(out
.trim())
647 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
649 pub compiler
: Compiler
,
652 impl Step
for Sysroot
{
653 type Output
= Interned
<PathBuf
>;
655 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
659 /// Returns the sysroot for the `compiler` specified that *this build system
662 /// That is, the sysroot for the stage0 compiler is not what the compiler
663 /// thinks it is by default, but it's the same as the default for stages
665 fn run(self, builder
: &Builder
<'_
>) -> Interned
<PathBuf
> {
666 let compiler
= self.compiler
;
667 let sysroot
= if compiler
.stage
== 0 {
668 builder
.out
.join(&compiler
.host
).join("stage0-sysroot")
670 builder
.out
.join(&compiler
.host
).join(format
!("stage{}", compiler
.stage
))
672 let _
= fs
::remove_dir_all(&sysroot
);
673 t
!(fs
::create_dir_all(&sysroot
));
674 INTERNER
.intern_path(sysroot
)
678 #[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
679 pub struct Assemble
{
680 /// The compiler which we will produce in this step. Assemble itself will
681 /// take care of ensuring that the necessary prerequisites to do so exist,
682 /// that is, this target can be a stage2 compiler and Assemble will build
683 /// previous stages for you.
684 pub target_compiler
: Compiler
,
687 impl Step
for Assemble
{
688 type Output
= Compiler
;
690 fn should_run(run
: ShouldRun
<'_
>) -> ShouldRun
<'_
> {
694 /// Prepare a new compiler from the artifacts in `stage`
696 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
697 /// must have been previously produced by the `stage - 1` builder.build
699 fn run(self, builder
: &Builder
<'_
>) -> Compiler
{
700 let target_compiler
= self.target_compiler
;
702 if target_compiler
.stage
== 0 {
704 builder
.config
.build
, target_compiler
.host
,
705 "Cannot obtain compiler for non-native build triple at stage 0"
707 // The stage 0 compiler for the build triple is always pre-built.
708 return target_compiler
;
711 // Get the compiler that we'll use to bootstrap ourselves.
713 // Note that this is where the recursive nature of the bootstrap
714 // happens, as this will request the previous stage's compiler on
715 // downwards to stage 0.
717 // Also note that we're building a compiler for the host platform. We
718 // only assume that we can run `build` artifacts, which means that to
719 // produce some other architecture compiler we need to start from
720 // `build` to get there.
722 // FIXME: Perhaps we should download those libraries?
723 // It would make builds faster...
725 // FIXME: It may be faster if we build just a stage 1 compiler and then
726 // use that to bootstrap this compiler forward.
727 let build_compiler
= builder
.compiler(target_compiler
.stage
- 1, builder
.config
.build
);
729 // Build the libraries for this compiler to link to (i.e., the libraries
730 // it uses at runtime). NOTE: Crates the target compiler compiles don't
731 // link to these. (FIXME: Is that correct? It seems to be correct most
732 // of the time but I think we do link to these for stage2/bin compilers
733 // when not performing a full bootstrap).
734 builder
.ensure(Rustc { compiler: build_compiler, target: target_compiler.host }
);
736 let lld_install
= if builder
.config
.lld_enabled
{
737 Some(builder
.ensure(native
::Lld { target: target_compiler.host }
))
742 let stage
= target_compiler
.stage
;
743 let host
= target_compiler
.host
;
744 builder
.info(&format
!("Assembling stage{} compiler ({})", stage
, host
));
746 // Link in all dylibs to the libdir
747 let sysroot
= builder
.sysroot(target_compiler
);
748 let rustc_libdir
= builder
.rustc_libdir(target_compiler
);
749 t
!(fs
::create_dir_all(&rustc_libdir
));
750 let src_libdir
= builder
.sysroot_libdir(build_compiler
, host
);
751 for f
in builder
.read_dir(&src_libdir
) {
752 let filename
= f
.file_name().into_string().unwrap();
753 if is_dylib(&filename
) {
754 builder
.copy(&f
.path(), &rustc_libdir
.join(&filename
));
758 let libdir
= builder
.sysroot_libdir(target_compiler
, target_compiler
.host
);
759 if let Some(lld_install
) = lld_install
{
760 let src_exe
= exe("lld", &target_compiler
.host
);
761 let dst_exe
= exe("rust-lld", &target_compiler
.host
);
762 // we prepend this bin directory to the user PATH when linking Rust binaries. To
763 // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
764 let dst
= libdir
.parent().unwrap().join("bin");
765 t
!(fs
::create_dir_all(&dst
));
766 builder
.copy(&lld_install
.join("bin").join(&src_exe
), &dst
.join(&dst_exe
));
769 // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
770 // so that it can be found when the newly built `rustc` is run.
771 dist
::maybe_install_llvm_dylib(builder
, target_compiler
.host
, &sysroot
);
773 // Link the compiler binary itself into place
774 let out_dir
= builder
.cargo_out(build_compiler
, Mode
::Rustc
, host
);
775 let rustc
= out_dir
.join(exe("rustc_binary", &*host
));
776 let bindir
= sysroot
.join("bin");
777 t
!(fs
::create_dir_all(&bindir
));
778 let compiler
= builder
.rustc(target_compiler
);
779 builder
.copy(&rustc
, &compiler
);
785 /// Link some files into a rustc sysroot.
787 /// For a particular stage this will link the file listed in `stamp` into the
788 /// `sysroot_dst` provided.
789 pub fn add_to_sysroot(
790 builder
: &Builder
<'_
>,
792 sysroot_host_dst
: &Path
,
795 t
!(fs
::create_dir_all(&sysroot_dst
));
796 t
!(fs
::create_dir_all(&sysroot_host_dst
));
797 for (path
, host
) in builder
.read_stamp_file(stamp
) {
799 builder
.copy(&path
, &sysroot_host_dst
.join(path
.file_name().unwrap()));
801 builder
.copy(&path
, &sysroot_dst
.join(path
.file_name().unwrap()));
807 builder
: &Builder
<'_
>,
809 tail_args
: Vec
<String
>,
811 additional_target_deps
: Vec
<PathBuf
>,
814 if builder
.config
.dry_run
{
818 // `target_root_dir` looks like $dir/$target/release
819 let target_root_dir
= stamp
.parent().unwrap();
820 // `target_deps_dir` looks like $dir/$target/release/deps
821 let target_deps_dir
= target_root_dir
.join("deps");
822 // `host_root_dir` looks like $dir/release
823 let host_root_dir
= target_root_dir
825 .unwrap() // chop off `release`
827 .unwrap() // chop off `$target`
828 .join(target_root_dir
.file_name().unwrap());
830 // Spawn Cargo slurping up its JSON output. We'll start building up the
831 // `deps` array of all files it generated along with a `toplevel` array of
832 // files we need to probe for later.
833 let mut deps
= Vec
::new();
834 let mut toplevel
= Vec
::new();
835 let ok
= stream_cargo(builder
, cargo
, tail_args
, &mut |msg
| {
836 let (filenames
, crate_types
) = match msg
{
837 CargoMessage
::CompilerArtifact
{
839 target
: CargoTarget { crate_types }
,
841 } => (filenames
, crate_types
),
844 for filename
in filenames
{
845 // Skip files like executables
846 if !(filename
.ends_with(".rlib")
847 || filename
.ends_with(".lib")
848 || filename
.ends_with(".a")
849 || is_dylib(&filename
)
850 || (is_check
&& filename
.ends_with(".rmeta")))
855 let filename
= Path
::new(&*filename
);
857 // If this was an output file in the "host dir" we don't actually
858 // worry about it, it's not relevant for us
859 if filename
.starts_with(&host_root_dir
) {
860 // Unless it's a proc macro used in the compiler
861 if crate_types
.iter().any(|t
| t
== "proc-macro") {
862 deps
.push((filename
.to_path_buf(), true));
867 // If this was output in the `deps` dir then this is a precise file
868 // name (hash included) so we start tracking it.
869 if filename
.starts_with(&target_deps_dir
) {
870 deps
.push((filename
.to_path_buf(), false));
874 // Otherwise this was a "top level artifact" which right now doesn't
875 // have a hash in the name, but there's a version of this file in
876 // the `deps` folder which *does* have a hash in the name. That's
877 // the one we'll want to we'll probe for it later.
879 // We do not use `Path::file_stem` or `Path::extension` here,
880 // because some generated files may have multiple extensions e.g.
881 // `std-<hash>.dll.lib` on Windows. The aforementioned methods only
882 // split the file name by the last extension (`.lib`) while we need
883 // to split by all extensions (`.dll.lib`).
884 let expected_len
= t
!(filename
.metadata()).len();
885 let filename
= filename
.file_name().unwrap().to_str().unwrap();
886 let mut parts
= filename
.splitn(2, '
.'
);
887 let file_stem
= parts
.next().unwrap().to_owned();
888 let extension
= parts
.next().unwrap().to_owned();
890 toplevel
.push((file_stem
, extension
, expected_len
));
898 // Ok now we need to actually find all the files listed in `toplevel`. We've
899 // got a list of prefix/extensions and we basically just need to find the
900 // most recent file in the `deps` folder corresponding to each one.
901 let contents
= t
!(target_deps_dir
.read_dir())
903 .map(|e
| (e
.path(), e
.file_name().into_string().unwrap(), t
!(e
.metadata())))
904 .collect
::<Vec
<_
>>();
905 for (prefix
, extension
, expected_len
) in toplevel
{
906 let candidates
= contents
.iter().filter(|&&(_
, ref filename
, ref meta
)| {
907 filename
.starts_with(&prefix
[..])
908 && filename
[prefix
.len()..].starts_with('
-'
)
909 && filename
.ends_with(&extension
[..])
910 && meta
.len() == expected_len
913 .max_by_key(|&&(_
, _
, ref metadata
)| FileTime
::from_last_modification_time(metadata
));
914 let path_to_add
= match max
{
915 Some(triple
) => triple
.0.to_str().unwrap(),
916 None
=> panic
!("no output generated for {:?} {:?}", prefix
, extension
),
918 if is_dylib(path_to_add
) {
919 let candidate
= format
!("{}.lib", path_to_add
);
920 let candidate
= PathBuf
::from(candidate
);
921 if candidate
.exists() {
922 deps
.push((candidate
, false));
925 deps
.push((path_to_add
.into(), false));
928 deps
.extend(additional_target_deps
.into_iter().map(|d
| (d
, false)));
930 let mut new_contents
= Vec
::new();
931 for (dep
, proc_macro
) in deps
.iter() {
932 new_contents
.extend(if *proc_macro { b"h" }
else { b"t" }
);
933 new_contents
.extend(dep
.to_str().unwrap().as_bytes());
934 new_contents
.extend(b
"\0");
936 t
!(fs
::write(&stamp
, &new_contents
));
937 deps
.into_iter().map(|(d
, _
)| d
).collect()
941 builder
: &Builder
<'_
>,
943 tail_args
: Vec
<String
>,
944 cb
: &mut dyn FnMut(CargoMessage
<'_
>),
946 let mut cargo
= Command
::from(cargo
);
947 if builder
.config
.dry_run
{
950 // Instruct Cargo to give us json messages on stdout, critically leaving
951 // stderr as piped so we can get those pretty colors.
952 let mut message_format
= String
::from("json-render-diagnostics");
953 if let Some(s
) = &builder
.config
.rustc_error_format
{
954 message_format
.push_str(",json-diagnostic-");
955 message_format
.push_str(s
);
957 cargo
.arg("--message-format").arg(message_format
).stdout(Stdio
::piped());
959 for arg
in tail_args
{
963 builder
.verbose(&format
!("running: {:?}", cargo
));
964 let mut child
= match cargo
.spawn() {
966 Err(e
) => panic
!("failed to execute command: {:?}\nerror: {}", cargo
, e
),
969 // Spawn Cargo slurping up its JSON output. We'll start building up the
970 // `deps` array of all files it generated along with a `toplevel` array of
971 // files we need to probe for later.
972 let stdout
= BufReader
::new(child
.stdout
.take().unwrap());
973 for line
in stdout
.lines() {
975 match serde_json
::from_str
::<CargoMessage
<'_
>>(&line
) {
977 // If this was informational, just print it out and continue
978 Err(_
) => println
!("{}", line
),
982 // Make sure Cargo actually succeeded after we read all of its stdout.
983 let status
= t
!(child
.wait());
984 if !status
.success() {
986 "command did not execute successfully: {:?}\n\
987 expected success, got: {}",
994 #[derive(Deserialize)]
995 pub struct CargoTarget
<'a
> {
996 crate_types
: Vec
<Cow
<'a
, str>>,
999 #[derive(Deserialize)]
1000 #[serde(tag = "reason", rename_all = "kebab-case")]
1001 pub enum CargoMessage
<'a
> {
1003 package_id
: Cow
<'a
, str>,
1004 features
: Vec
<Cow
<'a
, str>>,
1005 filenames
: Vec
<Cow
<'a
, str>>,
1006 target
: CargoTarget
<'a
>,
1008 BuildScriptExecuted
{
1009 package_id
: Cow
<'a
, str>,