1
1
use std:: collections:: { HashMap , HashSet } ;
2
2
use std:: env;
3
3
use std:: ffi:: OsStr ;
4
- use std:: fs:: File ;
5
- use std:: io:: { BufRead , BufReader } ;
6
4
use std:: path:: { Path , PathBuf } ;
7
5
use std:: time:: Instant ;
8
6
@@ -169,61 +167,92 @@ fn files_with_extension<'e>(dir: &Path, extension: impl AsRef<OsStr> + 'e) -> Re
169
167
} )
170
168
}
171
169
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) ;
170
+ mod header {
171
+ use std:: fs:: File ;
172
+ use std:: io:: { BufRead , BufReader } ;
173
+ use std:: path:: { Path , PathBuf } ;
174
+
175
+ use semver:: Version ;
176
+
177
+ pub fn get_module_header_dir ( header_dir : & Path ) -> Option < PathBuf > {
178
+ let mut out = header_dir. join ( "opencv2.framework/Headers" ) ;
179
+ if out. exists ( ) {
180
+ return Some ( out) ;
181
+ }
182
+ out = header_dir. join ( "opencv2" ) ;
183
+ if out. exists ( ) {
184
+ return Some ( out) ;
185
+ }
186
+ None
176
187
}
177
- out = header_dir. join ( "opencv2" ) ;
178
- if out. exists ( ) {
179
- return Some ( out) ;
188
+
189
+ pub fn get_version_header ( header_dir : & Path ) -> Option < PathBuf > {
190
+ get_module_header_dir ( header_dir)
191
+ . map ( |dir| dir. join ( "core/version.hpp" ) )
192
+ . filter ( |hdr| hdr. is_file ( ) )
180
193
}
181
- None
182
- }
183
194
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
- }
195
+ pub fn get_config_header ( header_dir : & Path ) -> Option < PathBuf > {
196
+ get_module_header_dir ( header_dir)
197
+ . map ( |dir| dir. join ( "cvconfig.h " ) )
198
+ . filter ( |hdr| hdr. is_file ( ) )
199
+ }
189
200
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 ( ) ?) ;
201
+ pub fn find_version ( header_dir : & Path ) -> Option < Version > {
202
+ let version_hpp = get_version_header ( header_dir) ?;
203
+ let mut major = None ;
204
+ let mut minor = None ;
205
+ let mut revision = None ;
206
+ let mut line = String :: with_capacity ( 256 ) ;
207
+ let mut reader = BufReader :: new ( File :: open ( version_hpp) . ok ( ) ?) ;
208
+ while let Ok ( bytes_read) = reader. read_line ( & mut line) {
209
+ if bytes_read == 0 {
210
+ break ;
211
+ }
212
+ if let Some ( line) = line. strip_prefix ( "#define CV_VERSION_" ) {
213
+ let mut parts = line. split_whitespace ( ) ;
214
+ if let ( Some ( ver_spec) , Some ( version) ) = ( parts. next ( ) , parts. next ( ) ) {
215
+ match ver_spec {
216
+ "MAJOR" => {
217
+ major = Some ( version. parse ( ) . ok ( ) ?) ;
218
+ }
219
+ "MINOR" => {
220
+ minor = Some ( version. parse ( ) . ok ( ) ?) ;
221
+ }
222
+ "REVISION" => {
223
+ revision = Some ( version. parse ( ) . ok ( ) ?) ;
224
+ }
225
+ _ => { }
213
226
}
214
- _ => { }
227
+ }
228
+ if major. is_some ( ) && minor. is_some ( ) && revision. is_some ( ) {
229
+ break ;
215
230
}
216
231
}
217
- if major. is_some ( ) && minor. is_some ( ) && revision. is_some ( ) {
232
+ line. clear ( ) ;
233
+ }
234
+ if let ( Some ( major) , Some ( minor) , Some ( revision) ) = ( major, minor, revision) {
235
+ Some ( Version :: new ( major, minor, revision) )
236
+ } else {
237
+ None
238
+ }
239
+ }
240
+
241
+ pub fn find_enabled_features ( header_dir : & Path ) -> Option < Vec < String > > {
242
+ let config_h = get_config_header ( header_dir) ?;
243
+ let mut out = Vec :: with_capacity ( 64 ) ;
244
+ let mut line = String :: with_capacity ( 256 ) ;
245
+ let mut reader = BufReader :: new ( File :: open ( config_h) . ok ( ) ?) ;
246
+ while let Ok ( bytes_read) = reader. read_line ( & mut line) {
247
+ if bytes_read == 0 {
218
248
break ;
219
249
}
250
+ if let Some ( feature) = line. strip_prefix ( "#define HAVE_" ) {
251
+ out. push ( feature. trim ( ) . to_lowercase ( ) ) ;
252
+ }
253
+ line. clear ( ) ;
220
254
}
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
255
+ Some ( out)
227
256
}
228
257
}
229
258
@@ -264,13 +293,18 @@ fn make_modules_and_alises(
264
293
Ok ( ( modules, aliases) )
265
294
}
266
295
267
- fn emit_inherent_features ( opencv_version : & Version ) {
296
+ fn emit_inherent_features ( opencv : & Library ) {
268
297
if VersionReq :: parse ( ">=4.10" )
269
298
. expect ( "Static version requirement" )
270
- . matches ( opencv_version )
299
+ . matches ( & opencv . version )
271
300
{
272
301
println ! ( "cargo::rustc-cfg=ocvrs_has_inherent_feature_hfloat" ) ;
273
302
}
303
+ for feature in & opencv. enabled_features {
304
+ if feature == "opencl" {
305
+ println ! ( "cargo::rustc-cfg=ocvrs_has_inherent_feature_opencl" ) ;
306
+ }
307
+ }
274
308
}
275
309
276
310
fn make_compiler ( opencv : & Library , ffi_export_suffix : & str ) -> cc:: Build {
@@ -374,9 +408,7 @@ fn main() -> Result<()> {
374
408
for module in SUPPORTED_MODULES {
375
409
println ! ( "cargo::rustc-check-cfg=cfg(ocvrs_has_module_{module})" ) ;
376
410
}
377
- // MSRV: switch to #[expect] when MSRV is 1.81
378
- #[ allow( clippy:: single_element_loop) ]
379
- for inherent_feature in [ "hfloat" ] {
411
+ for inherent_feature in [ "hfloat" , "opencl" ] {
380
412
println ! ( "cargo::rustc-check-cfg=cfg(ocvrs_has_inherent_feature_{inherent_feature})" ) ;
381
413
}
382
414
@@ -419,10 +451,10 @@ fn main() -> Result<()> {
419
451
let opencv_header_dir = opencv
420
452
. include_paths
421
453
. iter ( )
422
- . find ( |p| get_version_header ( p) . is_some ( ) )
423
- . expect ( "Discovered OpenCV include paths is empty or contains non-existent paths " ) ;
454
+ . find ( |p| header :: get_version_header ( p ) . is_some ( ) && header :: get_config_header ( p) . is_some ( ) )
455
+ . expect ( "Discovered OpenCV include paths do not contain valid OpenCV headers " ) ;
424
456
425
- if let Some ( header_version) = get_version_from_headers ( opencv_header_dir) {
457
+ if let Some ( header_version) = header :: find_version ( opencv_header_dir) {
426
458
if header_version != opencv. version {
427
459
panic ! (
428
460
"OpenCV version from the headers: {header_version} (at {}) must match version of the OpenCV library: {} (include paths: {:?})" ,
@@ -442,7 +474,7 @@ fn main() -> Result<()> {
442
474
)
443
475
}
444
476
445
- let opencv_module_header_dir = get_module_header_dir ( opencv_header_dir) . expect ( "Can't find OpenCV module header dir" ) ;
477
+ let opencv_module_header_dir = header :: get_module_header_dir ( opencv_header_dir) . expect ( "Can't find OpenCV module header dir" ) ;
446
478
eprintln ! (
447
479
"=== Detected OpenCV module header dir at: {}" ,
448
480
opencv_module_header_dir. display( )
@@ -452,7 +484,7 @@ fn main() -> Result<()> {
452
484
println ! ( "cargo::rustc-cfg=ocvrs_has_module_{module}" ) ;
453
485
}
454
486
455
- emit_inherent_features ( & opencv. version ) ;
487
+ emit_inherent_features ( & opencv) ;
456
488
457
489
setup_rerun ( ) ?;
458
490
0 commit comments