diff options
Diffstat (limited to 'src/librustc_back/rpath.rs')
| -rw-r--r-- | src/librustc_back/rpath.rs | 144 |
1 files changed, 62 insertions, 82 deletions
diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index 943ff52925a..4f9f1447d8a 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -10,26 +10,20 @@ use std::collections::HashSet; use std::env; -use std::old_io::IoError; -use std::os; +use std::io; +use std::path::{Path, PathBuf}; use syntax::ast; -pub struct RPathConfig<F, G> where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result<Path, IoError>, -{ - pub used_crates: Vec<(ast::CrateNum, Option<Path>)>, - pub out_filename: Path, +pub struct RPathConfig<'a> { + pub used_crates: Vec<(ast::CrateNum, Option<PathBuf>)>, + pub out_filename: PathBuf, pub is_like_osx: bool, pub has_rpath: bool, - pub get_install_prefix_lib_path: F, - pub realpath: G, + pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf, + pub realpath: &'a mut FnMut(&Path) -> io::Result<PathBuf>, } -pub fn get_rpath_flags<F, G>(config: RPathConfig<F, G>) -> Vec<String> where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result<Path, IoError>, -{ +pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> { // No rpath on windows if !config.has_rpath { return Vec::new(); @@ -54,10 +48,7 @@ fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> { return ret; } -fn get_rpaths<F, G>(mut config: RPathConfig<F, G>, libs: &[Path]) -> Vec<String> where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result<Path, IoError>, -{ +fn get_rpaths(config: &mut RPathConfig, libs: &[PathBuf]) -> Vec<String> { debug!("output: {:?}", config.out_filename.display()); debug!("libs:"); for libpath in libs { @@ -67,7 +58,7 @@ fn get_rpaths<F, G>(mut config: RPathConfig<F, G>, libs: &[Path]) -> Vec<String> // Use relative paths to the libraries. Binaries can be moved // as long as they maintain the relative relationship to the // crates they depend on. - let rel_rpaths = get_rpaths_relative_to_output(&mut config, libs); + let rel_rpaths = get_rpaths_relative_to_output(config, libs); // And a final backup rpath to the global library location. let fallback_rpaths = vec!(get_install_prefix_rpath(config)); @@ -90,18 +81,12 @@ fn get_rpaths<F, G>(mut config: RPathConfig<F, G>, libs: &[Path]) -> Vec<String> return rpaths; } -fn get_rpaths_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, - libs: &[Path]) -> Vec<String> where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result<Path, IoError>, -{ +fn get_rpaths_relative_to_output(config: &mut RPathConfig, + libs: &[PathBuf]) -> Vec<String> { libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect() } -fn get_rpath_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, lib: &Path) -> String where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result<Path, IoError>, -{ +fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String { // Mac doesn't appear to support $ORIGIN let prefix = if config.is_like_osx { "@loader_path" @@ -109,23 +94,36 @@ fn get_rpath_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, lib: &Path "$ORIGIN" }; - let cwd = os::getcwd().unwrap(); + let cwd = env::current_dir().unwrap(); let mut lib = (config.realpath)(&cwd.join(lib)).unwrap(); lib.pop(); let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap(); output.pop(); - let relative = lib.path_relative_from(&output); - let relative = relative.expect("could not create rpath relative to output"); + let relative = relativize(&lib, &output); // FIXME (#9639): This needs to handle non-utf8 paths - format!("{}/{}", - prefix, - relative.as_str().expect("non-utf8 component in path")) + format!("{}/{}", prefix, + relative.to_str().expect("non-utf8 component in path")) } -fn get_install_prefix_rpath<F, G>(config: RPathConfig<F, G>) -> String where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result<Path, IoError>, -{ +fn relativize(path: &Path, rel: &Path) -> PathBuf { + let mut res = PathBuf::new(""); + let mut cur = rel; + while !path.starts_with(cur) { + res.push(".."); + match cur.parent() { + Some(p) => cur = p, + None => panic!("can't create relative paths across filesystems"), + } + } + match path.relative_from(cur) { + Some(s) => { res.push(s); res } + None => panic!("couldn't create relative path from {:?} to {:?}", + rel, path), + } + +} + +fn get_install_prefix_rpath(config: &mut RPathConfig) -> String { let path = (config.get_install_prefix_lib_path)(); let path = env::current_dir().unwrap().join(&path); // FIXME (#9639): This needs to handle non-utf8 paths @@ -147,6 +145,7 @@ fn minimize_rpaths(rpaths: &[String]) -> Vec<String> { mod test { use super::{RPathConfig}; use super::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output}; + use std::path::{Path, PathBuf}; #[test] fn test_rpaths_to_flags() { @@ -195,50 +194,31 @@ mod test { } #[test] - #[cfg(any(target_os = "linux", target_os = "android"))] fn test_rpath_relative() { - let config = &mut RPathConfig { - used_crates: Vec::new(), - out_filename: Path::new("bin/rustc"), - get_install_prefix_lib_path: || panic!(), - has_rpath: true, - is_like_osx: false, - realpath: |p| Ok(p.clone()) - }; - let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); - assert_eq!(res, "$ORIGIN/../lib"); - } - - #[test] - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "bitrig", - target_os = "openbsd"))] - fn test_rpath_relative() { - let config = &mut RPathConfig { - used_crates: Vec::new(), - has_rpath: true, - is_like_osx: false, - out_filename: Path::new("bin/rustc"), - get_install_prefix_lib_path: || panic!(), - realpath: |p| Ok(p.clone()) - }; - let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); - assert_eq!(res, "$ORIGIN/../lib"); - } - - #[test] - #[cfg(target_os = "macos")] - fn test_rpath_relative() { - let config = &mut RPathConfig { - used_crates: Vec::new(), - has_rpath: true, - is_like_osx: true, - out_filename: Path::new("bin/rustc"), - get_install_prefix_lib_path: || panic!(), - realpath: |p| Ok(p.clone()) - }; - let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); - assert_eq!(res, "@loader_path/../lib"); + if cfg!(target_os = "macos") { + let config = &mut RPathConfig { + used_crates: Vec::new(), + has_rpath: true, + is_like_osx: true, + out_filename: PathBuf::new("bin/rustc"), + get_install_prefix_lib_path: &mut || panic!(), + realpath: &mut |p| Ok(p.to_path_buf()), + }; + let res = get_rpath_relative_to_output(config, + Path::new("lib/libstd.so")); + assert_eq!(res, "@loader_path/../lib"); + } else { + let config = &mut RPathConfig { + used_crates: Vec::new(), + out_filename: PathBuf::new("bin/rustc"), + get_install_prefix_lib_path: &mut || panic!(), + has_rpath: true, + is_like_osx: false, + realpath: &mut |p| Ok(p.to_path_buf()), + }; + let res = get_rpath_relative_to_output(config, + Path::new("lib/libstd.so")); + assert_eq!(res, "$ORIGIN/../lib"); + } } } |
