1
1
use std:: borrow:: Cow ;
2
- use std:: env;
3
2
use std:: num:: ParseIntError ;
3
+ use std:: str:: FromStr ;
4
+ use std:: { env, fmt} ;
5
+
6
+ use serde:: de;
4
7
5
8
use crate :: spec:: {
6
9
Cc , DebuginfoKind , FramePointer , LinkerFlavor , Lld , SplitDebuginfo , StackProbeType , StaticCow ,
@@ -201,14 +204,15 @@ pub fn os_minimum_deployment_target(os: &str) -> OSVersion {
201
204
// ```
202
205
// $ rustc --print deployment-target
203
206
// ```
204
- match os {
207
+ let ( major , minor , patch ) = match os {
205
208
"macos" => ( 10 , 12 , 0 ) ,
206
209
"ios" => ( 10 , 0 , 0 ) ,
207
210
"tvos" => ( 10 , 0 , 0 ) ,
208
211
"watchos" => ( 5 , 0 , 0 ) ,
209
212
"visionos" => ( 1 , 0 , 0 ) ,
210
213
_ => unreachable ! ( "tried to get deployment target for non-Apple platform" ) ,
211
- }
214
+ } ;
215
+ OSVersion { major, minor, patch }
212
216
}
213
217
214
218
/// The deployment target for the given target.
@@ -219,7 +223,7 @@ pub fn os_minimum_deployment_target(os: &str) -> OSVersion {
219
223
/// This matches what LLVM does, see in part:
220
224
/// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932>
221
225
pub fn minimum_deployment_target ( target : & Target ) -> OSVersion {
222
- match ( & * target. os , & * target. arch , & * target. abi ) {
226
+ let ( major , minor , patch ) = match ( & * target. os , & * target. arch , & * target. abi ) {
223
227
( "macos" , "aarch64" , _) => ( 11 , 0 , 0 ) ,
224
228
( "ios" , "aarch64" , "macabi" ) => ( 14 , 0 , 0 ) ,
225
229
( "ios" , "aarch64" , "sim" ) => ( 14 , 0 , 0 ) ,
@@ -228,8 +232,9 @@ pub fn minimum_deployment_target(target: &Target) -> OSVersion {
228
232
( "ios" , _, "macabi" ) => ( 13 , 1 , 0 ) ,
229
233
( "tvos" , "aarch64" , "sim" ) => ( 14 , 0 , 0 ) ,
230
234
( "watchos" , "aarch64" , "sim" ) => ( 7 , 0 , 0 ) ,
231
- ( os, _, _) => os_minimum_deployment_target ( os) ,
232
- }
235
+ ( os, _, _) => return os_minimum_deployment_target ( os) ,
236
+ } ;
237
+ OSVersion { major, minor, patch }
233
238
}
234
239
235
240
/// Name of the environment variable used to fetch the deployment target on the given OS.
@@ -307,18 +312,68 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
307
312
/// Deployment target or SDK version.
308
313
///
309
314
/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`.
310
- pub type OSVersion = ( u16 , u8 , u8 ) ;
311
-
312
- /// Parse an OS version triple (SDK version or deployment target).
313
- pub fn parse_version ( version : & str ) -> Result < OSVersion , ParseIntError > {
314
- if let Some ( ( major, minor) ) = version. split_once ( '.' ) {
315
- let major = major. parse ( ) ?;
316
- if let Some ( ( minor, patch) ) = minor. split_once ( '.' ) {
317
- Ok ( ( major, minor. parse ( ) ?, patch. parse ( ) ?) )
315
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
316
+ pub struct OSVersion {
317
+ pub major : u16 ,
318
+ pub minor : u8 ,
319
+ pub patch : u8 ,
320
+ }
321
+
322
+ impl OSVersion {
323
+ pub const MIN : Self = Self { major : u16:: MIN , minor : u8:: MIN , patch : u8:: MIN } ;
324
+
325
+ pub const MAX : Self = Self { major : u16:: MAX , minor : u8:: MAX , patch : u8:: MAX } ;
326
+
327
+ pub fn pretty ( self ) -> impl fmt:: Display {
328
+ let OSVersion { major, minor, patch } = self ;
329
+ fmt:: from_fn ( move |f| {
330
+ write ! ( f, "{major}.{minor}" ) ?;
331
+ if patch != 0 {
332
+ write ! ( f, ".{patch}" ) ?;
333
+ }
334
+ Ok ( ( ) )
335
+ } )
336
+ }
337
+ }
338
+
339
+ impl < ' de > de:: Deserialize < ' de > for OSVersion {
340
+ fn deserialize < D : de:: Deserializer < ' de > > ( deserializer : D ) -> Result < OSVersion , D :: Error > {
341
+ struct OSVersionVisitor ;
342
+
343
+ impl < ' de > de:: Visitor < ' de > for OSVersionVisitor {
344
+ type Value = OSVersion ;
345
+
346
+ fn expecting ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
347
+ f. write_str ( "a valid `major.minor.patch` version" )
348
+ }
349
+
350
+ fn visit_str < E : de:: Error > ( self , value : & str ) -> Result < Self :: Value , E > {
351
+ OSVersion :: from_str ( value) . map_err ( E :: custom)
352
+ }
353
+ }
354
+
355
+ deserializer. deserialize_str ( OSVersionVisitor )
356
+ }
357
+ }
358
+
359
+ impl FromStr for OSVersion {
360
+ type Err = ParseIntError ;
361
+
362
+ /// Parse an OS version triple (SDK version or deployment target).
363
+ fn from_str ( version : & str ) -> Result < Self , Self :: Err > {
364
+ if let Some ( ( major, minor) ) = version. split_once ( '.' ) {
365
+ let major = major. parse ( ) ?;
366
+ if let Some ( ( minor, patch) ) = minor. split_once ( '.' ) {
367
+ let minor = minor. parse ( ) ?;
368
+ let patch = patch. parse ( ) ?;
369
+ Ok ( Self { major, minor, patch } )
370
+ } else {
371
+ let minor = minor. parse ( ) ?;
372
+ Ok ( Self { major, minor, patch : 0 } )
373
+ }
318
374
} else {
319
- Ok ( ( major, minor. parse ( ) ?, 0 ) )
375
+ let major = version. parse ( ) ?;
376
+ Ok ( Self { major, minor : 0 , patch : 0 } )
320
377
}
321
- } else {
322
- Ok ( ( version. parse ( ) ?, 0 , 0 ) )
323
378
}
324
379
}
0 commit comments