rustc: Load the rustc_trans
crate at runtime
Building on the work of # 45684 this commit updates the compiler to unconditionally load the `rustc_trans` crate at runtime instead of linking to it at compile time. The end goal of this work is to implement # 46819 where rustc will have multiple backends available to it to load. This commit starts off by removing the `extern crate rustc_trans` from the driver. This involved moving some miscellaneous functionality into the `TransCrate` trait and also required an implementation of how to locate and load the trans backend. This ended up being a little tricky because the sysroot isn't always the right location (for example `--sysroot` arguments) so some extra code was added as well to probe a directory relative to the current dll (the rustc_driver dll). Rustbuild has been updated accordingly as well to have a separate compilation invocation for the `rustc_trans` crate and assembly it accordingly into the sysroot. Finally, the distribution logic for the `rustc` package was also updated to slurp up the trans backends folder. A number of assorted fallout changes were included here as well to ensure tests pass and such, and they should all be commented inline.
This commit is contained in:
parent
bacb5c58df
commit
884715c654
3
src/Cargo.lock
generated
3
src/Cargo.lock
generated
@ -1933,7 +1933,6 @@ dependencies = [
|
||||
"rustc_privacy 0.0.0",
|
||||
"rustc_resolve 0.0.0",
|
||||
"rustc_save_analysis 0.0.0",
|
||||
"rustc_trans 0.0.0",
|
||||
"rustc_trans_utils 0.0.0",
|
||||
"rustc_typeck 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
@ -1984,6 +1983,7 @@ dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"build_helper 0.1.0",
|
||||
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_cratesio_shim 0.0.0",
|
||||
]
|
||||
|
||||
@ -2121,6 +2121,7 @@ dependencies = [
|
||||
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
|
@ -4,6 +4,7 @@ members = [
|
||||
"rustc",
|
||||
"libstd",
|
||||
"libtest",
|
||||
"librustc_trans",
|
||||
"tools/cargotest",
|
||||
"tools/clippy",
|
||||
"tools/compiletest",
|
||||
|
@ -94,7 +94,7 @@ fn run(self, builder: &Builder) {
|
||||
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),
|
||||
|
@ -300,7 +300,11 @@ fn run(self, builder: &Builder) {
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -454,10 +458,6 @@ fn run(self, builder: &Builder) {
|
||||
|
||||
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),
|
||||
@ -487,7 +487,7 @@ fn run(self, builder: &Builder) {
|
||||
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),
|
||||
@ -501,14 +501,14 @@ fn run(self, builder: &Builder) {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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())
|
||||
@ -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);
|
||||
}
|
||||
@ -601,6 +580,137 @@ fn run(self, builder: &Builder) {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -690,20 +811,23 @@ fn run(self, builder: &Builder) -> Compiler {
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -721,7 +845,14 @@ fn run(self, builder: &Builder) -> Compiler {
|
||||
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;
|
||||
@ -740,9 +871,12 @@ fn run(self, builder: &Builder) -> Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -434,6 +434,15 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
@ -581,7 +590,9 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
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")
|
||||
|
@ -617,7 +617,7 @@ fn run(self, builder: &Builder) {
|
||||
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
|
||||
|
@ -432,9 +432,6 @@ fn rustc_features(&self) -> String {
|
||||
if self.config.use_jemalloc {
|
||||
features.push_str(" jemalloc");
|
||||
}
|
||||
if self.config.llvm_enabled {
|
||||
features.push_str(" llvm");
|
||||
}
|
||||
features
|
||||
}
|
||||
|
||||
|
@ -57,11 +57,6 @@ fn run(self, builder: &Builder) {
|
||||
let build = builder.build;
|
||||
let target = self.target;
|
||||
|
||||
// If we're not compiling for LLVM bail out here.
|
||||
if !build.config.llvm_enabled {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're using a custom LLVM bail out here, but we can only use a
|
||||
// custom LLVM for the build triple.
|
||||
if let Some(config) = build.config.target_config.get(&target) {
|
||||
|
@ -900,6 +900,8 @@ fn run(self, builder: &Builder) {
|
||||
cmd.env("PROFILER_SUPPORT", "1");
|
||||
}
|
||||
|
||||
cmd.env("RUST_TEST_TMPDIR", build.out.join("tmp"));
|
||||
|
||||
cmd.arg("--adb-path").arg("adb");
|
||||
cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
|
||||
if target.contains("android") {
|
||||
@ -1209,7 +1211,7 @@ fn run(self, builder: &Builder) {
|
||||
}
|
||||
Mode::Librustc => {
|
||||
builder.ensure(compile::Rustc { compiler, target });
|
||||
compile::rustc_cargo(build, target, &mut cargo);
|
||||
compile::rustc_cargo(build, &mut cargo);
|
||||
("librustc", "rustc-main")
|
||||
}
|
||||
_ => panic!("can only test libraries"),
|
||||
|
@ -14,7 +14,7 @@ bitflags = "1.0"
|
||||
fmt_macros = { path = "../libfmt_macros" }
|
||||
graphviz = { path = "../libgraphviz" }
|
||||
jobserver = "0.1"
|
||||
log = "0.4"
|
||||
log = { version = "0.4", features = ["release_max_level_info", "std"] }
|
||||
rustc_apfloat = { path = "../librustc_apfloat" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
@ -26,7 +26,6 @@ syntax_pos = { path = "../libsyntax_pos" }
|
||||
backtrace = "0.3.3"
|
||||
byteorder = { version = "1.1", features = ["i128"]}
|
||||
|
||||
|
||||
# Note that these dependencies are a lie, they're just here to get linkage to
|
||||
# work.
|
||||
#
|
||||
|
@ -11,7 +11,7 @@ crate-type = ["dylib"]
|
||||
[dependencies]
|
||||
arena = { path = "../libarena" }
|
||||
graphviz = { path = "../libgraphviz" }
|
||||
log = { version = "0.4", features = ["release_max_level_info"] }
|
||||
log = "0.4"
|
||||
env_logger = { version = "0.4", default-features = false }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_allocator = { path = "../librustc_allocator" }
|
||||
@ -29,7 +29,6 @@ rustc_plugin = { path = "../librustc_plugin" }
|
||||
rustc_privacy = { path = "../librustc_privacy" }
|
||||
rustc_resolve = { path = "../librustc_resolve" }
|
||||
rustc_save_analysis = { path = "../librustc_save_analysis" }
|
||||
rustc_trans = { path = "../librustc_trans", optional = true }
|
||||
rustc_trans_utils = { path = "../librustc_trans_utils" }
|
||||
rustc_typeck = { path = "../librustc_typeck" }
|
||||
serialize = { path = "../libserialize" }
|
||||
@ -38,6 +37,3 @@ syntax_ext = { path = "../libsyntax_ext" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
||||
ar = "0.3.0"
|
||||
|
||||
[features]
|
||||
llvm = ["rustc_trans"]
|
||||
|
@ -47,8 +47,6 @@
|
||||
extern crate rustc_mir;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_save_analysis;
|
||||
#[cfg(feature="llvm")]
|
||||
pub extern crate rustc_trans;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate rustc_typeck;
|
||||
extern crate serialize;
|
||||
@ -68,30 +66,36 @@
|
||||
use rustc::session::CompileIncomplete;
|
||||
use rustc::session::config::{Input, PrintRequest, ErrorOutputType};
|
||||
use rustc::session::config::nightly_options;
|
||||
use rustc::session::filesearch;
|
||||
use rustc::session::{early_error, early_warn};
|
||||
use rustc::lint::Lint;
|
||||
use rustc::lint;
|
||||
use rustc::middle::cstore::CrateStore;
|
||||
use rustc_metadata::locator;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc_metadata::dynamic_lib::DynamicLibrary;
|
||||
use rustc::util::common::{time, ErrorReported};
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
|
||||
use serialize::json::ToJson;
|
||||
|
||||
use std::any::Any;
|
||||
use std::cmp::max;
|
||||
use std::cmp::Ordering::Equal;
|
||||
use std::cmp::max;
|
||||
use std::default::Default;
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::iter::repeat;
|
||||
use std::mem;
|
||||
use std::panic;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::process::{self, Command, Stdio};
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::thread;
|
||||
|
||||
use syntax::ast;
|
||||
@ -176,57 +180,247 @@ pub fn run<F>(run_compiler: F) -> isize
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as DefaultTransCrate;
|
||||
#[cfg(feature="llvm")]
|
||||
pub use rustc_trans::LlvmTransCrate as DefaultTransCrate;
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
pub mod rustc_trans {
|
||||
pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate;
|
||||
|
||||
pub fn print_version() {}
|
||||
pub fn print_passes() {}
|
||||
}
|
||||
|
||||
fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box<TransCrate> {
|
||||
use std::path::Path;
|
||||
use rustc_metadata::dynamic_lib::DynamicLibrary;
|
||||
|
||||
match DynamicLibrary::open(Some(Path::new(backend_name))) {
|
||||
Ok(lib) => {
|
||||
unsafe {
|
||||
let trans = {
|
||||
let __rustc_codegen_backend: unsafe fn(&Session) -> Box<TransCrate>;
|
||||
__rustc_codegen_backend = match lib.symbol("__rustc_codegen_backend") {
|
||||
Ok(f) => ::std::mem::transmute::<*mut u8, _>(f),
|
||||
Err(e) => sess.fatal(&format!("Couldnt load codegen backend as it\
|
||||
doesn't export the __rustc_backend_new symbol: {:?}", e)),
|
||||
};
|
||||
__rustc_codegen_backend(sess)
|
||||
};
|
||||
::std::mem::forget(lib);
|
||||
trans
|
||||
}
|
||||
}
|
||||
fn load_backend_from_dylib(path: &Path) -> fn() -> Box<TransCrate> {
|
||||
// Note that we're specifically using `open_global_now` here rather than
|
||||
// `open`, namely we want the behavior on Unix of RTLD_GLOBAL and RTLD_NOW,
|
||||
// where NOW means "bind everything right now" because we don't want
|
||||
// surprises later on and RTLD_GLOBAL allows the symbols to be made
|
||||
// available for future dynamic libraries opened. This is currently used by
|
||||
// loading LLVM and then making its symbols available for other dynamic
|
||||
// libraries.
|
||||
let lib = match DynamicLibrary::open_global_now(path) {
|
||||
Ok(lib) => lib,
|
||||
Err(err) => {
|
||||
sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", backend_name, err));
|
||||
let err = format!("couldn't load codegen backend {:?}: {:?}",
|
||||
path,
|
||||
err);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
};
|
||||
unsafe {
|
||||
match lib.symbol("__rustc_codegen_backend") {
|
||||
Ok(f) => {
|
||||
mem::forget(lib);
|
||||
mem::transmute::<*mut u8, _>(f)
|
||||
}
|
||||
Err(e) => {
|
||||
let err = format!("couldn't load codegen backend as it \
|
||||
doesn't export the `__rustc_codegen_backend` \
|
||||
symbol: {:?}", e);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_trans(sess: &Session) -> Box<TransCrate> {
|
||||
let trans_name = sess.opts.debugging_opts.codegen_backend.clone();
|
||||
match trans_name.as_ref().map(|s|&**s) {
|
||||
None => DefaultTransCrate::new(&sess),
|
||||
Some("llvm") => rustc_trans::LlvmTransCrate::new(&sess),
|
||||
Some("metadata_only") => {
|
||||
rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
|
||||
static INIT: Once = ONCE_INIT;
|
||||
static mut LOAD: fn() -> Box<TransCrate> = || unreachable!();
|
||||
|
||||
INIT.call_once(|| {
|
||||
let trans_name = sess.opts.debugging_opts.codegen_backend.as_ref();
|
||||
let backend = match trans_name.map(|s| &**s) {
|
||||
None |
|
||||
Some("llvm") => get_trans_default(),
|
||||
Some("metadata_only") => {
|
||||
rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new
|
||||
}
|
||||
Some(filename) if filename.contains(".") => {
|
||||
load_backend_from_dylib(filename.as_ref())
|
||||
}
|
||||
Some(trans_name) => {
|
||||
sess.fatal(&format!("unknown codegen backend {}", trans_name));
|
||||
}
|
||||
};
|
||||
|
||||
unsafe {
|
||||
LOAD = backend;
|
||||
}
|
||||
Some(filename) if filename.contains(".") => {
|
||||
load_backend_from_dylib(&sess, &filename)
|
||||
});
|
||||
let backend = unsafe { LOAD() };
|
||||
backend.init(sess);
|
||||
backend
|
||||
}
|
||||
|
||||
fn get_trans_default() -> fn() -> Box<TransCrate> {
|
||||
// For now we only allow this function to be called once as it'll dlopen a
|
||||
// few things, which seems to work best if we only do that once. In
|
||||
// general this assertion never trips due to the once guard in `get_trans`,
|
||||
// but there's a few manual calls to this function in this file we protect
|
||||
// against.
|
||||
static LOADED: AtomicBool = ATOMIC_BOOL_INIT;
|
||||
assert!(!LOADED.fetch_or(true, Ordering::SeqCst),
|
||||
"cannot load the default trans backend twice");
|
||||
|
||||
// When we're compiling this library with `--test` it'll run as a binary but
|
||||
// not actually exercise much functionality. As a result most of the logic
|
||||
// here is defunkt (it assumes we're a dynamic library in a sysroot) so
|
||||
// let's just return a dummy creation function which won't be used in
|
||||
// general anyway.
|
||||
if cfg!(test) {
|
||||
return rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new
|
||||
}
|
||||
|
||||
let target = session::config::host_triple();
|
||||
let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()];
|
||||
let path = current_dll_path()
|
||||
.and_then(|s| s.canonicalize().ok());
|
||||
if let Some(dll) = path {
|
||||
// use `parent` twice to chop off the file name and then also the
|
||||
// directory containing the dll which should be either `lib` or `bin`.
|
||||
if let Some(path) = dll.parent().and_then(|p| p.parent()) {
|
||||
// The original `path` pointed at the `rustc_driver` crate's dll.
|
||||
// Now that dll should only be in one of two locations. The first is
|
||||
// in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
|
||||
// other is the target's libdir, for example
|
||||
// `$sysroot/lib/rustlib/$target/lib/*.dll`.
|
||||
//
|
||||
// We don't know which, so let's assume that if our `path` above
|
||||
// ends in `$target` we *could* be in the target libdir, and always
|
||||
// assume that we may be in the main libdir.
|
||||
sysroot_candidates.push(path.to_owned());
|
||||
|
||||
if path.ends_with(target) {
|
||||
sysroot_candidates.extend(path.parent() // chop off `$target`
|
||||
.and_then(|p| p.parent()) // chop off `rustlib`
|
||||
.and_then(|p| p.parent()) // chop off `lib`
|
||||
.map(|s| s.to_owned()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let sysroot = sysroot_candidates.iter()
|
||||
.map(|sysroot| {
|
||||
let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
|
||||
sysroot.join(&libdir).join("codegen-backends")
|
||||
})
|
||||
.filter(|f| {
|
||||
info!("codegen backend candidate: {}", f.display());
|
||||
f.exists()
|
||||
})
|
||||
.next();
|
||||
let sysroot = match sysroot {
|
||||
Some(path) => path,
|
||||
None => {
|
||||
let candidates = sysroot_candidates.iter()
|
||||
.map(|p| p.display().to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n* ");
|
||||
let err = format!("failed to find a `codegen-backends` folder \
|
||||
in the sysroot candidates:\n* {}", candidates);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
};
|
||||
info!("probing {} for a codegen backend", sysroot.display());
|
||||
|
||||
let d = match sysroot.read_dir() {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
let err = format!("failed to load default codegen backend, couldn't \
|
||||
read `{}`: {}", sysroot.display(), e);
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
};
|
||||
|
||||
let mut file: Option<PathBuf> = None;
|
||||
|
||||
for entry in d.filter_map(|e| e.ok()) {
|
||||
let path = entry.path();
|
||||
let filename = match path.file_name().and_then(|s| s.to_str()) {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
|
||||
continue
|
||||
}
|
||||
let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()];
|
||||
if !name.starts_with("rustc_trans") {
|
||||
continue
|
||||
}
|
||||
if let Some(ref prev) = file {
|
||||
let err = format!("duplicate codegen backends found\n\
|
||||
first: {}\n\
|
||||
second: {}\n\
|
||||
", prev.display(), path.display());
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
file = Some(path.clone());
|
||||
}
|
||||
|
||||
match file {
|
||||
Some(ref s) => return load_backend_from_dylib(s),
|
||||
None => {
|
||||
let err = format!("failed to load default codegen backend, no appropriate \
|
||||
codegen dylib found in `{}`", sysroot.display());
|
||||
early_error(ErrorOutputType::default(), &err);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn current_dll_path() -> Option<PathBuf> {
|
||||
use std::ffi::{OsStr, CStr};
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
unsafe {
|
||||
let addr = current_dll_path as usize as *mut _;
|
||||
let mut info = mem::zeroed();
|
||||
if libc::dladdr(addr, &mut info) == 0 {
|
||||
info!("dladdr failed");
|
||||
return None
|
||||
}
|
||||
if info.dli_fname.is_null() {
|
||||
info!("dladdr returned null pointer");
|
||||
return None
|
||||
}
|
||||
let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
|
||||
let os = OsStr::from_bytes(bytes);
|
||||
Some(PathBuf::from(os))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn current_dll_path() -> Option<PathBuf> {
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::prelude::*;
|
||||
|
||||
extern "system" {
|
||||
fn GetModuleHandleExW(dwFlags: u32,
|
||||
lpModuleName: usize,
|
||||
phModule: *mut usize) -> i32;
|
||||
fn GetModuleFileNameW(hModule: usize,
|
||||
lpFilename: *mut u16,
|
||||
nSize: u32) -> u32;
|
||||
}
|
||||
|
||||
const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: u32 = 0x00000004;
|
||||
|
||||
unsafe {
|
||||
let mut module = 0;
|
||||
let r = GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
current_dll_path as usize,
|
||||
&mut module);
|
||||
if r == 0 {
|
||||
info!("GetModuleHandleExW failed: {}", io::Error::last_os_error());
|
||||
return None
|
||||
}
|
||||
let mut space = Vec::with_capacity(1024);
|
||||
let r = GetModuleFileNameW(module,
|
||||
space.as_mut_ptr(),
|
||||
space.capacity() as u32);
|
||||
if r == 0 {
|
||||
info!("GetModuleFileNameW failed: {}", io::Error::last_os_error());
|
||||
return None
|
||||
}
|
||||
let r = r as usize;
|
||||
if r >= space.capacity() {
|
||||
info!("our buffer was too small? {}",
|
||||
io::Error::last_os_error());
|
||||
return None
|
||||
}
|
||||
space.set_len(r);
|
||||
let os = OsString::from_wide(&space);
|
||||
Some(PathBuf::from(os))
|
||||
}
|
||||
Some(trans_name) => sess.fatal(&format!("Unknown codegen backend {}", trans_name)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -878,7 +1072,7 @@ fn unw(x: Option<&str>) -> &str {
|
||||
println!("commit-date: {}", unw(commit_date_str()));
|
||||
println!("host: {}", config::host_triple());
|
||||
println!("release: {}", unw(release_str()));
|
||||
rustc_trans::print_version();
|
||||
get_trans_default()().print_version();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1175,7 +1369,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
|
||||
}
|
||||
|
||||
if cg_flags.contains(&"passes=list".to_string()) {
|
||||
rustc_trans::print_passes();
|
||||
get_trans_default()().print_passes();
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -1284,8 +1478,8 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
|
||||
all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
|
||||
#[cfg(feature="llvm")]
|
||||
all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
|
||||
// FIXME: need to figure out a way to get these back in here
|
||||
// all_errors.extend_from_slice(get_trans(sess).diagnostics());
|
||||
all_errors.extend_from_slice(&rustc_trans_utils::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
|
||||
|
@ -228,7 +228,8 @@ fn call_with_pp_support_hir<'tcx, A, F>(&self,
|
||||
}
|
||||
PpmTyped => {
|
||||
let control = &driver::CompileController::basic();
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
|
||||
let trans = ::get_trans(sess);
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
|
||||
control,
|
||||
sess,
|
||||
cstore,
|
||||
@ -1081,7 +1082,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
let mut out = Vec::new();
|
||||
|
||||
let control = &driver::CompileController::basic();
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
|
||||
let trans = ::get_trans(sess);
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
|
||||
control,
|
||||
sess,
|
||||
cstore,
|
||||
|
@ -7,13 +7,13 @@ build = "build.rs"
|
||||
[lib]
|
||||
name = "rustc_llvm"
|
||||
path = "lib.rs"
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[features]
|
||||
static-libstdcpp = []
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
libc = "0.2"
|
||||
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -146,6 +146,7 @@ fn main() {
|
||||
cfg.define(&flag, None);
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed-env=LLVM_RUSTLLVM");
|
||||
if env::var_os("LLVM_RUSTLLVM").is_some() {
|
||||
cfg.define("LLVM_RUSTLLVM", None);
|
||||
}
|
||||
|
@ -38,7 +38,17 @@ pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
|
||||
// run.
|
||||
match maybe_library {
|
||||
Err(err) => Err(err),
|
||||
Ok(handle) => Ok(DynamicLibrary { handle: handle })
|
||||
Ok(handle) => Ok(DynamicLibrary { handle })
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a dynamic library into the global namespace (RTLD_GLOBAL on Unix)
|
||||
/// and do it now (don't use RTLD_LAZY on Unix).
|
||||
pub fn open_global_now(filename: &Path) -> Result<DynamicLibrary, String> {
|
||||
let maybe_library = dl::open_global_now(filename.as_os_str());
|
||||
match maybe_library {
|
||||
Err(err) => Err(err),
|
||||
Ok(handle) => Ok(DynamicLibrary { handle })
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,15 +155,20 @@ pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
||||
})
|
||||
}
|
||||
|
||||
const LAZY: libc::c_int = 1;
|
||||
pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> {
|
||||
check_for_errors_in(|| unsafe {
|
||||
let s = CString::new(filename.as_bytes()).unwrap();
|
||||
libc::dlopen(s.as_ptr(), libc::RTLD_GLOBAL | libc::RTLD_NOW) as *mut u8
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn open_external(filename: &OsStr) -> *mut u8 {
|
||||
let s = CString::new(filename.as_bytes()).unwrap();
|
||||
libc::dlopen(s.as_ptr(), LAZY) as *mut u8
|
||||
libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8
|
||||
}
|
||||
|
||||
unsafe fn open_internal() -> *mut u8 {
|
||||
libc::dlopen(ptr::null(), LAZY) as *mut u8
|
||||
libc::dlopen(ptr::null(), libc::RTLD_LAZY) as *mut u8
|
||||
}
|
||||
|
||||
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
|
||||
@ -224,6 +239,10 @@ fn GetProcAddress(handle: HMODULE,
|
||||
fn FreeLibrary(handle: HMODULE) -> BOOL;
|
||||
}
|
||||
|
||||
pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> {
|
||||
open(Some(filename))
|
||||
}
|
||||
|
||||
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
||||
// disable "dll load failed" error dialog.
|
||||
let prev_error_mode = unsafe {
|
||||
|
@ -13,6 +13,7 @@ test = false
|
||||
bitflags = "1.0"
|
||||
flate2 = "1.0"
|
||||
jobserver = "0.1.5"
|
||||
libc = "0.2"
|
||||
log = "0.4"
|
||||
num_cpus = "1.0"
|
||||
rustc = { path = "../librustc" }
|
||||
@ -36,3 +37,6 @@ tempdir = "0.3"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
cc = "1.0.1"
|
||||
|
||||
[features]
|
||||
jemalloc = ["rustc_back/jemalloc"]
|
||||
|
@ -69,7 +69,7 @@
|
||||
|
||||
use back::bytecode::RLIB_BYTECODE_EXTENSION;
|
||||
|
||||
pub use llvm_util::{target_features, print_version, print_passes};
|
||||
pub use llvm_util::target_features;
|
||||
|
||||
use std::any::Any;
|
||||
use std::path::PathBuf;
|
||||
@ -149,13 +149,16 @@ impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
|
||||
impl !Sync for LlvmTransCrate {}
|
||||
|
||||
impl LlvmTransCrate {
|
||||
pub fn new(sess: &Session) -> Box<TransCrate> {
|
||||
llvm_util::init(sess); // Make sure llvm is inited
|
||||
pub fn new() -> Box<TransCrate> {
|
||||
box LlvmTransCrate(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TransCrate for LlvmTransCrate {
|
||||
fn init(&self, sess: &Session) {
|
||||
llvm_util::init(sess); // Make sure llvm is inited
|
||||
}
|
||||
|
||||
fn print(&self, req: PrintRequest, sess: &Session) {
|
||||
match req {
|
||||
PrintRequest::RelocationModels => {
|
||||
@ -183,6 +186,19 @@ fn print(&self, req: PrintRequest, sess: &Session) {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_passes(&self) {
|
||||
llvm_util::print_passes();
|
||||
}
|
||||
|
||||
fn print_version(&self) {
|
||||
llvm_util::print_version();
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn diagnostics(&self) -> &[(&'static str, &'static str)] {
|
||||
&DIAGNOSTICS
|
||||
}
|
||||
|
||||
fn target_features(&self, sess: &Session) -> Vec<Symbol> {
|
||||
target_features(sess)
|
||||
}
|
||||
@ -252,8 +268,8 @@ fn join_trans_and_link(
|
||||
|
||||
/// This is the entrypoint for a hot plugged rustc_trans
|
||||
#[no_mangle]
|
||||
pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
|
||||
LlvmTransCrate::new(sess)
|
||||
pub fn __rustc_codegen_backend() -> Box<TransCrate> {
|
||||
LlvmTransCrate::new()
|
||||
}
|
||||
|
||||
struct ModuleTranslation {
|
||||
|
@ -48,8 +48,12 @@
|
||||
use link::{build_link_meta, out_filename};
|
||||
|
||||
pub trait TransCrate {
|
||||
fn init(&self, _sess: &Session) {}
|
||||
fn print(&self, _req: PrintRequest, _sess: &Session) {}
|
||||
fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
|
||||
fn print_passes(&self) {}
|
||||
fn print_version(&self) {}
|
||||
fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
|
||||
|
||||
fn metadata_loader(&self) -> Box<MetadataLoader>;
|
||||
fn provide(&self, _providers: &mut Providers);
|
||||
@ -168,7 +172,13 @@ pub struct OngoingCrateTranslation {
|
||||
}
|
||||
|
||||
impl MetadataOnlyTransCrate {
|
||||
pub fn new(sess: &Session) -> Box<TransCrate> {
|
||||
pub fn new() -> Box<TransCrate> {
|
||||
box MetadataOnlyTransCrate(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TransCrate for MetadataOnlyTransCrate {
|
||||
fn init(&self, sess: &Session) {
|
||||
for cty in sess.opts.crate_types.iter() {
|
||||
match *cty {
|
||||
CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
|
||||
@ -180,12 +190,8 @@ pub fn new(sess: &Session) -> Box<TransCrate> {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
box MetadataOnlyTransCrate(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TransCrate for MetadataOnlyTransCrate {
|
||||
fn metadata_loader(&self) -> Box<MetadataLoader> {
|
||||
box NoLlvmMetadataLoader
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use rustc_lint;
|
||||
use rustc_driver::{driver, target_features, abort_on_err};
|
||||
use rustc_driver::{self, driver, target_features, abort_on_err};
|
||||
use rustc::session::{self, config};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def::Def;
|
||||
@ -18,7 +18,6 @@
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::lint;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_trans;
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_metadata::creader::CrateLoader;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
@ -151,7 +150,7 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
let mut sess = session::build_session_(
|
||||
sessopts, cpath, diagnostic_handler, codemap,
|
||||
);
|
||||
let trans = rustc_trans::LlvmTransCrate::new(&sess);
|
||||
let trans = rustc_driver::get_trans(&sess);
|
||||
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
|
@ -63,8 +63,6 @@
|
||||
use std::process;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use rustc_driver::rustc_trans;
|
||||
|
||||
use externalfiles::ExternalHtml;
|
||||
use rustc::session::search_paths::SearchPaths;
|
||||
use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options,
|
||||
|
@ -33,7 +33,6 @@
|
||||
use rustc_driver::driver::phase_2_configure_and_expand;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc_resolve::MakeGlobMap;
|
||||
use rustc_trans;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::CodeMap;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
@ -84,7 +83,7 @@ pub fn run(input_path: &Path,
|
||||
let mut sess = session::build_session_(
|
||||
sessopts, Some(input_path.to_owned()), handler, codemap.clone(),
|
||||
);
|
||||
let trans = rustc_trans::LlvmTransCrate::new(&sess);
|
||||
let trans = rustc_driver::get_trans(&sess);
|
||||
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
sess.parse_sess.config =
|
||||
@ -249,7 +248,7 @@ fn drop(&mut self) {
|
||||
let mut sess = session::build_session_(
|
||||
sessopts, None, diagnostic_handler, codemap,
|
||||
);
|
||||
let trans = rustc_trans::LlvmTransCrate::new(&sess);
|
||||
let trans = rustc_driver::get_trans(&sess);
|
||||
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
|
@ -7,12 +7,9 @@ version = "0.0.0"
|
||||
name = "rustc"
|
||||
path = "rustc.rs"
|
||||
|
||||
# All optional dependencies so the features passed to this Cargo.toml select
|
||||
# what should actually be built.
|
||||
[dependencies]
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_driver = { path = "../librustc_driver" }
|
||||
|
||||
[features]
|
||||
jemalloc = ["rustc_back/jemalloc"]
|
||||
llvm = ["rustc_driver/llvm"]
|
||||
|
@ -77,6 +77,6 @@ fn join_trans_and_link(
|
||||
|
||||
/// This is the entrypoint for a hot plugged rustc_trans
|
||||
#[no_mangle]
|
||||
pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
|
||||
Box::new(TheBackend(MetadataOnlyTransCrate::new(sess)))
|
||||
pub fn __rustc_codegen_backend() -> Box<TransCrate> {
|
||||
Box::new(TheBackend(MetadataOnlyTransCrate::new()))
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_trans;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate syntax;
|
||||
|
||||
@ -63,7 +62,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>, Box<TransCrate>) {
|
||||
|
||||
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
|
||||
let sess = build_session(opts, None, descriptions);
|
||||
let trans = rustc_trans::LlvmTransCrate::new(&sess);
|
||||
let trans = rustc_driver::get_trans(&sess);
|
||||
let cstore = Rc::new(CStore::new(trans.metadata_loader()));
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
(sess, cstore, trans)
|
||||
|
@ -1,5 +1,9 @@
|
||||
-include ../tools.mk
|
||||
|
||||
ifeq ($(UNAME),Darwin)
|
||||
PLUGIN_FLAGS := -C link-args=-Wl,-undefined,dynamic_lookup
|
||||
endif
|
||||
|
||||
ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1)
|
||||
# ignore stage1
|
||||
all:
|
||||
@ -11,7 +15,7 @@ ifdef IS_WINDOWS
|
||||
all:
|
||||
else
|
||||
all: $(call NATIVE_STATICLIB,llvm-function-pass) $(call NATIVE_STATICLIB,llvm-module-pass)
|
||||
$(RUSTC) plugin.rs -C prefer-dynamic
|
||||
$(RUSTC) plugin.rs -C prefer-dynamic $(PLUGIN_FLAGS)
|
||||
$(RUSTC) main.rs
|
||||
|
||||
$(TMPDIR)/libllvm-function-pass.o:
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
extern crate rustc;
|
||||
extern crate rustc_plugin;
|
||||
extern crate rustc_trans;
|
||||
|
||||
#[link(name = "llvm-function-pass", kind = "static")]
|
||||
#[link(name = "llvm-module-pass", kind = "static")]
|
||||
|
@ -8,18 +8,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-cross-compile
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate tempdir;
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use tempdir::TempDir;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let td = TempDir::new("create-dir-all-bare").unwrap();
|
||||
env::set_current_dir(td.path()).unwrap();
|
||||
let path = PathBuf::from(env::var_os("RUST_TEST_TMPDIR").unwrap());
|
||||
env::set_current_dir(&path).unwrap();
|
||||
fs::create_dir_all("create-dir-all-bare").unwrap();
|
||||
}
|
||||
|
@ -11,15 +11,11 @@
|
||||
// no-prefer-dynamic
|
||||
// ignore-cross-compile
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate tempdir;
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::process;
|
||||
use std::str;
|
||||
use tempdir::TempDir;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
// If we're the child, make sure we were invoked correctly
|
||||
@ -41,8 +37,9 @@ fn test() {
|
||||
let my_path = env::current_exe().unwrap();
|
||||
let my_dir = my_path.parent().unwrap();
|
||||
|
||||
let child_dir = TempDir::new_in(&my_dir, "issue-15140-child").unwrap();
|
||||
let child_dir = child_dir.path();
|
||||
let child_dir = PathBuf::from(env::var_os("RUST_TEST_TMPDIR").unwrap());
|
||||
let child_dir = child_dir.join("issue-15140-child");
|
||||
fs::create_dir_all(&child_dir).unwrap();
|
||||
|
||||
let child_path = child_dir.join(&format!("mytest{}",
|
||||
env::consts::EXE_SUFFIX));
|
||||
@ -63,11 +60,4 @@ fn test() {
|
||||
format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
|
||||
str::from_utf8(&child_output.stdout).unwrap(),
|
||||
str::from_utf8(&child_output.stderr).unwrap()));
|
||||
|
||||
let res = fs::remove_dir_all(&child_dir);
|
||||
if res.is_err() {
|
||||
// On Windows deleting just executed mytest.exe can fail because it's still locked
|
||||
std::thread::sleep_ms(1000);
|
||||
fs::remove_dir_all(&child_dir).unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -13,17 +13,13 @@
|
||||
|
||||
// ignore-cross-compile
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate tempdir;
|
||||
|
||||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::fs::{self, File};
|
||||
use tempdir::TempDir;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn rename_directory() {
|
||||
let tmpdir = TempDir::new("rename_directory").ok().expect("rename_directory failed");
|
||||
let tmpdir = tmpdir.path();
|
||||
let tmpdir = PathBuf::from(env::var_os("RUST_TEST_TMPDIR").unwrap());
|
||||
let old_path = tmpdir.join("foo/bar/baz");
|
||||
fs::create_dir_all(&old_path).unwrap();
|
||||
let test_file = &old_path.join("temp.txt");
|
||||
|
@ -10,17 +10,12 @@
|
||||
|
||||
// ignore-cross-compile
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate tempdir;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::{Read, Write};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use tempdir::TempDir;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
if env::args().len() > 1 {
|
||||
@ -31,9 +26,9 @@ fn main() {
|
||||
}
|
||||
|
||||
fn parent() -> io::Result<()> {
|
||||
let td = TempDir::new("foo").unwrap();
|
||||
let input = td.path().join("input");
|
||||
let output = td.path().join("output");
|
||||
let td = PathBuf::from(env::var_os("RUST_TEST_TMPDIR").unwrap());
|
||||
let input = td.join("stdio-from-input");
|
||||
let output = td.join("stdio-from-output");
|
||||
|
||||
File::create(&input)?.write_all(b"foo\n")?;
|
||||
|
||||
|
@ -8,14 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate tempdir;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use tempdir::TempDir;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(unix)]
|
||||
fn switch_stdout_to(file: File) {
|
||||
@ -48,8 +44,8 @@ fn switch_stdout_to(file: File) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let td = TempDir::new("foo").unwrap();
|
||||
let path = td.path().join("bar");
|
||||
let path = PathBuf::from(env::var_os("RUST_TEST_TMPDIR").unwrap());
|
||||
let path = path.join("switch-stdout-output");
|
||||
let f = File::create(&path).unwrap();
|
||||
|
||||
println!("foo");
|
||||
|
@ -667,9 +667,16 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
|
||||
for pretty_printer_file in &pretty_printer_files {
|
||||
inputs.push(mtime(&rust_src_dir.join(pretty_printer_file)));
|
||||
}
|
||||
for lib in config.run_lib_path.read_dir().unwrap() {
|
||||
let lib = lib.unwrap();
|
||||
inputs.push(mtime(&lib.path()));
|
||||
let mut entries = config.run_lib_path.read_dir().unwrap()
|
||||
.collect::<Vec<_>>();
|
||||
while let Some(entry) = entries.pop() {
|
||||
let entry = entry.unwrap();
|
||||
let path = entry.path();
|
||||
if entry.metadata().unwrap().is_file() {
|
||||
inputs.push(mtime(&path));
|
||||
} else {
|
||||
entries.extend(path.read_dir().unwrap());
|
||||
}
|
||||
}
|
||||
if let Some(ref rustdoc_path) = config.rustdoc_path {
|
||||
inputs.push(mtime(&rustdoc_path));
|
||||
|
Loading…
Reference in New Issue
Block a user