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.
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.
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.
21 pub type pick
<'
self, T
> = &'
self fn(path
: &Path
) -> Option
<T
>;
23 pub fn pick_file(file
: Path
, path
: &Path
) -> Option
<Path
> {
24 if path
.file_path() == file { option::Some(copy *path) }
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
;
35 pub fn mk_filesearch(maybe_sysroot
: &Option
<@Path
>,
37 addl_lib_search_paths
: @
mut ~[Path
])
39 struct FileSearchImpl
{
41 addl_lib_search_paths
: @
mut ~[Path
],
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());
50 self.addl_lib_search_paths
.iter().advance(|path
| f(path
));
52 debug
!("filesearch: searching target lib path");
53 if !f(&make_target_lib_path(self.sysroot
,
54 self.target_triple
)) {
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
64 debug
!("filesearch: searching rustpkg lib path");
65 match get_rustpkg_lib_path() {
66 result
::Ok(ref p
) => f(p
),
67 result
::Err(_
) => true
70 fn get_target_lib_path(&self) -> Path
{
71 make_target_lib_path(self.sysroot
, self.target_triple
)
73 fn get_target_lib_file_path(&self, file
: &Path
) -> Path
{
74 self.get_target_lib_path().push_rel(file
)
78 let sysroot
= get_sysroot(maybe_sysroot
);
79 debug
!("using sysroot = %s", sysroot
.to_str());
82 addl_lib_search_paths
: addl_lib_search_paths
,
83 target_triple
: str::to_owned(target_triple
)
87 pub fn search
<T
:Copy
>(filesearch
: @FileSearch
, pick
: pick
<T
>) -> Option
<T
> {
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());
100 debug
!("rejected %s", path
.to_str());
103 if rslt
.is_some() { break; }
108 pub fn relative_target_lib_path(target_triple
: &str) -> Path
{
109 Path(libdir()).push_many([~"rustc",
110 str::to_owned(target_triple
),
114 fn make_target_lib_path(sysroot
: &Path
,
115 target_triple
: &str) -> Path
{
116 sysroot
.push_rel(&relative_target_lib_path(target_triple
))
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")
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()
133 pub fn get_rustpkg_sysroot() -> Result
<Path
, ~str> {
134 result
::Ok(get_or_default_sysroot().push_many([libdir(), ~"rustpkg"]))
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")
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
);
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
);
162 if par_rustpkg
.components
.len() == 1 {
163 // We just checked /.rustpkg, stop now.
166 par_rustpkg
= par_rustpkg
.pop().pop().push(".rustpkg");
173 fn get_rustpkg_lib_path() -> Result
<Path
, ~str> {
174 do result
::chain(get_rustpkg_root()) |p
| {
175 result
::Ok(p
.push(libdir()))
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()))
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");