From e9a897c10f1636fca5c99bdbf12d02ea7ffd6e4c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Feb 2016 23:50:32 -0800 Subject: [PATCH] rustbuild: Add steps for linking a sysroot When cross compiling for a new host, we can't actually run the host compiler to generate its own libs. In theory, however, all stage2 compilers (for any host) will produce the same libraries, so we just require the build compiler to produce the necessary host libraries and then we link those into place. --- src/bootstrap/build/compile.rs | 41 +++++++++++++++++++++++++++++-- src/bootstrap/build/mod.rs | 8 ++++++ src/bootstrap/build/step.rs | 45 +++++++++++++++++++++++++++++++--- 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/build/compile.rs b/src/bootstrap/build/compile.rs index dc547f74db1..3be4199352c 100644 --- a/src/bootstrap/build/compile.rs +++ b/src/bootstrap/build/compile.rs @@ -58,6 +58,30 @@ pub fn std<'a>(build: &'a Build, stage: u32, target: &str, } build.run(&mut cargo); + std_link(build, stage, target, compiler, host); +} + +/// Link all libstd rlibs/dylibs into the sysroot location. +/// +/// Links those artifacts generated in the given `stage` for `target` produced +/// by `compiler` into `host`'s sysroot. +pub fn std_link(build: &Build, + stage: u32, + target: &str, + compiler: &Compiler, + host: &str) { + let libdir = build.sysroot_libdir(stage, host, target); + let out_dir = build.cargo_out(stage, compiler.host, true, target); + + // If we're linking one compiler host's output into another, then we weren't + // called from the `std` method above. In that case we clean out what's + // already there and then also link compiler-rt into place. + if host != compiler.host { + let _ = fs::remove_dir_all(&libdir); + t!(fs::create_dir_all(&libdir)); + t!(fs::hard_link(&build.compiler_rt_built.borrow()[target], + libdir.join(staticlib("compiler-rt", target)))); + } add_to_sysroot(&out_dir, &libdir); } @@ -150,8 +174,21 @@ pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str, } build.run(&mut cargo); - let sysroot_libdir = build.sysroot_libdir(stage, host, target); - add_to_sysroot(&out_dir, &sysroot_libdir); + rustc_link(build, stage, target, compiler, compiler.host); +} + +/// Link all librustc rlibs/dylibs into the sysroot location. +/// +/// Links those artifacts generated in the given `stage` for `target` produced +/// by `compiler` into `host`'s sysroot. +pub fn rustc_link(build: &Build, + stage: u32, + target: &str, + compiler: &Compiler, + host: &str) { + let libdir = build.sysroot_libdir(stage, host, target); + let out_dir = build.cargo_out(stage, compiler.host, false, target); + add_to_sysroot(&out_dir, &libdir); } /// Cargo's output path for the standard library in a given stage, compiled diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs index 88ec6b72edd..4a77aeb9786 100644 --- a/src/bootstrap/build/mod.rs +++ b/src/bootstrap/build/mod.rs @@ -146,6 +146,14 @@ impl Build { Librustc { stage, compiler } => { compile::rustc(self, stage, target.target, &compiler); } + LibstdLink { stage, compiler, host } => { + compile::std_link(self, stage, target.target, + &compiler, host); + } + LibrustcLink { stage, compiler, host } => { + compile::rustc_link(self, stage, target.target, + &compiler, host); + } Rustc { stage: 0 } => { assert!(target.target == self.config.build, "only have one stage0 compiler"); diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs index f09a6ffbbf1..49d418580a0 100644 --- a/src/bootstrap/build/step.rs +++ b/src/bootstrap/build/step.rs @@ -32,6 +32,19 @@ macro_rules! targets { (libstd, Libstd { stage: u32, compiler: Compiler<'a> }), (librustc, Librustc { stage: u32, compiler: Compiler<'a> }), + // Links the standard library/librustc produced by the compiler + // provided into the host's directory also provided. + (libstd_link, LibstdLink { + stage: u32, + compiler: Compiler<'a>, + host: &'a str + }), + (librustc_link, LibrustcLink { + stage: u32, + compiler: Compiler<'a>, + host: &'a str + }), + // Steps for long-running native builds. Ideally these wouldn't // actually exist and would be part of build scripts, but for now // these are here. @@ -107,13 +120,25 @@ fn top_level(build: &Build) -> Vec { continue } let host = t.target(host); - targets.push(host.librustc(stage, t.compiler(stage))); + if host.target == build.config.build { + targets.push(host.librustc(stage, host.compiler(stage))); + } else { + targets.push(host.librustc_link(stage, t.compiler(stage), + host.target)); + } for target in build.config.target.iter() { if !build.flags.target.contains(target) { continue } - targets.push(host.target(target) - .libstd(stage, t.compiler(stage))); + + if host.target == build.config.build { + targets.push(host.target(target) + .libstd(stage, host.compiler(stage))); + } else { + targets.push(host.target(target) + .libstd_link(stage, t.compiler(stage), + host.target)); + } } } } @@ -128,10 +153,14 @@ fn add_steps<'a>(build: &'a Build, target: &Step<'a>, targets: &mut Vec>) { for step in build.flags.step.iter() { - let compiler = host.compiler(stage); + let compiler = host.target(&build.config.build).compiler(stage); match &step[..] { "libstd" => targets.push(target.libstd(stage, compiler)), "librustc" => targets.push(target.librustc(stage, compiler)), + "libstd-link" => targets.push(target.libstd_link(stage, compiler, + host.target)), + "librustc-link" => targets.push(target.librustc_link(stage, compiler, + host.target)), "rustc" => targets.push(host.rustc(stage)), "llvm" => targets.push(target.llvm(())), "compiler-rt" => targets.push(target.compiler_rt(())), @@ -179,6 +208,14 @@ impl<'a> Step<'a> { vec![self.compiler_rt(()), self.rustc(compiler.stage).target(compiler.host)] } + Source::LibrustcLink { stage, compiler, host } => { + vec![self.librustc(stage, compiler), + self.libstd_link(stage, compiler, host)] + } + Source::LibstdLink { stage, compiler, host } => { + vec![self.libstd(stage, compiler), + self.target(host).rustc(stage)] + } Source::CompilerRt { _dummy } => { vec![self.llvm(()).target(&build.config.build)] }