@@ -4,40 +4,42 @@ use std::{
4
4
fs,
5
5
io:: { self , BufRead } ,
6
6
path:: { Path , PathBuf } ,
7
+ process:: Command ,
7
8
} ;
8
9
9
- /// A library found in system
10
10
#[ derive( Debug , Clone ) ]
11
- pub enum Library {
12
- PkgConfig {
13
- config : Config ,
14
- lib : pkg_config:: Library ,
15
- } ,
16
- Directory {
17
- config : Config ,
18
- /// Directory where `mkl.h` and `mkl_version.h` exists
19
- include_dir : PathBuf ,
20
- /// Directory where `libmkl_core.a` or `libmkl_rt.so` exists
21
- library_dir : PathBuf ,
22
- /// Directory where `libiomp5.a` or `libiomp5.so` exists
23
- ///
24
- /// They are sometimes placed in different position.
25
- /// Returns `None` if they exist on `library_dir`.
26
- iomp5_dir : Option < PathBuf > ,
27
- } ,
11
+ pub struct Library {
12
+ config : Config ,
13
+ /// Directory where `mkl.h` and `mkl_version.h` exists
14
+ include_dir : PathBuf ,
15
+ /// Directory where `libmkl_core.a` or `libmkl_rt.so` exists
16
+ library_dir : PathBuf ,
17
+ /// Directory where `libiomp5.a` or `libiomp5.so` exists
18
+ ///
19
+ /// They are sometimes placed in different position.
20
+ /// Returns `None` if they exist on `library_dir`.
21
+ iomp5_dir : Option < PathBuf > ,
28
22
}
29
23
30
24
impl Library {
31
25
/// Try to find MKL using pkg-config
32
- pub fn pkg_config ( config : Config ) -> Option < Self > {
33
- if let Ok ( lib ) = pkg_config :: Config :: new ( )
34
- . cargo_metadata ( false )
35
- . env_metadata ( false )
36
- . probe ( & config . to_string ( ) )
26
+ pub fn pkg_config ( config : Config ) -> Result < Option < Self > > {
27
+ if let Ok ( out ) = Command :: new ( "pkg-config" )
28
+ . arg ( "--variable=prefix" )
29
+ . arg ( config . to_string ( ) )
30
+ . output ( )
37
31
{
38
- Some ( Library :: PkgConfig { config, lib } )
32
+ if out. status . success ( ) {
33
+ let path = String :: from_utf8 ( out. stdout ) . context ( "Non-UTF8 MKL prefix" ) ?;
34
+ let prefix = Path :: new ( path. trim ( ) ) ;
35
+ Self :: seek_directory ( config, prefix)
36
+ } else {
37
+ // pkg-config does not find MKL
38
+ Ok ( None )
39
+ }
39
40
} else {
40
- None
41
+ // pkg-config is not found
42
+ Ok ( None )
41
43
}
42
44
}
43
45
@@ -136,7 +138,7 @@ impl Library {
136
138
iomp5_dir = None ;
137
139
}
138
140
Ok ( match ( library_dir, include_dir) {
139
- ( Some ( library_dir) , Some ( include_dir) ) => Some ( Library :: Directory {
141
+ ( Some ( library_dir) , Some ( include_dir) ) => Some ( Library {
140
142
config,
141
143
include_dir,
142
144
library_dir,
@@ -157,7 +159,7 @@ impl Library {
157
159
/// - `C:/Program Files (x86)/IntelSWTools/` for Windows
158
160
///
159
161
pub fn new ( config : Config ) -> Result < Self > {
160
- if let Some ( lib) = Self :: pkg_config ( config) {
162
+ if let Some ( lib) = Self :: pkg_config ( config) ? {
161
163
return Ok ( lib) ;
162
164
}
163
165
if let Ok ( mklroot) = std:: env:: var ( "MKLROOT" ) {
@@ -182,10 +184,7 @@ impl Library {
182
184
}
183
185
184
186
pub fn config ( & self ) -> & Config {
185
- match self {
186
- Library :: PkgConfig { config, .. } => config,
187
- Library :: Directory { config, .. } => config,
188
- }
187
+ & self . config
189
188
}
190
189
191
190
/// Found MKL version parsed from `mkl_version.h`
@@ -201,19 +200,7 @@ impl Library {
201
200
/// and this corresponds to `(2020, 0, 1)`
202
201
///
203
202
pub fn version ( & self ) -> Result < ( u32 , u32 , u32 ) > {
204
- let version_h = match self {
205
- Library :: PkgConfig { lib, .. } => {
206
- let mut version_h = None ;
207
- for path in & lib. include_paths {
208
- let candidate = path. join ( "mkl_version.h" ) ;
209
- if candidate. exists ( ) {
210
- version_h = Some ( candidate) ;
211
- }
212
- }
213
- version_h. context ( "mkl_version.h not found in pkg-config" ) ?
214
- }
215
- Library :: Directory { include_dir, .. } => include_dir. join ( "mkl_version.h" ) ,
216
- } ;
203
+ let version_h = self . include_dir . join ( "mkl_version.h" ) ;
217
204
218
205
let f = fs:: File :: open ( version_h) . context ( "Failed to open mkl_version.h" ) ?;
219
206
let f = io:: BufReader :: new ( f) ;
@@ -242,29 +229,17 @@ impl Library {
242
229
243
230
/// Print `cargo:rustc-link-*` metadata to stdout
244
231
pub fn print_cargo_metadata ( & self ) -> Result < ( ) > {
245
- match self {
246
- Library :: PkgConfig { config, .. } => {
247
- pkg_config:: probe_library ( & config. to_string ( ) ) ?;
248
- }
249
- Library :: Directory {
250
- config,
251
- library_dir,
252
- iomp5_dir,
253
- ..
254
- } => {
255
- println ! ( "cargo:rustc-link-search={}" , library_dir. display( ) ) ;
256
- if let Some ( iomp5_dir) = iomp5_dir {
257
- println ! ( "cargo:rustc-link-search={}" , iomp5_dir. display( ) ) ;
232
+ println ! ( "cargo:rustc-link-search={}" , self . library_dir. display( ) ) ;
233
+ if let Some ( iomp5_dir) = & self . iomp5_dir {
234
+ println ! ( "cargo:rustc-link-search={}" , iomp5_dir. display( ) ) ;
235
+ }
236
+ for lib in self . config . libs ( ) {
237
+ match self . config . link {
238
+ LinkType :: Static => {
239
+ println ! ( "cargo:rustc-link-lib=static={}" , lib) ;
258
240
}
259
- for lib in config. libs ( ) {
260
- match config. link {
261
- LinkType :: Static => {
262
- println ! ( "cargo:rustc-link-lib=static={}" , lib) ;
263
- }
264
- LinkType :: Dynamic => {
265
- println ! ( "cargo:rustc-link-lib=dylib={}" , lib) ;
266
- }
267
- }
241
+ LinkType :: Dynamic => {
242
+ println ! ( "cargo:rustc-link-lib=dylib={}" , lib) ;
268
243
}
269
244
}
270
245
}
@@ -290,7 +265,7 @@ mod tests {
290
265
#[ test]
291
266
fn pkg_config ( ) {
292
267
for cfg in Config :: possibles ( ) {
293
- let lib = Library :: pkg_config ( cfg) . unwrap ( ) ;
268
+ let lib = Library :: pkg_config ( cfg) . unwrap ( ) . unwrap ( ) ;
294
269
dbg ! ( lib. version( ) . unwrap( ) ) ;
295
270
}
296
271
}
0 commit comments