diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 9091602d75b71..7c6ace84ee1ae 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -2,6 +2,12 @@ codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not imp codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} +codegen_ssa_apple_deployment_target_invalid = + failed to parse deployment target specified in {$env_var}: {$error} + +codegen_ssa_apple_deployment_target_too_low = + deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} + codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs index 23acfde5fd4f5..21ef509553182 100644 --- a/compiler/rustc_codegen_ssa/src/apple.rs +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -1,30 +1,58 @@ use std::borrow::Cow; use std::env; +use std::fmt::{Display, from_fn}; use rustc_session::Session; use rustc_target::spec::{ AppleOSVersion, apple_deployment_target_env_var, apple_minimum_deployment_target, - apple_parse_version, + apple_os_minimum_deployment_target, apple_parse_version, }; +use crate::errors::AppleDeploymentTarget; + #[cfg(test)] mod tests; +pub fn pretty_version(version: AppleOSVersion) -> impl Display { + let (major, minor, patch) = version; + from_fn(move |f| { + write!(f, "{major}.{minor}")?; + if patch != 0 { + write!(f, ".{patch}")?; + } + Ok(()) + }) +} + /// Get the deployment target based on the standard environment variables, or fall back to the /// minimum version supported by `rustc`. pub fn deployment_target(sess: &Session) -> AppleOSVersion { + let os_min = apple_os_minimum_deployment_target(&sess.target.os); let min = apple_minimum_deployment_target(&sess.target); + let env_var = apple_deployment_target_env_var(&sess.target.os); - if let Ok(deployment_target) = env::var(apple_deployment_target_env_var(&sess.target.os)) { + if let Ok(deployment_target) = env::var(env_var) { match apple_parse_version(&deployment_target) { - // It is common that the deployment target is set too low, e.g. on macOS Aarch64 to also - // target older x86_64, the user may set a lower deployment target than supported. - // - // To avoid such issues, we silently raise the deployment target here. - // FIXME: We want to show a warning when `version < os_min`. - Ok(version) => version.max(min), - // FIXME: Report erroneous environment variable to user. - Err(_) => min, + Ok(version) => { + // It is common that the deployment target is set a bit too low, for example on + // macOS Aarch64 to also target older x86_64. So we only want to warn when variable + // is lower than the minimum OS supported by rustc, not when the variable is lower + // than the minimum for a specific target. + if version < os_min { + sess.dcx().emit_warn(AppleDeploymentTarget::TooLow { + env_var, + version: pretty_version(version).to_string(), + os_min: pretty_version(os_min).to_string(), + }); + } + + // Raise the deployment target to the minimum supported. + version.max(min) + } + Err(error) => { + sess.dcx().emit_err(AppleDeploymentTarget::Invalid { env_var, error }); + min + } } } else { // If no deployment target variable is set, default to the minimum found above. diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 08b326e3ac3c6..5dadfdc66a2bc 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::io::Error; +use std::num::ParseIntError; use std::path::{Path, PathBuf}; use std::process::ExitStatus; @@ -539,6 +540,14 @@ pub(crate) struct UnsupportedArch<'a> { pub os: &'a str, } +#[derive(Diagnostic)] +pub(crate) enum AppleDeploymentTarget { + #[diag(codegen_ssa_apple_deployment_target_invalid)] + Invalid { env_var: &'static str, error: ParseIntError }, + #[diag(codegen_ssa_apple_deployment_target_too_low)] + TooLow { env_var: &'static str, version: String, os_min: String }, +} + #[derive(Diagnostic)] pub(crate) enum AppleSdkRootError<'a> { #[diag(codegen_ssa_apple_sdk_error_sdk_path)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index cae753ae50cee..a79424e28c6e1 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2ebcb245ed112..d743148f316df 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -856,10 +856,10 @@ fn print_crate_info( } } DeploymentTarget => { + use rustc_codegen_ssa::apple::{deployment_target, pretty_version}; + if sess.target.is_like_osx { - let (major, minor, patch) = rustc_codegen_ssa::apple::deployment_target(sess); - let patch = if patch != 0 { format!(".{patch}") } else { String::new() }; - println_info!("deployment_target={major}.{minor}{patch}") + println_info!("deployment_target={}", pretty_version(deployment_target(sess))) } else { #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("only Apple targets currently support deployment version info")