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