1- use std:: ffi:: OsStr ;
21use std:: fs;
32use std:: fs:: File ;
43use std:: io:: { BufRead , BufReader } ;
@@ -8,91 +7,8 @@ use std::process::{Command, Output};
87use semver:: Version ;
98use shlex:: Shlex ;
109
11- use super :: library:: Linkage ;
12- use super :: { Result , TARGET_ENV_MSVC } ;
13-
14- #[ derive( Debug , PartialEq , Eq ) ]
15- pub struct LinkLib ( pub Linkage , pub String ) ;
16-
17- impl LinkLib {
18- #[ inline]
19- pub fn emit_cargo_rustc_link ( & self ) -> String {
20- format ! (
21- "cargo::rustc-link-lib={}{}" ,
22- self . 0 . as_cargo_rustc_link_spec_no_static( ) ,
23- self . 1
24- )
25- }
26-
27- /// Removes some common library filename parts that are not meant to be passed as part of the link name.
28- ///
29- /// E.g. "libopencv_core.so.4.6.0" becomes "opencv_core".
30- pub fn cleanup_lib_filename ( filename : & OsStr ) -> & OsStr {
31- let mut new_filename = filename;
32- // used to check for the file extension (with dots stripped) and for the part of the filename
33- const LIB_EXTS : [ & str ; 6 ] = [ ".so." , ".a." , ".dll." , ".lib." , ".dylib." , ".tbd." ] ;
34- let filename_path = Path :: new ( new_filename) ;
35- // strip lib extension from the filename
36- if let ( Some ( stem) , Some ( extension) ) = ( filename_path. file_stem ( ) , filename_path. extension ( ) . and_then ( OsStr :: to_str) ) {
37- if LIB_EXTS . iter ( ) . any ( |e| e. trim_matches ( '.' ) . eq_ignore_ascii_case ( extension) ) {
38- new_filename = stem;
39- }
40- }
41- if let Some ( mut file) = new_filename. to_str ( ) {
42- let orig_len = file. len ( ) ;
43-
44- // strip "lib" prefix from the filename unless targeting MSVC
45- if !* TARGET_ENV_MSVC {
46- file = file. strip_prefix ( "lib" ) . unwrap_or ( file) ;
47- }
48-
49- // strip lib extension + suffix (e.g. .so.4.6.0) from the filename
50- LIB_EXTS . iter ( ) . for_each ( |& inner_ext| {
51- if let Some ( inner_ext_idx) = file. rfind ( inner_ext) {
52- file = & file[ ..inner_ext_idx] ;
53- }
54- } ) ;
55- if orig_len != file. len ( ) {
56- new_filename = OsStr :: new ( file) ;
57- }
58- }
59- new_filename
60- }
61- }
62-
63- impl From < & str > for LinkLib {
64- fn from ( value : & str ) -> Self {
65- let ( linkage, value) = Linkage :: from_prefixed_str ( value) ;
66- let path = Path :: new ( value) ;
67- let value = path
68- . file_name ( )
69- . map ( Self :: cleanup_lib_filename)
70- . and_then ( OsStr :: to_str)
71- . unwrap_or ( value) ;
72- Self ( linkage, value. to_string ( ) )
73- }
74- }
75-
76- #[ derive( Debug , PartialEq , Eq ) ]
77- pub struct LinkSearch ( pub Linkage , pub PathBuf ) ;
78-
79- impl LinkSearch {
80- #[ inline]
81- pub fn emit_cargo_rustc_link_search ( & self ) -> String {
82- format ! (
83- "cargo::rustc-link-search={}{}" ,
84- self . 0 . as_cargo_rustc_link_search_spec( ) ,
85- self . 1 . to_str( ) . expect( "Can't convert link search path to UTF-8 string" )
86- )
87- }
88- }
89-
90- impl From < & str > for LinkSearch {
91- fn from ( value : & str ) -> Self {
92- let ( linkage, value) = Linkage :: from_prefixed_str ( value) ;
93- Self ( linkage, PathBuf :: from ( value) )
94- }
95- }
10+ use super :: library:: { LinkLib , LinkSearch , Linkage } ;
11+ use super :: Result ;
9612
9713pub struct ProbeResult {
9814 pub version : Option < Version > ,
@@ -221,6 +137,9 @@ impl<'r> CmakeProbe<'r> {
221137 }
222138 while let Some ( arg) = args. next ( ) {
223139 let arg = arg. trim ( ) ;
140+ if Self :: skip_ignorable_arg ( & mut args, arg) {
141+ continue ;
142+ }
224143 if let Some ( path) = arg. strip_prefix ( "-I" ) {
225144 let path = PathBuf :: from ( path. trim_start ( ) ) ;
226145 if !include_paths. contains ( & path) {
@@ -244,31 +163,46 @@ impl<'r> CmakeProbe<'r> {
244163 framework. to_string ( )
245164 } ;
246165 link_libs. push ( LinkLib ( Linkage :: Framework , framework) ) ;
247- } else if let Some ( output_file) = arg. strip_prefix ( "-o" ) {
248- if output_file. trim ( ) . is_empty ( ) {
249- args. next ( ) . expect ( "No output file after -o" ) ;
250- }
251166 } else if !arg. starts_with ( '-' ) {
252167 let path = Path :: new ( arg) ;
253- if let Some ( cleaned_lib_filename) = path. file_name ( ) . map ( LinkLib :: cleanup_lib_filename) {
254- let linkage = Linkage :: from_path ( path) ;
168+ if let Some ( link_lib) = LinkLib :: try_from_library_path ( path) {
255169 if let Some ( parent) = path. parent ( ) . map ( |p| p. to_owned ( ) ) {
256- let search_path = LinkSearch ( linkage, parent) ;
257- if !link_paths. contains ( & search_path) {
258- link_paths. push ( search_path) ;
170+ // only care about non-empty parent paths
171+ if parent. components ( ) . next ( ) . is_some ( ) {
172+ let search_path = LinkSearch ( link_lib. 0 , parent) ;
173+ if !link_paths. contains ( & search_path) {
174+ link_paths. push ( search_path) ;
175+ }
259176 }
260177 }
261- link_libs. push ( LinkLib (
262- linkage,
263- cleaned_lib_filename. to_str ( ) . expect ( "Non-UTF8 filename" ) . to_string ( ) ,
264- ) ) ;
178+ link_libs. push ( link_lib) ;
265179 }
266180 } else {
267181 eprintln ! ( "=== Unexpected cmake compiler argument found: {arg}" ) ;
268182 }
269183 }
270184 }
271185
186+ fn skip_ignorable_arg ( args : & mut Shlex , arg : & str ) -> bool {
187+ if let Some ( output_file) = arg. strip_prefix ( "-o" ) {
188+ if output_file. trim ( ) . is_empty ( ) {
189+ args. next ( ) . expect ( "No output file after -o" ) ;
190+ return true ;
191+ }
192+ } else if let Some ( sysroot) = arg. strip_prefix ( "-isysroot" ) {
193+ if sysroot. trim ( ) . is_empty ( ) {
194+ args. next ( ) . expect ( "No sysroot path after -isysroot" ) ;
195+ return true ;
196+ }
197+ } else if let Some ( arch) = arg. strip_prefix ( "-arch" ) {
198+ if arch. trim ( ) . is_empty ( ) {
199+ args. next ( ) . expect ( "No arch name after -arch" ) ;
200+ return true ;
201+ }
202+ }
203+ false
204+ }
205+
272206 fn extract_from_makefile ( & self , link_paths : & mut Vec < LinkSearch > , link_libs : & mut Vec < LinkLib > ) -> Result < ( ) > {
273207 let link_cmdline = fs:: read_to_string ( self . build_dir . join ( "CMakeFiles/ocvrs_probe.dir/link.txt" ) ) ?;
274208 Self :: extract_from_cmdline ( & link_cmdline, true , & mut vec ! [ ] , link_paths, link_libs) ;
0 commit comments