Skip to content

rustc: Load the rustc_trans crate at runtime #47671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"rustc",
"libstd",
"libtest",
"librustc_trans",
"tools/cargotest",
"tools/clippy",
"tools/compiletest",
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl Step for Rustc {
build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target));

let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
rustc_cargo(build, target, &mut cargo);
rustc_cargo(build, &mut cargo);
run_cargo(build,
&mut cargo,
&librustc_stamp(build, compiler, target),
Expand Down
234 changes: 184 additions & 50 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,11 @@ impl Step for StartupObjects {
}

for obj in ["crt2.o", "dllcrt2.o"].iter() {
copy(&compiler_file(build.cc(target), obj), &sysroot_dir.join(obj));
let src = compiler_file(build,
build.cc(target),
target,
obj);
copy(&src, &sysroot_dir.join(obj));
}
}
}
Expand Down Expand Up @@ -454,10 +458,6 @@ impl Step for Rustc {

builder.ensure(Test { compiler, target });

// Build LLVM for our target. This will implicitly build the host LLVM
// if necessary.
builder.ensure(native::Llvm { target });

if build.force_use_stage1(compiler, target) {
builder.ensure(Rustc {
compiler: builder.compiler(1, build.build),
Expand Down Expand Up @@ -487,7 +487,7 @@ impl Step for Rustc {
build.clear_if_dirty(&stage_out, &libtest_stamp(build, compiler, target));

let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
rustc_cargo(build, target, &mut cargo);
rustc_cargo(build, &mut cargo);
run_cargo(build,
&mut cargo,
&librustc_stamp(build, compiler, target),
Expand All @@ -501,14 +501,14 @@ impl Step for Rustc {
}
}

/// Same as `std_cargo`, but for libtest
pub fn rustc_cargo(build: &Build,
target: Interned<String>,
cargo: &mut Command) {
pub fn rustc_cargo(build: &Build, cargo: &mut Command) {
cargo.arg("--features").arg(build.rustc_features())
.arg("--manifest-path")
.arg(build.src.join("src/rustc/Cargo.toml"));
rustc_cargo_env(build, cargo);
}

fn rustc_cargo_env(build: &Build, cargo: &mut Command) {
// Set some configuration variables picked up by build scripts and
// the compiler alike
cargo.env("CFG_RELEASE", build.rust_release())
Expand Down Expand Up @@ -536,27 +536,6 @@ pub fn rustc_cargo(build: &Build,
if !build.unstable_features() {
cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
}
// Flag that rust llvm is in use
if build.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
cargo.env("LLVM_CONFIG", build.llvm_config(target));
let target_config = build.config.target_config.get(&target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
cargo.env("CFG_LLVM_ROOT", s);
}
// Building with a static libstdc++ is only supported on linux right now,
// not for MSVC or macOS
if build.config.llvm_static_stdcpp &&
!target.contains("freebsd") &&
!target.contains("windows") &&
!target.contains("apple") {
cargo.env("LLVM_STATIC_STDCPP",
compiler_file(build.cxx(target).unwrap(), "libstdc++.a"));
}
if build.config.llvm_link_shared {
cargo.env("LLVM_LINK_SHARED", "1");
}
if let Some(ref s) = build.config.rustc_default_linker {
cargo.env("CFG_DEFAULT_LINKER", s);
}
Expand Down Expand Up @@ -601,6 +580,137 @@ impl Step for RustcLink {
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct RustcTrans {
pub compiler: Compiler,
pub target: Interned<String>,
}

impl Step for RustcTrans {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;

fn should_run(run: ShouldRun) -> ShouldRun {
run.path("src/librustc_trans").krate("rustc_trans")
}

fn make_run(run: RunConfig) {
run.builder.ensure(RustcTrans {
compiler: run.builder.compiler(run.builder.top_stage, run.host),
target: run.target,
});
}

fn run(self, builder: &Builder) {
let build = builder.build;
let compiler = self.compiler;
let target = self.target;

builder.ensure(Rustc { compiler, target });

// Build LLVM for our target. This will implicitly build the host LLVM
// if necessary.
builder.ensure(native::Llvm { target });

if build.force_use_stage1(compiler, target) {
builder.ensure(RustcTrans {
compiler: builder.compiler(1, build.build),
target,
});
return;
}

let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
println!("Building stage{} trans artifacts ({} -> {})",
compiler.stage, &compiler.host, target);

let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
cargo.arg("--manifest-path")
.arg(build.src.join("src/librustc_trans/Cargo.toml"))
.arg("--features").arg(build.rustc_features());
rustc_cargo_env(build, &mut cargo);

// Pass down configuration from the LLVM build into the build of
// librustc_llvm and librustc_trans.
if build.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
}
cargo.env("LLVM_CONFIG", build.llvm_config(target));
let target_config = build.config.target_config.get(&target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
cargo.env("CFG_LLVM_ROOT", s);
}
// Building with a static libstdc++ is only supported on linux right now,
// not for MSVC or macOS
if build.config.llvm_static_stdcpp &&
!target.contains("freebsd") &&
!target.contains("windows") &&
!target.contains("apple") {
let file = compiler_file(build,
build.cxx(target).unwrap(),
target,
"libstdc++.a");
cargo.env("LLVM_STATIC_STDCPP", file);
}
if build.config.llvm_link_shared {
cargo.env("LLVM_LINK_SHARED", "1");
}

run_cargo(build,
&mut cargo,
&librustc_trans_stamp(build, compiler, target),
false);
}
}

/// Creates the `codegen-backends` folder for a compiler that's about to be
/// assembled as a complete compiler.
///
/// This will take the codegen artifacts produced by `compiler` and link them
/// into an appropriate location for `target_compiler` to be a functional
/// compiler.
fn copy_codegen_backends_to_sysroot(builder: &Builder,
compiler: Compiler,
target_compiler: Compiler) {
let build = builder.build;
let target = target_compiler.host;

// Note that this step is different than all the other `*Link` steps in
// that it's not assembling a bunch of libraries but rather is primarily
// moving the codegen backend into place. The codegen backend of rustc is
// not linked into the main compiler by default but is rather dynamically
// selected at runtime for inclusion.
//
// Here we're looking for the output dylib of the `RustcTrans` step and
// we're copying that into the `codegen-backends` folder.
let libdir = builder.sysroot_libdir(target_compiler, target);
let dst = libdir.join("codegen-backends");
t!(fs::create_dir_all(&dst));
let stamp = librustc_trans_stamp(build, compiler, target);

let mut copied = None;
for file in read_stamp_file(&stamp) {
let filename = match file.file_name().and_then(|s| s.to_str()) {
Some(s) => s,
None => continue,
};
if !is_dylib(filename) || !filename.contains("rustc_trans-") {
continue
}
match copied {
None => copied = Some(file.clone()),
Some(ref s) => {
panic!("copied two codegen backends:\n{}\n{}",
s.display(),
file.display());
}
}
copy(&file, &dst.join(filename));
}
assert!(copied.is_some(), "failed to find a codegen backend to copy");
}

/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
Expand All @@ -619,9 +729,20 @@ pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned<String
build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
}

fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
let out = output(Command::new(compiler)
.arg(format!("-print-file-name={}", file)));
pub fn librustc_trans_stamp(build: &Build,
compiler: Compiler,
target: Interned<String>) -> PathBuf {
build.cargo_out(compiler, Mode::Librustc, target).join(".librustc_trans.stamp")
}

fn compiler_file(build: &Build,
compiler: &Path,
target: Interned<String>,
file: &str) -> PathBuf {
let mut cmd = Command::new(compiler);
cmd.args(build.cflags(target));
cmd.arg(format!("-print-file-name={}", file));
let out = output(&mut cmd);
PathBuf::from(out.trim())
}

Expand Down Expand Up @@ -690,20 +811,23 @@ impl Step for Assemble {
}

// Get the compiler that we'll use to bootstrap ourselves.
let build_compiler = if target_compiler.host != build.build {
// Build a compiler for the host platform. We cannot use the stage0
// compiler for the host platform for this because it doesn't have
// the libraries we need. FIXME: Perhaps we should download those
// libraries? It would make builds faster...
// FIXME: It may be faster if we build just a stage 1
// compiler and then use that to bootstrap this compiler
// forward.
builder.compiler(target_compiler.stage - 1, build.build)
} else {
// Build the compiler we'll use to build the stage requested. This
// may build more than one compiler (going down to stage 0).
builder.compiler(target_compiler.stage - 1, target_compiler.host)
};
//
// Note that this is where the recursive nature of the bootstrap
// happens, as this will request the previous stage's compiler on
// downwards to stage 0.
//
// Also note that we're building a compiler for the host platform. We
// only assume that we can run `build` artifacts, which means that to
// produce some other architecture compiler we need to start from
// `build` to get there.
//
// FIXME: Perhaps we should download those libraries?
// It would make builds faster...
//
// FIXME: It may be faster if we build just a stage 1 compiler and then
// use that to bootstrap this compiler forward.
let build_compiler =
builder.compiler(target_compiler.stage - 1, build.build);

// Build the libraries for this compiler to link to (i.e., the libraries
// it uses at runtime). NOTE: Crates the target compiler compiles don't
Expand All @@ -721,7 +845,14 @@ impl Step for Assemble {
builder.ensure(RustcLink { compiler, target_compiler, target });
}
} else {
builder.ensure(Rustc { compiler: build_compiler, target: target_compiler.host });
builder.ensure(Rustc {
compiler: build_compiler,
target: target_compiler.host,
});
builder.ensure(RustcTrans {
compiler: build_compiler,
target: target_compiler.host,
});
}

let stage = target_compiler.stage;
Expand All @@ -740,9 +871,12 @@ impl Step for Assemble {
}
}

let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
copy_codegen_backends_to_sysroot(builder,
build_compiler,
target_compiler);

// Link the compiler binary itself into place
let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
let rustc = out_dir.join(exe("rustc", &*host));
let bindir = sysroot.join("bin");
t!(fs::create_dir_all(&bindir));
Expand Down
13 changes: 12 additions & 1 deletion src/bootstrap/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,15 @@ impl Step for Rustc {
}
}

// Copy over the codegen backends
let backends_src = builder.sysroot_libdir(compiler, host)
.join("codegen-backends");
let backends_dst = image.join("lib/rustlib")
.join(&*host)
.join("lib/codegen-backends");
t!(fs::create_dir_all(&backends_dst));
cp_r(&backends_src, &backends_dst);

// Man pages
t!(fs::create_dir_all(image.join("share/man/man1")));
let man_src = build.src.join("src/doc/man");
Expand Down Expand Up @@ -581,7 +590,9 @@ impl Step for Std {
t!(fs::create_dir_all(&dst));
let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
cp_r(&src, &dst);
cp_filtered(&src, &dst, &|path| {
path.file_name().and_then(|s| s.to_str()) != Some("codegen-backends")
});

let mut cmd = rust_installer(builder);
cmd.arg("generate")
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ impl Step for Rustc {
t!(symlink_dir_force(&my_out, &out_dir));

let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
compile::rustc_cargo(build, target, &mut cargo);
compile::rustc_cargo(build, &mut cargo);

if build.config.compiler_docs {
// src/rustc/Cargo.toml contains a bin crate called rustc which
Expand Down
3 changes: 0 additions & 3 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,6 @@ impl Build {
if self.config.use_jemalloc {
features.push_str(" jemalloc");
}
if self.config.llvm_enabled {
features.push_str(" llvm");
}
features
}

Expand Down
Loading