From 5981d477f52d5ec435d6af9b4162e75412461294 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 15:16:02 +0900 Subject: [PATCH 01/27] Start Entry2 --- intel-mkl-tool/src/entry.rs | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 8ef12560..3f54f895 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -9,6 +9,58 @@ use std::{ str::FromStr, }; +#[derive(Debug, Clone)] +pub enum Entry2 { + PkgConfig { + config: Config, + lib: pkg_config::Library, + }, + Directory { + config: Config, + root_dir: PathBuf, + }, +} + +impl Entry2 { + pub fn try_pkg_config(config: Config) -> Option { + if let Ok(lib) = pkg_config::Config::new() + .cargo_metadata(false) + .env_metadata(false) + .probe(&config.to_string()) + { + Some(Entry2::PkgConfig { config, lib }) + } else { + None + } + } + + /// Seek MKL libraries in the given directory. + /// + /// This will seek the directory recursively until finding MKL libraries. + /// Returns `Ok(None)` if not found. `Err` means IO error while seeking. + /// + pub fn seek_directory(_config: Config, dir_root: impl AsRef) -> Result> { + let _dir = dir_root.as_ref(); + todo!() + } + + pub fn new(config: Config) -> Result { + todo!() + } + + pub fn config(&self) -> &Config { + match self { + Entry2::PkgConfig { config, .. } => config, + Entry2::Directory { config, .. } => config, + } + } + + /// Found MKL version parsed from `mkl_version.h`, e.g. `(2020, 1)` + pub fn version(&self) -> (u32, u32) { + todo!() + } +} + #[derive(Debug, Deref)] struct Targets(HashMap>); From 1fcc4c4e5d77fdf7235a2374c11bb4b18bab5f7b Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 16:15:52 +0900 Subject: [PATCH 02/27] Rename Entry2 to Library, add documents --- intel-mkl-tool/src/entry.rs | 52 +++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 3f54f895..2c79434a 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -9,26 +9,36 @@ use std::{ str::FromStr, }; +/// A library found in system #[derive(Debug, Clone)] -pub enum Entry2 { +pub enum Library { PkgConfig { config: Config, lib: pkg_config::Library, }, Directory { config: Config, - root_dir: PathBuf, + /// Directory where `mkl.h` and `mkl_version.h` exists + include_dir: PathBuf, + /// Directory where `libmkl_core.a` or `libmkl_rt.so` exists + library_dir: PathBuf, + /// Directory where `libiomp5.a` or `libiomp5.so` exists + /// + /// They are sometimes placed in different position. + /// Returns `None` if they exist on `library_dir`. + iomp5_dir: Option, }, } -impl Entry2 { - pub fn try_pkg_config(config: Config) -> Option { +impl Library { + /// Try to find MKL using pkg-config + pub fn pkg_config(config: Config) -> Option { if let Ok(lib) = pkg_config::Config::new() .cargo_metadata(false) .env_metadata(false) .probe(&config.to_string()) { - Some(Entry2::PkgConfig { config, lib }) + Some(Library::PkgConfig { config, lib }) } else { None } @@ -39,24 +49,44 @@ impl Entry2 { /// This will seek the directory recursively until finding MKL libraries. /// Returns `Ok(None)` if not found. `Err` means IO error while seeking. /// - pub fn seek_directory(_config: Config, dir_root: impl AsRef) -> Result> { - let _dir = dir_root.as_ref(); + pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Result> { todo!() } + /// Seek MKL in system + /// + /// This try to find installed MKL in following order: + /// + /// - Ask to `pkg-config` + /// - Seek the directory specified by `$MKLROOT` environment variable + /// - Seek well-known directory + /// - `/opt/intel` for Linux + /// - `C:/Program Files (x86)/IntelSWTools/` for Windows + /// pub fn new(config: Config) -> Result { todo!() } pub fn config(&self) -> &Config { match self { - Entry2::PkgConfig { config, .. } => config, - Entry2::Directory { config, .. } => config, + Library::PkgConfig { config, .. } => config, + Library::Directory { config, .. } => config, } } - /// Found MKL version parsed from `mkl_version.h`, e.g. `(2020, 1)` - pub fn version(&self) -> (u32, u32) { + /// Found MKL version parsed from `mkl_version.h` + /// + /// `mkl_version.h` will define + /// + /// ```c + /// #define __INTEL_MKL__ 2020 + /// #define __INTEL_MKL_MINOR__ 0 + /// #define __INTEL_MKL_UPDATE__ 1 + /// ``` + /// + /// and this corresponds to `(2020, 0, 1)` + /// + pub fn version(&self) -> (u32, u32, u32) { todo!() } } From 8166537a4c240deb703964f93b1c55c0ba5f95e2 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 17:22:23 +0900 Subject: [PATCH 03/27] Library::seek_directory --- .github/workflows/intel-mkl-tool.yml | 17 ++++++++ intel-mkl-tool/Cargo.toml | 1 + intel-mkl-tool/src/entry.rs | 65 ++++++++++++++++++++++++++-- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/.github/workflows/intel-mkl-tool.yml b/.github/workflows/intel-mkl-tool.yml index 8cb2fee2..64407402 100644 --- a/.github/workflows/intel-mkl-tool.yml +++ b/.github/workflows/intel-mkl-tool.yml @@ -45,3 +45,20 @@ jobs: - uses: actions/checkout@v1 - name: Test with mkl-rust container run: make -C intel-mkl-tool ${{ matrix.target }} + + seek-opt-intel: + runs-on: ubuntu-22.04 + container: + image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0 + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/cargo@v1 + name: cargo test seek_opt_intel + with: + command: test + args: > + --manifest-path=intel-mkl-tool/Cargo.toml + seek_opt_intel + -- + --ignored + --show-output diff --git a/intel-mkl-tool/Cargo.toml b/intel-mkl-tool/Cargo.toml index 6e9aebfd..c58af7c7 100644 --- a/intel-mkl-tool/Cargo.toml +++ b/intel-mkl-tool/Cargo.toml @@ -29,6 +29,7 @@ zstd = { version = "0.11.2", optional = true } # CLI structopt = { version = "0.3.26", optional = true } +walkdir = "2.3.2" [dev-dependencies] paste = "1.0.7" diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 2c79434a..6e26adce 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -47,10 +47,60 @@ impl Library { /// Seek MKL libraries in the given directory. /// /// This will seek the directory recursively until finding MKL libraries. - /// Returns `Ok(None)` if not found. `Err` means IO error while seeking. + /// This do not follow symbolic links. /// - pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Result> { - todo!() + pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Option { + let mut library_dir = None; + let mut include_dir = None; + let mut iomp5_dir = None; + for entry in walkdir::WalkDir::new(root_dir) { + let path = entry.unwrap().into_path(); + if path.is_dir() { + continue; + } + let (stem, ext) = match (path.file_stem(), path.extension()) { + (Some(stem), Some(ext)) => ( + stem.to_str().expect("Non UTF8 filename"), + ext.to_str().expect("Non UTF8 filename"), + ), + _ => continue, + }; + let dir = path.parent().unwrap().to_owned(); + if stem == "mkl" && ext == "h" { + include_dir = Some(dir); + continue; + } + let name = if let Some(name) = stem.strip_prefix(mkl::PREFIX) { + name + } else { + continue; + }; + match (config.link, ext) { + (LinkType::Static, mkl::EXTENSION_STATIC) => match name { + "mkl_core" => library_dir = Some(dir), + "iomp5" => iomp5_dir = Some(dir), + _ => {} + }, + (LinkType::Dynamic, mkl::EXTENSION_SHARED) => match name { + "mkl_rt" => library_dir = Some(dir), + "iomp5" => iomp5_dir = Some(dir), + _ => {} + }, + _ => {} + } + } + if library_dir == iomp5_dir { + iomp5_dir = None; + } + match (library_dir, include_dir) { + (Some(library_dir), Some(include_dir)) => Some(Library::Directory { + config, + include_dir, + library_dir, + iomp5_dir, + }), + _ => None, + } } /// Seek MKL in system @@ -319,4 +369,13 @@ mod tests { fn with_mkl_availables() { assert_eq!(Entry::available().len(), 8); } + + /// Seek /opt/intel in Linux system + #[ignore] + #[test] + fn seek_opt_intel() { + let cfg = Config::from_str("mkl-static-lp64-seq").unwrap(); + let lib = Library::seek_directory(cfg, "/opt/intel").unwrap(); + dbg!(lib); + } } From 9c0ed5e9fdf1bbc8ab16b09626df8320503e29cc Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 17:42:05 +0900 Subject: [PATCH 04/27] Do not seek ia32 directory --- intel-mkl-tool/src/entry.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 6e26adce..e2152e98 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -46,8 +46,9 @@ impl Library { /// Seek MKL libraries in the given directory. /// - /// This will seek the directory recursively until finding MKL libraries. - /// This do not follow symbolic links. + /// - This will seek the directory recursively until finding MKL libraries, + /// but do not follow symbolic links. + /// - This will not seek directory named `ia32*` /// pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Option { let mut library_dir = None; @@ -65,7 +66,25 @@ impl Library { ), _ => continue, }; - let dir = path.parent().unwrap().to_owned(); + // Skip directory for ia32 + if path.components().any(|c| { + if let std::path::Component::Normal(c) = c { + if c.to_str() + .expect("Non-UTF8 directory name") + .starts_with("ia32") + { + return true; + } + } + false + }) { + continue; + } + + let dir = path + .parent() + .expect("parent must exist here since this is under `root_dir`") + .to_owned(); if stem == "mkl" && ext == "h" { include_dir = Some(dir); continue; From 047296c1b522fe4bc91ac3343b169f2341ea793f Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 18:33:33 +0900 Subject: [PATCH 05/27] Panic if two MKL found in a root directory --- intel-mkl-tool/src/entry.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index e2152e98..b7c1191c 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -51,6 +51,7 @@ impl Library { /// - This will not seek directory named `ia32*` /// pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Option { + let root_dir = root_dir.as_ref(); let mut library_dir = None; let mut include_dir = None; let mut iomp5_dir = None; @@ -96,13 +97,37 @@ impl Library { }; match (config.link, ext) { (LinkType::Static, mkl::EXTENSION_STATIC) => match name { - "mkl_core" => library_dir = Some(dir), - "iomp5" => iomp5_dir = Some(dir), + "mkl_core" => { + assert!( + library_dir.replace(dir).is_none(), + "Two or more MKL found in {}", + root_dir.display() + ) + } + "iomp5" => { + assert!( + iomp5_dir.replace(dir).is_none(), + "Two or more MKL found in {}", + root_dir.display() + ) + } _ => {} }, (LinkType::Dynamic, mkl::EXTENSION_SHARED) => match name { - "mkl_rt" => library_dir = Some(dir), - "iomp5" => iomp5_dir = Some(dir), + "mkl_rt" => { + assert!( + library_dir.replace(dir).is_none(), + "Two or more MKL found in {}", + root_dir.display() + ) + } + "iomp5" => { + assert!( + iomp5_dir.replace(dir).is_none(), + "Two or more MKL found in {}", + root_dir.display() + ) + } _ => {} }, _ => {} From 1edb6b10dcde2622afae17096f4f40cb046ff243 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 20:57:10 +0900 Subject: [PATCH 06/27] Library::new --- intel-mkl-tool/src/entry.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index b7c1191c..2fd257a4 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -158,7 +158,21 @@ impl Library { /// - `C:/Program Files (x86)/IntelSWTools/` for Windows /// pub fn new(config: Config) -> Result { - todo!() + if let Some(lib) = Self::pkg_config(config.clone()) { + return Ok(lib); + } + if let Ok(mklroot) = std::env::var("MKLROOT") { + if let Some(lib) = Self::seek_directory(config.clone(), mklroot) { + return Ok(lib); + } + } + for path in ["/opt/intel", "C:/Program Files (x86)/IntelSWTools/"] { + let path = Path::new(path); + if let Some(lib) = Self::seek_directory(config.clone(), path) { + return Ok(lib); + } + } + bail!("Intel MKL not found in system"); } pub fn config(&self) -> &Config { From 5b7dcd086aab8d7f72078d1189aea119f236b90d Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 21:13:29 +0900 Subject: [PATCH 07/27] Test Library::pkg_config --- .github/workflows/intel-mkl-tool.yml | 27 ++++++++++----------------- intel-mkl-tool/src/entry.rs | 19 +++++++++++-------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/.github/workflows/intel-mkl-tool.yml b/.github/workflows/intel-mkl-tool.yml index 64407402..c9443a68 100644 --- a/.github/workflows/intel-mkl-tool.yml +++ b/.github/workflows/intel-mkl-tool.yml @@ -35,30 +35,23 @@ jobs: args: --manifest-path=intel-mkl-tool/Cargo.toml --no-default-features name: cargo-test no-default-features - docker: + find_system_mkl: runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: - target: ["test", "package", "seek", "seek-ubuntu", "seek-centos"] - steps: - - uses: actions/checkout@v1 - - name: Test with mkl-rust container - run: make -C intel-mkl-tool ${{ matrix.target }} - - seek-opt-intel: - runs-on: ubuntu-22.04 + image: ["mkl-rust", "mkl-ubuntu", "mkl-centos"] container: - image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0 + image: ghcr.io/rust-math/intel-mkl-src/${{ matrix.image }}:1.56.0 steps: - uses: actions/checkout@v1 - uses: actions-rs/cargo@v1 - name: cargo test seek_opt_intel + name: Seek /opt/intel + with: + command: test + args: --manifest-path=intel-mkl-tool/Cargo.toml seek_opt_intel -- --ignored --show-output + - uses: actions-rs/cargo@v1 + name: Use pkg-config with: command: test - args: > - --manifest-path=intel-mkl-tool/Cargo.toml - seek_opt_intel - -- - --ignored - --show-output + args: --manifest-path=intel-mkl-tool/Cargo.toml pkg_config -- --ignored --show-output diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 2fd257a4..67cbd210 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -421,19 +421,22 @@ impl Entry { mod tests { use super::*; - /// Test all available MKL are detected + /// Seek /opt/intel in Linux system #[ignore] #[test] - fn with_mkl_availables() { - assert_eq!(Entry::available().len(), 8); + fn seek_opt_intel() { + for cfg in Config::possibles() { + let lib = Library::seek_directory(cfg, "/opt/intel").unwrap(); + dbg!(lib); + } } - /// Seek /opt/intel in Linux system #[ignore] #[test] - fn seek_opt_intel() { - let cfg = Config::from_str("mkl-static-lp64-seq").unwrap(); - let lib = Library::seek_directory(cfg, "/opt/intel").unwrap(); - dbg!(lib); + fn pkg_config() { + for cfg in Config::possibles() { + let lib = Library::pkg_config(cfg).unwrap(); + dbg!(lib); + } } } From 0c35a34f6ec15e8a373914667ab4cc5748f4a1c8 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Tue, 2 Aug 2022 23:24:39 +0900 Subject: [PATCH 08/27] clippy fix --- intel-mkl-src/build.rs | 2 +- intel-mkl-tool/src/entry.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/intel-mkl-src/build.rs b/intel-mkl-src/build.rs index eb6ede2f..8f5da293 100644 --- a/intel-mkl-src/build.rs +++ b/intel-mkl-src/build.rs @@ -24,7 +24,7 @@ use anyhow::{bail, Result}; use intel_mkl_tool::*; -use std::{env, path::PathBuf, str::FromStr}; +use std::{str::FromStr}; #[cfg(feature = "mkl-static-lp64-iomp")] const MKL_CONFIG: &str = "mkl-static-lp64-iomp"; diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 67cbd210..55359a6e 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -158,17 +158,17 @@ impl Library { /// - `C:/Program Files (x86)/IntelSWTools/` for Windows /// pub fn new(config: Config) -> Result { - if let Some(lib) = Self::pkg_config(config.clone()) { + if let Some(lib) = Self::pkg_config(config) { return Ok(lib); } if let Ok(mklroot) = std::env::var("MKLROOT") { - if let Some(lib) = Self::seek_directory(config.clone(), mklroot) { + if let Some(lib) = Self::seek_directory(config, mklroot) { return Ok(lib); } } for path in ["/opt/intel", "C:/Program Files (x86)/IntelSWTools/"] { let path = Path::new(path); - if let Some(lib) = Self::seek_directory(config.clone(), path) { + if let Some(lib) = Self::seek_directory(config, path) { return Ok(lib); } } From 7dbcd0646a3c59098b3ea2d192f2ae7b3c4a085d Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Wed, 3 Aug 2022 12:21:26 +0900 Subject: [PATCH 09/27] Revise error handling in Library::seek_directory --- intel-mkl-tool/src/entry.rs | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 55359a6e..864890ec 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -1,5 +1,5 @@ use crate::{mkl, Config, LinkType, VALID_CONFIGS}; -use anyhow::{bail, Result}; +use anyhow::{bail, ensure, Context, Result}; use derive_more::Deref; use std::{ collections::{HashMap, HashSet}, @@ -50,8 +50,11 @@ impl Library { /// but do not follow symbolic links. /// - This will not seek directory named `ia32*` /// - pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Option { + pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Result> { let root_dir = root_dir.as_ref(); + if !root_dir.is_dir() { + return Ok(None); + } let mut library_dir = None; let mut include_dir = None; let mut iomp5_dir = None; @@ -62,19 +65,18 @@ impl Library { } let (stem, ext) = match (path.file_stem(), path.extension()) { (Some(stem), Some(ext)) => ( - stem.to_str().expect("Non UTF8 filename"), - ext.to_str().expect("Non UTF8 filename"), + stem.to_str().context("Non UTF8 filename")?, + ext.to_str().context("Non UTF8 filename")?, ), _ => continue, }; // Skip directory for ia32 if path.components().any(|c| { if let std::path::Component::Normal(c) = c { - if c.to_str() - .expect("Non-UTF8 directory name") - .starts_with("ia32") - { - return true; + if let Some(c) = c.to_str() { + if c.starts_with("ia32") { + return true; + } } } false @@ -98,14 +100,14 @@ impl Library { match (config.link, ext) { (LinkType::Static, mkl::EXTENSION_STATIC) => match name { "mkl_core" => { - assert!( + ensure!( library_dir.replace(dir).is_none(), "Two or more MKL found in {}", root_dir.display() ) } "iomp5" => { - assert!( + ensure!( iomp5_dir.replace(dir).is_none(), "Two or more MKL found in {}", root_dir.display() @@ -115,14 +117,14 @@ impl Library { }, (LinkType::Dynamic, mkl::EXTENSION_SHARED) => match name { "mkl_rt" => { - assert!( + ensure!( library_dir.replace(dir).is_none(), "Two or more MKL found in {}", root_dir.display() ) } "iomp5" => { - assert!( + ensure!( iomp5_dir.replace(dir).is_none(), "Two or more MKL found in {}", root_dir.display() @@ -136,7 +138,7 @@ impl Library { if library_dir == iomp5_dir { iomp5_dir = None; } - match (library_dir, include_dir) { + Ok(match (library_dir, include_dir) { (Some(library_dir), Some(include_dir)) => Some(Library::Directory { config, include_dir, @@ -144,7 +146,7 @@ impl Library { iomp5_dir, }), _ => None, - } + }) } /// Seek MKL in system @@ -162,13 +164,13 @@ impl Library { return Ok(lib); } if let Ok(mklroot) = std::env::var("MKLROOT") { - if let Some(lib) = Self::seek_directory(config, mklroot) { + if let Some(lib) = Self::seek_directory(config, mklroot)? { return Ok(lib); } } for path in ["/opt/intel", "C:/Program Files (x86)/IntelSWTools/"] { let path = Path::new(path); - if let Some(lib) = Self::seek_directory(config, path) { + if let Some(lib) = Self::seek_directory(config, path)? { return Ok(lib); } } From 47f20b9e8f8a632aad2b43e7e3fea110ffe3bf7c Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Wed, 3 Aug 2022 12:37:54 +0900 Subject: [PATCH 10/27] Library::version --- intel-mkl-tool/src/entry.rs | 46 +++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 864890ec..100830ae 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -196,8 +196,44 @@ impl Library { /// /// and this corresponds to `(2020, 0, 1)` /// - pub fn version(&self) -> (u32, u32, u32) { - todo!() + pub fn version(&self) -> Result<(u32, u32, u32)> { + let version_h = match self { + Library::PkgConfig { lib, .. } => { + let mut version_h = None; + for path in &lib.include_paths { + let candidate = path.join("mkl_version.h"); + if candidate.exists() { + version_h = Some(candidate); + } + } + version_h.context("mkl_version.h not found in pkg-config")? + } + Library::Directory { include_dir, .. } => include_dir.join("mkl_version.h"), + }; + + let f = fs::File::open(version_h).context("Failed to open mkl_version.h")?; + let f = io::BufReader::new(f); + let mut year = None; + let mut minor = None; + let mut update = None; + for line in f.lines() { + if let Ok(line) = line { + if !line.starts_with("#define") { + continue; + } + let ss: Vec<&str> = line.split(' ').collect(); + match ss[1] { + "__INTEL_MKL__" => year = Some(ss[2].parse()?), + "__INTEL_MKL_MINOR__" => minor = Some(ss[2].parse()?), + "__INTEL_MKL_UPDATE__" => update = Some(ss[2].parse()?), + _ => continue, + } + } + } + match (year, minor, update) { + (Some(year), Some(minor), Some(update)) => Ok((year, minor, update)), + _ => bail!("Invalid mkl_version.h"), + } } } @@ -428,8 +464,8 @@ mod tests { #[test] fn seek_opt_intel() { for cfg in Config::possibles() { - let lib = Library::seek_directory(cfg, "/opt/intel").unwrap(); - dbg!(lib); + let lib = Library::seek_directory(cfg, "/opt/intel").unwrap().unwrap(); + dbg!(lib.version().unwrap()); } } @@ -438,7 +474,7 @@ mod tests { fn pkg_config() { for cfg in Config::possibles() { let lib = Library::pkg_config(cfg).unwrap(); - dbg!(lib); + dbg!(lib.version().unwrap()); } } } From ad20eac69d849e7e55f430bb1b1c1af74d94ee13 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Wed, 3 Aug 2022 17:03:23 +0900 Subject: [PATCH 11/27] Library::print_cargo_metadata --- intel-mkl-src/build.rs | 25 ++++--------------------- intel-mkl-tool/src/entry.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/intel-mkl-src/build.rs b/intel-mkl-src/build.rs index 8f5da293..f4fc8f35 100644 --- a/intel-mkl-src/build.rs +++ b/intel-mkl-src/build.rs @@ -24,7 +24,7 @@ use anyhow::{bail, Result}; use intel_mkl_tool::*; -use std::{str::FromStr}; +use std::str::FromStr; #[cfg(feature = "mkl-static-lp64-iomp")] const MKL_CONFIG: &str = "mkl-static-lp64-iomp"; @@ -45,26 +45,9 @@ const MKL_CONFIG: &str = "mkl-dynamic-ilp64-seq"; fn main() -> Result<()> { let cfg = Config::from_str(MKL_CONFIG).unwrap(); - - // already exists on system - if let Ok(entry) = Entry::from_config(cfg) { - entry.print_cargo_metadata(); + if let Ok(lib) = Library::new(cfg) { + lib.print_cargo_metadata()?; return Ok(()); } - - // download if not found - #[cfg(feature = "download")] - { - let path = PathBuf::from(env::var("OUT_DIR").unwrap()); - println!( - r#"cargo:warning="Download Intel MKL archive into {}""#, - path.display() - ); - cfg.download(path)?; - let entry = Entry::from_config(cfg).unwrap(); // must found - entry.print_cargo_metadata(); - return Ok(()); - } - - bail!("No MKL found, and download flag is off."); + bail!("No MKL found"); } diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 100830ae..0c25fcb1 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -235,6 +235,37 @@ impl Library { _ => bail!("Invalid mkl_version.h"), } } + + /// Print `cargo:rustc-link-*` metadata to stdout + pub fn print_cargo_metadata(&self) -> Result<()> { + match self { + Library::PkgConfig { config, .. } => { + pkg_config::probe_library(&config.to_string())?; + } + Library::Directory { + config, + library_dir, + iomp5_dir, + .. + } => { + println!("cargo:rustc-link-search={}", library_dir.display()); + if let Some(iomp5_dir) = iomp5_dir { + println!("cargo:rustc-link-search={}", iomp5_dir.display()); + } + for lib in config.libs() { + match config.link { + LinkType::Static => { + println!("cargo:rustc-link-lib=static={}", lib); + } + LinkType::Dynamic => { + println!("cargo:rustc-link-lib=dylib={}", lib); + } + } + } + } + } + Ok(()) + } } #[derive(Debug, Deref)] From 6d21c982c0e01781fd929db0c076d2655d33dad2 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Wed, 3 Aug 2022 17:25:26 +0900 Subject: [PATCH 12/27] Use macos-11 and windows-2022 runner --- .github/workflows/intel-mkl-tool.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/intel-mkl-tool.yml b/.github/workflows/intel-mkl-tool.yml index 10f53319..26128c9f 100644 --- a/.github/workflows/intel-mkl-tool.yml +++ b/.github/workflows/intel-mkl-tool.yml @@ -12,8 +12,8 @@ jobs: fail-fast: false matrix: os: - - windows-2019 - - macos-10.15 + - windows-2022 + - macos-11 - ubuntu-22.04 runs-on: ${{ matrix.os }} steps: From 4a83eaf1dc4971f7a46da31795765e70c03dc45e Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Wed, 3 Aug 2022 17:38:24 +0900 Subject: [PATCH 13/27] Remove out-dated --- intel-mkl-tool/src/cli.rs | 16 +-- intel-mkl-tool/src/entry.rs | 230 ++---------------------------------- 2 files changed, 13 insertions(+), 233 deletions(-) diff --git a/intel-mkl-tool/src/cli.rs b/intel-mkl-tool/src/cli.rs index ea9cb6c4..8d142193 100644 --- a/intel-mkl-tool/src/cli.rs +++ b/intel-mkl-tool/src/cli.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Result}; -use intel_mkl_tool::*; +use intel_mkl_tool::Library; use structopt::StructOpt; /// CLI tool for intel-mkl crate @@ -14,19 +14,13 @@ fn main() -> Result<()> { match opt { Opt::Seek {} => { - let available = Entry::available(); + let available = Library::available(); if available.is_empty() { bail!("No MKL found"); } - for lib in Entry::available() { - if let Ok(version) = lib.version() { - println!("{:<22}: {}.{}", lib.name(), version.0, version.1); - } else { - println!("{:<22}", lib.name()); - } - for (path, name) in &lib.found_files() { - println!(" {:<25} at {}", name, path.display()); - } + for lib in available { + let (year, minor, update) = lib.version()?; + println!("{:<22}: {}.{}.{}", lib.config(), year, minor, update); } } } diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 0c25fcb1..d69f3bfa 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -1,12 +1,9 @@ -use crate::{mkl, Config, LinkType, VALID_CONFIGS}; +use crate::{mkl, Config, LinkType}; use anyhow::{bail, ensure, Context, Result}; -use derive_more::Deref; use std::{ - collections::{HashMap, HashSet}, fs, io::{self, BufRead}, path::{Path, PathBuf}, - str::FromStr, }; /// A library found in system @@ -177,6 +174,13 @@ impl Library { bail!("Intel MKL not found in system"); } + pub fn available() -> Vec { + Config::possibles() + .into_iter() + .flat_map(|cfg| Self::new(cfg).ok()) + .collect() + } + pub fn config(&self) -> &Config { match self { Library::PkgConfig { config, .. } => config, @@ -268,224 +272,6 @@ impl Library { } } -#[derive(Debug, Deref)] -struct Targets(HashMap>); - -impl Targets { - fn new(config: Config) -> Self { - let mut targets: HashMap> = HashMap::new(); - for name in config - .libs() - .into_iter() - .chain(config.additional_libs().into_iter()) - { - let target = match config.link { - LinkType::Static => format!("{}{}.{}", mkl::PREFIX, name, mkl::EXTENSION_STATIC), - LinkType::Dynamic => format!("{}{}.{}", mkl::PREFIX, name, mkl::EXTENSION_SHARED), - }; - targets.insert(target, None); - } - Self(targets) - } - - fn found_files(&self) -> Vec<(PathBuf, String)> { - self.iter() - .flat_map(|(name, path)| Some((path.as_ref()?.clone(), name.clone()))) - .collect() - } - - fn found_any(&self) -> bool { - self.0.iter().any(|(_key, value)| value.is_some()) - } - - fn seek>(&mut self, dir: P) { - let dir = dir.as_ref(); - for (key, value) in &mut self.0 { - if dir.join(key).exists() { - value.get_or_insert(dir.canonicalize().unwrap()); - } - } - } -} - -#[derive(Debug)] -enum EntryTarget { - Manual(Targets), - PkgConfig, -} - -/// Handler for found library -#[derive(Debug)] -pub struct Entry { - config: Config, - target: EntryTarget, -} - -impl Entry { - /// Get the directory where the library exists - /// - /// This will seek followings in this order: - /// - /// - `$OUT_DIR` - /// - Only for build.rs - /// - This exists only when the previous build downloads archive here - /// - pkg-config `${name}` - /// - Installed by package manager or official downloader - /// - /// Returns error if no library found - /// - pub fn from_config(config: Config) -> Result { - let mut targets = Targets::new(config); - - // OUT_DIR - if let Ok(dir) = std::env::var("OUT_DIR") { - let out_dir = PathBuf::from(dir); - targets.seek(&out_dir); - } - - // pkg-config - if let Ok(_) = pkg_config::Config::new() - .cargo_metadata(false) - .probe(&config.to_string()) - { - return Ok(Self { - config, - target: EntryTarget::PkgConfig, - }); - } - - // $MKLROOT - let mkl_root = std::env::var("MKLROOT").map(PathBuf::from); - if let Ok(path) = mkl_root { - if path.exists() { - targets.seek(path.join("lib/intel64")); - } - } - - // /opt/intel - let opt_mkl = PathBuf::from("/opt/intel"); - if opt_mkl.exists() { - targets.seek(opt_mkl.join("lib/intel64")); - targets.seek(opt_mkl.join("mkl/lib/intel64")); - } - - // Default setting for Windows installer - let windows_mkl = - PathBuf::from("C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows"); - if windows_mkl.exists() { - targets.seek(windows_mkl.join("mkl/lib/intel64")); - targets.seek(windows_mkl.join("compiler/lib/intel64")); - } - - if targets.found_any() { - Ok(Self { - config, - target: EntryTarget::Manual(targets), - }) - } else { - // None found - bail!("No library found for {}", config); - } - } - - pub fn name(&self) -> String { - self.config.to_string() - } - - pub fn found_files(&self) -> Vec<(PathBuf, String)> { - if let EntryTarget::Manual(m) = &self.target { - m.found_files() - } else { - vec![] - } - } - - pub fn available() -> Vec { - VALID_CONFIGS - .iter() - .flat_map(|name| Self::from_config(Config::from_str(name).unwrap())) - .collect() - } - - /// Get MKL version info from its C header - /// - /// - This will not work for OUT_DIR, or Pkgconfig entry, - /// and returns Error in these cases - pub fn version(&self) -> Result<(u32, u32)> { - for (path, _) in &self.found_files() { - // assumes following directory structure: - // - // - mkl - // - include - // - lib/intel64 <- this is cached in targets - // - let version_header = path.join("../../include/mkl_version.h"); - if !version_header.exists() { - continue; - } - - // Extract version info from C header - // - // ``` - // #define __INTEL_MKL__ 2020 - // #define __INTEL_MKL_MINOR__ 0 - // #define __INTEL_MKL_UPDATE__ 1 - // ``` - let f = fs::File::open(version_header)?; - let f = io::BufReader::new(f); - let mut year = 0; - let mut update = 0; - for line in f.lines() { - if let Ok(line) = line { - if !line.starts_with("#define") { - continue; - } - let ss: Vec<&str> = line.split(' ').collect(); - match ss[1] { - "__INTEL_MKL__" => year = ss[2].parse()?, - "__INTEL_MKL_UPDATE__" => update = ss[2].parse()?, - _ => continue, - } - } - } - if year > 0 && update > 0 { - return Ok((year, update)); - } - } - bail!("Cannot determine MKL versions"); - } - - pub fn print_cargo_metadata(&self) { - match &self.target { - EntryTarget::Manual(_target) => { - let paths: HashSet = self - .found_files() - .into_iter() - .map(|(path, _name)| path) - .collect(); // must be redundant - for path in paths { - println!("cargo:rustc-link-search={}", path.display()); - } - for lib in self.config.libs() { - match self.config.link { - LinkType::Static => { - println!("cargo:rustc-link-lib=static={}", lib); - } - LinkType::Dynamic => { - println!("cargo:rustc-link-lib=dylib={}", lib); - } - } - } - } - EntryTarget::PkgConfig => { - pkg_config::Config::new() - .probe(&self.config.to_string()) - .unwrap(); - } - } - } -} - #[cfg(test)] mod tests { use super::*; From c60613df8216b9b2b3fa1efe7bb6ab3e98c145f0 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Wed, 3 Aug 2022 23:34:17 +0900 Subject: [PATCH 14/27] Use pkg-config only for prefix --- intel-mkl-tool/src/entry.rs | 109 ++++++++++++++---------------------- 1 file changed, 42 insertions(+), 67 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index d69f3bfa..419a8204 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -4,40 +4,42 @@ use std::{ fs, io::{self, BufRead}, path::{Path, PathBuf}, + process::Command, }; -/// A library found in system #[derive(Debug, Clone)] -pub enum Library { - PkgConfig { - config: Config, - lib: pkg_config::Library, - }, - Directory { - config: Config, - /// Directory where `mkl.h` and `mkl_version.h` exists - include_dir: PathBuf, - /// Directory where `libmkl_core.a` or `libmkl_rt.so` exists - library_dir: PathBuf, - /// Directory where `libiomp5.a` or `libiomp5.so` exists - /// - /// They are sometimes placed in different position. - /// Returns `None` if they exist on `library_dir`. - iomp5_dir: Option, - }, +pub struct Library { + config: Config, + /// Directory where `mkl.h` and `mkl_version.h` exists + include_dir: PathBuf, + /// Directory where `libmkl_core.a` or `libmkl_rt.so` exists + library_dir: PathBuf, + /// Directory where `libiomp5.a` or `libiomp5.so` exists + /// + /// They are sometimes placed in different position. + /// Returns `None` if they exist on `library_dir`. + iomp5_dir: Option, } impl Library { /// Try to find MKL using pkg-config - pub fn pkg_config(config: Config) -> Option { - if let Ok(lib) = pkg_config::Config::new() - .cargo_metadata(false) - .env_metadata(false) - .probe(&config.to_string()) + pub fn pkg_config(config: Config) -> Result> { + if let Ok(out) = Command::new("pkg-config") + .arg("--variable=prefix") + .arg(config.to_string()) + .output() { - Some(Library::PkgConfig { config, lib }) + if out.status.success() { + let path = String::from_utf8(out.stdout).context("Non-UTF8 MKL prefix")?; + let prefix = Path::new(path.trim()); + Self::seek_directory(config, prefix) + } else { + // pkg-config does not find MKL + Ok(None) + } } else { - None + // pkg-config is not found + Ok(None) } } @@ -136,7 +138,7 @@ impl Library { iomp5_dir = None; } Ok(match (library_dir, include_dir) { - (Some(library_dir), Some(include_dir)) => Some(Library::Directory { + (Some(library_dir), Some(include_dir)) => Some(Library { config, include_dir, library_dir, @@ -157,7 +159,7 @@ impl Library { /// - `C:/Program Files (x86)/IntelSWTools/` for Windows /// pub fn new(config: Config) -> Result { - if let Some(lib) = Self::pkg_config(config) { + if let Some(lib) = Self::pkg_config(config)? { return Ok(lib); } if let Ok(mklroot) = std::env::var("MKLROOT") { @@ -182,10 +184,7 @@ impl Library { } pub fn config(&self) -> &Config { - match self { - Library::PkgConfig { config, .. } => config, - Library::Directory { config, .. } => config, - } + &self.config } /// Found MKL version parsed from `mkl_version.h` @@ -201,19 +200,7 @@ impl Library { /// and this corresponds to `(2020, 0, 1)` /// pub fn version(&self) -> Result<(u32, u32, u32)> { - let version_h = match self { - Library::PkgConfig { lib, .. } => { - let mut version_h = None; - for path in &lib.include_paths { - let candidate = path.join("mkl_version.h"); - if candidate.exists() { - version_h = Some(candidate); - } - } - version_h.context("mkl_version.h not found in pkg-config")? - } - Library::Directory { include_dir, .. } => include_dir.join("mkl_version.h"), - }; + let version_h = self.include_dir.join("mkl_version.h"); let f = fs::File::open(version_h).context("Failed to open mkl_version.h")?; let f = io::BufReader::new(f); @@ -242,29 +229,17 @@ impl Library { /// Print `cargo:rustc-link-*` metadata to stdout pub fn print_cargo_metadata(&self) -> Result<()> { - match self { - Library::PkgConfig { config, .. } => { - pkg_config::probe_library(&config.to_string())?; - } - Library::Directory { - config, - library_dir, - iomp5_dir, - .. - } => { - println!("cargo:rustc-link-search={}", library_dir.display()); - if let Some(iomp5_dir) = iomp5_dir { - println!("cargo:rustc-link-search={}", iomp5_dir.display()); + println!("cargo:rustc-link-search={}", self.library_dir.display()); + if let Some(iomp5_dir) = &self.iomp5_dir { + println!("cargo:rustc-link-search={}", iomp5_dir.display()); + } + for lib in self.config.libs() { + match self.config.link { + LinkType::Static => { + println!("cargo:rustc-link-lib=static={}", lib); } - for lib in config.libs() { - match config.link { - LinkType::Static => { - println!("cargo:rustc-link-lib=static={}", lib); - } - LinkType::Dynamic => { - println!("cargo:rustc-link-lib=dylib={}", lib); - } - } + LinkType::Dynamic => { + println!("cargo:rustc-link-lib=dylib={}", lib); } } } @@ -290,7 +265,7 @@ mod tests { #[test] fn pkg_config() { for cfg in Config::possibles() { - let lib = Library::pkg_config(cfg).unwrap(); + let lib = Library::pkg_config(cfg).unwrap().unwrap(); dbg!(lib.version().unwrap()); } } From b4b79904892cc40728c1011ddbe23287c69d60f5 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 10:36:11 +0900 Subject: [PATCH 15/27] Use libmkl_core.so instead of libmkl_rt.so --- intel-mkl-tool/src/entry.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 419a8204..bbb997e2 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -12,7 +12,7 @@ pub struct Library { config: Config, /// Directory where `mkl.h` and `mkl_version.h` exists include_dir: PathBuf, - /// Directory where `libmkl_core.a` or `libmkl_rt.so` exists + /// Directory where `libmkl_core.a` or `libmkl_core.so` exists library_dir: PathBuf, /// Directory where `libiomp5.a` or `libiomp5.so` exists /// @@ -115,7 +115,7 @@ impl Library { _ => {} }, (LinkType::Dynamic, mkl::EXTENSION_SHARED) => match name { - "mkl_rt" => { + "mkl_core" => { ensure!( library_dir.replace(dir).is_none(), "Two or more MKL found in {}", From d709c0a428e5f1d71431f22493a1c35095e43497 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 10:41:31 +0900 Subject: [PATCH 16/27] Returns None if iomp5 is not found with *-iomp setting --- intel-mkl-tool/src/entry.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index bbb997e2..29f5be0a 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -1,4 +1,4 @@ -use crate::{mkl, Config, LinkType}; +use crate::{mkl, Config, LinkType, Threading}; use anyhow::{bail, ensure, Context, Result}; use std::{ fs, @@ -134,6 +134,9 @@ impl Library { _ => {} } } + if config.parallel == Threading::OpenMP && iomp5_dir.is_none() { + return Ok(None); + } if library_dir == iomp5_dir { iomp5_dir = None; } From 89cc62919742f2486c923e347e06490f9c9e8cd4 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 11:18:31 +0900 Subject: [PATCH 17/27] pkg-config feature will not works for mkl-*-*-iomp cases --- intel-mkl-tool/src/entry.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 29f5be0a..57c3e361 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -22,7 +22,24 @@ pub struct Library { } impl Library { - /// Try to find MKL using pkg-config + /// Find MKL using `pkg-config` + /// + /// This only use the installed prefix obtained by `pkg-config --variable=prefix` + /// + /// ```text + /// $ pkg-config --variable=prefix mkl-static-lp64-seq + /// /opt/intel/mkl + /// ``` + /// + /// Then pass it to [Self::seek_directory]. + /// + /// Limitation + /// ----------- + /// This will not work for `mkl-*-*-iomp` configure since `libiomp5.{a,so}` + /// will not be found under the prefix directory of MKL. + /// Please use `$MKLROOT` environment variable for this case, + /// see [Self::new] for detail. + /// pub fn pkg_config(config: Config) -> Result> { if let Ok(out) = Command::new("pkg-config") .arg("--variable=prefix") @@ -48,6 +65,8 @@ impl Library { /// - This will seek the directory recursively until finding MKL libraries, /// but do not follow symbolic links. /// - This will not seek directory named `ia32*` + /// - Retuns `Ok(None)` if `libiomp5.{a,so}` is not found with `mkl-*-*-iomp` configure + /// even if MKL binaries are found. /// pub fn seek_directory(config: Config, root_dir: impl AsRef) -> Result> { let root_dir = root_dir.as_ref(); @@ -268,6 +287,10 @@ mod tests { #[test] fn pkg_config() { for cfg in Config::possibles() { + // pkg-config will not work for `mkl-*-*-iomp` cases + if cfg.parallel == Threading::OpenMP { + continue; + } let lib = Library::pkg_config(cfg).unwrap().unwrap(); dbg!(lib.version().unwrap()); } From 45d83aa002a360c1889d470b54939ed27815651b Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 11:28:07 +0900 Subject: [PATCH 18/27] Library::iomp5_dir becomes None only for `mkl-*-*-seq` cases --- intel-mkl-tool/src/entry.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 57c3e361..9b932b18 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -16,8 +16,8 @@ pub struct Library { library_dir: PathBuf, /// Directory where `libiomp5.a` or `libiomp5.so` exists /// - /// They are sometimes placed in different position. - /// Returns `None` if they exist on `library_dir`. + /// They are not required for `mkl-*-*-seq` cases, + /// and then this is `None`. iomp5_dir: Option, } @@ -156,9 +156,6 @@ impl Library { if config.parallel == Threading::OpenMP && iomp5_dir.is_none() { return Ok(None); } - if library_dir == iomp5_dir { - iomp5_dir = None; - } Ok(match (library_dir, include_dir) { (Some(library_dir), Some(include_dir)) => Some(Library { config, @@ -253,7 +250,9 @@ impl Library { pub fn print_cargo_metadata(&self) -> Result<()> { println!("cargo:rustc-link-search={}", self.library_dir.display()); if let Some(iomp5_dir) = &self.iomp5_dir { - println!("cargo:rustc-link-search={}", iomp5_dir.display()); + if iomp5_dir != &self.library_dir { + println!("cargo:rustc-link-search={}", iomp5_dir.display()); + } } for lib in self.config.libs() { match self.config.link { From 07fbbb4b2f5fd91616248341d89d064a458d9b39 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 13:48:48 +0900 Subject: [PATCH 19/27] Add doc for Library, make members public --- intel-mkl-tool/src/cli.rs | 2 +- intel-mkl-tool/src/entry.rs | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/intel-mkl-tool/src/cli.rs b/intel-mkl-tool/src/cli.rs index 8d142193..1dabab73 100644 --- a/intel-mkl-tool/src/cli.rs +++ b/intel-mkl-tool/src/cli.rs @@ -20,7 +20,7 @@ fn main() -> Result<()> { } for lib in available { let (year, minor, update) = lib.version()?; - println!("{:<22}: {}.{}.{}", lib.config(), year, minor, update); + println!("{:<22}: {}.{}.{}", lib.config, year, minor, update); } } } diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index 9b932b18..ce961d8b 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -7,18 +7,29 @@ use std::{ process::Command, }; +/// Found MKL library +/// +/// ```no_run +/// use std::str::FromStr; +/// use intel_mkl_tool::{Config, Library}; +/// +/// let cfg = Config::from_str("mkl-static-lp64-iomp").unwrap(); +/// if let Ok(lib) = Library::new(cfg) { +/// lib.print_cargo_metadata().unwrap(); +/// } +/// ``` #[derive(Debug, Clone)] pub struct Library { - config: Config, + pub config: Config, /// Directory where `mkl.h` and `mkl_version.h` exists - include_dir: PathBuf, + pub include_dir: PathBuf, /// Directory where `libmkl_core.a` or `libmkl_core.so` exists - library_dir: PathBuf, + pub library_dir: PathBuf, /// Directory where `libiomp5.a` or `libiomp5.so` exists /// /// They are not required for `mkl-*-*-seq` cases, /// and then this is `None`. - iomp5_dir: Option, + pub iomp5_dir: Option, } impl Library { @@ -202,10 +213,6 @@ impl Library { .collect() } - pub fn config(&self) -> &Config { - &self.config - } - /// Found MKL version parsed from `mkl_version.h` /// /// `mkl_version.h` will define From 6d53319f5316c90fdda987eb3a092deef562e094 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 15:32:49 +0900 Subject: [PATCH 20/27] Use 1.56.0-1 image --- .github/workflows/intel-mkl-sys.yml | 2 +- .github/workflows/intel-mkl-tool.yml | 3 +-- .github/workflows/rust.yml | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/intel-mkl-sys.yml b/.github/workflows/intel-mkl-sys.yml index dba38b69..c49d4f0c 100644 --- a/.github/workflows/intel-mkl-sys.yml +++ b/.github/workflows/intel-mkl-sys.yml @@ -22,7 +22,7 @@ jobs: - mkl-dynamic-ilp64-seq runs-on: ubuntu-22.04 container: - image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0 + image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0-1 steps: - uses: actions/checkout@v1 - uses: actions-rs/cargo@v1 diff --git a/.github/workflows/intel-mkl-tool.yml b/.github/workflows/intel-mkl-tool.yml index 26128c9f..d42fb746 100644 --- a/.github/workflows/intel-mkl-tool.yml +++ b/.github/workflows/intel-mkl-tool.yml @@ -44,13 +44,12 @@ jobs: image: - mkl-rust - mkl-ubuntu - - mkl-centos test: - seek_opt_intel - pkg_config runs-on: ubuntu-22.04 container: - image: ghcr.io/rust-math/intel-mkl-src/${{ matrix.image }}:1.56.0 + image: ghcr.io/rust-math/intel-mkl-src/${{ matrix.image }}:1.56.0-1 steps: - uses: actions/checkout@v1 - uses: actions-rs/cargo@v1 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6c6e8235..9a269abe 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,7 +10,7 @@ jobs: check-format: runs-on: ubuntu-22.04 container: - image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0 + image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0-1 steps: - uses: actions/checkout@v1 - uses: actions-rs/cargo@v1 @@ -21,7 +21,7 @@ jobs: clippy: runs-on: ubuntu-22.04 container: - image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0 + image: ghcr.io/rust-math/intel-mkl-src/mkl-rust:1.56.0-1 steps: - uses: actions/checkout@v1 - uses: actions-rs/cargo@v1 From 027b2d7e650ec7bcb80799519222170359c1970a Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 15:53:36 +0900 Subject: [PATCH 21/27] Skip symlink --- intel-mkl-tool/src/entry.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index ce961d8b..cd4e3ac6 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -88,7 +88,11 @@ impl Library { let mut include_dir = None; let mut iomp5_dir = None; for entry in walkdir::WalkDir::new(root_dir) { - let path = entry.unwrap().into_path(); + let entry = entry.unwrap(); + if entry.path_is_symlink() { + continue; + } + let path = entry.into_path(); if path.is_dir() { continue; } From bdb5222044d506857bce6bce2967fc4e5b4975fc Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 18:22:26 +0900 Subject: [PATCH 22/27] Drop seek_opt_intel test --- .github/workflows/intel-mkl-tool.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/intel-mkl-tool.yml b/.github/workflows/intel-mkl-tool.yml index d42fb746..ada75202 100644 --- a/.github/workflows/intel-mkl-tool.yml +++ b/.github/workflows/intel-mkl-tool.yml @@ -37,16 +37,13 @@ jobs: --manifest-path=intel-mkl-tool/Cargo.toml --no-default-features - seek: + test_pkg_config: strategy: fail-fast: false matrix: image: - mkl-rust - mkl-ubuntu - test: - - seek_opt_intel - - pkg_config runs-on: ubuntu-22.04 container: image: ghcr.io/rust-math/intel-mkl-src/${{ matrix.image }}:1.56.0-1 @@ -58,7 +55,7 @@ jobs: command: test args: > --manifest-path=intel-mkl-tool/Cargo.toml - ${{ matrix.test }} + pkg_config -- --ignored --show-output From a88c0dc674d575bcb665c509cc18a3e88d9cd55a Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 18:44:23 +0900 Subject: [PATCH 23/27] Remove outdated --- intel-mkl-tool/src/lib.rs | 102 -------------------------------------- 1 file changed, 102 deletions(-) diff --git a/intel-mkl-tool/src/lib.rs b/intel-mkl-tool/src/lib.rs index 2ce4de97..26e8d333 100644 --- a/intel-mkl-tool/src/lib.rs +++ b/intel-mkl-tool/src/lib.rs @@ -1,97 +1,3 @@ -//! Library files in Intel MKL 2020.1 for Linux -//! -------------------------------------------- -//! -//! ### MKL Core -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_core | libmkl_core.so| libmkl_core.a| -//! |mkl_def | libmkl_def.so| - | -//! |mkl_rt | libmkl_rt.so| - | -//! |mkl_avx | libmkl_avx.so| - | -//! |mkl_avx2 | libmkl_avx2.so| - | -//! |mkl_avx512 | libmkl_avx512.so| - | -//! |mkl_avx512_mic | libmkl_avx512_mic.so| - | -//! |mkl_mc | libmkl_mc.so| - | -//! |mkl_mc3 | libmkl_mc3.so| - | -//! -//! ### Vector Math library -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_vml_def | libmkl_vml_def.so| - | -//! |mkl_vml_avx | libmkl_vml_avx.so| - | -//! |mkl_vml_avx2 | libmkl_vml_avx2.so| - | -//! |mkl_vml_avx512 | libmkl_vml_avx512.so| - | -//! |mkl_vml_avx512_mic | libmkl_vml_avx512_mic.so| - | -//! |mkl_vml_mc | libmkl_vml_mc.so| - | -//! |mkl_vml_mc2 | libmkl_vml_mc2.so| - | -//! |mkl_vml_mc3 | libmkl_vml_mc3.so| - | -//! |mkl_vml_cmpt | libmkl_vml_cmpt.so| - | -//! -//! ### Intel OpenMP -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |iomp5 | libiomp5.so| libiomp5.a| -//! |iomp5_db | libiomp5_db.so| - | -//! |iompstubs5 | libiompstubs5.so| libiompstubs5.a| -//! -//! ### Threading switch -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_sequential | libmkl_sequential.so| libmkl_sequential.a| -//! |mkl_gnu_thread | libmkl_gnu_thread.so| libmkl_gnu_thread.a| -//! |mkl_intel_thread | libmkl_intel_thread.so| libmkl_intel_thread.a| -//! |mkl_pgi_thread | libmkl_pgi_thread.so| libmkl_pgi_thread.a| -//! |mkl_tbb_thread | libmkl_tbb_thread.so| libmkl_tbb_thread.a| -//! -//! ### LP64/ILP64 switch for Intel and GCC Fortran compilers -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_intel_ilp64 | libmkl_intel_ilp64.so| libmkl_intel_ilp64.a| -//! |mkl_intel_lp64 | libmkl_intel_lp64.so| libmkl_intel_lp64.a| -//! |mkl_gf_ilp64 | libmkl_gf_ilp64.so| libmkl_gf_ilp64.a| -//! |mkl_gf_lp64 | libmkl_gf_lp64.so| libmkl_gf_lp64.a| -//! -//! ### Fortran 95 interface -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_blas95_ilp64 | - | libmkl_blas95_ilp64.a| -//! |mkl_blas95_lp64 | - | libmkl_blas95_lp64.a| -//! |mkl_lapack95_ilp64 | - | libmkl_lapack95_ilp64.a| -//! |mkl_lapack95_lp64 | - | libmkl_lapack95_lp64.a| -//! -//! ### ScaLAPACK -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_scalapack_ilp64 | libmkl_scalapack_ilp64.so| libmkl_scalapack_ilp64.a| -//! |mkl_scalapack_lp64 | libmkl_scalapack_lp64.so| libmkl_scalapack_lp64.a| -//! -//! ### BLACS -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_blacs_intelmpi_ilp64| libmkl_blacs_intelmpi_ilp64.so| libmkl_blacs_intelmpi_ilp64.a| -//! |mkl_blacs_intelmpi_lp64 | libmkl_blacs_intelmpi_lp64.so| libmkl_blacs_intelmpi_lp64.a| -//! |mkl_blacs_openmpi_ilp64 | libmkl_blacs_openmpi_ilp64.so| libmkl_blacs_openmpi_ilp64.a| -//! |mkl_blacs_openmpi_lp64 | libmkl_blacs_openmpi_lp64.so| libmkl_blacs_openmpi_lp64.a| -//! |mkl_blacs_sgimpt_ilp64 | libmkl_blacs_sgimpt_ilp64.so| libmkl_blacs_sgimpt_ilp64.a| -//! |mkl_blacs_sgimpt_lp64 | libmkl_blacs_sgimpt_lp64.so| libmkl_blacs_sgimpt_lp64.a| -//! -//! ### FFT -//! -//! | | shared | static | -//! |:-----------------------|:-------------------------------|:------------------------------| -//! |mkl_cdft_core | libmkl_cdft_core.so| libmkl_cdft_core.a| -//! - -#![cfg_attr(not(feature = "archive"), allow(dead_code))] - mod config; mod entry; @@ -103,26 +9,18 @@ mod mkl { pub const EXTENSION_STATIC: &str = "a"; pub const EXTENSION_SHARED: &str = "so"; pub const PREFIX: &str = "lib"; - pub const VERSION_YEAR: u32 = 2020; - pub const VERSION_UPDATE: u32 = 1; } #[cfg(all(target_os = "macos", target_arch = "x86_64"))] mod mkl { - pub const OS: &str = "macos"; pub const EXTENSION_STATIC: &'static str = "a"; pub const EXTENSION_SHARED: &'static str = "dylib"; pub const PREFIX: &'static str = "lib"; - pub const VERSION_YEAR: u32 = 2019; - pub const VERSION_UPDATE: u32 = 3; } #[cfg(all(target_os = "windows", target_arch = "x86_64"))] mod mkl { - pub const OS: &str = "windows"; pub const EXTENSION_STATIC: &'static str = "lib"; pub const EXTENSION_SHARED: &'static str = "lib"; pub const PREFIX: &'static str = ""; - pub const VERSION_YEAR: u32 = 2020; - pub const VERSION_UPDATE: u32 = 1; } From 5285ae77d7a09e791885cec5cede02d2407e8c12 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 18:50:27 +0900 Subject: [PATCH 24/27] Use std::env::consts::{DLL_*} --- intel-mkl-tool/src/entry.rs | 15 +++++++++++---- intel-mkl-tool/src/lib.rs | 21 --------------------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index cd4e3ac6..ef44c953 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -1,4 +1,4 @@ -use crate::{mkl, Config, LinkType, Threading}; +use crate::{Config, LinkType, Threading}; use anyhow::{bail, ensure, Context, Result}; use std::{ fs, @@ -7,6 +7,13 @@ use std::{ process::Command, }; +/// Lacked definition of [std::env::consts] +pub const STATIC_EXTENSION: &str = if cfg!(any(target_os = "linux", target_os = "macos")) { + "a" +} else { + "lib" +}; + /// Found MKL library /// /// ```no_run @@ -125,13 +132,13 @@ impl Library { include_dir = Some(dir); continue; } - let name = if let Some(name) = stem.strip_prefix(mkl::PREFIX) { + let name = if let Some(name) = stem.strip_prefix(std::env::consts::DLL_PREFIX) { name } else { continue; }; match (config.link, ext) { - (LinkType::Static, mkl::EXTENSION_STATIC) => match name { + (LinkType::Static, STATIC_EXTENSION) => match name { "mkl_core" => { ensure!( library_dir.replace(dir).is_none(), @@ -148,7 +155,7 @@ impl Library { } _ => {} }, - (LinkType::Dynamic, mkl::EXTENSION_SHARED) => match name { + (LinkType::Dynamic, std::env::consts::DLL_EXTENSION) => match name { "mkl_core" => { ensure!( library_dir.replace(dir).is_none(), diff --git a/intel-mkl-tool/src/lib.rs b/intel-mkl-tool/src/lib.rs index 26e8d333..c1701e03 100644 --- a/intel-mkl-tool/src/lib.rs +++ b/intel-mkl-tool/src/lib.rs @@ -3,24 +3,3 @@ mod entry; pub use config::*; pub use entry::*; - -#[cfg(all(target_os = "linux", target_arch = "x86_64"))] -mod mkl { - pub const EXTENSION_STATIC: &str = "a"; - pub const EXTENSION_SHARED: &str = "so"; - pub const PREFIX: &str = "lib"; -} - -#[cfg(all(target_os = "macos", target_arch = "x86_64"))] -mod mkl { - pub const EXTENSION_STATIC: &'static str = "a"; - pub const EXTENSION_SHARED: &'static str = "dylib"; - pub const PREFIX: &'static str = "lib"; -} - -#[cfg(all(target_os = "windows", target_arch = "x86_64"))] -mod mkl { - pub const EXTENSION_STATIC: &'static str = "lib"; - pub const EXTENSION_SHARED: &'static str = "lib"; - pub const PREFIX: &'static str = ""; -} From d9a0e6c02c60d9cc3fd48d9723f8aee13bebaa7d Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 19:01:20 +0900 Subject: [PATCH 25/27] Remove intel-mkl-tool CLI --- intel-mkl-tool/Cargo.toml | 15 +-------------- intel-mkl-tool/src/cli.rs | 28 ---------------------------- 2 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 intel-mkl-tool/src/cli.rs diff --git a/intel-mkl-tool/Cargo.toml b/intel-mkl-tool/Cargo.toml index 5f598d6c..c2514b2f 100644 --- a/intel-mkl-tool/Cargo.toml +++ b/intel-mkl-tool/Cargo.toml @@ -7,28 +7,15 @@ rust-version = "1.56.0" # MSRV is introduced description = "CLI utility for redistributiing Intel(R) MKL" repository = "https://github.com/rust-math/intel-mkl-src" -keywords = ["cli"] +keywords = [] license = "MIT" -[features] -default = ["cli"] -cli = ["structopt"] - [dependencies] anyhow = "1.0.58" derive_more = "0.99.17" dirs = "4.0.0" glob = "0.3.0" -pkg-config = "0.3.25" - -# CLI -structopt = { version = "0.3.26", optional = true } walkdir = "2.3.2" [dev-dependencies] paste = "1.0.7" - -[[bin]] -name = "intel-mkl-tool" -path = "src/cli.rs" -required-features = ["cli"] diff --git a/intel-mkl-tool/src/cli.rs b/intel-mkl-tool/src/cli.rs deleted file mode 100644 index 1dabab73..00000000 --- a/intel-mkl-tool/src/cli.rs +++ /dev/null @@ -1,28 +0,0 @@ -use anyhow::{bail, Result}; -use intel_mkl_tool::Library; -use structopt::StructOpt; - -/// CLI tool for intel-mkl crate -#[derive(Debug, StructOpt)] -enum Opt { - /// Seek Intel-MKL library - Seek {}, -} - -fn main() -> Result<()> { - let opt = Opt::from_args(); - - match opt { - Opt::Seek {} => { - let available = Library::available(); - if available.is_empty() { - bail!("No MKL found"); - } - for lib in available { - let (year, minor, update) = lib.version()?; - println!("{:<22}: {}.{}.{}", lib.config, year, minor, update); - } - } - } - Ok(()) -} From b7eb03fa08eb20b1d610490f52663a29513024da Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 19:39:26 +0900 Subject: [PATCH 26/27] Drop unused crates --- intel-mkl-tool/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/intel-mkl-tool/Cargo.toml b/intel-mkl-tool/Cargo.toml index c2514b2f..6ca8cd25 100644 --- a/intel-mkl-tool/Cargo.toml +++ b/intel-mkl-tool/Cargo.toml @@ -12,9 +12,6 @@ license = "MIT" [dependencies] anyhow = "1.0.58" -derive_more = "0.99.17" -dirs = "4.0.0" -glob = "0.3.0" walkdir = "2.3.2" [dev-dependencies] From 2356b1a1aa49ec6c8f99588f1eb747557be385bf Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Thu, 4 Aug 2022 19:46:18 +0900 Subject: [PATCH 27/27] clippy --fix --- intel-mkl-tool/src/entry.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/intel-mkl-tool/src/entry.rs b/intel-mkl-tool/src/entry.rs index ef44c953..00234e00 100644 --- a/intel-mkl-tool/src/entry.rs +++ b/intel-mkl-tool/src/entry.rs @@ -244,18 +244,16 @@ impl Library { let mut year = None; let mut minor = None; let mut update = None; - for line in f.lines() { - if let Ok(line) = line { - if !line.starts_with("#define") { - continue; - } - let ss: Vec<&str> = line.split(' ').collect(); - match ss[1] { - "__INTEL_MKL__" => year = Some(ss[2].parse()?), - "__INTEL_MKL_MINOR__" => minor = Some(ss[2].parse()?), - "__INTEL_MKL_UPDATE__" => update = Some(ss[2].parse()?), - _ => continue, - } + for line in f.lines().flatten() { + if !line.starts_with("#define") { + continue; + } + let ss: Vec<&str> = line.split(' ').collect(); + match ss[1] { + "__INTEL_MKL__" => year = Some(ss[2].parse()?), + "__INTEL_MKL_MINOR__" => minor = Some(ss[2].parse()?), + "__INTEL_MKL_UPDATE__" => update = Some(ss[2].parse()?), + _ => continue, } } match (year, minor, update) {