diff options
| author | Mads Marquart <mads@marquart.dk> | 2025-02-11 10:43:25 +0100 |
|---|---|---|
| committer | Mads Marquart <mads@marquart.dk> | 2025-04-04 15:01:27 +0200 |
| commit | d74ce25b65e60cd5ccade3c6fd4234dbd201bda8 (patch) | |
| tree | e3b3d6cb241c5d4598cd2cf77133f322b755d713 | |
| parent | a4166dabaae56ab0d35a7825c3e7008778eacf34 (diff) | |
| download | rust-d74ce25b65e60cd5ccade3c6fd4234dbd201bda8.tar.gz rust-d74ce25b65e60cd5ccade3c6fd4234dbd201bda8.zip | |
refactor: Move Apple OSVersion (back) to rustc_target
Also convert OSVersion into a proper struct for better type-safety.
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/apple.rs | 91 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/apple/tests.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/metadata.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_driver_impl/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_target/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/base/apple/mod.rs | 97 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/base/apple/tests.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/base/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/mod.rs | 1 |
11 files changed, 125 insertions, 100 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 2c8b0ec418d..8954ec0fcdd 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -1,7 +1,6 @@ use std::env; use std::ffi::OsString; -use std::fmt::{Display, from_fn}; -use std::num::ParseIntError; +use std::str::FromStr; use std::path::PathBuf; use std::process::Command; @@ -9,6 +8,7 @@ use itertools::Itertools; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::Session; use rustc_target::spec::Target; +pub(super) use rustc_target::spec::apple::OSVersion; use tracing::debug; use crate::errors::{AppleDeploymentTarget, XcrunError, XcrunSdkPathWarning}; @@ -134,76 +134,6 @@ pub(super) fn add_data_and_relocation( Ok(()) } -/// Deployment target or SDK version. -/// -/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. -type OSVersion = (u16, u8, u8); - -/// Parse an OS version triple (SDK version or deployment target). -fn parse_version(version: &str) -> Result<OSVersion, ParseIntError> { - if let Some((major, minor)) = version.split_once('.') { - let major = major.parse()?; - if let Some((minor, patch)) = minor.split_once('.') { - Ok((major, minor.parse()?, patch.parse()?)) - } else { - Ok((major, minor.parse()?, 0)) - } - } else { - Ok((version.parse()?, 0, 0)) - } -} - -pub fn pretty_version(version: OSVersion) -> impl Display { - let (major, minor, patch) = version; - from_fn(move |f| { - write!(f, "{major}.{minor}")?; - if patch != 0 { - write!(f, ".{patch}")?; - } - Ok(()) - }) -} - -/// Minimum operating system versions currently supported by `rustc`. -fn os_minimum_deployment_target(os: &str) -> OSVersion { - // When bumping a version in here, remember to update the platform-support docs too. - // - // NOTE: The defaults may change in future `rustc` versions, so if you are looking for the - // default deployment target, prefer: - // ``` - // $ rustc --print deployment-target - // ``` - match os { - "macos" => (10, 12, 0), - "ios" => (10, 0, 0), - "tvos" => (10, 0, 0), - "watchos" => (5, 0, 0), - "visionos" => (1, 0, 0), - _ => unreachable!("tried to get deployment target for non-Apple platform"), - } -} - -/// The deployment target for the given target. -/// -/// This is similar to `os_minimum_deployment_target`, except that on certain targets it makes sense -/// to raise the minimum OS version. -/// -/// This matches what LLVM does, see in part: -/// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932> -fn minimum_deployment_target(target: &Target) -> OSVersion { - match (&*target.os, &*target.arch, &*target.abi) { - ("macos", "aarch64", _) => (11, 0, 0), - ("ios", "aarch64", "macabi") => (14, 0, 0), - ("ios", "aarch64", "sim") => (14, 0, 0), - ("ios", _, _) if target.llvm_target.starts_with("arm64e") => (14, 0, 0), - // Mac Catalyst defaults to 13.1 in Clang. - ("ios", _, "macabi") => (13, 1, 0), - ("tvos", "aarch64", "sim") => (14, 0, 0), - ("watchos", "aarch64", "sim") => (7, 0, 0), - (os, _, _) => os_minimum_deployment_target(os), - } -} - /// Name of the environment variable used to fetch the deployment target on the given OS. pub fn deployment_target_env_var(os: &str) -> &'static str { match os { @@ -219,13 +149,13 @@ pub fn deployment_target_env_var(os: &str) -> &'static str { /// 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) -> OSVersion { - let min = minimum_deployment_target(&sess.target); + let min = OSVersion::minimum_deployment_target(&sess.target); let env_var = deployment_target_env_var(&sess.target.os); if let Ok(deployment_target) = env::var(env_var) { - match parse_version(&deployment_target) { + match OSVersion::from_str(&deployment_target) { Ok(version) => { - let os_min = os_minimum_deployment_target(&sess.target.os); + let os_min = OSVersion::os_minimum_deployment_target(&sess.target.os); // 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 @@ -233,8 +163,8 @@ pub fn deployment_target(sess: &Session) -> OSVersion { 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(), + version: version.fmt_pretty().to_string(), + os_min: os_min.fmt_pretty().to_string(), }); } @@ -263,18 +193,17 @@ pub(super) fn add_version_to_llvm_target( let environment = components.next(); assert_eq!(components.next(), None, "too many LLVM triple components"); - let (major, minor, patch) = deployment_target; - assert!( !os.contains(|c: char| c.is_ascii_digit()), "LLVM target must not already be versioned" ); + let version = deployment_target.fmt_full(); if let Some(env) = environment { // Insert version into OS, before environment - format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}-{env}") + format!("{arch}-{vendor}-{os}{version}-{env}") } else { - format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}") + format!("{arch}-{vendor}-{os}{version}") } } diff --git a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs index 8df740a4bcf..5afe79b7195 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs @@ -3,24 +3,16 @@ use super::*; #[test] fn test_add_version_to_llvm_target() { assert_eq!( - add_version_to_llvm_target("aarch64-apple-macosx", (10, 14, 1)), + add_version_to_llvm_target("aarch64-apple-macosx", OSVersion::new(10, 14, 1)), "aarch64-apple-macosx10.14.1" ); assert_eq!( - add_version_to_llvm_target("aarch64-apple-ios-simulator", (16, 1, 0)), + add_version_to_llvm_target("aarch64-apple-ios-simulator", OSVersion::new(16, 1, 0)), "aarch64-apple-ios16.1.0-simulator" ); } #[test] -fn test_parse_version() { - assert_eq!(parse_version("10"), Ok((10, 0, 0))); - assert_eq!(parse_version("10.12"), Ok((10, 12, 0))); - assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6))); - assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99))); -} - -#[test] #[cfg_attr(not(target_os = "macos"), ignore = "xcode-select is only available on macOS")] fn lookup_developer_dir() { let _developer_dir = xcode_select_developer_dir().unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1c885a2fd5f..8ea8c5b01f4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3115,8 +3115,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo _ => bug!("invalid OS/ABI combination for Apple target: {target_os}, {target_abi}"), }; - let (major, minor, patch) = apple::deployment_target(sess); - let min_version = format!("{major}.{minor}.{patch}"); + let min_version = apple::deployment_target(sess).fmt_full().to_string(); // The SDK version is used at runtime when compiling with a newer SDK / version of Xcode: // - By dyld to give extra warnings and errors, see e.g.: @@ -3185,10 +3184,10 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // The presence of `-mmacosx-version-min` makes CC default to // macOS, and it sets the deployment target. - let (major, minor, patch) = apple::deployment_target(sess); + let version = apple::deployment_target(sess).fmt_full(); // Intentionally pass this as a single argument, Clang doesn't // seem to like it otherwise. - cmd.cc_arg(&format!("-mmacosx-version-min={major}.{minor}.{patch}")); + cmd.cc_arg(&format!("-mmacosx-version-min={version}")); // macOS has no environment, so with these two, we've told CC the // four desired parameters. diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index e2c009712d1..aac2f2da029 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -388,7 +388,7 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { fn macho_object_build_version_for_target(sess: &Session) -> object::write::MachOBuildVersion { /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz" /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200 - fn pack_version((major, minor, patch): (u16, u8, u8)) -> u32 { + fn pack_version(apple::OSVersion { major, minor, patch }: apple::OSVersion) -> u32 { let (major, minor, patch) = (major as u32, minor as u32, patch as u32); (major << 16) | (minor << 8) | patch } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index f36e42cc6b9..67217927a87 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -7,7 +7,6 @@ #![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 21b9542d0e1..12f85c23a14 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -811,7 +811,7 @@ fn print_crate_info( println_info!( "{}={}", apple::deployment_target_env_var(&sess.target.os), - apple::pretty_version(apple::deployment_target(sess)), + apple::deployment_target(sess).fmt_pretty(), ) } else { #[allow(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index a8d7da5692d..df99280f571 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -12,6 +12,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(debug_closure_helpers)] #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index fd0e47b55aa..dce1b9dab66 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,9 +1,12 @@ use std::borrow::Cow; use std::env; +use std::fmt::{Display, from_fn}; +use std::num::ParseIntError; +use std::str::FromStr; use crate::spec::{ BinaryFormat, Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, RustcAbi, - SplitDebuginfo, StackProbeType, StaticCow, TargetOptions, cvs, + SplitDebuginfo, StackProbeType, StaticCow, Target, TargetOptions, cvs, }; #[cfg(test)] @@ -222,3 +225,95 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> { cvs!["MACOSX_DEPLOYMENT_TARGET"] } } + +/// Deployment target or SDK version. +/// +/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct OSVersion { + pub major: u16, + pub minor: u8, + pub patch: u8, +} + +impl FromStr for OSVersion { + type Err = ParseIntError; + + /// Parse an OS version triple (SDK version or deployment target). + fn from_str(version: &str) -> Result<Self, ParseIntError> { + if let Some((major, minor)) = version.split_once('.') { + let major = major.parse()?; + if let Some((minor, patch)) = minor.split_once('.') { + Ok(Self { major, minor: minor.parse()?, patch: patch.parse()? }) + } else { + Ok(Self { major, minor: minor.parse()?, patch: 0 }) + } + } else { + Ok(Self { major: version.parse()?, minor: 0, patch: 0 }) + } + } +} + +impl OSVersion { + pub fn new(major: u16, minor: u8, patch: u8) -> Self { + Self { major, minor, patch } + } + + pub fn fmt_pretty(self) -> impl Display { + let Self { major, minor, patch } = self; + from_fn(move |f| { + write!(f, "{major}.{minor}")?; + if patch != 0 { + write!(f, ".{patch}")?; + } + Ok(()) + }) + } + + pub fn fmt_full(self) -> impl Display { + let Self { major, minor, patch } = self; + from_fn(move |f| write!(f, "{major}.{minor}.{patch}")) + } + + /// Minimum operating system versions currently supported by `rustc`. + pub fn os_minimum_deployment_target(os: &str) -> Self { + // When bumping a version in here, remember to update the platform-support docs too. + // + // NOTE: The defaults may change in future `rustc` versions, so if you are looking for the + // default deployment target, prefer: + // ``` + // $ rustc --print deployment-target + // ``` + let (major, minor, patch) = match os { + "macos" => (10, 12, 0), + "ios" => (10, 0, 0), + "tvos" => (10, 0, 0), + "watchos" => (5, 0, 0), + "visionos" => (1, 0, 0), + _ => unreachable!("tried to get deployment target for non-Apple platform"), + }; + Self { major, minor, patch } + } + + /// The deployment target for the given target. + /// + /// This is similar to `os_minimum_deployment_target`, except that on certain targets it makes sense + /// to raise the minimum OS version. + /// + /// This matches what LLVM does, see in part: + /// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932> + pub fn minimum_deployment_target(target: &Target) -> Self { + let (major, minor, patch) = match (&*target.os, &*target.arch, &*target.abi) { + ("macos", "aarch64", _) => (11, 0, 0), + ("ios", "aarch64", "macabi") => (14, 0, 0), + ("ios", "aarch64", "sim") => (14, 0, 0), + ("ios", _, _) if target.llvm_target.starts_with("arm64e") => (14, 0, 0), + // Mac Catalyst defaults to 13.1 in Clang. + ("ios", _, "macabi") => (13, 1, 0), + ("tvos", "aarch64", "sim") => (14, 0, 0), + ("watchos", "aarch64", "sim") => (7, 0, 0), + (os, _, _) => return Self::os_minimum_deployment_target(os), + }; + Self { major, minor, patch } + } +} diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs index 7a985ad4dc0..391f3470104 100644 --- a/compiler/rustc_target/src/spec/base/apple/tests.rs +++ b/compiler/rustc_target/src/spec/base/apple/tests.rs @@ -1,3 +1,4 @@ +use super::OSVersion; use crate::spec::targets::{ aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_visionos_sim, aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios, @@ -42,3 +43,11 @@ fn macos_link_environment_unmodified() { ); } } + +#[test] +fn test_parse_version() { + assert_eq!("10".parse(), Ok(OSVersion::new(10, 0, 0))); + assert_eq!("10.12".parse(), Ok(OSVersion::new(10, 12, 0))); + assert_eq!("10.12.6".parse(), Ok(OSVersion::new(10, 12, 6))); + assert_eq!("9999.99.99".parse(), Ok(OSVersion::new(9999, 99, 99))); +} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index e8fdc871785..71b6528c2dd 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -1,6 +1,6 @@ pub(crate) mod aix; pub(crate) mod android; -pub(crate) mod apple; +pub mod apple; pub(crate) mod avr; pub(crate) mod bpf; pub(crate) mod cygwin; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 981dded2601..486bf9012ff 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -60,6 +60,7 @@ pub mod crt_objects; mod base; mod json; +pub use base::apple; pub use base::avr::ef_avr_arch; /// Linker is called through a C/C++ compiler. |
