"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",
"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",
]
"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",
"rustc",
"libstd",
"libtest",
+ "librustc_trans",
"tools/cargotest",
"tools/clippy",
"tools/compiletest",
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),
}
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));
}
}
}
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),
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),
}
}
-/// 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())
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);
}
}
}
+#[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 {
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())
}
}
// 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
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;
}
}
- 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));
}
}
+ // 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");
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")
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
if self.config.use_jemalloc {
features.push_str(" jemalloc");
}
- if self.config.llvm_enabled {
- features.push_str(" llvm");
- }
features
}
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) {
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") {
}
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"),
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" }
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.
#
[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" }
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" }
syntax_pos = { path = "../libsyntax_pos" }
ar = "0.3.0"
-
-[features]
-llvm = ["rustc_trans"]
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;
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;
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;
+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) => {
+ 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);
+ }
+ }
+ }
+}
-#[cfg(not(feature="llvm"))]
-pub mod rustc_trans {
- pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate;
+pub fn get_trans(sess: &Session) -> Box<TransCrate> {
+ 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));
+ }
+ };
- pub fn print_version() {}
- pub fn print_passes() {}
+ unsafe {
+ LOAD = backend;
+ }
+ });
+ let backend = unsafe { LOAD() };
+ backend.init(sess);
+ backend
}
-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 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()));
}
}
- Err(err) => {
- sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", backend_name, err));
+ }
+
+ 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());
}
-}
-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)
+ 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);
}
- Some(filename) if filename.contains(".") => {
- load_backend_from_dylib(&sess, &filename)
+ }
+
+ #[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)),
}
}
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();
}
}
}
if cg_flags.contains(&"passes=list".to_string()) {
- rustc_trans::print_passes();
+ get_trans_default()().print_passes();
return None;
}
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);
}
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,
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,
[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]
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);
}
// 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 })
}
}
})
}
- 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
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 {
bitflags = "1.0"
flate2 = "1.0"
jobserver = "0.1.5"
+libc = "0.2"
log = "0.4"
num_cpus = "1.0"
rustc = { path = "../librustc" }
[target."cfg(windows)".dependencies]
cc = "1.0.1"
+
+[features]
+jemalloc = ["rustc_back/jemalloc"]
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;
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 => {
}
}
+ 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)
}
/// 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 {
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);
}
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 |
},
}
}
-
- box MetadataOnlyTransCrate(())
}
-}
-impl TransCrate for MetadataOnlyTransCrate {
fn metadata_loader(&self) -> Box<MetadataLoader> {
box NoLlvmMetadataLoader
}
// 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;
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;
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));
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,
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;
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 =
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));
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"]
/// 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()))
}
extern crate rustc_lint;
extern crate rustc_metadata;
extern crate rustc_errors;
-extern crate rustc_trans;
extern crate rustc_trans_utils;
extern crate syntax;
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)
-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:
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:
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")]
// 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();
}
// 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
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));
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();
- }
}
// 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");
// 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 {
}
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")?;
// 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) {
}
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");
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));