|
1 |
| -use crate::{mkl, Config, LinkType, VALID_CONFIGS}; |
| 1 | +use crate::{mkl, Config, LinkType}; |
2 | 2 | use anyhow::{bail, ensure, Context, Result};
|
3 |
| -use derive_more::Deref; |
4 | 3 | use std::{
|
5 |
| - collections::{HashMap, HashSet}, |
6 | 4 | fs,
|
7 | 5 | io::{self, BufRead},
|
8 | 6 | path::{Path, PathBuf},
|
9 |
| - str::FromStr, |
10 | 7 | };
|
11 | 8 |
|
12 | 9 | /// A library found in system
|
@@ -177,6 +174,13 @@ impl Library {
|
177 | 174 | bail!("Intel MKL not found in system");
|
178 | 175 | }
|
179 | 176 |
|
| 177 | + pub fn available() -> Vec<Self> { |
| 178 | + Config::possibles() |
| 179 | + .into_iter() |
| 180 | + .flat_map(|cfg| Self::new(cfg).ok()) |
| 181 | + .collect() |
| 182 | + } |
| 183 | + |
180 | 184 | pub fn config(&self) -> &Config {
|
181 | 185 | match self {
|
182 | 186 | Library::PkgConfig { config, .. } => config,
|
@@ -268,224 +272,6 @@ impl Library {
|
268 | 272 | }
|
269 | 273 | }
|
270 | 274 |
|
271 |
| -#[derive(Debug, Deref)] |
272 |
| -struct Targets(HashMap<String, Option<PathBuf>>); |
273 |
| - |
274 |
| -impl Targets { |
275 |
| - fn new(config: Config) -> Self { |
276 |
| - let mut targets: HashMap<String, Option<PathBuf>> = HashMap::new(); |
277 |
| - for name in config |
278 |
| - .libs() |
279 |
| - .into_iter() |
280 |
| - .chain(config.additional_libs().into_iter()) |
281 |
| - { |
282 |
| - let target = match config.link { |
283 |
| - LinkType::Static => format!("{}{}.{}", mkl::PREFIX, name, mkl::EXTENSION_STATIC), |
284 |
| - LinkType::Dynamic => format!("{}{}.{}", mkl::PREFIX, name, mkl::EXTENSION_SHARED), |
285 |
| - }; |
286 |
| - targets.insert(target, None); |
287 |
| - } |
288 |
| - Self(targets) |
289 |
| - } |
290 |
| - |
291 |
| - fn found_files(&self) -> Vec<(PathBuf, String)> { |
292 |
| - self.iter() |
293 |
| - .flat_map(|(name, path)| Some((path.as_ref()?.clone(), name.clone()))) |
294 |
| - .collect() |
295 |
| - } |
296 |
| - |
297 |
| - fn found_any(&self) -> bool { |
298 |
| - self.0.iter().any(|(_key, value)| value.is_some()) |
299 |
| - } |
300 |
| - |
301 |
| - fn seek<P: AsRef<Path>>(&mut self, dir: P) { |
302 |
| - let dir = dir.as_ref(); |
303 |
| - for (key, value) in &mut self.0 { |
304 |
| - if dir.join(key).exists() { |
305 |
| - value.get_or_insert(dir.canonicalize().unwrap()); |
306 |
| - } |
307 |
| - } |
308 |
| - } |
309 |
| -} |
310 |
| - |
311 |
| -#[derive(Debug)] |
312 |
| -enum EntryTarget { |
313 |
| - Manual(Targets), |
314 |
| - PkgConfig, |
315 |
| -} |
316 |
| - |
317 |
| -/// Handler for found library |
318 |
| -#[derive(Debug)] |
319 |
| -pub struct Entry { |
320 |
| - config: Config, |
321 |
| - target: EntryTarget, |
322 |
| -} |
323 |
| - |
324 |
| -impl Entry { |
325 |
| - /// Get the directory where the library exists |
326 |
| - /// |
327 |
| - /// This will seek followings in this order: |
328 |
| - /// |
329 |
| - /// - `$OUT_DIR` |
330 |
| - /// - Only for build.rs |
331 |
| - /// - This exists only when the previous build downloads archive here |
332 |
| - /// - pkg-config `${name}` |
333 |
| - /// - Installed by package manager or official downloader |
334 |
| - /// |
335 |
| - /// Returns error if no library found |
336 |
| - /// |
337 |
| - pub fn from_config(config: Config) -> Result<Self> { |
338 |
| - let mut targets = Targets::new(config); |
339 |
| - |
340 |
| - // OUT_DIR |
341 |
| - if let Ok(dir) = std::env::var("OUT_DIR") { |
342 |
| - let out_dir = PathBuf::from(dir); |
343 |
| - targets.seek(&out_dir); |
344 |
| - } |
345 |
| - |
346 |
| - // pkg-config |
347 |
| - if let Ok(_) = pkg_config::Config::new() |
348 |
| - .cargo_metadata(false) |
349 |
| - .probe(&config.to_string()) |
350 |
| - { |
351 |
| - return Ok(Self { |
352 |
| - config, |
353 |
| - target: EntryTarget::PkgConfig, |
354 |
| - }); |
355 |
| - } |
356 |
| - |
357 |
| - // $MKLROOT |
358 |
| - let mkl_root = std::env::var("MKLROOT").map(PathBuf::from); |
359 |
| - if let Ok(path) = mkl_root { |
360 |
| - if path.exists() { |
361 |
| - targets.seek(path.join("lib/intel64")); |
362 |
| - } |
363 |
| - } |
364 |
| - |
365 |
| - // /opt/intel |
366 |
| - let opt_mkl = PathBuf::from("/opt/intel"); |
367 |
| - if opt_mkl.exists() { |
368 |
| - targets.seek(opt_mkl.join("lib/intel64")); |
369 |
| - targets.seek(opt_mkl.join("mkl/lib/intel64")); |
370 |
| - } |
371 |
| - |
372 |
| - // Default setting for Windows installer |
373 |
| - let windows_mkl = |
374 |
| - PathBuf::from("C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows"); |
375 |
| - if windows_mkl.exists() { |
376 |
| - targets.seek(windows_mkl.join("mkl/lib/intel64")); |
377 |
| - targets.seek(windows_mkl.join("compiler/lib/intel64")); |
378 |
| - } |
379 |
| - |
380 |
| - if targets.found_any() { |
381 |
| - Ok(Self { |
382 |
| - config, |
383 |
| - target: EntryTarget::Manual(targets), |
384 |
| - }) |
385 |
| - } else { |
386 |
| - // None found |
387 |
| - bail!("No library found for {}", config); |
388 |
| - } |
389 |
| - } |
390 |
| - |
391 |
| - pub fn name(&self) -> String { |
392 |
| - self.config.to_string() |
393 |
| - } |
394 |
| - |
395 |
| - pub fn found_files(&self) -> Vec<(PathBuf, String)> { |
396 |
| - if let EntryTarget::Manual(m) = &self.target { |
397 |
| - m.found_files() |
398 |
| - } else { |
399 |
| - vec![] |
400 |
| - } |
401 |
| - } |
402 |
| - |
403 |
| - pub fn available() -> Vec<Self> { |
404 |
| - VALID_CONFIGS |
405 |
| - .iter() |
406 |
| - .flat_map(|name| Self::from_config(Config::from_str(name).unwrap())) |
407 |
| - .collect() |
408 |
| - } |
409 |
| - |
410 |
| - /// Get MKL version info from its C header |
411 |
| - /// |
412 |
| - /// - This will not work for OUT_DIR, or Pkgconfig entry, |
413 |
| - /// and returns Error in these cases |
414 |
| - pub fn version(&self) -> Result<(u32, u32)> { |
415 |
| - for (path, _) in &self.found_files() { |
416 |
| - // assumes following directory structure: |
417 |
| - // |
418 |
| - // - mkl |
419 |
| - // - include |
420 |
| - // - lib/intel64 <- this is cached in targets |
421 |
| - // |
422 |
| - let version_header = path.join("../../include/mkl_version.h"); |
423 |
| - if !version_header.exists() { |
424 |
| - continue; |
425 |
| - } |
426 |
| - |
427 |
| - // Extract version info from C header |
428 |
| - // |
429 |
| - // ``` |
430 |
| - // #define __INTEL_MKL__ 2020 |
431 |
| - // #define __INTEL_MKL_MINOR__ 0 |
432 |
| - // #define __INTEL_MKL_UPDATE__ 1 |
433 |
| - // ``` |
434 |
| - let f = fs::File::open(version_header)?; |
435 |
| - let f = io::BufReader::new(f); |
436 |
| - let mut year = 0; |
437 |
| - let mut update = 0; |
438 |
| - for line in f.lines() { |
439 |
| - if let Ok(line) = line { |
440 |
| - if !line.starts_with("#define") { |
441 |
| - continue; |
442 |
| - } |
443 |
| - let ss: Vec<&str> = line.split(' ').collect(); |
444 |
| - match ss[1] { |
445 |
| - "__INTEL_MKL__" => year = ss[2].parse()?, |
446 |
| - "__INTEL_MKL_UPDATE__" => update = ss[2].parse()?, |
447 |
| - _ => continue, |
448 |
| - } |
449 |
| - } |
450 |
| - } |
451 |
| - if year > 0 && update > 0 { |
452 |
| - return Ok((year, update)); |
453 |
| - } |
454 |
| - } |
455 |
| - bail!("Cannot determine MKL versions"); |
456 |
| - } |
457 |
| - |
458 |
| - pub fn print_cargo_metadata(&self) { |
459 |
| - match &self.target { |
460 |
| - EntryTarget::Manual(_target) => { |
461 |
| - let paths: HashSet<PathBuf> = self |
462 |
| - .found_files() |
463 |
| - .into_iter() |
464 |
| - .map(|(path, _name)| path) |
465 |
| - .collect(); // must be redundant |
466 |
| - for path in paths { |
467 |
| - println!("cargo:rustc-link-search={}", path.display()); |
468 |
| - } |
469 |
| - for lib in self.config.libs() { |
470 |
| - match self.config.link { |
471 |
| - LinkType::Static => { |
472 |
| - println!("cargo:rustc-link-lib=static={}", lib); |
473 |
| - } |
474 |
| - LinkType::Dynamic => { |
475 |
| - println!("cargo:rustc-link-lib=dylib={}", lib); |
476 |
| - } |
477 |
| - } |
478 |
| - } |
479 |
| - } |
480 |
| - EntryTarget::PkgConfig => { |
481 |
| - pkg_config::Config::new() |
482 |
| - .probe(&self.config.to_string()) |
483 |
| - .unwrap(); |
484 |
| - } |
485 |
| - } |
486 |
| - } |
487 |
| -} |
488 |
| - |
489 | 275 | #[cfg(test)]
|
490 | 276 | mod tests {
|
491 | 277 | use super::*;
|
|
0 commit comments