11use curl:: easy:: Easy ;
22use failure:: * ;
3+ use glob:: glob;
34use log:: * ;
45use std:: {
56 fs,
6- io:: { self , Write } ,
7+ io:: { self , BufRead , Write } ,
78 path:: * ,
89} ;
910
1011const 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" ) ) ]
1314mod 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" ) ) ]
2023mod 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" ) ) ]
2732mod 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
3349pub 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