Auto merge of #138947 - madsmtm:refactor-apple-versions, r=Noratrieb
Refactor Apple version handling in the compiler Move various Apple version handling code in the compiler out `rustc_codegen_ssa` and into a place where it can be accessed by `rustc_attr_parsing`, which I found to be necessary when doing https://github.com/rust-lang/rust/pull/136867. Thought I'd split it out to make it easier to land, and to make further changes like https://github.com/rust-lang/rust/pull/131477 have fewer conflicts / PR dependencies. There should be no functional changes in this PR. `@rustbot` label O-apple r? rust-lang/compiler
This commit is contained in:
commit
f5c510260b
17 changed files with 190 additions and 166 deletions
|
@ -4,12 +4,6 @@ codegen_ssa_add_native_library = failed to add native library {$library_path}: {
|
|||
|
||||
codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to AIX which is not guaranteed to work
|
||||
|
||||
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_archive_build_failure = failed to build archive at `{$path}`: {$error}
|
||||
|
||||
codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fmt::{Display, from_fn};
|
||||
use std::num::ParseIntError;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
|
@ -9,9 +6,10 @@ 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};
|
||||
use crate::errors::{XcrunError, XcrunSdkPathWarning};
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -134,124 +132,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 {
|
||||
"macos" => "MACOSX_DEPLOYMENT_TARGET",
|
||||
"ios" => "IPHONEOS_DEPLOYMENT_TARGET",
|
||||
"watchos" => "WATCHOS_DEPLOYMENT_TARGET",
|
||||
"tvos" => "TVOS_DEPLOYMENT_TARGET",
|
||||
"visionos" => "XROS_DEPLOYMENT_TARGET",
|
||||
_ => unreachable!("tried to get deployment target env var for non-Apple platform"),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 env_var = deployment_target_env_var(&sess.target.os);
|
||||
|
||||
if let Ok(deployment_target) = env::var(env_var) {
|
||||
match parse_version(&deployment_target) {
|
||||
Ok(version) => {
|
||||
let os_min = 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
|
||||
// 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.
|
||||
min
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn add_version_to_llvm_target(
|
||||
llvm_target: &str,
|
||||
deployment_target: OSVersion,
|
||||
|
@ -263,18 +143,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}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,23 +3,15 @@ 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() {
|
||||
|
|
|
@ -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 = sess.apple_deployment_target().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 = sess.apple_deployment_target().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.
|
||||
|
|
|
@ -388,13 +388,13 @@ 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
|
||||
}
|
||||
|
||||
let platform = apple::macho_platform(&sess.target);
|
||||
let min_os = apple::deployment_target(sess);
|
||||
let min_os = sess.apple_deployment_target();
|
||||
|
||||
let mut build_version = object::write::MachOBuildVersion::default();
|
||||
build_version.platform = platform;
|
||||
|
|
|
@ -20,7 +20,7 @@ pub mod write;
|
|||
/// Certain optimizations also depend on the deployment target.
|
||||
pub fn versioned_llvm_target(sess: &Session) -> Cow<'_, str> {
|
||||
if sess.target.is_like_darwin {
|
||||
apple::add_version_to_llvm_target(&sess.target.llvm_target, apple::deployment_target(sess))
|
||||
apple::add_version_to_llvm_target(&sess.target.llvm_target, sess.apple_deployment_target())
|
||||
.into()
|
||||
} else {
|
||||
// FIXME(madsmtm): Certain other targets also include a version,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
use std::borrow::Cow;
|
||||
use std::ffi::OsString;
|
||||
use std::io::Error;
|
||||
use std::num::ParseIntError;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitStatus;
|
||||
|
||||
|
@ -738,14 +737,6 @@ pub enum ExtractBundledLibsError<'a> {
|
|||
ExtractSection { rlib: &'a Path, error: Box<dyn std::error::Error> },
|
||||
}
|
||||
|
||||
#[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)]
|
||||
#[diag(codegen_ssa_read_file)]
|
||||
pub(crate) struct ReadFileError {
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -34,7 +34,6 @@ use std::time::{Instant, SystemTime};
|
|||
use std::{env, str};
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::back::apple;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_codegen_ssa::{CodegenErrors, CodegenResults};
|
||||
use rustc_data_structures::profiling::{
|
||||
|
@ -807,8 +806,8 @@ fn print_crate_info(
|
|||
if sess.target.is_like_darwin {
|
||||
println_info!(
|
||||
"{}={}",
|
||||
apple::deployment_target_env_var(&sess.target.os),
|
||||
apple::pretty_version(apple::deployment_target(sess)),
|
||||
rustc_target::spec::apple::deployment_target_env_var(&sess.target.os),
|
||||
sess.apple_deployment_target().fmt_pretty(),
|
||||
)
|
||||
} else {
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
session_apple_deployment_target_invalid =
|
||||
failed to parse deployment target specified in {$env_var}: {$error}
|
||||
|
||||
session_apple_deployment_target_too_low =
|
||||
deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min}
|
||||
|
||||
session_binary_float_literal_not_supported = binary float literal is not supported
|
||||
session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::num::NonZero;
|
||||
use std::num::{NonZero, ParseIntError};
|
||||
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::util::literal::LitError;
|
||||
|
@ -14,6 +14,14 @@ use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTuple};
|
|||
use crate::config::CrateType;
|
||||
use crate::parse::ParseSess;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub(crate) enum AppleDeploymentTarget {
|
||||
#[diag(session_apple_deployment_target_invalid)]
|
||||
Invalid { env_var: &'static str, error: ParseIntError },
|
||||
#[diag(session_apple_deployment_target_too_low)]
|
||||
TooLow { env_var: &'static str, version: String, os_min: String },
|
||||
}
|
||||
|
||||
pub(crate) struct FeatureGateError {
|
||||
pub(crate) span: MultiSpan,
|
||||
pub(crate) explain: DiagMessage,
|
||||
|
|
|
@ -29,7 +29,7 @@ use rustc_target::asm::InlineAsmArch;
|
|||
use rustc_target::spec::{
|
||||
CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
|
||||
SmallDataThresholdSupport, SplitDebuginfo, StackProtector, SymbolVisibility, Target,
|
||||
TargetTuple, TlsModel,
|
||||
TargetTuple, TlsModel, apple,
|
||||
};
|
||||
|
||||
use crate::code_stats::CodeStats;
|
||||
|
@ -895,6 +895,45 @@ impl Session {
|
|||
FileNameDisplayPreference::Local
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the deployment target on Apple platforms based on the standard environment variables,
|
||||
/// or fall back to the minimum version supported by `rustc`.
|
||||
///
|
||||
/// This should be guarded behind `if sess.target.is_like_darwin`.
|
||||
pub fn apple_deployment_target(&self) -> apple::OSVersion {
|
||||
let min = apple::OSVersion::minimum_deployment_target(&self.target);
|
||||
let env_var = apple::deployment_target_env_var(&self.target.os);
|
||||
|
||||
// FIXME(madsmtm): Track changes to this.
|
||||
if let Ok(deployment_target) = env::var(env_var) {
|
||||
match apple::OSVersion::from_str(&deployment_target) {
|
||||
Ok(version) => {
|
||||
let os_min = apple::OSVersion::os_minimum_deployment_target(&self.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
|
||||
// than the minimum for a specific target.
|
||||
if version < os_min {
|
||||
self.dcx().emit_warn(errors::AppleDeploymentTarget::TooLow {
|
||||
env_var,
|
||||
version: version.fmt_pretty().to_string(),
|
||||
os_min: os_min.fmt_pretty().to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
// Raise the deployment target to the minimum supported.
|
||||
version.max(min)
|
||||
}
|
||||
Err(error) => {
|
||||
self.dcx().emit_err(errors::AppleDeploymentTarget::Invalid { env_var, error });
|
||||
min
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If no deployment target variable is set, default to the minimum found above.
|
||||
min
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JUSTIFICATION: part of session construction
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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,107 @@ 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 }
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
"macos" => "MACOSX_DEPLOYMENT_TARGET",
|
||||
"ios" => "IPHONEOS_DEPLOYMENT_TARGET",
|
||||
"watchos" => "WATCHOS_DEPLOYMENT_TARGET",
|
||||
"tvos" => "TVOS_DEPLOYMENT_TARGET",
|
||||
"visionos" => "XROS_DEPLOYMENT_TARGET",
|
||||
_ => unreachable!("tried to get deployment target env var for non-Apple platform"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue