|
1 | 1 | use std::env;
|
| 2 | +use std::fs::read_dir; |
2 | 3 | use std::path::{Path, PathBuf};
|
3 | 4 | use std::process::Command;
|
4 | 5 |
|
5 | 6 | use failure::Error;
|
6 | 7 |
|
7 | 8 | pub fn find_lib_path() -> Result<PathBuf, Error> {
|
8 |
| - let paths = collect_possible_paths()?; |
| 9 | + let directories = collect_possible_directories(); |
9 | 10 |
|
10 |
| - if paths.is_empty() { |
| 11 | + if directories.is_empty() { |
11 | 12 | bail!("Unable to find possible LLVM shared lib locations.");
|
12 | 13 | }
|
13 | 14 |
|
14 |
| - for path in &paths { |
15 |
| - if path.join("librustc_codegen_llvm-llvm.so").exists() { |
16 |
| - return Ok(path.join("librustc_codegen_llvm-llvm.so")); |
17 |
| - } |
18 |
| - |
19 |
| - if path.join("librustc_codegen_llvm-llvm.dylib").exists() { |
20 |
| - return Ok(path.join("librustc_codegen_llvm-llvm.dylib")); |
21 |
| - } |
22 |
| - |
23 |
| - if path.join("rustc_codegen_llvm-llvm.dll").exists() { |
24 |
| - return Ok(path.join("rustc_codegen_llvm-llvm.dll")); |
| 15 | + for directory in &directories { |
| 16 | + if let Some(library) = find_library_in_directory(&directory) { |
| 17 | + return Ok(library); |
25 | 18 | }
|
26 | 19 | }
|
27 | 20 |
|
28 | 21 | bail!(
|
29 | 22 | "Unable to find LLVM shared lib in possible locations:\n- {}",
|
30 |
| - paths |
| 23 | + directories |
31 | 24 | .into_iter()
|
32 | 25 | .map(|item| item.to_str().unwrap().to_owned())
|
33 | 26 | .collect::<Vec<_>>()
|
34 | 27 | .join("\n- ")
|
35 | 28 | );
|
36 | 29 | }
|
37 | 30 |
|
38 |
| -fn collect_possible_paths() -> Result<Vec<PathBuf>, Error> { |
| 31 | +fn collect_possible_directories() -> Vec<PathBuf> { |
39 | 32 | let mut paths = vec![];
|
40 | 33 |
|
41 |
| - // Special case: find the location for Rust built from sources. |
42 |
| - if let Ok(env_path) = env::var("PATH") { |
43 |
| - for item in env_path.split(':') { |
44 |
| - let mut rustc_path = PathBuf::from(item); |
45 |
| - |
46 |
| - rustc_path.pop(); |
47 |
| - paths.push(rustc_path.join("codegen-backends")); |
48 |
| - } |
49 |
| - } |
50 |
| - |
51 |
| - if let Ok(rustup_home) = env::var("RUSTUP_HOME") { |
52 |
| - let rustup_home = PathBuf::from(rustup_home); |
53 |
| - let rustup_toolchain = env::var("RUSTUP_TOOLCHAIN")?; |
54 |
| - let rustup_arch = extract_arch(&rustup_toolchain); |
55 |
| - |
56 |
| - paths.push( |
57 |
| - rustup_home |
58 |
| - .join("toolchains") |
59 |
| - .join(&rustup_toolchain) |
60 |
| - .join("lib") |
61 |
| - .join("rustlib") |
62 |
| - .join(rustup_arch) |
63 |
| - .join("codegen-backends"), |
64 |
| - ); |
65 |
| - } |
66 |
| - |
67 | 34 | if let Ok(lib_paths) = env::var("LD_LIBRARY_PATH") {
|
68 | 35 | for item in lib_paths.split(':') {
|
69 |
| - let mut possible_path = PathBuf::from(item); |
70 |
| - possible_path.pop(); |
71 |
| - |
72 |
| - if let Some(possible_toolchain) = possible_path.file_name() { |
73 |
| - let possible_arch = extract_arch(possible_toolchain.to_str().unwrap()); |
74 |
| - |
75 |
| - paths.push( |
76 |
| - possible_path |
77 |
| - .join("lib") |
78 |
| - .join("rustlib") |
79 |
| - .join(possible_arch) |
80 |
| - .join("codegen-backends"), |
81 |
| - ); |
82 |
| - } |
| 36 | + paths.push(PathBuf::from(item)); |
83 | 37 | }
|
84 | 38 | }
|
85 | 39 |
|
86 |
| - if let Ok(cargo) = env::var("CARGO") { |
87 |
| - let mut cargo_path = PathBuf::from(cargo); |
88 |
| - cargo_path.pop(); |
89 |
| - cargo_path.pop(); |
90 |
| - |
91 |
| - if let Some(toolchain) = cargo_path.file_name() { |
92 |
| - let arch = env::var("HOST").unwrap_or_else(|_| extract_arch(toolchain.to_str().unwrap())); |
93 |
| - |
94 |
| - paths.push( |
95 |
| - cargo_path |
96 |
| - .join("lib") |
97 |
| - .join("rustlib") |
98 |
| - .join(arch) |
99 |
| - .join("codegen-backends"), |
100 |
| - ); |
101 |
| - } |
102 |
| - } |
103 |
| - |
104 |
| - if let Some(rustc) = find_rustc() { |
105 |
| - if let Ok(output) = Command::new(&rustc).args(&["--print", "sysroot"]).output() { |
106 |
| - let mut sysroot = PathBuf::from(String::from_utf8_lossy(&output.stdout).trim()); |
107 |
| - if let Some(arch) = find_arch(&rustc, &sysroot) { |
108 |
| - paths.push( |
109 |
| - sysroot |
110 |
| - .join("lib") |
111 |
| - .join("rustlib") |
112 |
| - .join(arch) |
113 |
| - .join("codegen-backends"), |
114 |
| - ); |
115 |
| - } |
116 |
| - } |
117 |
| - } |
118 |
| - |
119 |
| - if let Ok(output) = Command::new("rustup").args(&["which", "rustc"]).output() { |
120 |
| - let mut rustc_path = PathBuf::from(String::from_utf8_lossy(&output.stdout).trim()); |
121 |
| - rustc_path.pop(); |
122 |
| - rustc_path.pop(); |
123 |
| - |
124 |
| - if let Some(toolchain) = rustc_path.file_name() { |
125 |
| - let arch = extract_arch(toolchain.to_str().unwrap()); |
| 40 | + if let Ok(bin_paths) = env::var("PATH") { |
| 41 | + for item in bin_paths.split(':') { |
| 42 | + let mut possible_path = PathBuf::from(item); |
126 | 43 |
|
127 |
| - paths.push( |
128 |
| - rustc_path |
129 |
| - .join("lib") |
130 |
| - .join("rustlib") |
131 |
| - .join(arch) |
132 |
| - .join("codegen-backends"), |
133 |
| - ); |
| 44 | + possible_path.pop(); |
| 45 | + possible_path.push("lib"); |
| 46 | + paths.push(possible_path); |
134 | 47 | }
|
135 | 48 | }
|
136 | 49 |
|
137 |
| - Ok(paths) |
| 50 | + paths |
138 | 51 | }
|
139 | 52 |
|
140 |
| -// Fails if using nightly build from a specific date |
141 |
| -// e.g. nightly-2018-11-30-x86_64-unknown-linux-gnu |
142 |
| -fn extract_arch(toolchain: &str) -> String { |
143 |
| - toolchain |
144 |
| - .split('-') |
145 |
| - // Skip `nightly` rust version prefix. |
146 |
| - .skip(1) |
147 |
| - // Also skip rust version specification if exists. |
148 |
| - .skip_while(|item| match item.chars().next() { |
149 |
| - None | Some('0'...'9') => true, |
150 |
| - _ => false, |
151 |
| - }) |
152 |
| - .collect::<Vec<_>>() |
153 |
| - .join("-") |
154 |
| -} |
| 53 | +fn find_library_in_directory(directory: &Path) -> Option<PathBuf> { |
| 54 | + match read_dir(directory) { |
| 55 | + Ok(files) => files |
| 56 | + .filter_map(Result::ok) |
| 57 | + .find(|file| file.file_name().to_string_lossy().starts_with("libLLVM")) |
| 58 | + .map(|file| file.path()), |
155 | 59 |
|
156 |
| -fn find_rustc() -> Option<PathBuf> { |
157 |
| - if let Some(path) = env::var_os("RUSTC") { |
158 |
| - Some(path.into()) |
159 |
| - } else if let Ok(output) = Command::new("rustup").args(&["which", "rustc"]).output() { |
160 |
| - Some(String::from_utf8_lossy(&output.stdout).trim().into()) |
161 |
| - } else { |
162 |
| - None |
163 |
| - } |
164 |
| -} |
165 |
| - |
166 |
| -fn find_arch(rustc: &Path, sysroot: &Path) -> Option<String> { |
167 |
| - if let Ok(path) = env::var("HOST") { |
168 |
| - Some(path) |
169 |
| - } else if let Ok(output) = Command::new(&rustc).args(&["-vV"]).output() { |
170 |
| - for line in String::from_utf8_lossy(&output.stdout).lines() { |
171 |
| - if line.starts_with("host") { |
172 |
| - return Some(line.trim_start_matches("host:").trim().to_string()); |
173 |
| - } |
174 |
| - } |
175 |
| - None |
176 |
| - } else if let Some(toolchain) = sysroot.file_name() { |
177 |
| - Some(extract_arch(toolchain.to_str().unwrap())) |
178 |
| - } else { |
179 |
| - None |
| 60 | + Err(_) => None, |
180 | 61 | }
|
181 | 62 | }
|
0 commit comments