summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-10-04 15:23:32 -0700
committerBrian Anderson <banderson@mozilla.com>2011-10-05 16:21:55 -0700
commit19ba9b4d8d0fec474acbbd472e17ef0351c20df2 (patch)
treeac1ac70a724f6049fc5e98d489cd76e4ae9cd978 /src/comp
parente963cfd41a4c8acbd42e88511fb0ab27ea11f5b3 (diff)
downloadrust-19ba9b4d8d0fec474acbbd472e17ef0351c20df2.tar.gz
rust-19ba9b4d8d0fec474acbbd472e17ef0351c20df2.zip
Begin work on rpath
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/back/link.rs3
-rw-r--r--src/comp/back/rpath.rs205
-rw-r--r--src/comp/rustc.rc1
-rw-r--r--src/comp/util/filesearch.rs11
4 files changed, 218 insertions, 2 deletions
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index c9c03e82775..d3dbeaa6cf4 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -7,6 +7,7 @@ import metadata::{encoder, cstore};
 import middle::trans_common::crate_ctxt;
 import std::str;
 import std::fs;
+import std::os;
 import std::vec;
 import std::option;
 import std::run;
@@ -573,6 +574,8 @@ fn link_binary(sess: session::session,
 
     gcc_args += ["-Lrt", "-lrustrt"];
 
+    gcc_args += rpath::get_rpath_flags(sess, saved_out_filename);
+
     // We run 'gcc' here
     let err_code = run::run_program(prog, gcc_args);
     if 0 != err_code {
diff --git a/src/comp/back/rpath.rs b/src/comp/back/rpath.rs
new file mode 100644
index 00000000000..1ced0de2fde
--- /dev/null
+++ b/src/comp/back/rpath.rs
@@ -0,0 +1,205 @@
+import std::os;
+import std::fs;
+import std::vec;
+import metadata::cstore;
+import driver::session;
+import util::filesearch;
+import std::map;
+
+export get_rpath_flags, test;
+
+#[cfg(target_os="linux")]
+#[cfg(target_os="macos")]
+fn get_rpath_flags(_sess: session::session, _out_filename: str) -> [str] {
+    log "preparing the RPATH!";
+
+    // FIXME
+    /*
+    let cwd = os::getcwd();
+    let sysroot = sess.filesearch().sysroot();
+    let output = out_filename;
+    let libs = cstore::get_used_crate_files(sess.get_cstore());
+    let target_triple = sess.get_opts().target_triple;
+    let rpaths = get_rpaths(cwd, sysroot, output, libs, target_triple);
+    */
+    let rpaths = [];
+    rpaths_to_flags(rpaths)
+}
+
+#[cfg(target_os="win32")]
+fn get_rpath_flags(_sess: session::session, _out_filename: str) -> [str] {
+    []
+}
+
+fn rpaths_to_flags(rpaths: [str]) -> [str] {
+    vec::map({ |rpath| #fmt("-Wl,-rpath,%s",rpath)}, rpaths)
+}
+
+fn get_rpaths(cwd: fs::path, sysroot: fs::path,
+              output: fs::path, libs: [fs::path],
+              target_triple: str) -> [str] {
+    log #fmt("cwd: %s", cwd);
+    log #fmt("sysroot: %s", sysroot);
+    log #fmt("output: %s", output);
+    log #fmt("libs:");
+    for libpath in libs {
+        log #fmt("    %s", libpath);
+    }
+    log #fmt("target_triple: %s", target_triple);
+
+    // 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 rpaths = get_rpaths_relative_to_output(cwd, output, libs);
+
+    // Make backup absolute paths to the libraries. Binaries can
+    // be moved as long as the crates they link against don't move.
+    rpaths += get_absolute_rpaths(cwd, libs);
+
+    // And a final backup rpath to the global library location.
+    rpaths += [get_install_prefix_rpath(target_triple)];
+
+    // Remove duplicates
+    let rpaths = minimize_rpaths(rpaths);
+    ret rpaths;
+}
+
+fn get_rpaths_relative_to_output(cwd: fs::path,
+                                 output: fs::path,
+                                 libs: [fs::path]) -> [str] {
+    vec::map(bind get_rpath_relative_to_output(cwd, output, _), libs)
+}
+
+fn get_rpath_relative_to_output(_cwd: fs::path,
+                                _output: fs::path,
+                                _lib: fs::path) -> str {
+    fail;
+    /*get_relative_to(
+        get_absolute(cwd, output),
+        get_absolute(cwd, lib))*/
+}
+
+// Find the relative path from one file to another
+fn get_relative_to(_abs1: fs::path, _abs2: fs::path) -> fs::path {
+    fail;
+}
+
+fn get_absolute_rpaths(cwd: fs::path, libs: [fs::path]) -> [str] {
+    vec::map(bind get_absolute_rpath(cwd, _), libs)
+}
+
+fn get_absolute_rpath(cwd: fs::path, lib: fs::path) -> str {
+    get_absolute(cwd, lib)
+}
+
+fn get_absolute(cwd: fs::path, lib: fs::path) -> fs::path {
+    if fs::path_is_absolute(lib) {
+        lib
+    } else {
+        fs::connect(cwd, lib)
+    }
+}
+
+fn get_install_prefix_rpath(target_triple: str) -> str {
+    let install_prefix = #env("CFG_PREFIX");
+
+    if install_prefix == "" {
+        fail "rustc compiled without CFG_PREFIX environment variable";
+    }
+
+    let path = [install_prefix]
+        + filesearch::relative_target_lib_path(target_triple);
+    check vec::is_not_empty(path);
+    fs::connect_many(path)
+}
+
+fn minimize_rpaths(rpaths: [str]) -> [str] {
+    let set = map::new_str_hash::<()>();
+    for rpath in rpaths { set.insert(rpath, ()); }
+    let minimized = [];
+    for each rpath in set.keys() { minimized += [rpath]; }
+    ret minimized;
+}
+
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+mod test {
+    #[test]
+    fn test_rpaths_to_flags() {
+        let flags = rpaths_to_flags(["path1", "path2"]);
+        assert flags == ["-Wl,-rpath,path1", "-Wl,-rpath,path2"];
+    }
+
+    #[test]
+    fn test_get_absolute1() {
+        let cwd = "/dir";
+        let lib = "some/path/lib";
+        let res = get_absolute(cwd, lib);
+        assert res == "/dir/some/path/lib";
+    }
+
+    #[test]
+    fn test_get_absolute2() {
+        let cwd = "/dir";
+        let lib = "/some/path/lib";
+        let res = get_absolute(cwd, lib);
+        assert res == "/some/path/lib";
+    }
+
+    #[test]
+    fn test_prefix_rpath() {
+        let res = get_install_prefix_rpath("triple");
+        assert res == #env("CFG_PREFIX") + "/lib/rustc/triple/lib";
+    }
+
+    #[test]
+    fn test_minimize() {
+        let res = minimize_rpaths(["rpath1", "rpath2", "rpath1"]);
+        assert res == ["rpath1", "rpath2"];
+    }
+
+    #[test]
+    #[ignore]
+    fn test_relative_to1() {
+        let p1 = "/usr/bin/rustc";
+        let p2 = "/usr/lib/mylib";
+        let res = get_relative_to(p1, p2);
+        assert res == "../lib";
+    }
+
+    #[test]
+    #[ignore]
+    fn test_relative_to2() {
+        let p1 = "/usr/bin/rustc";
+        let p2 = "/usr/bin/../lib/mylib";
+        let res = get_relative_to(p1, p2);
+        assert res == "../lib";
+    }
+
+    #[test]
+    #[ignore]
+    fn test_relative_to3() {
+        let p1 = "/usr/bin/whatever/rustc";
+        let p2 = "/usr/lib/whatever/mylib";
+        let res = get_relative_to(p1, p2);
+        assert res == "../../lib/whatever";
+    }
+
+    #[test]
+    #[ignore]
+    fn test_relative_to4() {
+        let p1 = "/usr/bin/whatever/../rustc";
+        let p2 = "/usr/lib/whatever/mylib";
+        let res = get_relative_to(p1, p2);
+        assert res == "../lib/whatever";
+    }
+
+    #[test]
+    #[ignore]
+    fn test_relative_to5() {
+        let p1 = "/usr/bin/whatever/../rustc";
+        let p2 = "/usr/lib/whatever/../mylib";
+        let res = get_relative_to(p1, p2);
+        assert res == "../lib/whatever";
+    }
+}
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index c685139d54b..9b1dff75769 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -91,6 +91,7 @@ mod back {
     mod abi;
     mod upcall;
     mod x86;
+    mod rpath;
 }
 
 mod metadata {
diff --git a/src/comp/util/filesearch.rs b/src/comp/util/filesearch.rs
index 580360b967f..792ea029724 100644
--- a/src/comp/util/filesearch.rs
+++ b/src/comp/util/filesearch.rs
@@ -1,4 +1,6 @@
 // A module for searching for libraries
+// FIXME: I'm not happy how this module turned out. Should probably
+// just be folded into cstore.
 
 import std::option;
 import std::fs;
@@ -12,6 +14,7 @@ export mk_filesearch;
 export pick;
 export pick_file;
 export search;
+export relative_target_lib_path;
 
 type pick<@T> = block(path: fs::path) -> option::t<T>;
 
@@ -71,9 +74,13 @@ fn search<@T>(filesearch: filesearch, pick: pick<T>) -> option::t<T> {
     ret option::none;
 }
 
+fn relative_target_lib_path(target_triple: str) -> [fs::path] {
+    ["lib", "rustc", target_triple, "lib"]
+}
+
 fn make_target_lib_path(sysroot: fs::path,
                         target_triple: str) -> fs::path {
-    let path = [sysroot, "lib/rustc", target_triple, "lib"];
+    let path = [sysroot] + relative_target_lib_path(target_triple);
     check vec::is_not_empty(path);
     let path = fs::connect_many(path);
     ret path;
@@ -81,7 +88,7 @@ fn make_target_lib_path(sysroot: fs::path,
 
 fn get_default_sysroot() -> fs::path {
     alt os::get_exe_path() {
-      option::some(p) { fs::connect(p, "../") }
+      option::some(p) { fs::connect(p, "..") }
       option::none. {
         fail "can't determine value for sysroot";
       }