@@ -17,6 +17,7 @@ use super::errors::AnyError;
17
17
lazy_static ! {
18
18
static ref LDCONFIG_STDC_RE : Regex = Regex :: new( r"libstdc\+\+.* => (.+)" ) . unwrap( ) ;
19
19
static ref LDD_VERSION_RE : BinRegex = BinRegex :: new( r"^ldd.*(.+)\.(.+)\s" ) . unwrap( ) ;
20
+ static ref GENERIC_VERSION_RE : Regex = Regex :: new( r"^([0-9]+)\.([0-9]+)$" ) . unwrap( ) ;
20
21
static ref LIBSTD_CXX_VERSION_RE : BinRegex =
21
22
BinRegex :: new( r"GLIBCXX_([0-9]+)\.([0-9]+)(?:\.([0-9]+))?" ) . unwrap( ) ;
22
23
static ref MIN_CXX_VERSION : SimpleSemver = SimpleSemver :: new( 3 , 4 , 18 ) ;
@@ -116,13 +117,23 @@ async fn check_musl_interpreter() -> Result<(), String> {
116
117
117
118
#[ allow( dead_code) ]
118
119
async fn check_glibc_version ( ) -> Result < ( ) , String > {
119
- let ldd_version = capture_command ( "ldd" , [ "--version" ] )
120
- . await
121
- . ok ( )
122
- . and_then ( |o| extract_ldd_version ( & o. stdout ) ) ;
120
+ #[ cfg( target_env = "gnu" ) ]
121
+ let version = {
122
+ let v = unsafe { libc:: gnu_get_libc_version ( ) } ;
123
+ let v = unsafe { std:: ffi:: CStr :: from_ptr ( v) } ;
124
+ let v = v. to_str ( ) . unwrap ( ) ;
125
+ extract_generic_version ( v)
126
+ } ;
127
+ #[ cfg( not( target_env = "gnu" ) ) ]
128
+ let version = {
129
+ capture_command ( "ldd" , [ "--version" ] )
130
+ . await
131
+ . ok ( )
132
+ . and_then ( |o| extract_ldd_version ( & o. stdout ) )
133
+ } ;
123
134
124
- if let Some ( v) = ldd_version {
125
- return if v. gte ( & MIN_LDD_VERSION ) {
135
+ if let Some ( v) = version {
136
+ return if v >= * MIN_LDD_VERSION {
126
137
Ok ( ( ) )
127
138
} else {
128
139
Err ( format ! (
@@ -181,7 +192,7 @@ fn check_for_sufficient_glibcxx_versions(contents: Vec<u8>) -> Result<(), String
181
192
} )
182
193
. collect ( ) ;
183
194
184
- if !all_versions. iter ( ) . any ( |v| MIN_CXX_VERSION . gte ( v ) ) {
195
+ if !all_versions. iter ( ) . any ( |v| & * MIN_CXX_VERSION >= v ) {
185
196
return Err ( format ! (
186
197
"find GLIBCXX >= 3.4.18 (but found {} instead) for GNU environments" ,
187
198
all_versions
@@ -195,6 +206,7 @@ fn check_for_sufficient_glibcxx_versions(contents: Vec<u8>) -> Result<(), String
195
206
Ok ( ( ) )
196
207
}
197
208
209
+ #[ allow( dead_code) ]
198
210
fn extract_ldd_version ( output : & [ u8 ] ) -> Option < SimpleSemver > {
199
211
LDD_VERSION_RE . captures ( output) . map ( |m| SimpleSemver {
200
212
major : m. get ( 1 ) . map_or ( 0 , |s| u32_from_bytes ( s. as_bytes ( ) ) ) ,
@@ -203,6 +215,15 @@ fn extract_ldd_version(output: &[u8]) -> Option<SimpleSemver> {
203
215
} )
204
216
}
205
217
218
+ #[ allow( dead_code) ]
219
+ fn extract_generic_version ( output : & str ) -> Option < SimpleSemver > {
220
+ GENERIC_VERSION_RE . captures ( output) . map ( |m| SimpleSemver {
221
+ major : m. get ( 1 ) . map_or ( 0 , |s| s. as_str ( ) . parse ( ) . unwrap ( ) ) ,
222
+ minor : m. get ( 2 ) . map_or ( 0 , |s| s. as_str ( ) . parse ( ) . unwrap ( ) ) ,
223
+ patch : 0 ,
224
+ } )
225
+ }
226
+
206
227
fn extract_libstd_from_ldconfig ( output : & [ u8 ] ) -> Option < String > {
207
228
String :: from_utf8_lossy ( output)
208
229
. lines ( )
@@ -215,13 +236,35 @@ fn u32_from_bytes(b: &[u8]) -> u32 {
215
236
String :: from_utf8_lossy ( b) . parse :: < u32 > ( ) . unwrap_or ( 0 )
216
237
}
217
238
218
- #[ derive( Debug , PartialEq ) ]
239
+ #[ derive( Debug , Default , PartialEq , Eq ) ]
219
240
struct SimpleSemver {
220
241
major : u32 ,
221
242
minor : u32 ,
222
243
patch : u32 ,
223
244
}
224
245
246
+ impl PartialOrd for SimpleSemver {
247
+ fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
248
+ Some ( self . cmp ( other) )
249
+ }
250
+ }
251
+
252
+ impl Ord for SimpleSemver {
253
+ fn cmp ( & self , other : & Self ) -> Ordering {
254
+ let major = self . major . cmp ( & other. major ) ;
255
+ if major != Ordering :: Equal {
256
+ return major;
257
+ }
258
+
259
+ let minor = self . minor . cmp ( & other. minor ) ;
260
+ if minor != Ordering :: Equal {
261
+ return minor;
262
+ }
263
+
264
+ self . patch . cmp ( & other. patch )
265
+ }
266
+ }
267
+
225
268
impl From < & SimpleSemver > for String {
226
269
fn from ( s : & SimpleSemver ) -> Self {
227
270
format ! ( "v{}.{}.{}" , s. major, s. minor, s. patch)
@@ -243,18 +286,6 @@ impl SimpleSemver {
243
286
patch,
244
287
}
245
288
}
246
-
247
- fn gte ( & self , other : & SimpleSemver ) -> bool {
248
- match self . major . cmp ( & other. major ) {
249
- Ordering :: Greater => true ,
250
- Ordering :: Less => false ,
251
- Ordering :: Equal => match self . minor . cmp ( & other. minor ) {
252
- Ordering :: Greater => true ,
253
- Ordering :: Less => false ,
254
- Ordering :: Equal => self . patch >= other. patch ,
255
- } ,
256
- }
257
- }
258
289
}
259
290
260
291
#[ cfg( test) ]
@@ -284,13 +315,13 @@ mod tests {
284
315
285
316
#[ test]
286
317
fn test_gte ( ) {
287
- assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) . gte ( & SimpleSemver :: new( 1 , 2 , 3 ) ) ) ;
288
- assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) . gte ( & SimpleSemver :: new( 0 , 10 , 10 ) ) ) ;
289
- assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) . gte ( & SimpleSemver :: new( 1 , 1 , 10 ) ) ) ;
318
+ assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) >= SimpleSemver :: new( 1 , 2 , 3 ) ) ;
319
+ assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) >= SimpleSemver :: new( 0 , 10 , 10 ) ) ;
320
+ assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) >= SimpleSemver :: new( 1 , 1 , 10 ) ) ;
290
321
291
- assert ! ( ! SimpleSemver :: new( 1 , 2 , 3 ) . gte ( & SimpleSemver :: new( 1 , 2 , 10 ) ) ) ;
292
- assert ! ( ! SimpleSemver :: new( 1 , 2 , 3 ) . gte ( & SimpleSemver :: new( 1 , 3 , 1 ) ) ) ;
293
- assert ! ( ! SimpleSemver :: new( 1 , 2 , 3 ) . gte ( & SimpleSemver :: new( 2 , 2 , 1 ) ) ) ;
322
+ assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) < SimpleSemver :: new( 1 , 2 , 10 ) ) ;
323
+ assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) < SimpleSemver :: new( 1 , 3 , 1 ) ) ;
324
+ assert ! ( SimpleSemver :: new( 1 , 2 , 3 ) < SimpleSemver :: new( 2 , 2 , 1 ) ) ;
294
325
}
295
326
296
327
#[ test]
0 commit comments