]>
Commit | Line | Data |
---|---|---|
60c5eb7d | 1 | use crate::filesearch::make_target_lib_path; |
dfeec247 XL |
2 | use crate::{config, early_error}; |
3 | use std::path::{Path, PathBuf}; | |
1a4d82fc | 4 | |
85aaf69f | 5 | #[derive(Clone, Debug)] |
0731742a XL |
6 | pub struct SearchPath { |
7 | pub kind: PathKind, | |
8 | pub dir: PathBuf, | |
ba9703b0 XL |
9 | pub files: Vec<SearchPathFile>, |
10 | } | |
11 | ||
12 | // The obvious implementation of `SearchPath::files` is a `Vec<PathBuf>`. But | |
13 | // it is searched repeatedly by `find_library_crate`, and the searches involve | |
14 | // checking the prefix and suffix of the filename of each `PathBuf`. This is | |
15 | // doable, but very slow, because it involves calls to `file_name` and | |
16 | // `extension` that are themselves slow. | |
17 | // | |
18 | // This type augments the `PathBuf` with an `Option<String>` containing the | |
19 | // `PathBuf`'s filename. The prefix and suffix checking is much faster on the | |
20 | // `Option<String>` than the `PathBuf`. (It's an `Option` because | |
21 | // `Path::file_name` can fail; if that happens then all subsequent checking | |
22 | // will also fail, which is fine.) | |
23 | #[derive(Clone, Debug)] | |
24 | pub struct SearchPathFile { | |
25 | pub path: PathBuf, | |
26 | pub file_name_str: Option<String>, | |
27 | } | |
28 | ||
29 | impl SearchPathFile { | |
30 | fn new(path: PathBuf) -> SearchPathFile { | |
31 | let file_name_str = path.file_name().and_then(|f| f.to_str()).map(|s| s.to_string()); | |
32 | SearchPathFile { path, file_name_str } | |
33 | } | |
1a4d82fc JJ |
34 | } |
35 | ||
3dfed10e | 36 | #[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable)] |
1a4d82fc JJ |
37 | pub enum PathKind { |
38 | Native, | |
39 | Crate, | |
40 | Dependency, | |
85aaf69f SL |
41 | Framework, |
42 | ExternFlag, | |
1a4d82fc JJ |
43 | All, |
44 | } | |
45 | ||
60c5eb7d XL |
46 | rustc_data_structures::impl_stable_hash_via_hash!(PathKind); |
47 | ||
0731742a XL |
48 | impl PathKind { |
49 | pub fn matches(&self, kind: PathKind) -> bool { | |
50 | match (self, kind) { | |
51 | (PathKind::All, _) | (_, PathKind::All) => true, | |
52 | _ => *self == kind, | |
53 | } | |
1a4d82fc | 54 | } |
0731742a | 55 | } |
1a4d82fc | 56 | |
0731742a XL |
57 | impl SearchPath { |
58 | pub fn from_cli_opt(path: &str, output: config::ErrorOutputType) -> Self { | |
1a4d82fc | 59 | let (kind, path) = if path.starts_with("native=") { |
85aaf69f | 60 | (PathKind::Native, &path["native=".len()..]) |
1a4d82fc | 61 | } else if path.starts_with("crate=") { |
85aaf69f | 62 | (PathKind::Crate, &path["crate=".len()..]) |
1a4d82fc | 63 | } else if path.starts_with("dependency=") { |
85aaf69f SL |
64 | (PathKind::Dependency, &path["dependency=".len()..]) |
65 | } else if path.starts_with("framework=") { | |
66 | (PathKind::Framework, &path["framework=".len()..]) | |
1a4d82fc | 67 | } else if path.starts_with("all=") { |
85aaf69f | 68 | (PathKind::All, &path["all=".len()..]) |
1a4d82fc JJ |
69 | } else { |
70 | (PathKind::All, path) | |
71 | }; | |
c34b1796 | 72 | if path.is_empty() { |
9cc50fc6 | 73 | early_error(output, "empty search path given via `-L`"); |
c34b1796 | 74 | } |
1a4d82fc | 75 | |
0731742a XL |
76 | let dir = PathBuf::from(path); |
77 | Self::new(kind, dir) | |
1a4d82fc | 78 | } |
1a4d82fc | 79 | |
0731742a XL |
80 | pub fn from_sysroot_and_triple(sysroot: &Path, triple: &str) -> Self { |
81 | Self::new(PathKind::All, make_target_lib_path(sysroot, triple)) | |
82 | } | |
1a4d82fc | 83 | |
0731742a XL |
84 | fn new(kind: PathKind, dir: PathBuf) -> Self { |
85 | // Get the files within the directory. | |
86 | let files = match std::fs::read_dir(&dir) { | |
ba9703b0 XL |
87 | Ok(files) => files |
88 | .filter_map(|e| e.ok().map(|e| SearchPathFile::new(e.path()))) | |
89 | .collect::<Vec<_>>(), | |
0731742a XL |
90 | Err(..) => vec![], |
91 | }; | |
0531ce1d | 92 | |
0731742a | 93 | SearchPath { kind, dir, files } |
0531ce1d | 94 | } |
1a4d82fc | 95 | } |