]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | pub use self::FileMatch::*; |
2 | ||
c30ab7b3 | 3 | use std::borrow::Cow; |
85aaf69f | 4 | use std::env; |
c34b1796 | 5 | use std::fs; |
c34b1796 | 6 | use std::path::{Path, PathBuf}; |
1a4d82fc | 7 | |
ba9703b0 | 8 | use crate::search_paths::{PathKind, SearchPath, SearchPathFile}; |
dfeec247 | 9 | use rustc_fs_util::fix_windows_verbatim_for_gcc; |
3dfed10e | 10 | use tracing::debug; |
1a4d82fc | 11 | |
c34b1796 | 12 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
13 | pub enum FileMatch { |
14 | FileMatches, | |
15 | FileDoesntMatch, | |
16 | } | |
970d7e83 | 17 | |
223e47cc | 18 | // A module for searching for libraries |
223e47cc | 19 | |
532ac7d7 | 20 | #[derive(Clone)] |
1a4d82fc | 21 | pub struct FileSearch<'a> { |
0731742a XL |
22 | sysroot: &'a Path, |
23 | triple: &'a str, | |
24 | search_paths: &'a [SearchPath], | |
25 | tlib_path: &'a SearchPath, | |
26 | kind: PathKind, | |
223e47cc LB |
27 | } |
28 | ||
1a4d82fc | 29 | impl<'a> FileSearch<'a> { |
0731742a XL |
30 | pub fn search_paths(&self) -> impl Iterator<Item = &'a SearchPath> { |
31 | let kind = self.kind; | |
dfeec247 XL |
32 | self.search_paths |
33 | .iter() | |
0731742a XL |
34 | .filter(move |sp| sp.kind.matches(kind)) |
35 | .chain(std::iter::once(self.tlib_path)) | |
223e47cc LB |
36 | } |
37 | ||
c34b1796 | 38 | pub fn get_lib_path(&self) -> PathBuf { |
1a4d82fc JJ |
39 | make_target_lib_path(self.sysroot, self.triple) |
40 | } | |
223e47cc | 41 | |
f035d41b XL |
42 | pub fn get_self_contained_lib_path(&self) -> PathBuf { |
43 | self.get_lib_path().join("self-contained") | |
44 | } | |
45 | ||
85aaf69f | 46 | pub fn search<F>(&self, mut pick: F) |
dfeec247 | 47 | where |
ba9703b0 | 48 | F: FnMut(&SearchPathFile, PathKind) -> FileMatch, |
85aaf69f | 49 | { |
0731742a XL |
50 | for search_path in self.search_paths() { |
51 | debug!("searching {}", search_path.dir.display()); | |
ba9703b0 XL |
52 | fn is_rlib(spf: &SearchPathFile) -> bool { |
53 | if let Some(f) = &spf.file_name_str { f.ends_with(".rlib") } else { false } | |
c30ab7b3 SL |
54 | } |
55 | // Reading metadata out of rlibs is faster, and if we find both | |
56 | // an rlib and a dylib we only read one of the files of | |
57 | // metadata, so in the name of speed, bring all rlib files to | |
58 | // the front of the search list. | |
ba9703b0 XL |
59 | let files1 = search_path.files.iter().filter(|spf| is_rlib(&spf)); |
60 | let files2 = search_path.files.iter().filter(|spf| !is_rlib(&spf)); | |
61 | for spf in files1.chain(files2) { | |
62 | debug!("testing {}", spf.path.display()); | |
63 | let maybe_picked = pick(spf, search_path.kind); | |
c30ab7b3 SL |
64 | match maybe_picked { |
65 | FileMatches => { | |
ba9703b0 | 66 | debug!("picked {}", spf.path.display()); |
1a4d82fc | 67 | } |
c30ab7b3 | 68 | FileDoesntMatch => { |
ba9703b0 | 69 | debug!("rejected {}", spf.path.display()); |
1a4d82fc | 70 | } |
1a4d82fc | 71 | } |
223e47cc | 72 | } |
0731742a | 73 | } |
1a4d82fc JJ |
74 | } |
75 | ||
dfeec247 XL |
76 | pub fn new( |
77 | sysroot: &'a Path, | |
78 | triple: &'a str, | |
79 | search_paths: &'a Vec<SearchPath>, | |
80 | tlib_path: &'a SearchPath, | |
81 | kind: PathKind, | |
82 | ) -> FileSearch<'a> { | |
1a4d82fc | 83 | debug!("using sysroot = {}, triple = {}", sysroot.display(), triple); |
dfeec247 | 84 | FileSearch { sysroot, triple, search_paths, tlib_path, kind } |
223e47cc | 85 | } |
1a4d82fc | 86 | |
0731742a XL |
87 | // Returns just the directories within the search paths. |
88 | pub fn search_path_dirs(&self) -> Vec<PathBuf> { | |
dfeec247 | 89 | self.search_paths().map(|sp| sp.dir.to_path_buf()).collect() |
1a4d82fc JJ |
90 | } |
91 | ||
92 | // Returns a list of directories where target-specific tool binaries are located. | |
f035d41b | 93 | pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> { |
c34b1796 | 94 | let mut p = PathBuf::from(self.sysroot); |
c30ab7b3 SL |
95 | p.push(find_libdir(self.sysroot).as_ref()); |
96 | p.push(RUST_LIB_DIR); | |
c34b1796 | 97 | p.push(&self.triple); |
1a4d82fc | 98 | p.push("bin"); |
3dfed10e | 99 | if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } |
1a4d82fc | 100 | } |
223e47cc LB |
101 | } |
102 | ||
c34b1796 | 103 | pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { |
c30ab7b3 | 104 | let mut p = PathBuf::from(find_libdir(sysroot).as_ref()); |
1a4d82fc | 105 | assert!(p.is_relative()); |
c30ab7b3 | 106 | p.push(RUST_LIB_DIR); |
1a4d82fc JJ |
107 | p.push(target_triple); |
108 | p.push("lib"); | |
109 | p | |
223e47cc LB |
110 | } |
111 | ||
0731742a | 112 | pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { |
1a4d82fc | 113 | sysroot.join(&relative_target_lib_path(sysroot, target_triple)) |
223e47cc LB |
114 | } |
115 | ||
c34b1796 | 116 | pub fn get_or_default_sysroot() -> PathBuf { |
1a4d82fc | 117 | // Follow symlinks. If the resolved path is relative, make it absolute. |
3dfed10e XL |
118 | fn canonicalize(path: PathBuf) -> PathBuf { |
119 | let path = fs::canonicalize(&path).unwrap_or(path); | |
120 | // See comments on this target function, but the gist is that | |
121 | // gcc chokes on verbatim paths which fs::canonicalize generates | |
122 | // so we try to avoid those kinds of paths. | |
123 | fix_windows_verbatim_for_gcc(&path) | |
1a4d82fc JJ |
124 | } |
125 | ||
7cac9316 | 126 | match env::current_exe() { |
3dfed10e XL |
127 | Ok(exe) => { |
128 | let mut p = canonicalize(exe); | |
129 | p.pop(); | |
130 | p.pop(); | |
131 | p | |
132 | } | |
133 | Err(e) => panic!("failed to get current_exe: {}", e), | |
223e47cc LB |
134 | } |
135 | } | |
136 | ||
1a4d82fc | 137 | // The name of the directory rustc expects libraries to be located. |
c30ab7b3 | 138 | fn find_libdir(sysroot: &Path) -> Cow<'static, str> { |
1a4d82fc JJ |
139 | // FIXME: This is a quick hack to make the rustc binary able to locate |
140 | // Rust libraries in Linux environments where libraries might be installed | |
141 | // to lib64/lib32. This would be more foolproof by basing the sysroot off | |
ba9703b0 XL |
142 | // of the directory where `librustc_driver` is located, rather than |
143 | // where the rustc binary is. | |
0bf4aa26 | 144 | // If --libdir is set during configuration to the value other than |
0731742a | 145 | // "lib" (i.e., non-default), this value is used (see issue #16552). |
1a4d82fc | 146 | |
85aaf69f | 147 | #[cfg(target_pointer_width = "64")] |
0731742a | 148 | const PRIMARY_LIB_DIR: &str = "lib64"; |
223e47cc | 149 | |
85aaf69f | 150 | #[cfg(target_pointer_width = "32")] |
0731742a | 151 | const PRIMARY_LIB_DIR: &str = "lib32"; |
1a4d82fc | 152 | |
0731742a | 153 | const SECONDARY_LIB_DIR: &str = "lib"; |
0bf4aa26 XL |
154 | |
155 | match option_env!("CFG_LIBDIR_RELATIVE") { | |
29967ef6 | 156 | None | Some("lib") => { |
dfeec247 XL |
157 | if sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR).exists() { |
158 | PRIMARY_LIB_DIR.into() | |
159 | } else { | |
160 | SECONDARY_LIB_DIR.into() | |
161 | } | |
0bf4aa26 | 162 | } |
29967ef6 | 163 | Some(libdir) => libdir.into(), |
0bf4aa26 | 164 | } |
223e47cc LB |
165 | } |
166 | ||
1a4d82fc JJ |
167 | // The name of rustc's own place to organize libraries. |
168 | // Used to be "rustc", now the default is "rustlib" | |
0731742a | 169 | const RUST_LIB_DIR: &str = "rustlib"; |