about summary refs log tree commit diff
path: root/src/rustc/metadata
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-05-29 20:38:46 -0700
committerBrian Anderson <banderson@mozilla.com>2012-05-29 20:38:49 -0700
commit736ff34e8ac714671fcce7ca903144832fec0338 (patch)
treef294ea484e628d55ee2ed25a175f0016a4c4a49f /src/rustc/metadata
parent3f3c9caf4d2c434982d840e65c4014c1787f8d47 (diff)
downloadrust-736ff34e8ac714671fcce7ca903144832fec0338.tar.gz
rust-736ff34e8ac714671fcce7ca903144832fec0338.zip
rustc: Move filesearch into metadata mod
It's not that related to metadata, but metadata needs it and it will
probably be useful for doing dynamic loading.
Diffstat (limited to 'src/rustc/metadata')
-rw-r--r--src/rustc/metadata/creader.rs2
-rw-r--r--src/rustc/metadata/filesearch.rs176
-rw-r--r--src/rustc/metadata/loader.rs1
3 files changed, 177 insertions, 2 deletions
diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs
index 0fadf1b1f68..2aacd87cbe8 100644
--- a/src/rustc/metadata/creader.rs
+++ b/src/rustc/metadata/creader.rs
@@ -11,7 +11,7 @@ import syntax::visit;
 import syntax::codemap::span;
 import std::map::{hashmap, int_hash};
 import syntax::print::pprust;
-import util::filesearch::filesearch;
+import filesearch::filesearch;
 import common::*;
 
 export read_crates;
diff --git a/src/rustc/metadata/filesearch.rs b/src/rustc/metadata/filesearch.rs
new file mode 100644
index 00000000000..a5cc6c28d53
--- /dev/null
+++ b/src/rustc/metadata/filesearch.rs
@@ -0,0 +1,176 @@
+// A module for searching for libraries
+// FIXME: I'm not happy how this module turned out. Should probably
+// just be folded into cstore.
+
+import result::result;
+export filesearch;
+export mk_filesearch;
+export pick;
+export pick_file;
+export search;
+export relative_target_lib_path;
+export get_cargo_sysroot;
+export get_cargo_root;
+export get_cargo_root_nearest;
+export libdir;
+
+import path::path;
+
+type pick<T> = fn(path: path) -> option<T>;
+
+fn pick_file(file: path, path: path) -> option<path> {
+    if path::basename(path) == file { option::some(path) }
+    else { option::none }
+}
+
+iface filesearch {
+    fn sysroot() -> path;
+    fn lib_search_paths() -> [path];
+    fn get_target_lib_path() -> path;
+    fn get_target_lib_file_path(file: path) -> path;
+}
+
+fn mk_filesearch(maybe_sysroot: option<path>,
+                 target_triple: str,
+                 addl_lib_search_paths: [path]) -> filesearch {
+    type filesearch_impl = {sysroot: path,
+                            addl_lib_search_paths: [path],
+                            target_triple: str};
+    impl of filesearch for filesearch_impl {
+        fn sysroot() -> path { self.sysroot }
+        fn lib_search_paths() -> [path] {
+            self.addl_lib_search_paths
+                + [make_target_lib_path(self.sysroot, self.target_triple)]
+                + alt get_cargo_lib_path_nearest() {
+                  result::ok(p) { [p] }
+                  result::err(p) { [] }
+                }
+                + alt get_cargo_lib_path() {
+                  result::ok(p) { [p] }
+                  result::err(p) { [] }
+                }
+        }
+        fn get_target_lib_path() -> path {
+            make_target_lib_path(self.sysroot, self.target_triple)
+        }
+        fn get_target_lib_file_path(file: path) -> path {
+            path::connect(self.get_target_lib_path(), file)
+        }
+    }
+
+    let sysroot = get_sysroot(maybe_sysroot);
+    #debug("using sysroot = %s", sysroot);
+    {sysroot: sysroot,
+     addl_lib_search_paths: addl_lib_search_paths,
+     target_triple: target_triple} as filesearch
+}
+
+fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
+    let mut rslt = none;
+    for filesearch.lib_search_paths().each {|lib_search_path|
+        #debug("searching %s", lib_search_path);
+        for os::list_dir_path(lib_search_path).each {|path|
+            #debug("testing %s", path);
+            let maybe_picked = pick(path);
+            if option::is_some(maybe_picked) {
+                #debug("picked %s", path);
+                rslt = maybe_picked;
+                break;
+            } else {
+                #debug("rejected %s", path);
+            }
+        }
+        if option::is_some(rslt) { break; }
+    }
+    ret rslt;
+}
+
+fn relative_target_lib_path(target_triple: str) -> [path] {
+    [libdir(), "rustc", target_triple, libdir()]
+}
+
+fn make_target_lib_path(sysroot: path,
+                        target_triple: str) -> path {
+    let path = [sysroot] + relative_target_lib_path(target_triple);
+    let path = path::connect_many(path);
+    ret path;
+}
+
+fn get_default_sysroot() -> path {
+    alt os::self_exe_path() {
+      option::some(p) { path::normalize(path::connect(p, "..")) }
+      option::none {
+        fail "can't determine value for sysroot";
+      }
+    }
+}
+
+fn get_sysroot(maybe_sysroot: option<path>) -> path {
+    alt maybe_sysroot {
+      option::some(sr) { sr }
+      option::none { get_default_sysroot() }
+    }
+}
+
+fn get_cargo_sysroot() -> result<path, str> {
+    let path = [get_default_sysroot(), libdir(), "cargo"];
+    result::ok(path::connect_many(path))
+}
+
+fn get_cargo_root() -> result<path, str> {
+    alt os::getenv("CARGO_ROOT") {
+        some(_p) { result::ok(_p) }
+        none {
+          alt os::homedir() {
+            some(_q) { result::ok(path::connect(_q, ".cargo")) }
+            none { result::err("no CARGO_ROOT or home directory") }
+          }
+        }
+    }
+}
+
+fn get_cargo_root_nearest() -> result<path, str> {
+    result::chain(get_cargo_root()) { |p|
+        let cwd = os::getcwd();
+        let mut dirname = path::dirname(cwd);
+        let mut dirpath = path::split(dirname);
+        let cwd_cargo = path::connect(cwd, ".cargo");
+        let mut par_cargo = path::connect(dirname, ".cargo");
+        let mut rslt = result::ok(cwd_cargo);
+
+        if !os::path_is_dir(cwd_cargo) && cwd_cargo != p {
+            while vec::is_not_empty(dirpath) && par_cargo != p {
+                if os::path_is_dir(par_cargo) {
+                    rslt = result::ok(par_cargo);
+                    break;
+                }
+                vec::pop(dirpath);
+                dirname = path::dirname(dirname);
+                par_cargo = path::connect(dirname, ".cargo");
+            }
+        }
+        rslt
+    }
+}
+
+fn get_cargo_lib_path() -> result<path, str> {
+    result::chain(get_cargo_root()) { |p|
+        result::ok(path::connect(p, libdir()))
+    }
+}
+
+fn get_cargo_lib_path_nearest() -> result<path, str> {
+    result::chain(get_cargo_root_nearest()) { |p|
+        result::ok(path::connect(p, libdir()))
+    }
+}
+
+// The name of the directory rustc expects libraries to be located.
+// On Unix should be "lib", on windows "bin"
+fn libdir() -> str {
+   let libdir = #env("CFG_LIBDIR");
+   if str::is_empty(libdir) {
+      fail "rustc compiled without CFG_LIBDIR environment variable";
+   }
+   libdir
+}
diff --git a/src/rustc/metadata/loader.rs b/src/rustc/metadata/loader.rs
index da991ec0c2a..2123a6179f0 100644
--- a/src/rustc/metadata/loader.rs
+++ b/src/rustc/metadata/loader.rs
@@ -9,7 +9,6 @@ import syntax::{ast, attr};
 import syntax::print::pprust;
 import syntax::codemap::span;
 import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
-import util::filesearch;
 import filesearch::filesearch;
 import io::writer_util;