(index<- )        ./librustc/metadata/filesearch.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012-2014 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  #![allow(non_camel_case_types)]
  12  
  13  use std::cell::RefCell;
  14  use std::os;
  15  use std::io::fs;
  16  use std::unstable::dynamic_lib::DynamicLibrary;
  17  use collections::HashSet;
  18  
  19  use myfs = util::fs;
  20  
  21  pub enum FileMatch { FileMatches, FileDoesntMatch }
  22  
  23  // A module for searching for libraries
  24  // FIXME (#2658): I'm not happy how this module turned out. Should
  25  // probably just be folded into cstore.
  26  
  27  /// Functions with type `pick` take a parent directory as well as
  28  /// a file found in that directory.
  29  pub type pick<'a> = |path: &Path|: 'a -> FileMatch;
  30  
  31  pub struct FileSearch<'a> {
  32      pub sysroot: &'a Path,
  33      pub addl_lib_search_paths: &'a RefCell<HashSet<Path>>,
  34      pub triple: &'a str,
  35  }
  36  
  37  impl<'a> FileSearch<'a> {
  38      pub fn for_each_lib_search_path(&self, f|&Path-> FileMatch) {
  39          let mut visited_dirs = HashSet::new();
  40          let mut found = false;
  41  
  42          debug!("filesearch: searching additional lib search paths [{:?}]",
  43                 self.addl_lib_search_paths.borrow().len());
  44          for path in self.addl_lib_search_paths.borrow().iter() {
  45              match f(path) {
  46                  FileMatches => found = true,
  47                  FileDoesntMatch => ()
  48              }
  49              visited_dirs.insert(path.as_vec().to_owned());
  50          }
  51  
  52          debug!("filesearch: searching lib path");
  53          let tlib_path = make_target_lib_path(self.sysroot,
  54                                      self.triple);
  55          if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
  56              match f(&tlib_path) {
  57                  FileMatches => found = true,
  58                  FileDoesntMatch => ()
  59              }
  60          }
  61  
  62          visited_dirs.insert(tlib_path.as_vec().to_owned());
  63          // Try RUST_PATH
  64          if !found {
  65              let rustpath = rust_path();
  66              for path in rustpath.iter() {
  67                  let tlib_path = make_rustpkg_lib_path(
  68                      self.sysroot, path, self.triple);
  69                  debug!("is {} in visited_dirs? {:?}", tlib_path.display(),
  70                          visited_dirs.contains_equiv(&tlib_path.as_vec().to_owned()));
  71  
  72                  if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
  73                      visited_dirs.insert(tlib_path.as_vec().to_owned());
  74                      // Don't keep searching the RUST_PATH if one match turns up --
  75                      // if we did, we'd get a "multiple matching crates" error
  76                      match f(&tlib_path) {
  77                         FileMatches => {
  78                             break;
  79                         }
  80                         FileDoesntMatch => ()
  81                      }
  82                  }
  83              }
  84          }
  85      }
  86  
  87      pub fn get_lib_path(&self) -> Path {
  88          make_target_lib_path(self.sysroot, self.triple)
  89      }
  90  
  91      pub fn search(&self, pickpick) {
  92          self.for_each_lib_search_path(|lib_search_path| {
  93              debug!("searching {}", lib_search_path.display());
  94              match fs::readdir(lib_search_path) {
  95                  Ok(files) => {
  96                      let mut rslt = FileDoesntMatch;
  97                      fn is_rlib(p& &Path) -> bool {
  98                          p.extension_str() == Some("rlib")
  99                      }
 100                      // Reading metadata out of rlibs is faster, and if we find both
 101                      // an rlib and a dylib we only read one of the files of
 102                      // metadata, so in the name of speed, bring all rlib files to
 103                      // the front of the search list.
 104                      let files1 = files.iter().filter(|p| is_rlib(p));
 105                      let files2 = files.iter().filter(|p| !is_rlib(p));
 106                      for path in files1.chain(files2) {
 107                          debug!("testing {}", path.display());
 108                          let maybe_picked = pick(path);
 109                          match maybe_picked {
 110                              FileMatches => {
 111                                  debug!("picked {}", path.display());
 112                                  rslt = FileMatches;
 113                              }
 114                              FileDoesntMatch => {
 115                                  debug!("rejected {}", path.display());
 116                              }
 117                          }
 118                      }
 119                      rslt
 120                  }
 121                  Err(..) => FileDoesntMatch,
 122              }
 123          });
 124      }
 125  
 126      pub fn new(sysroot&'a Path,
 127                 triple&'a str,
 128                 addl_lib_search_paths&'a RefCell<HashSet<Path>>) -> FileSearch<'a> {
 129          debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
 130          FileSearch {
 131              sysroot: sysroot,
 132              addl_lib_search_paths: addl_lib_search_paths,
 133              triple: triple,
 134          }
 135      }
 136  
 137      pub fn add_dylib_search_paths(&self) {
 138          self.for_each_lib_search_path(|lib_search_path| {
 139              DynamicLibrary::add_search_path(lib_search_path);
 140              FileDoesntMatch
 141          })
 142      }
 143  }
 144  
 145  pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> Path {
 146      let mut p = Path::new(find_libdir(sysroot));
 147      assert!(p.is_relative());
 148      p.push(rustlibdir());
 149      p.push(target_triple);
 150      p.push("lib");
 151      p
 152  }
 153  
 154  fn make_target_lib_path(sysroot: &Path,
 155                          target_triple: &str) -> Path {
 156      sysroot.join(&relative_target_lib_path(sysroot, target_triple))
 157  }
 158  
 159  fn make_rustpkg_lib_path(sysroot: &Path,
 160                           dir: &Path,
 161                           triple: &str) -> Path {
 162      let mut p = dir.join(find_libdir(sysroot));
 163      p.push(triple);
 164      p
 165  }
 166  
 167  pub fn get_or_default_sysroot() -> Path {
 168      // Follow symlinks.  If the resolved path is relative, make it absolute.
 169      fn canonicalize(pathOption<Path>) -> Option<Path> {
 170          path.and_then(|path|
 171              match myfs::realpath(&path) {
 172                  Ok(canon) => Some(canon),
 173                  Err(e) => fail!("failed to get realpath: {}", e),
 174              })
 175      }
 176  
 177      match canonicalize(os::self_exe_name()) {
 178          Some(mut p) => { p.pop(); p.pop(); p }
 179          None => fail!("can't determine value for sysroot")
 180      }
 181  }
 182  
 183  #[cfg(windows)]
 184  static PATH_ENTRY_SEPARATOR: &'static str = ";";
 185  #[cfg(not(windows))]
 186  static PATH_ENTRY_SEPARATOR: &'static str = ":";
 187  
 188  /// Returns RUST_PATH as a string, without default paths added
 189  pub fn get_rust_path() -> Option<~str> {
 190      os::getenv("RUST_PATH")
 191  }
 192  
 193  /// Returns the value of RUST_PATH, as a list
 194  /// of Paths. Includes default entries for, if they exist:
 195  /// $HOME/.rust
 196  /// DIR/.rust for any DIR that's the current working directory
 197  /// or an ancestor of it
 198  pub fn rust_path() -> Vec<Path> {
 199      let mut env_rust_pathVec<Path> = match get_rust_path() {
 200          Some(env_path) => {
 201              let env_path_components =
 202                  env_path.split_str(PATH_ENTRY_SEPARATOR);
 203              env_path_components.map(|s| Path::new(s)).collect()
 204          }
 205          None => Vec::new()
 206      };
 207      let mut cwd = os::getcwd();
 208      // now add in default entries
 209      let cwd_dot_rust = cwd.join(".rust");
 210      if !env_rust_path.contains(&cwd_dot_rust) {
 211          env_rust_path.push(cwd_dot_rust);
 212      }
 213      if !env_rust_path.contains(&cwd) {
 214          env_rust_path.push(cwd.clone());
 215      }
 216      loop {
 217          if { let f = cwd.filename(); f.is_none() || f.unwrap() == bytes!("..") } {
 218              break
 219          }
 220          cwd.set_filename(".rust");
 221          if !env_rust_path.contains(&cwd) && cwd.exists() {
 222              env_rust_path.push(cwd.clone());
 223          }
 224          cwd.pop();
 225      }
 226      let h = os::homedir();
 227      for h in h.iter() {
 228          let p = h.join(".rust");
 229          if !env_rust_path.contains(&p) && p.exists() {
 230              env_rust_path.push(p);
 231          }
 232      }
 233      env_rust_path
 234  }
 235  
 236  // The name of the directory rustc expects libraries to be located.
 237  // On Unix should be "lib", on windows "bin"
 238  #[cfg(unix)]
 239  fn find_libdir(sysroot: &Path) -> ~str {
 240      // FIXME: This is a quick hack to make the rustc binary able to locate
 241      // Rust libraries in Linux environments where libraries might be installed
 242      // to lib64/lib32. This would be more foolproof by basing the sysroot off
 243      // of the directory where librustc is located, rather than where the rustc
 244      // binary is.
 245  
 246      if sysroot.join(primary_libdir_name()).join(rustlibdir()).exists() {
 247          return primary_libdir_name();
 248      } else {
 249          return secondary_libdir_name();
 250      }
 251  
 252      #[cfg(target_word_size = "64")]
 253      fn primary_libdir_name() -> ~str { "lib64".to_owned() }
 254  
 255      #[cfg(target_word_size = "32")]
 256      fn primary_libdir_name() -> ~str { "lib32".to_owned() }
 257  
 258      fn secondary_libdir_name() -> ~str { "lib".to_owned() }
 259  }
 260  
 261  #[cfg(windows)]
 262  fn find_libdir(_sysroot: &Path) -> ~str {
 263      "bin".to_owned()
 264  }
 265  
 266  // The name of rustc's own place to organize libraries.
 267  // Used to be "rustc", now the default is "rustlib"
 268  pub fn rustlibdir() -> ~str {
 269      "rustlib".to_owned()
 270  }


librustc/metadata/filesearch.rs:153:1-153:1 -fn- definition:
fn make_target_lib_path(sysroot: &Path,
                        target_triple: &str) -> Path {
    sysroot.join(&relative_target_lib_path(sysroot, target_triple))
references:- 2
87:     pub fn get_lib_path(&self) -> Path {
88:         make_target_lib_path(self.sysroot, self.triple)
89:     }


librustc/metadata/filesearch.rs:253:4-253:4 -fn- definition:
    fn primary_libdir_name() -> ~str { "lib64".to_owned() }
    #[cfg(target_word_size = "32")]
    fn primary_libdir_name() -> ~str { "lib32".to_owned() }
references:- 2
246:     if sysroot.join(primary_libdir_name()).join(rustlibdir()).exists() {
247:         return primary_libdir_name();
248:     } else {


librustc/metadata/filesearch.rs:238:13-238:13 -fn- definition:
fn find_libdir(sysroot: &Path) -> ~str {
    // FIXME: This is a quick hack to make the rustc binary able to locate
    // Rust libraries in Linux environments where libraries might be installed
references:- 2
161:                          triple: &str) -> Path {
162:     let mut p = dir.join(find_libdir(sysroot));
163:     p.push(triple);


librustc/metadata/filesearch.rs:267:52-267:52 -fn- definition:
// Used to be "rustc", now the default is "rustlib"
pub fn rustlibdir() -> ~str {
    "rustlib".to_owned()
references:- 2
246:     if sysroot.join(primary_libdir_name()).join(rustlibdir()).exists() {
247:         return primary_libdir_name();


librustc/metadata/filesearch.rs:97:20-97:20 -fn- definition:
                    fn is_rlib(p: & &Path) -> bool {
                        p.extension_str() == Some("rlib")
                    }
references:- 2
104:                     let files1 = files.iter().filter(|p| is_rlib(p));
105:                     let files2 = files.iter().filter(|p| !is_rlib(p));
106:                     for path in files1.chain(files2) {


librustc/metadata/filesearch.rs:144:1-144:1 -fn- definition:
pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> Path {
    let mut p = Path::new(find_libdir(sysroot));
    assert!(p.is_relative());
references:- 2
librustc/back/rpath.rs:
138:     let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
139:     let mut path = Path::new(install_prefix);
librustc/metadata/filesearch.rs:
155:                         target_triple: &str) -> Path {
156:     sysroot.join(&relative_target_lib_path(sysroot, target_triple))
157: }


librustc/metadata/filesearch.rs:197:25-197:25 -fn- definition:
/// or an ancestor of it
pub fn rust_path() -> Vec<Path> {
    let mut env_rust_path: Vec<Path> = match get_rust_path() {
references:- 3
64:         if !found {
65:             let rustpath = rust_path();
66:             for path in rustpath.iter() {
librustc/back/archive.rs:
186:         let mut rustpath = filesearch::rust_path();
187:         rustpath.push(self.sess.target_filesearch().get_lib_path());
librustc/back/link.rs:
1324:     let rustpath = filesearch::rust_path();
1325:     for path in rustpath.iter() {


librustc/metadata/filesearch.rs:30:1-30:1 -struct- definition:
pub struct FileSearch<'a> {
    pub sysroot: &'a Path,
    pub addl_lib_search_paths: &'a RefCell<HashSet<Path>>,
references:- 6
129:         debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
130:         FileSearch {
131:             sysroot: sysroot,
librustc/driver/session.rs:
332:     }
333:     pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
334:         filesearch::FileSearch::new(
librustc/metadata/loader.rs:
75:     pub os: Os,
76:     pub filesearch: FileSearch<'a>,
77:     pub root: &'a Option<CratePaths>,
librustc/metadata/filesearch.rs:
37: impl<'a> FileSearch<'a> {
38:     pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {


librustc/metadata/filesearch.rs:20:1-20:1 -enum- definition:
pub enum FileMatch { FileMatches, FileDoesntMatch }
// A module for searching for libraries
// FIXME (#2658): I'm not happy how this module turned out. Should
references:- 2
28: /// a file found in that directory.
29: pub type pick<'a> = |path: &Path|: 'a -> FileMatch;
--
37: impl<'a> FileSearch<'a> {
38:     pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {
39:         let mut visited_dirs = HashSet::new();