@@ -7,11 +7,7 @@ use std::os::raw::{c_int, c_uint};
77use std:: path:: { Path , PathBuf } ;
88use std:: process:: Command ;
99use std:: str;
10- use std:: sync:: Mutex ;
1110
12- use bindgen:: callbacks:: IntKind ;
13- use bindgen:: callbacks:: ParseCallbacks ;
14- use lazy_static:: lazy_static;
1511use regex:: Regex ;
1612
1713#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Default ) ]
@@ -167,53 +163,43 @@ pub struct Header {
167163 pub version : Version ,
168164}
169165
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-
205166impl Header {
206167 pub fn parse < P : AsRef < Path > > ( inc_dir : P ) -> Self {
207168 let inc_dir = inc_dir. as_ref ( ) ;
208169 let header = inc_dir. join ( "H5pubconf.h" ) ;
209170 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+
217203 if !hdr. version . is_valid ( ) {
218204 panic ! ( "Invalid H5_VERSION in the header: {:?}" ) ;
219205 }
@@ -226,6 +212,7 @@ pub struct LibrarySearcher {
226212 pub version : Option < Version > ,
227213 pub inc_dir : Option < PathBuf > ,
228214 pub link_paths : Vec < PathBuf > ,
215+ pub user_provided_dir : bool ,
229216}
230217
231218#[ cfg( all( unix, not( target_os = "macos" ) ) ) ]
@@ -456,7 +443,15 @@ impl LibrarySearcher {
456443 if let Ok ( var) = env:: var ( "HDF5_DIR" ) {
457444 println ! ( "Setting HDF5 root from environment variable:" ) ;
458445 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" ) ) ;
460455 }
461456 if cfg ! ( target_env = "msvc" ) {
462457 // in order to allow HDF5_DIR to be pointed to a conda environment, we have
@@ -503,9 +498,9 @@ impl LibrarySearcher {
503498 if let Some ( ref inc_dir) = self . inc_dir {
504499 if cfg ! ( unix) {
505500 if let Some ( envdir) = inc_dir. parent ( ) {
506- if envdir . join ( "conda-meta" ) . is_dir ( ) {
501+ if self . user_provided_dir {
507502 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:" ) ;
509504 println ! ( " RUSTFLAGS=\" -C link-args=-Wl,-rpath,{}\" " , lib_dir) ;
510505 if cfg ! ( target_os = "macos" ) {
511506 println ! ( "On some OS X installations, you may also need to set:" ) ;
0 commit comments