11use std:: collections:: { HashMap , HashSet } ;
22use std:: env;
33use std:: ffi:: OsStr ;
4- use std:: fs:: File ;
5- use std:: io:: { BufRead , BufReader } ;
64use std:: path:: { Path , PathBuf } ;
75use std:: time:: Instant ;
86
97use binding_generator:: handle_running_binding_generator;
108use docs:: handle_running_in_docsrs;
119use generator:: BindingGenerator ;
10+ use header:: IncludePath ;
1211use library:: Library ;
1312use once_cell:: sync:: Lazy ;
1413use semver:: { Version , VersionReq } ;
@@ -21,6 +20,8 @@ pub mod cmake_probe;
2120mod docs;
2221#[ path = "build/generator.rs" ]
2322mod generator;
23+ #[ path = "build/header.rs" ]
24+ mod header;
2425#[ path = "build/library.rs" ]
2526pub mod library;
2627
@@ -144,6 +145,8 @@ static SUPPORTED_MODULES: [&str; 73] = [
144145 "xstereo" ,
145146] ;
146147
148+ static SUPPORTED_INHERENT_FEATURES : [ & str ; 2 ] = [ "hfloat" , "opencl" ] ;
149+
147150/// The contents of these vars will be present in the debug log, but will not cause the source rebuild
148151static DEBUG_ENV_VARS : [ & str ; 1 ] = [ "PATH" ] ;
149152
@@ -169,64 +172,6 @@ fn files_with_extension<'e>(dir: &Path, extension: impl AsRef<OsStr> + 'e) -> Re
169172 } )
170173}
171174
172- fn get_module_header_dir ( header_dir : & Path ) -> Option < PathBuf > {
173- let mut out = header_dir. join ( "opencv2.framework/Headers" ) ;
174- if out. exists ( ) {
175- return Some ( out) ;
176- }
177- out = header_dir. join ( "opencv2" ) ;
178- if out. exists ( ) {
179- return Some ( out) ;
180- }
181- None
182- }
183-
184- fn get_version_header ( header_dir : & Path ) -> Option < PathBuf > {
185- get_module_header_dir ( header_dir)
186- . map ( |dir| dir. join ( "core/version.hpp" ) )
187- . filter ( |hdr| hdr. is_file ( ) )
188- }
189-
190- fn get_version_from_headers ( header_dir : & Path ) -> Option < Version > {
191- let version_hpp = get_version_header ( header_dir) ?;
192- let mut major = None ;
193- let mut minor = None ;
194- let mut revision = None ;
195- let mut line = String :: with_capacity ( 256 ) ;
196- let mut reader = BufReader :: new ( File :: open ( version_hpp) . ok ( ) ?) ;
197- while let Ok ( bytes_read) = reader. read_line ( & mut line) {
198- if bytes_read == 0 {
199- break ;
200- }
201- if let Some ( line) = line. strip_prefix ( "#define CV_VERSION_" ) {
202- let mut parts = line. split_whitespace ( ) ;
203- if let ( Some ( ver_spec) , Some ( version) ) = ( parts. next ( ) , parts. next ( ) ) {
204- match ver_spec {
205- "MAJOR" => {
206- major = Some ( version. parse ( ) . ok ( ) ?) ;
207- }
208- "MINOR" => {
209- minor = Some ( version. parse ( ) . ok ( ) ?) ;
210- }
211- "REVISION" => {
212- revision = Some ( version. parse ( ) . ok ( ) ?) ;
213- }
214- _ => { }
215- }
216- }
217- if major. is_some ( ) && minor. is_some ( ) && revision. is_some ( ) {
218- break ;
219- }
220- }
221- line. clear ( ) ;
222- }
223- if let ( Some ( major) , Some ( minor) , Some ( revision) ) = ( major, minor, revision) {
224- Some ( Version :: new ( major, minor, revision) )
225- } else {
226- None
227- }
228- }
229-
230175fn make_modules_and_alises (
231176 opencv_dir : & Path ,
232177 opencv_version : & Version ,
@@ -264,13 +209,18 @@ fn make_modules_and_alises(
264209 Ok ( ( modules, aliases) )
265210}
266211
267- fn emit_inherent_features ( opencv_version : & Version ) {
212+ fn emit_inherent_features ( opencv : & Library ) {
268213 if VersionReq :: parse ( ">=4.10" )
269214 . expect ( "Static version requirement" )
270- . matches ( opencv_version )
215+ . matches ( & opencv . version )
271216 {
272217 println ! ( "cargo::rustc-cfg=ocvrs_has_inherent_feature_hfloat" ) ;
273218 }
219+ for feature in & opencv. enabled_features {
220+ if SUPPORTED_INHERENT_FEATURES . contains ( & feature. as_str ( ) ) {
221+ println ! ( "cargo::rustc-cfg=ocvrs_has_inherent_feature_{feature}" ) ;
222+ }
223+ }
274224}
275225
276226fn make_compiler ( opencv : & Library , ffi_export_suffix : & str ) -> cc:: Build {
@@ -374,9 +324,7 @@ fn main() -> Result<()> {
374324 for module in SUPPORTED_MODULES {
375325 println ! ( "cargo::rustc-check-cfg=cfg(ocvrs_has_module_{module})" ) ;
376326 }
377- // MSRV: switch to #[expect] when MSRV is 1.81
378- #[ allow( clippy:: single_element_loop) ]
379- for inherent_feature in [ "hfloat" ] {
327+ for inherent_feature in SUPPORTED_INHERENT_FEATURES {
380328 println ! ( "cargo::rustc-check-cfg=cfg(ocvrs_has_inherent_feature_{inherent_feature})" ) ;
381329 }
382330
@@ -419,10 +367,10 @@ fn main() -> Result<()> {
419367 let opencv_header_dir = opencv
420368 . include_paths
421369 . iter ( )
422- . find ( |p| get_version_header ( p ) . is_some ( ) )
423- . expect ( "Discovered OpenCV include paths is empty or contains non-existent paths " ) ;
370+ . find ( |p| p . get_version_header ( ) . is_some ( ) )
371+ . expect ( "Discovered OpenCV include paths do not contain valid OpenCV headers " ) ;
424372
425- if let Some ( header_version) = get_version_from_headers ( opencv_header_dir) {
373+ if let Some ( header_version) = opencv_header_dir. find_version ( ) {
426374 if header_version != opencv. version {
427375 panic ! (
428376 "OpenCV version from the headers: {header_version} (at {}) must match version of the OpenCV library: {} (include paths: {:?})" ,
@@ -442,7 +390,9 @@ fn main() -> Result<()> {
442390 )
443391 }
444392
445- let opencv_module_header_dir = get_module_header_dir ( opencv_header_dir) . expect ( "Can't find OpenCV module header dir" ) ;
393+ let opencv_module_header_dir = opencv_header_dir
394+ . get_module_header_dir ( )
395+ . expect ( "Can't find OpenCV module header dir" ) ;
446396 eprintln ! (
447397 "=== Detected OpenCV module header dir at: {}" ,
448398 opencv_module_header_dir. display( )
@@ -452,7 +402,7 @@ fn main() -> Result<()> {
452402 println ! ( "cargo::rustc-cfg=ocvrs_has_module_{module}" ) ;
453403 }
454404
455- emit_inherent_features ( & opencv. version ) ;
405+ emit_inherent_features ( & opencv) ;
456406
457407 setup_rerun ( ) ?;
458408
0 commit comments