diff --git a/mk/main.mk b/mk/main.mk index fa19a4b380ec6..f2bcdbd4bd539 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -358,7 +358,6 @@ CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 endif endif -ifdef CFG_DISABLE_RPATH ifeq ($$(OSTYPE_$(3)),apple-darwin) RPATH_VAR$(1)_T_$(2)_H_$(3) := \ DYLD_LIBRARY_PATH="$$$$DYLD_LIBRARY_PATH:$$(CURDIR)/$$(HLIB$(1)_H_$(3))" @@ -366,9 +365,6 @@ else RPATH_VAR$(1)_T_$(2)_H_$(3) := \ LD_LIBRARY_PATH="$$$$LD_LIBRARY_PATH:$$(CURDIR)/$$(HLIB$(1)_H_$(3))" endif -else - RPATH_VAR$(1)_T_$(2)_H_$(3) := -endif STAGE$(1)_T_$(2)_H_$(3) := \ $$(Q)$$(RPATH_VAR$(1)_T_$(2)_H_$(3)) \ diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index c47f9893cd2ef..e455c4ad23ce0 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -12,9 +12,10 @@ use driver::session::Session; use metadata::cstore; use metadata::filesearch; +use util::fs; use collections::HashSet; -use std::{os, slice}; +use std::os; use syntax::abi; fn not_win32(os: abi::Os) -> bool { @@ -42,10 +43,9 @@ pub fn get_rpath_flags(sess: &Session, out_filename: &Path) -> Vec<~str> { let sysroot = sess.filesearch().sysroot; let output = out_filename; let libs = sess.cstore.get_used_crates(cstore::RequireDynamic); - let libs = libs.move_iter().filter_map(|(_, l)| l.map(|p| p.clone())).collect(); - // We don't currently rpath extern libraries, but we know - // where rustrt is and we know every rust program needs it - let libs = slice::append_one(libs, get_sysroot_absolute_rt_lib(sess)); + let libs = libs.move_iter().filter_map(|(_, l)| { + l.map(|p| p.clone()) + }).collect::<~[_]>(); let rpaths = get_rpaths(os, sysroot, output, libs, sess.opts.target_triple); @@ -53,14 +53,6 @@ pub fn get_rpath_flags(sess: &Session, out_filename: &Path) -> Vec<~str> { flags } -fn get_sysroot_absolute_rt_lib(sess: &Session) -> Path { - let sysroot = sess.filesearch().sysroot; - let r = filesearch::relative_target_lib_path(sysroot, sess.opts.target_triple); - let mut p = sysroot.join(&r); - p.push(os::dll_filename("rustrt")); - p -} - pub fn rpaths_to_flags(rpaths: &[~str]) -> Vec<~str> { let mut ret = Vec::new(); for rpath in rpaths.iter() { @@ -87,10 +79,6 @@ fn get_rpaths(os: abi::Os, // crates they depend on. let rel_rpaths = get_rpaths_relative_to_output(os, output, libs); - // Make backup absolute paths to the libraries. Binaries can - // be moved as long as the crates they link against don't move. - let abs_rpaths = get_absolute_rpaths(libs); - // And a final backup rpath to the global library location. let fallback_rpaths = vec!(get_install_prefix_rpath(sysroot, target_triple)); @@ -102,11 +90,9 @@ fn get_rpaths(os: abi::Os, } log_rpaths("relative", rel_rpaths.as_slice()); - log_rpaths("absolute", abs_rpaths.as_slice()); log_rpaths("fallback", fallback_rpaths.as_slice()); let mut rpaths = rel_rpaths; - rpaths.push_all(abs_rpaths.as_slice()); rpaths.push_all(fallback_rpaths.as_slice()); // Remove duplicates @@ -136,9 +122,9 @@ pub fn get_rpath_relative_to_output(os: abi::Os, abi::OsWin32 => unreachable!() }; - let mut lib = os::make_absolute(lib); + let mut lib = fs::realpath(&os::make_absolute(lib)).unwrap(); lib.pop(); - let mut output = os::make_absolute(output); + let mut output = fs::realpath(&os::make_absolute(output)).unwrap(); output.pop(); let relative = lib.path_relative_from(&output); let relative = relative.expect("could not create rpath relative to output"); @@ -146,17 +132,6 @@ pub fn get_rpath_relative_to_output(os: abi::Os, prefix+"/"+relative.as_str().expect("non-utf8 component in path") } -fn get_absolute_rpaths(libs: &[Path]) -> Vec<~str> { - libs.iter().map(|a| get_absolute_rpath(a)).collect() -} - -pub fn get_absolute_rpath(lib: &Path) -> ~str { - let mut p = os::make_absolute(lib); - p.pop(); - // FIXME (#9639): This needs to handle non-utf8 paths - p.as_str().expect("non-utf8 component in rpath").to_owned() -} - pub fn get_install_prefix_rpath(sysroot: &Path, target_triple: &str) -> ~str { let install_prefix = env!("CFG_PREFIX"); @@ -183,7 +158,7 @@ pub fn minimize_rpaths(rpaths: &[~str]) -> Vec<~str> { mod test { use std::os; - use back::rpath::{get_absolute_rpath, get_install_prefix_rpath}; + use back::rpath::get_install_prefix_rpath; use back::rpath::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output}; use syntax::abi; use metadata::filesearch; @@ -258,15 +233,4 @@ mod test { &Path::new("lib/libstd.so")); assert_eq!(res.as_slice(), "@loader_path/../lib"); } - - #[test] - fn test_get_absolute_rpath() { - let res = get_absolute_rpath(&Path::new("lib/libstd.so")); - let lib = os::make_absolute(&Path::new("lib")); - debug!("test_get_absolute_rpath: {} vs. {}", - res.to_str(), lib.display()); - - // FIXME (#9639): This needs to handle non-utf8 paths - assert_eq!(res.as_slice(), lib.as_str().expect("non-utf8 component in path")); - } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 95627cd1039af..f8b701ee5b018 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -127,6 +127,7 @@ pub mod util { pub mod ppaux; pub mod sha2; pub mod nodemap; + pub mod fs; } pub mod lib { diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index b83f42da0a056..a752a3e1444bb 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -15,6 +15,8 @@ use std::os; use std::io::fs; use collections::HashSet; +use myfs = util::fs; + pub enum FileMatch { FileMatches, FileDoesntMatch } // A module for searching for libraries @@ -156,17 +158,10 @@ fn make_rustpkg_target_lib_path(sysroot: &Path, pub fn get_or_default_sysroot() -> Path { // Follow symlinks. If the resolved path is relative, make it absolute. fn canonicalize(path: Option) -> Option { - path.and_then(|mut path| - match fs::readlink(&path) { - Ok(canon) => { - if canon.is_absolute() { - Some(canon) - } else { - path.pop(); - Some(path.join(canon)) - } - }, - Err(..) => Some(path), + path.and_then(|path| + match myfs::realpath(&path) { + Ok(canon) => Some(canon), + Err(e) => fail!("failed to get realpath: {}", e), }) } diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs new file mode 100644 index 0000000000000..c051b8e60cd80 --- /dev/null +++ b/src/librustc/util/fs.rs @@ -0,0 +1,103 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::io; +use std::io::fs; +use std::os; + +/// Returns an absolute path in the filesystem that `path` points to. The +/// returned path does not contain any symlinks in its hierarchy. +pub fn realpath(original: &Path) -> io::IoResult { + static MAX_LINKS_FOLLOWED: uint = 256; + let original = os::make_absolute(original); + + // Right now lstat on windows doesn't work quite well + if cfg!(windows) { + return Ok(original) + } + + let result = original.root_path(); + let mut result = result.expect("make_absolute has no root_path"); + let mut followed = 0; + + for part in original.components() { + result.push(part); + + loop { + if followed == MAX_LINKS_FOLLOWED { + return Err(io::standard_error(io::InvalidInput)) + } + + match fs::lstat(&result) { + Err(..) => break, + Ok(ref stat) if stat.kind != io::TypeSymlink => break, + Ok(..) => { + followed += 1; + let path = try!(fs::readlink(&result)); + result.pop(); + result.push(path); + } + } + } + } + + return Ok(result); +} + +#[cfg(not(windows), test)] +mod test { + use std::io; + use std::io::fs::{File, symlink, mkdir, mkdir_recursive}; + use super::realpath; + use std::io::TempDir; + + #[test] + fn realpath_works() { + let tmpdir = TempDir::new("rustc-fs").unwrap(); + let tmpdir = realpath(tmpdir.path()).unwrap(); + let file = tmpdir.join("test"); + let dir = tmpdir.join("test2"); + let link = dir.join("link"); + let linkdir = tmpdir.join("test3"); + + File::create(&file).unwrap(); + mkdir(&dir, io::UserRWX).unwrap(); + symlink(&file, &link).unwrap(); + symlink(&dir, &linkdir).unwrap(); + + assert!(realpath(&tmpdir).unwrap() == tmpdir); + assert!(realpath(&file).unwrap() == file); + assert!(realpath(&link).unwrap() == file); + assert!(realpath(&linkdir).unwrap() == dir); + assert!(realpath(&linkdir.join("link")).unwrap() == file); + } + + #[test] + fn realpath_works_tricky() { + let tmpdir = TempDir::new("rustc-fs").unwrap(); + let tmpdir = realpath(tmpdir.path()).unwrap(); + + let a = tmpdir.join("a"); + let b = a.join("b"); + let c = b.join("c"); + let d = a.join("d"); + let e = d.join("e"); + let f = a.join("f"); + + mkdir_recursive(&b, io::UserRWX).unwrap(); + mkdir_recursive(&d, io::UserRWX).unwrap(); + File::create(&f).unwrap(); + symlink(&Path::new("../d/e"), &c).unwrap(); + symlink(&Path::new("../f"), &e).unwrap(); + + assert!(realpath(&c).unwrap() == f); + assert!(realpath(&e).unwrap() == f); + } +}