@@ -9,27 +9,62 @@ use semver::Version;
9
9
use shlex:: Shlex ;
10
10
11
11
use super :: library:: Linkage ;
12
- use super :: Result ;
12
+ use super :: { Result , TARGET_ENV_MSVC } ;
13
13
14
14
#[ derive( Debug , PartialEq , Eq ) ]
15
15
pub struct LinkLib ( pub Linkage , pub String ) ;
16
16
17
17
impl LinkLib {
18
18
#[ inline]
19
19
pub fn emit_cargo_rustc_link ( & self ) -> String {
20
- let link_spec = self . 0 . as_cargo_rustc_link_spec ( ) ;
21
- let link_spec = if self . 1 . starts_with ( link_spec) {
22
- ""
20
+ format ! ( "cargo:rustc-link-lib={}{}" , self . 0 . as_cargo_rustc_link_spec( ) , self . 1 )
21
+ }
22
+
23
+ /// Returns Some(new_file_name) with extra parts of the filename were removed, None in case of error
24
+ pub fn with_cleaned_up_lib_filename ( self ) -> Option < Self > {
25
+ return Some ( self ) ;
26
+ if matches ! ( self . 0 , Linkage :: Static | Linkage :: Framework ) {
27
+ Some ( self )
23
28
} else {
24
- link_spec
25
- } ;
26
- format ! ( "cargo:rustc-link-lib={link_spec}{}" , self . 1 )
29
+ let mut new_filename = Path :: new ( & self . 1 ) . as_os_str ( ) ;
30
+ // used to check for the file extension (with dots stripped) and for the part of the filename
31
+ const LIB_EXTS : [ & str ; 7 ] = [ ".so." , ".a." , ".dll." , ".lib." , ".dylib." , ".framework." , ".tbd." ] ;
32
+ let filename_path = Path :: new ( new_filename) ;
33
+ // strip lib extension from the filename
34
+ if let ( Some ( stem) , Some ( extension) ) = ( filename_path. file_stem ( ) , filename_path. extension ( ) . and_then ( OsStr :: to_str) ) {
35
+ if LIB_EXTS . iter ( ) . any ( |e| e. trim_matches ( '.' ) . eq_ignore_ascii_case ( extension) ) {
36
+ new_filename = stem;
37
+ }
38
+ }
39
+ if let Some ( mut file) = new_filename. to_str ( ) {
40
+ let orig_len = file. len ( ) ;
41
+
42
+ // strip "lib" prefix from the filename unless targeting MSVC
43
+ if !* TARGET_ENV_MSVC {
44
+ file = file. strip_prefix ( "lib" ) . unwrap_or ( file) ;
45
+ }
46
+
47
+ // strip lib extension + suffix (e.g. .so.4.6.0) from the filename
48
+ LIB_EXTS . iter ( ) . for_each ( |& inner_ext| {
49
+ if let Some ( inner_ext_idx) = file. find ( inner_ext) {
50
+ file = & file[ ..inner_ext_idx] ;
51
+ }
52
+ } ) ;
53
+ if orig_len != file. len ( ) {
54
+ new_filename = OsStr :: new ( file) ;
55
+ }
56
+ }
57
+ new_filename
58
+ . to_str ( )
59
+ . map ( |new_filename| Self ( self . 0 , new_filename. to_string ( ) ) )
60
+ }
27
61
}
28
62
}
29
63
30
64
impl From < & str > for LinkLib {
31
65
fn from ( value : & str ) -> Self {
32
- Self ( Linkage :: Default , value. to_string ( ) )
66
+ let ( linkage, value) = Linkage :: from_prefixed_str ( value) ;
67
+ Self ( linkage, value. to_string ( ) )
33
68
}
34
69
}
35
70
@@ -49,7 +84,8 @@ impl LinkSearch {
49
84
50
85
impl From < & str > for LinkSearch {
51
86
fn from ( value : & str ) -> Self {
52
- Self ( Linkage :: Default , value. into ( ) )
87
+ let ( linkage, value) = Linkage :: from_prefixed_str ( value) ;
88
+ Self ( linkage, value. into ( ) )
53
89
}
54
90
}
55
91
@@ -190,43 +226,30 @@ impl<'r> CmakeProbe<'r> {
190
226
} else {
191
227
framework. to_string ( )
192
228
} ;
193
- let framework_path = Path :: new ( & framework) ;
194
- let has_extension = framework_path
195
- . extension ( )
196
- . and_then ( OsStr :: to_str)
197
- . map_or ( false , |ext| ext. eq_ignore_ascii_case ( "framework" ) ) ;
198
- let name = if has_extension {
199
- framework
200
- } else {
201
- format ! ( "{}.framework" , framework)
202
- } ;
203
- link_libs. push ( LinkLib ( Linkage :: Framework , name) ) ;
229
+ link_libs. push ( LinkLib ( Linkage :: Framework , framework) ) ;
204
230
} else if !arg. starts_with ( '-' ) {
205
231
let path = Path :: new ( arg) ;
206
- let linkage = if Self :: is_library_static ( path) {
232
+ let linkage = if Self :: is_library_static_archive ( path) {
207
233
Linkage :: Static
208
234
} else {
209
- Linkage :: Default
210
- } ;
211
- if let Some ( file) = path. file_name ( ) . and_then ( super :: cleanup_lib_filename) {
212
235
if let Some ( parent) = path. parent ( ) . map ( |p| p. to_owned ( ) ) {
213
- let search_path = LinkSearch ( linkage , parent) ;
236
+ let search_path = LinkSearch ( Linkage :: Default , parent) ;
214
237
if !link_paths. contains ( & search_path) {
215
238
link_paths. push ( search_path) ;
216
239
}
217
240
} else {
218
241
panic ! ( "{}" , arg. to_string( ) ) ;
219
242
}
220
- let file = file . to_str ( ) . expect ( "Non-UTF8 filename" ) ;
221
- link_libs . push ( LinkLib ( linkage , file . to_string ( ) ) ) ;
222
- }
243
+ Linkage :: Default
244
+ } ;
245
+ link_libs . push ( LinkLib ( linkage , path . to_str ( ) . expect ( "Non-UTF8 filename" ) . to_string ( ) ) ) ;
223
246
} else {
224
247
eprintln ! ( "=== Unexpected cmake compiler argument found: {arg}" ) ;
225
248
}
226
249
}
227
250
}
228
251
229
- fn is_library_static ( path : & Path ) -> bool {
252
+ fn is_library_static_archive ( path : & Path ) -> bool {
230
253
path. extension ( ) . map_or ( false , |ext| ext. eq_ignore_ascii_case ( "a" ) )
231
254
}
232
255
0 commit comments