]> git.proxmox.com Git - rustc.git/blob - src/librustc/metadata/filesearch.rs
Imported Upstream version 0.7
[rustc.git] / src / librustc / metadata / filesearch.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 use std::option;
13 use std::os;
14 use std::result;
15 use std::str;
16
17 // A module for searching for libraries
18 // FIXME (#2658): I'm not happy how this module turned out. Should
19 // probably just be folded into cstore.
20
21 pub type pick<'self, T> = &'self fn(path: &Path) -> Option<T>;
22
23 pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
24 if path.file_path() == file { option::Some(copy *path) }
25 else { option::None }
26 }
27
28 pub trait FileSearch {
29 fn sysroot(&self) -> @Path;
30 fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool;
31 fn get_target_lib_path(&self) -> Path;
32 fn get_target_lib_file_path(&self, file: &Path) -> Path;
33 }
34
35 pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
36 target_triple: &str,
37 addl_lib_search_paths: @mut ~[Path])
38 -> @FileSearch {
39 struct FileSearchImpl {
40 sysroot: @Path,
41 addl_lib_search_paths: @mut ~[Path],
42 target_triple: ~str
43 }
44 impl FileSearch for FileSearchImpl {
45 fn sysroot(&self) -> @Path { self.sysroot }
46 fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool {
47 debug!("filesearch: searching additional lib search paths [%?]",
48 self.addl_lib_search_paths.len());
49 // a little weird
50 self.addl_lib_search_paths.iter().advance(|path| f(path));
51
52 debug!("filesearch: searching target lib path");
53 if !f(&make_target_lib_path(self.sysroot,
54 self.target_triple)) {
55 return false;
56 }
57 debug!("filesearch: searching rustpkg lib path nearest");
58 if match get_rustpkg_lib_path_nearest() {
59 result::Ok(ref p) => f(p),
60 result::Err(_) => true
61 } {
62 return true;
63 }
64 debug!("filesearch: searching rustpkg lib path");
65 match get_rustpkg_lib_path() {
66 result::Ok(ref p) => f(p),
67 result::Err(_) => true
68 }
69 }
70 fn get_target_lib_path(&self) -> Path {
71 make_target_lib_path(self.sysroot, self.target_triple)
72 }
73 fn get_target_lib_file_path(&self, file: &Path) -> Path {
74 self.get_target_lib_path().push_rel(file)
75 }
76 }
77
78 let sysroot = get_sysroot(maybe_sysroot);
79 debug!("using sysroot = %s", sysroot.to_str());
80 @FileSearchImpl {
81 sysroot: sysroot,
82 addl_lib_search_paths: addl_lib_search_paths,
83 target_triple: str::to_owned(target_triple)
84 } as @FileSearch
85 }
86
87 pub fn search<T:Copy>(filesearch: @FileSearch, pick: pick<T>) -> Option<T> {
88 let mut rslt = None;
89 for filesearch.for_each_lib_search_path() |lib_search_path| {
90 debug!("searching %s", lib_search_path.to_str());
91 let r = os::list_dir_path(lib_search_path);
92 for r.iter().advance |path| {
93 debug!("testing %s", path.to_str());
94 let maybe_picked = pick(*path);
95 if maybe_picked.is_some() {
96 debug!("picked %s", path.to_str());
97 rslt = maybe_picked;
98 break;
99 } else {
100 debug!("rejected %s", path.to_str());
101 }
102 }
103 if rslt.is_some() { break; }
104 }
105 return rslt;
106 }
107
108 pub fn relative_target_lib_path(target_triple: &str) -> Path {
109 Path(libdir()).push_many([~"rustc",
110 str::to_owned(target_triple),
111 libdir()])
112 }
113
114 fn make_target_lib_path(sysroot: &Path,
115 target_triple: &str) -> Path {
116 sysroot.push_rel(&relative_target_lib_path(target_triple))
117 }
118
119 fn get_or_default_sysroot() -> Path {
120 match os::self_exe_path() {
121 option::Some(ref p) => (*p).pop(),
122 option::None => fail!("can't determine value for sysroot")
123 }
124 }
125
126 fn get_sysroot(maybe_sysroot: &Option<@Path>) -> @Path {
127 match *maybe_sysroot {
128 option::Some(sr) => sr,
129 option::None => @get_or_default_sysroot()
130 }
131 }
132
133 pub fn get_rustpkg_sysroot() -> Result<Path, ~str> {
134 result::Ok(get_or_default_sysroot().push_many([libdir(), ~"rustpkg"]))
135 }
136
137 pub fn get_rustpkg_root() -> Result<Path, ~str> {
138 match os::getenv("RUSTPKG_ROOT") {
139 Some(ref _p) => result::Ok(Path((*_p))),
140 None => match os::homedir() {
141 Some(ref _q) => result::Ok((*_q).push(".rustpkg")),
142 None => result::Err(~"no RUSTPKG_ROOT or home directory")
143 }
144 }
145 }
146
147 pub fn get_rustpkg_root_nearest() -> Result<Path, ~str> {
148 do result::chain(get_rustpkg_root()) |p| {
149 let cwd = os::getcwd();
150 let cwd_rustpkg = cwd.push(".rustpkg");
151 let rustpkg_is_non_root_file =
152 !os::path_is_dir(&cwd_rustpkg) && cwd_rustpkg != p;
153 let mut par_rustpkg = cwd.pop().push(".rustpkg");
154 let mut rslt = result::Ok(cwd_rustpkg);
155
156 if rustpkg_is_non_root_file {
157 while par_rustpkg != p {
158 if os::path_is_dir(&par_rustpkg) {
159 rslt = result::Ok(par_rustpkg);
160 break;
161 }
162 if par_rustpkg.components.len() == 1 {
163 // We just checked /.rustpkg, stop now.
164 break;
165 }
166 par_rustpkg = par_rustpkg.pop().pop().push(".rustpkg");
167 }
168 }
169 rslt
170 }
171 }
172
173 fn get_rustpkg_lib_path() -> Result<Path, ~str> {
174 do result::chain(get_rustpkg_root()) |p| {
175 result::Ok(p.push(libdir()))
176 }
177 }
178
179 fn get_rustpkg_lib_path_nearest() -> Result<Path, ~str> {
180 do result::chain(get_rustpkg_root_nearest()) |p| {
181 result::Ok(p.push(libdir()))
182 }
183 }
184
185 // The name of the directory rustc expects libraries to be located.
186 // On Unix should be "lib", on windows "bin"
187 pub fn libdir() -> ~str {
188 let libdir = env!("CFG_LIBDIR");
189 if libdir.is_empty() {
190 fail!("rustc compiled without CFG_LIBDIR environment variable");
191 }
192 libdir.to_owned()
193 }