]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Load the `rustc_trans` crate at runtime
authorAlex Crichton <alex@alexcrichton.com>
Mon, 22 Jan 2018 15:29:24 +0000 (07:29 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 28 Jan 2018 03:16:21 +0000 (19:16 -0800)
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.

33 files changed:
src/Cargo.lock
src/Cargo.toml
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/librustc/Cargo.toml
src/librustc_driver/Cargo.toml
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_llvm/Cargo.toml
src/librustc_llvm/build.rs
src/librustc_metadata/dynamic_lib.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/lib.rs
src/librustc_trans_utils/trans_crate.rs
src/librustdoc/core.rs
src/librustdoc/lib.rs
src/librustdoc/test.rs
src/rustc/Cargo.toml
src/test/run-make/hotplug_codegen_backend/the_backend.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-make/llvm-pass/Makefile
src/test/run-make/llvm-pass/plugin.rs
src/test/run-pass-fulldeps/create-dir-all-bare.rs
src/test/run-pass-fulldeps/issue-15149.rs
src/test/run-pass-fulldeps/rename-directory.rs
src/test/run-pass-fulldeps/stdio-from.rs
src/test/run-pass-fulldeps/switch-stdout.rs
src/tools/compiletest/src/main.rs

index e7bf1b6b4e14ddc21f98d968d29cd00a725c1705..d26098903eec5a05931545f94a6a665c149c9290 100644 (file)
@@ -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",
index ad795b23cf2158983ac99ec52d7369a0d5f13247..c22ba7a37c8b07032f6b768be64101e7a2150c4d 100644 (file)
@@ -4,6 +4,7 @@ members = [
   "rustc",
   "libstd",
   "libtest",
+  "librustc_trans",
   "tools/cargotest",
   "tools/clippy",
   "tools/compiletest",
index 0bc82c4f9f2c2571235083bca558478f6eeaf536..e6871764b2c78ffee2d47dcdab3e9c2c8b156dc7 100644 (file)
@@ -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),
index 21bbd82dd333a725df98687ff1ad0559ae54fc7b..0b247c6f7555762317546dcb782e5bc88fc38c61 100644 (file)
@@ -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));
index 224b31ef26872469d600fc87ff4b99cb006fb0bf..4127239dc49b87d27eed38ff93fa3f7302f290dd 100644 (file)
@@ -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")
index 9bf762a3b4bfda3b41648e0d4628bc64157873bf..6a75fc5112f5c2d07043aaf0063cbc0744d3415e 100644 (file)
@@ -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
index a6a5ba67723901ea32cd44de9a85449c521be26f..8928bef9faa56b5d5172f58c10e6f0f869e000c1 100644 (file)
@@ -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
     }
 
index ba8cf3a8e2eb597844e202e5563937646c758f80..442098a7afa77d7bfd55342149e66ace16b163d7 100644 (file)
@@ -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) {
index 5faec27943847e5a63314d807667baeaa9e80866..a316b0f7ef91b7ef1da39d9c64a6bc212b66e141 100644 (file)
@@ -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"),
index f95dbcf411cba5eee54b9437a0e3e14e821ff348..2c4898cb2c006dc61f1dfbe69d9910c6d94bd319 100644 (file)
@@ -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.
 #
index 4f7bbd7927575ac8b92c69be9b35d2b426a996b7..18493b8bb39406cab6e41d8b9a48c44a6dc93d97 100644 (file)
@@ -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"]
index cdb50a0ae48507a90d180fb1b9e32aaaa4f9a4c5..029cceda532e56add40a15bc1a50be1c5fc5ae43 100644 (file)
@@ -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;
 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;
+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)),
     }
 }
 
@@ -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);
index 68f4b17a6a3f24a8f7b99bc46052f3df7f7c912c..4ae6a93d6983a12bd8535c7b19f1fca136ce4401 100644 (file)
@@ -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,
index a9566c4bcacd7e791d2ac470632e4c46714b7bdb..45e97127ede7f81634e3861ff7171e8c8ad3a220 100644 (file)
@@ -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]
index 91dc3210e11abc025d5671947f3f1eea0eccf149..49b93f3c7d6a248fd37b9020a5b606b582ef6849 100644 (file)
@@ -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);
     }
index 1b42fa03a4fb621e3957708aac4424e122c4c670..d7da0d00012e15261e1ffd2f4c7df5271bf374a6 100644 (file)
@@ -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 {
index 79dd57b37f41fdead93d80145de0f452ab39cf42..14591de31ca96efb13651121530e7e4a79f3c41f 100644 (file)
@@ -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"]
index b67997081aa67c04e79688cd2760710e109f53b4..908d3790170acd110ba21fe75811844c1ad3c15a 100644 (file)
@@ -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 {
index 49756d754fe55edead0878dda179bb50d59aa575..e14abdff3391830cd130df181c2588ec3aa99803 100644 (file)
 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
     }
index 5fe4794389ff5a7cfe59a9d4f44cceb84fdf50d5..0674a0b5a3b1096863cc3d4316a22e4a95de575f 100644 (file)
@@ -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));
 
index ccd79e5b2c5f4e7066cdc8a44af7e885799ab18e..e39fe20310c2851a8288033b32fed37c2376e9a8 100644 (file)
@@ -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,
index 10850f88f2d624d2944d0aef915f9a4ba2f65638..d61b80c9aa03efae6e6504473926a20c96fe68e8 100644 (file)
@@ -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));
 
index d185c061d5bd9fb6656b7240de820824447d2137..bbc4c2ee43e079dd9cb0f2900aaf68e586c6d5bd 100644 (file)
@@ -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"]
index 0de404ed249d5eec54acb15d7ef2ab178180bbba..5972149590c23cfaf25903f161d3d0aab84bcb6e 100644 (file)
@@ -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()))
 }
index c360dde618ef54f2f2a7167c0081f4643a505716..b4b29e15ce174c4c08a14c07459d3d833df34c03 100644 (file)
@@ -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)
index 0d31d2c823500ab64d6d9412b77de4300d71db1d..8a18aadf36a8bb635684927b165c09f869f0c862 100644 (file)
@@ -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:
index 37aab2bbd059aa61579de5e914b41bdb71381abc..f77b2fca857a613e3759bb50b4fec40995186fc6 100644 (file)
@@ -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")]
index ba42cb870c97edf124f38b8192c76314cfb0074f..a35eed1f72d7913814a43ef64c2c8b62cf48802a 100644 (file)
@@ -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();
 }
index 121fd4a9825df0d3770b66ed3db7a1da5a468bf8..15ac1d55cc8c41a2164112f0f917eac8dff55bda 100644 (file)
 // 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();
-    }
 }
index 7a2a4343522bb05e4ce8b062c246a3441f527793..417707e89322c27611f685ec7a724d73c87a7a3c 100644 (file)
 
 // 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");
index 535ab711f5bcf62ee8803cd4c229a5809ec6775d..5b28ce0f0c68da7ae13d20e28387493e5201f3d4 100644 (file)
 
 // 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")?;
 
index 16f7e2832853663452934ebbd86f0be7dc52783c..316b97f17ef94eeb44f0bcecfa24ddbec6ac6f05 100644 (file)
@@ -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");
index 533aaf9cd27353bf9e0b78eab246f8df8728da72..b98a4248d81d68429318859d256b05c4ded72f82 100644 (file)
@@ -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));