Skip to content

Commit e37c781

Browse files
authored
Merge pull request #23 from rust-math/package
Package subcommand for intel-mkl-tool
2 parents 28d0a02 + ec080c8 commit e37c781

File tree

5 files changed

+113
-23
lines changed

5 files changed

+113
-23
lines changed

ci/Dockerfile

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
FROM rust:latest
22
LABEL maintainer "Toshiki Teramura <[email protected]>"
33

4-
RUN apt-get update \
5-
&& apt-get install -y wget apt-transport-https \
6-
&& wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB \
7-
&& apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB \
8-
&& wget https://apt.repos.intel.com/setup/intelproducts.list -O /etc/apt/sources.list.d/intelproducts.list \
9-
&& apt-get update \
10-
&& apt-get install -y intel-mkl-core-rt-2019.3 \
11-
&& apt-get clean \
12-
&& rm -rf /var/lib/apt/lists/*
4+
COPY install.sh /
5+
RUN /install.sh && apt-get clean && rm -rf /var/lib/apt/lists/*
136

147
ENV PKG_CONFIG_PATH /opt/intel/compilers_and_libraries/linux/mkl/bin/pkgconfig
158
ENV LD_LIBRARY_PATH /opt/intel/compilers_and_libraries/linux/mkl/lib/intel64

ci/install.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
# Intel MKL installer for ubuntu/debian
3+
set -eux
4+
5+
apt-get update
6+
apt-get install -y wget apt-transport-https
7+
curl -sfL https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB | apt-key add -
8+
curl -sfL https://apt.repos.intel.com/setup/intelproducts.list -o /etc/apt/sources.list.d/intelproducts.list
9+
apt-get update
10+
apt-get install -y intel-mkl-core-rt-2019.5 # Please update version number

intel-mkl-tool/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ curl = "0.4.25"
1313
failure = "0.1.6"
1414
pkg-config = "0.3.17"
1515
tar = "0.4.26"
16-
xz2 = "0.1.6"
1716
log = "0.4.8"
18-
dirs = "*"
17+
dirs = "2.0.2"
18+
glob = "0.3.0"
19+
zstd = "0.5.1"
1920

2021
# CLI
21-
structopt = { version = "0.3.4", optional = true }
22+
structopt = { version = "0.3.5", optional = true }
2223
env_logger = { version = "0.7.1", optional = true }
2324

2425
[[bin]]

intel-mkl-tool/src/cli.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ enum Opt {
1010
/// Install destination. Default is `$XDG_DATA_HOME/intel-mkl-tool`
1111
path: Option<PathBuf>,
1212
},
13+
1314
/// Seek Intel-MKL library
1415
///
1516
/// 1. pkg-config
1617
/// 2. `$XDG_DATA_HOME/intel-mkl-tool`
1718
/// will be sought.
1819
Seek {},
20+
21+
/// Package Intel MKL libraries into an archive
22+
Package { path: PathBuf },
1923
}
2024

2125
fn main() -> Fallible<()> {
@@ -33,6 +37,7 @@ fn main() -> Fallible<()> {
3337
};
3438
intel_mkl_tool::download(&path)?;
3539
}
40+
3641
Opt::Seek {} => {
3742
if let Some(path) = intel_mkl_tool::seek_pkg_config() {
3843
println!("{}", path.display());
@@ -44,6 +49,10 @@ fn main() -> Fallible<()> {
4449
}
4550
bail!("Intel-MKL not found.");
4651
}
52+
53+
Opt::Package { path } => {
54+
let _out = intel_mkl_tool::package(&path)?;
55+
}
4756
}
4857
Ok(())
4958
}

intel-mkl-tool/src/lib.rs

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,49 @@
11
use curl::easy::Easy;
22
use failure::*;
3+
use glob::glob;
34
use log::*;
45
use std::{
56
fs,
6-
io::{self, Write},
7+
io::{self, BufRead, Write},
78
path::*,
89
};
910

1011
const S3_ADDR: &'static str = "https://s3-ap-northeast-1.amazonaws.com/rust-intel-mkl";
1112

12-
#[cfg(target_os = "linux")]
13+
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
1314
mod mkl {
14-
pub const ARCHIVE: &'static str = "mkl_linux.tar.xz";
15+
pub const ARCHIVE: &'static str = "mkl_linux64";
1516
pub const EXT: &'static str = "so";
1617
pub const PREFIX: &'static str = "lib";
18+
pub const VERSION_YEAR: u32 = 2019;
19+
pub const VERSION_UPDATE: u32 = 5;
1720
}
1821

19-
#[cfg(target_os = "macos")]
22+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
2023
mod mkl {
21-
pub const ARCHIVE: &'static str = "mkl_osx.tar.xz";
24+
pub const ARCHIVE: &'static str = "mkl_macos64";
2225
pub const EXT: &'static str = "dylib";
2326
pub const PREFIX: &'static str = "lib";
27+
pub const VERSION_YEAR: u32 = 2019;
28+
pub const VERSION_UPDATE: u32 = 3;
2429
}
2530

26-
#[cfg(target_os = "windows")]
31+
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
2732
mod mkl {
28-
pub const ARCHIVE: &'static str = "mkl_windows64.tar.xz";
33+
pub const ARCHIVE: &'static str = "mkl_windows64";
2934
pub const EXT: &'static str = "lib";
3035
pub const PREFIX: &'static str = "";
36+
pub const VERSION_YEAR: u32 = 2019;
37+
pub const VERSION_UPDATE: u32 = 5;
38+
}
39+
40+
pub fn archive_filename() -> String {
41+
format!(
42+
"{}_{}_{}.tar.zst",
43+
mkl::ARCHIVE,
44+
mkl::VERSION_YEAR,
45+
mkl::VERSION_UPDATE
46+
)
3147
}
3248

3349
pub fn home_library_path() -> PathBuf {
@@ -61,13 +77,14 @@ pub fn download(out_dir: &Path) -> Fallible<()> {
6177
bail!("Not a directory: {}", out_dir.display());
6278
}
6379

64-
let archive = out_dir.join(mkl::ARCHIVE);
80+
let archive = out_dir.join(archive_filename());
6581
if !archive.exists() {
66-
info!("Download archive from AWS S3: {}/{}", S3_ADDR, mkl::ARCHIVE);
82+
let url = format!("{}/{}", S3_ADDR, archive_filename());
83+
info!("Download archive from AWS S3: {}", url);
6784
let f = fs::File::create(&archive)?;
6885
let mut buf = io::BufWriter::new(f);
6986
let mut easy = Easy::new();
70-
easy.url(&format!("{}/{}", S3_ADDR, mkl::ARCHIVE))?;
87+
easy.url(&url)?;
7188
easy.write_function(move |data| Ok(buf.write(data).unwrap()))?;
7289
easy.perform()?;
7390
assert!(archive.exists());
@@ -78,7 +95,7 @@ pub fn download(out_dir: &Path) -> Fallible<()> {
7895
let core = out_dir.join(format!("{}mkl_core.{}", mkl::PREFIX, mkl::EXT));
7996
if !core.exists() {
8097
let f = fs::File::open(&archive)?;
81-
let de = xz2::read::XzDecoder::new(f);
98+
let de = zstd::stream::read::Decoder::new(f)?;
8299
let mut arc = tar::Archive::new(de);
83100
arc.unpack(&out_dir)?;
84101
assert!(core.exists());
@@ -87,3 +104,63 @@ pub fn download(out_dir: &Path) -> Fallible<()> {
87104
}
88105
Ok(())
89106
}
107+
108+
// Read mkl_version.h to get MKL version (e.g. 2019.5)
109+
fn get_mkl_version(version_header: &Path) -> Fallible<(u32, u32)> {
110+
if !version_header.exists() {
111+
bail!("MKL Version file not found: {}", version_header.display());
112+
}
113+
let f = fs::File::open(version_header)?;
114+
let f = io::BufReader::new(f);
115+
let mut year = 0;
116+
let mut update = 0;
117+
for line in f.lines() {
118+
if let Ok(line) = line {
119+
if !line.starts_with("#define") {
120+
continue;
121+
}
122+
let ss: Vec<&str> = line.split(" ").collect();
123+
match ss[1] {
124+
"__INTEL_MKL__" => year = ss[2].parse()?,
125+
"__INTEL_MKL_UPDATE__" => update = ss[2].parse()?,
126+
_ => continue,
127+
}
128+
}
129+
}
130+
if year == 0 || update == 0 {
131+
bail!("Cannot determine MKL versions");
132+
}
133+
Ok((year, update))
134+
}
135+
136+
pub fn package(mkl_path: &Path) -> Fallible<PathBuf> {
137+
if !mkl_path.exists() {
138+
bail!("MKL directory not found: {}", mkl_path.display());
139+
}
140+
let (year, update) = get_mkl_version(&mkl_path.join("include/mkl_version.h"))?;
141+
info!("Intel MKL version: {}.{}", year, update);
142+
let out = PathBuf::from(archive_filename());
143+
info!("Create archive: {}", out.display());
144+
145+
let shared_libs: Vec<_> = glob(
146+
mkl_path
147+
.join(format!("lib/intel64/*.{}", mkl::EXT))
148+
.to_str()
149+
.unwrap(),
150+
)?
151+
.map(|path| path.unwrap())
152+
.collect();
153+
let f = fs::File::create(&out)?;
154+
let buf = io::BufWriter::new(f);
155+
let zstd = zstd::stream::write::Encoder::new(buf, 6)?;
156+
let mut ar = tar::Builder::new(zstd);
157+
ar.mode(tar::HeaderMode::Deterministic);
158+
for lib in &shared_libs {
159+
info!("Add {}", lib.display());
160+
ar.append_path_with_name(lib, lib.file_name().unwrap())?;
161+
}
162+
let zstd = ar.into_inner()?;
163+
zstd.finish()?;
164+
165+
Ok(out)
166+
}

0 commit comments

Comments
 (0)