11use std:: env;
2- use std:: fmt:: { Display , from_fn} ;
3- use std:: num:: ParseIntError ;
2+ use std:: str:: FromStr ;
43
54use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
65use rustc_session:: Session ;
76use rustc_target:: spec:: Target ;
7+ pub ( super ) use rustc_target:: spec:: apple:: OSVersion ;
88
99use crate :: errors:: AppleDeploymentTarget ;
1010
@@ -110,76 +110,6 @@ pub(super) fn add_data_and_relocation(
110110 Ok ( ( ) )
111111}
112112
113- /// Deployment target or SDK version.
114- ///
115- /// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`.
116- type OSVersion = ( u16 , u8 , u8 ) ;
117-
118- /// Parse an OS version triple (SDK version or deployment target).
119- fn parse_version ( version : & str ) -> Result < OSVersion , ParseIntError > {
120- if let Some ( ( major, minor) ) = version. split_once ( '.' ) {
121- let major = major. parse ( ) ?;
122- if let Some ( ( minor, patch) ) = minor. split_once ( '.' ) {
123- Ok ( ( major, minor. parse ( ) ?, patch. parse ( ) ?) )
124- } else {
125- Ok ( ( major, minor. parse ( ) ?, 0 ) )
126- }
127- } else {
128- Ok ( ( version. parse ( ) ?, 0 , 0 ) )
129- }
130- }
131-
132- pub fn pretty_version ( version : OSVersion ) -> impl Display {
133- let ( major, minor, patch) = version;
134- from_fn ( move |f| {
135- write ! ( f, "{major}.{minor}" ) ?;
136- if patch != 0 {
137- write ! ( f, ".{patch}" ) ?;
138- }
139- Ok ( ( ) )
140- } )
141- }
142-
143- /// Minimum operating system versions currently supported by `rustc`.
144- fn os_minimum_deployment_target ( os : & str ) -> OSVersion {
145- // When bumping a version in here, remember to update the platform-support docs too.
146- //
147- // NOTE: The defaults may change in future `rustc` versions, so if you are looking for the
148- // default deployment target, prefer:
149- // ```
150- // $ rustc --print deployment-target
151- // ```
152- match os {
153- "macos" => ( 10 , 12 , 0 ) ,
154- "ios" => ( 10 , 0 , 0 ) ,
155- "tvos" => ( 10 , 0 , 0 ) ,
156- "watchos" => ( 5 , 0 , 0 ) ,
157- "visionos" => ( 1 , 0 , 0 ) ,
158- _ => unreachable ! ( "tried to get deployment target for non-Apple platform" ) ,
159- }
160- }
161-
162- /// The deployment target for the given target.
163- ///
164- /// This is similar to `os_minimum_deployment_target`, except that on certain targets it makes sense
165- /// to raise the minimum OS version.
166- ///
167- /// This matches what LLVM does, see in part:
168- /// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932>
169- fn minimum_deployment_target ( target : & Target ) -> OSVersion {
170- match ( & * target. os , & * target. arch , & * target. abi ) {
171- ( "macos" , "aarch64" , _) => ( 11 , 0 , 0 ) ,
172- ( "ios" , "aarch64" , "macabi" ) => ( 14 , 0 , 0 ) ,
173- ( "ios" , "aarch64" , "sim" ) => ( 14 , 0 , 0 ) ,
174- ( "ios" , _, _) if target. llvm_target . starts_with ( "arm64e" ) => ( 14 , 0 , 0 ) ,
175- // Mac Catalyst defaults to 13.1 in Clang.
176- ( "ios" , _, "macabi" ) => ( 13 , 1 , 0 ) ,
177- ( "tvos" , "aarch64" , "sim" ) => ( 14 , 0 , 0 ) ,
178- ( "watchos" , "aarch64" , "sim" ) => ( 7 , 0 , 0 ) ,
179- ( os, _, _) => os_minimum_deployment_target ( os) ,
180- }
181- }
182-
183113/// Name of the environment variable used to fetch the deployment target on the given OS.
184114pub fn deployment_target_env_var ( os : & str ) -> & ' static str {
185115 match os {
@@ -195,22 +125,22 @@ pub fn deployment_target_env_var(os: &str) -> &'static str {
195125/// Get the deployment target based on the standard environment variables, or fall back to the
196126/// minimum version supported by `rustc`.
197127pub fn deployment_target ( sess : & Session ) -> OSVersion {
198- let min = minimum_deployment_target ( & sess. target ) ;
128+ let min = OSVersion :: minimum_deployment_target ( & sess. target ) ;
199129 let env_var = deployment_target_env_var ( & sess. target . os ) ;
200130
201131 if let Ok ( deployment_target) = env:: var ( env_var) {
202- match parse_version ( & deployment_target) {
132+ match OSVersion :: from_str ( & deployment_target) {
203133 Ok ( version) => {
204- let os_min = os_minimum_deployment_target ( & sess. target . os ) ;
134+ let os_min = OSVersion :: os_minimum_deployment_target ( & sess. target . os ) ;
205135 // It is common that the deployment target is set a bit too low, for example on
206136 // macOS Aarch64 to also target older x86_64. So we only want to warn when variable
207137 // is lower than the minimum OS supported by rustc, not when the variable is lower
208138 // than the minimum for a specific target.
209139 if version < os_min {
210140 sess. dcx ( ) . emit_warn ( AppleDeploymentTarget :: TooLow {
211141 env_var,
212- version : pretty_version ( version) . to_string ( ) ,
213- os_min : pretty_version ( os_min) . to_string ( ) ,
142+ version : version. fmt_pretty ( ) . to_string ( ) ,
143+ os_min : os_min. fmt_pretty ( ) . to_string ( ) ,
214144 } ) ;
215145 }
216146
@@ -239,17 +169,16 @@ pub(super) fn add_version_to_llvm_target(
239169 let environment = components. next ( ) ;
240170 assert_eq ! ( components. next( ) , None , "too many LLVM triple components" ) ;
241171
242- let ( major, minor, patch) = deployment_target;
243-
244172 assert ! (
245173 !os. contains( |c: char | c. is_ascii_digit( ) ) ,
246174 "LLVM target must not already be versioned"
247175 ) ;
248176
177+ let version = deployment_target. fmt_full ( ) ;
249178 if let Some ( env) = environment {
250179 // Insert version into OS, before environment
251- format ! ( "{arch}-{vendor}-{os}{major}.{minor}.{patch }-{env}" )
180+ format ! ( "{arch}-{vendor}-{os}{version }-{env}" )
252181 } else {
253- format ! ( "{arch}-{vendor}-{os}{major}.{minor}.{patch }" )
182+ format ! ( "{arch}-{vendor}-{os}{version }" )
254183 }
255184}
0 commit comments