]> git.lizzy.rs Git - rust.git/blob - src/comp/util/filesearch.rs
e4ac615d97314ca5cdf30b762554a3b8a3c926f5
[rust.git] / src / comp / util / filesearch.rs
1 // A module for searching for libraries
2 // FIXME: I'm not happy how this module turned out. Should probably
3 // just be folded into cstore.
4
5 import core::option;
6 import std::fs;
7 import vec;
8 import std::os;
9 import result;
10 import std::generic_os;
11
12 export filesearch;
13 export mk_filesearch;
14 export pick;
15 export pick_file;
16 export search;
17 export relative_target_lib_path;
18 export get_cargo_root;
19
20 type pick<T> = block(path: fs::path) -> option::t<T>;
21
22 fn pick_file(file: fs::path, path: fs::path) -> option::t<fs::path> {
23     if fs::basename(path) == file { option::some(path) }
24     else { option::none }
25 }
26
27 type filesearch = obj {
28     fn sysroot() -> fs::path;
29     fn lib_search_paths() -> [fs::path];
30     fn get_target_lib_path() -> fs::path;
31     fn get_target_lib_file_path(file: fs::path) -> fs::path;
32 };
33
34 fn mk_filesearch(maybe_sysroot: option::t<fs::path>,
35                  target_triple: str,
36                  addl_lib_search_paths: [fs::path]) -> filesearch {
37     obj filesearch_impl(sysroot: fs::path,
38                         addl_lib_search_paths: [fs::path],
39                         target_triple: str) {
40         fn sysroot() -> fs::path { sysroot }
41         fn lib_search_paths() -> [fs::path] {
42             addl_lib_search_paths
43                 + [make_target_lib_path(sysroot, target_triple)]
44                 + alt get_cargo_lib_path() {
45                   result::ok(p) { [p] }
46                   result::err(p) { [] }
47                 }
48         }
49
50         fn get_target_lib_path() -> fs::path {
51             make_target_lib_path(sysroot, target_triple)
52         }
53
54         fn get_target_lib_file_path(file: fs::path) -> fs::path {
55             fs::connect(self.get_target_lib_path(), file)
56         }
57     }
58
59     let sysroot = get_sysroot(maybe_sysroot);
60     #debug("using sysroot = %s", sysroot);
61     ret filesearch_impl(sysroot, addl_lib_search_paths, target_triple);
62 }
63
64 // FIXME #1001: This can't be an obj method
65 fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option::t<T> {
66     for lib_search_path in filesearch.lib_search_paths() {
67         #debug("searching %s", lib_search_path);
68         for path in fs::list_dir(lib_search_path) {
69             #debug("testing %s", path);
70             let maybe_picked = pick(path);
71             if option::is_some(maybe_picked) {
72                 #debug("picked %s", path);
73                 ret maybe_picked;
74             } else {
75                 #debug("rejected %s", path);
76             }
77         }
78     }
79     ret option::none;
80 }
81
82 fn relative_target_lib_path(target_triple: str) -> [fs::path] {
83     ["lib", "rustc", target_triple, "lib"]
84 }
85
86 fn make_target_lib_path(sysroot: fs::path,
87                         target_triple: str) -> fs::path {
88     let path = [sysroot] + relative_target_lib_path(target_triple);
89     check vec::is_not_empty(path);
90     let path = fs::connect_many(path);
91     ret path;
92 }
93
94 fn get_default_sysroot() -> fs::path {
95     alt os::get_exe_path() {
96       option::some(p) { fs::normalize(fs::connect(p, "..")) }
97       option::none. {
98         fail "can't determine value for sysroot";
99       }
100     }
101 }
102
103 fn get_sysroot(maybe_sysroot: option::t<fs::path>) -> fs::path {
104     alt maybe_sysroot {
105       option::some(sr) { sr }
106       option::none. { get_default_sysroot() }
107     }
108 }
109
110 fn get_cargo_root() -> result::t<fs::path, str> {
111     alt generic_os::getenv("CARGO_ROOT") {
112         some(_p) { result::ok(_p) }
113         none. {
114             alt generic_os::getenv("HOME") {
115                 some(_q) { result::ok(fs::connect(_q, ".cargo")) }
116                 none. { result::err("no CARGO_ROOT or HOME") }
117             }
118         }
119     }
120 }
121
122 fn get_cargo_lib_path() -> result::t<fs::path, str> {
123     result::chain(get_cargo_root()) { |p|
124         result::ok(fs::connect(p, "lib"))
125     }
126 }