about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/compiletest/procsrv.rs61
-rw-r--r--src/librustc/metadata/filesearch.rs2
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/librustdoc/test.rs28
-rw-r--r--src/libstd/unstable/dynamic_lib.rs68
5 files changed, 99 insertions, 62 deletions
diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs
index 9f62fd7096c..6b273c2d463 100644
--- a/src/compiletest/procsrv.rs
+++ b/src/compiletest/procsrv.rs
@@ -11,54 +11,31 @@
 use std::os;
 use std::str;
 use std::io::process::{ProcessExit, Command, Process, ProcessOutput};
+use std::unstable::dynamic_lib::DynamicLibrary;
 
-#[cfg(target_os = "win32")]
 fn target_env(lib_path: &str, prog: &str) -> Vec<(StrBuf, StrBuf)> {
-    let env = os::env();
+    let prog = if cfg!(windows) {prog.slice_to(prog.len() - 4)} else {prog};
+    let aux_path = prog + ".libaux";
 
-    // Make sure we include the aux directory in the path
-    assert!(prog.ends_with(".exe"));
-    let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ".libaux";
+    // Need to be sure to put both the lib_path and the aux path in the dylib
+    // search path for the child.
+    let mut path = DynamicLibrary::search_path();
+    path.insert(0, Path::new(aux_path));
+    path.insert(0, Path::new(lib_path));
 
-    let mut new_env: Vec<_> = env.move_iter().map(|(k, v)| {
-        let new_v = if "PATH" == k {
-            format_strbuf!("{};{};{}", v, lib_path, aux_path)
-        } else {
-            v.to_strbuf()
-        };
-        (k.to_strbuf(), new_v)
-    }).collect();
-    if prog.ends_with("rustc.exe") {
-        new_env.push(("RUST_THREADS".to_strbuf(), "1".to_strbuf()));
+    // Remove the previous dylib search path var
+    let var = DynamicLibrary::envvar();
+    let mut env: Vec<(StrBuf,StrBuf)> =
+        os::env().move_iter().map(|(a,b)|(a.to_strbuf(), b.to_strbuf())).collect();
+    match env.iter().position(|&(ref k, _)| k.as_slice() == var) {
+        Some(i) => { env.remove(i); }
+        None => {}
     }
-    return new_env;
-}
 
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
-fn target_env(lib_path: &str, prog: &str) -> Vec<(StrBuf,StrBuf)> {
-    // Make sure we include the aux directory in the path
-    let aux_path = prog + ".libaux";
-
-    let mut env: Vec<(StrBuf,StrBuf)> =
-        os::env().move_iter()
-                 .map(|(ref k, ref v)| (k.to_strbuf(), v.to_strbuf()))
-                 .collect();
-    let var = if cfg!(target_os = "macos") {
-        "DYLD_LIBRARY_PATH"
-    } else {
-        "LD_LIBRARY_PATH"
-    };
-    let prev = match env.iter().position(|&(ref k, _)| k.as_slice() == var) {
-        Some(i) => env.remove(i).unwrap().val1(),
-        None => "".to_strbuf(),
-    };
-    env.push((var.to_strbuf(), if prev.is_empty() {
-        format_strbuf!("{}:{}", lib_path, aux_path)
-    } else {
-        format_strbuf!("{}:{}:{}", lib_path, aux_path, prev)
-    }));
+    // Add the new dylib search path var
+    let newpath = DynamicLibrary::create_path(path.as_slice());
+    env.push((var.to_strbuf(),
+              str::from_utf8(newpath.as_slice()).unwrap().to_strbuf()));
     return env;
 }
 
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index f339c6c8f74..238b23d6c5a 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -136,7 +136,7 @@ impl<'a> FileSearch<'a> {
 
     pub fn add_dylib_search_paths(&self) {
         self.for_each_lib_search_path(|lib_search_path| {
-            DynamicLibrary::add_search_path(lib_search_path);
+            DynamicLibrary::prepend_search_path(lib_search_path);
             FileDoesntMatch
         })
     }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 2a7808fdf77..48db910fc39 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -284,7 +284,7 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
         core::run_core(libs.move_iter().map(|x| x.clone()).collect(),
                        cfgs.move_iter().map(|x| x.to_strbuf()).collect(),
                        &cr)
-    }).unwrap();
+    }).map_err(|boxed_any|format!("{:?}", boxed_any)).unwrap();
     info!("finished with rustc");
     analysiskey.replace(Some(analysis));
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index c56841a076d..6a07b7a906e 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -15,6 +15,7 @@ use std::io::{Command, TempDir};
 use std::os;
 use std::str;
 use std::strbuf::StrBuf;
+use std::unstable::dynamic_lib::DynamicLibrary;
 
 use collections::{HashSet, HashMap};
 use testing;
@@ -150,12 +151,37 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
     let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
     let out = Some(outdir.path().clone());
     let cfg = config::build_configuration(&sess);
+    let libdir = sess.target_filesearch().get_lib_path();
     driver::compile_input(sess, cfg, &input, &out, &None);
 
     if no_run { return }
 
     // Run the code!
-    match Command::new(outdir.path().join("rust_out")).output() {
+    //
+    // We're careful to prepend the *target* dylib search path to the child's
+    // environment to ensure that the target loads the right libraries at
+    // runtime. It would be a sad day if the *host* libraries were loaded as a
+    // mistake.
+    let exe = outdir.path().join("rust_out");
+    let env = {
+        let mut path = DynamicLibrary::search_path();
+        path.insert(0, libdir.clone());
+
+        // Remove the previous dylib search path var
+        let var = DynamicLibrary::envvar();
+        let mut env: Vec<(~str,~str)> = os::env().move_iter().collect();
+        match env.iter().position(|&(ref k, _)| k.as_slice() == var) {
+            Some(i) => { env.remove(i); }
+            None => {}
+        };
+
+        // Add the new dylib search path var
+        let newpath = DynamicLibrary::create_path(path.as_slice());
+        env.push((var.to_owned(),
+                  str::from_utf8(newpath.as_slice()).unwrap().to_owned()));
+        env
+    };
+    match Command::new(exe).env(env.as_slice()).output() {
         Err(e) => fail!("couldn't run the test: {}{}", e,
                         if e.kind == io::PermissionDenied {
                             " - maybe your tempdir is mounted with noexec?"
diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs
index 4a9c5349459..d50c63c5832 100644
--- a/src/libstd/unstable/dynamic_lib.rs
+++ b/src/libstd/unstable/dynamic_lib.rs
@@ -16,16 +16,16 @@ A simple wrapper over the platform's dynamic library facilities
 
 */
 
-
+use clone::Clone;
 use c_str::ToCStr;
+use iter::Iterator;
 use mem;
 use ops::*;
 use option::*;
 use os;
-use path::GenericPath;
-use path;
+use path::{Path,GenericPath};
 use result::*;
-use slice::Vector;
+use slice::{Vector,ImmutableVector};
 use str;
 use vec::Vec;
 
@@ -76,22 +76,55 @@ impl DynamicLibrary {
         }
     }
 
-    /// Appends a path to the system search path for dynamic libraries
-    pub fn add_search_path(path: &path::Path) {
-        let (envvar, sep) = if cfg!(windows) {
-            ("PATH", ';' as u8)
+    /// Prepends a path to this process's search path for dynamic libraries
+    pub fn prepend_search_path(path: &Path) {
+        let mut search_path = DynamicLibrary::search_path();
+        search_path.insert(0, path.clone());
+        let newval = DynamicLibrary::create_path(search_path.as_slice());
+        os::setenv(DynamicLibrary::envvar(),
+                   str::from_utf8(newval.as_slice()).unwrap());
+    }
+
+    /// From a slice of paths, create a new vector which is suitable to be an
+    /// environment variable for this platforms dylib search path.
+    pub fn create_path(path: &[Path]) -> Vec<u8> {
+        let mut newvar = Vec::new();
+        for (i, path) in path.iter().enumerate() {
+            if i > 0 { newvar.push(DynamicLibrary::separator()); }
+            newvar.push_all(path.as_vec());
+        }
+        return newvar;
+    }
+
+    /// Returns the environment variable for this process's dynamic library
+    /// search path
+    pub fn envvar() -> &'static str {
+        if cfg!(windows) {
+            "PATH"
         } else if cfg!(target_os = "macos") {
-            ("DYLD_LIBRARY_PATH", ':' as u8)
+            "DYLD_LIBRARY_PATH"
         } else {
-            ("LD_LIBRARY_PATH", ':' as u8)
-        };
-        let mut newenv = Vec::from_slice(path.as_vec());
-        newenv.push(sep);
-        match os::getenv_as_bytes(envvar) {
-            Some(bytes) => newenv.push_all(bytes),
+            "LD_LIBRARY_PATH"
+        }
+    }
+
+    fn separator() -> u8 {
+        if cfg!(windows) {';' as u8} else {':' as u8}
+    }
+
+    /// Returns the current search path for dynamic libraries being used by this
+    /// process
+    pub fn search_path() -> Vec<Path> {
+        let mut ret = Vec::new();
+        match os::getenv_as_bytes(DynamicLibrary::envvar()) {
+            Some(env) => {
+                for portion in env.split(|a| *a == DynamicLibrary::separator()) {
+                    ret.push(Path::new(portion));
+                }
+            }
             None => {}
         }
-        os::setenv(envvar, str::from_utf8(newenv.as_slice()).unwrap());
+        return ret;
     }
 
     /// Access the value at the symbol of the dynamic library
@@ -168,11 +201,12 @@ mod test {
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
 pub mod dl {
+    use prelude::*;
+
     use c_str::ToCStr;
     use libc;
     use ptr;
     use str;
-    use result::*;
 
     pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
         filename.with_c_str(|raw_name| {