@@ -7,11 +7,7 @@ use std::os::raw::{c_int, c_uint};
7
7
use std:: path:: { Path , PathBuf } ;
8
8
use std:: process:: Command ;
9
9
use std:: str;
10
- use std:: sync:: Mutex ;
11
10
12
- use bindgen:: callbacks:: IntKind ;
13
- use bindgen:: callbacks:: ParseCallbacks ;
14
- use lazy_static:: lazy_static;
15
11
use regex:: Regex ;
16
12
17
13
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Default ) ]
@@ -167,53 +163,43 @@ pub struct Header {
167
163
pub version : Version ,
168
164
}
169
165
170
- lazy_static ! {
171
- static ref HEADER : Mutex <Header > = Default :: default ( ) ;
172
- }
173
-
174
- #[ derive( Debug ) ]
175
- struct HeaderParser ;
176
-
177
- impl ParseCallbacks for HeaderParser {
178
- fn int_macro ( & self , name : & str , value : i64 ) -> Option < IntKind > {
179
- let mut hdr = HEADER . lock ( ) . unwrap ( ) ;
180
- if name == "H5_HAVE_STDBOOL_H" {
181
- hdr. have_stdbool_h = value > 0 ;
182
- } else if name == "H5_HAVE_DIRECT" {
183
- hdr. have_direct = value > 0 ;
184
- } else if name == "H5_HAVE_PARALLEL" {
185
- hdr. have_parallel = value > 0 ;
186
- } else if name == "H5_HAVE_THREADSAFE" {
187
- hdr. have_threadsafe = value > 0 ;
188
- }
189
- None
190
- }
191
-
192
- fn str_macro ( & self , name : & str , value : & [ u8 ] ) {
193
- let mut hdr = HEADER . lock ( ) . unwrap ( ) ;
194
- let str_value = unsafe { str:: from_utf8_unchecked ( value) } ;
195
- if name == "H5_VERSION" {
196
- if let Some ( version) = Version :: parse ( str_value) {
197
- hdr. version = version;
198
- } else {
199
- panic ! ( "Invalid H5_VERSION: {:?}" , str_value) ;
200
- }
201
- }
202
- }
203
- }
204
-
205
166
impl Header {
206
167
pub fn parse < P : AsRef < Path > > ( inc_dir : P ) -> Self {
207
168
let inc_dir = inc_dir. as_ref ( ) ;
208
169
let header = inc_dir. join ( "H5pubconf.h" ) ;
209
170
println ! ( "Parsing HDF5 config from:\n {:?}" , header) ;
210
- bindgen:: builder ( )
211
- . header ( header. to_str ( ) . unwrap ( ) )
212
- . clang_args ( & [ "-I" , inc_dir. to_str ( ) . unwrap ( ) ] )
213
- . parse_callbacks ( Box :: new ( HeaderParser ) )
214
- . generate ( )
215
- . unwrap ( ) ;
216
- let hdr = HEADER . lock ( ) . unwrap ( ) . clone ( ) ;
171
+
172
+ let contents = fs:: read_to_string ( header) . unwrap ( ) ;
173
+ let mut hdr = Self :: default ( ) ;
174
+
175
+ let num_def_re = Regex :: new ( r"(?m)^#define\s+(H5_[A-Z_]+)\s+([0-9]+)\s*$" ) . unwrap ( ) ;
176
+ for captures in num_def_re. captures_iter ( & contents) {
177
+ let name = captures. get ( 1 ) . unwrap ( ) . as_str ( ) ;
178
+ let value = captures. get ( 2 ) . unwrap ( ) . as_str ( ) . parse :: < i64 > ( ) . unwrap ( ) ;
179
+ if name == "H5_HAVE_STDBOOL_H" {
180
+ hdr. have_stdbool_h = value > 0 ;
181
+ } else if name == "H5_HAVE_DIRECT" {
182
+ hdr. have_direct = value > 0 ;
183
+ } else if name == "H5_HAVE_PARALLEL" {
184
+ hdr. have_parallel = value > 0 ;
185
+ } else if name == "H5_HAVE_THREADSAFE" {
186
+ hdr. have_threadsafe = value > 0 ;
187
+ }
188
+ }
189
+
190
+ let str_def_re = Regex :: new ( r#"(?m)^#define\s+(H5_[A-Z_]+)\s+"([^"]+)"\s*$"# ) . unwrap ( ) ;
191
+ for captures in str_def_re. captures_iter ( & contents) {
192
+ let name = captures. get ( 1 ) . unwrap ( ) . as_str ( ) ;
193
+ let value = captures. get ( 2 ) . unwrap ( ) . as_str ( ) ;
194
+ if name == "H5_VERSION" {
195
+ if let Some ( version) = Version :: parse ( value) {
196
+ hdr. version = version;
197
+ } else {
198
+ panic ! ( "Invalid H5_VERSION: {:?}" , value) ;
199
+ }
200
+ }
201
+ }
202
+
217
203
if !hdr. version . is_valid ( ) {
218
204
panic ! ( "Invalid H5_VERSION in the header: {:?}" ) ;
219
205
}
@@ -226,6 +212,7 @@ pub struct LibrarySearcher {
226
212
pub version : Option < Version > ,
227
213
pub inc_dir : Option < PathBuf > ,
228
214
pub link_paths : Vec < PathBuf > ,
215
+ pub user_provided_dir : bool ,
229
216
}
230
217
231
218
#[ cfg( all( unix, not( target_os = "macos" ) ) ) ]
@@ -456,7 +443,15 @@ impl LibrarySearcher {
456
443
if let Ok ( var) = env:: var ( "HDF5_DIR" ) {
457
444
println ! ( "Setting HDF5 root from environment variable:" ) ;
458
445
println ! ( " HDF5_DIR = {:?}" , var) ;
459
- config. inc_dir = Some ( PathBuf :: from ( var) . join ( "include" ) ) ;
446
+ let root = PathBuf :: from ( var) ;
447
+ if root. is_relative ( ) {
448
+ panic ! ( "HDF5_DIR cannot be relative." ) ;
449
+ }
450
+ if !root. is_dir ( ) {
451
+ panic ! ( "HDF5_DIR is not a directory." ) ;
452
+ }
453
+ config. user_provided_dir = true ;
454
+ config. inc_dir = Some ( root. join ( "include" ) ) ;
460
455
}
461
456
if cfg ! ( target_env = "msvc" ) {
462
457
// in order to allow HDF5_DIR to be pointed to a conda environment, we have
@@ -503,9 +498,9 @@ impl LibrarySearcher {
503
498
if let Some ( ref inc_dir) = self . inc_dir {
504
499
if cfg ! ( unix) {
505
500
if let Some ( envdir) = inc_dir. parent ( ) {
506
- if envdir . join ( "conda-meta" ) . is_dir ( ) {
501
+ if self . user_provided_dir {
507
502
let lib_dir = format ! ( "{}/lib" , envdir. to_string_lossy( ) ) ;
508
- println ! ( "Conda environment detected, rpath can be set via:" ) ;
503
+ println ! ( "Custom HDF5_DIR provided; rpath can be set via:" ) ;
509
504
println ! ( " RUSTFLAGS=\" -C link-args=-Wl,-rpath,{}\" " , lib_dir) ;
510
505
if cfg ! ( target_os = "macos" ) {
511
506
println ! ( "On some OS X installations, you may also need to set:" ) ;
0 commit comments