diff --git a/Cargo.lock b/Cargo.lock index 502920350d5c5..8b3696e0dac9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3478,6 +3478,7 @@ dependencies = [ "rustc_target", "rustc_trait_selection", "rustc_type_ir", + "serde", "serde_json", "smallvec", "tempfile", @@ -4450,6 +4451,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "serde", "serde_json", "tracing", ] diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index f6b7981395a5f..da67116e4e8a1 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -39,6 +39,7 @@ use std::sync::Arc; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::CodegenResults; +use rustc_codegen_ssa::apple::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::ErrorGuaranteed; @@ -259,7 +260,9 @@ impl CodegenBackend for CraneliftCodegenBackend { } fn target_triple(sess: &Session) -> target_lexicon::Triple { - match sess.target.llvm_target.parse() { + // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS. + // See + match versioned_llvm_target(sess).parse() { Ok(triple) => triple, Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)), } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index afdd2b581b86e..9b794c6fbb98f 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -8,6 +8,7 @@ use libc::{c_char, c_int, c_void, size_t}; use llvm::{ LLVMRustLLVMHasZlibCompressionForDebugSymbols, LLVMRustLLVMHasZstdCompressionForDebugSymbols, }; +use rustc_codegen_ssa::apple::versioned_llvm_target; use rustc_codegen_ssa::back::link::ensure_removed; use rustc_codegen_ssa::back::write::{ BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig, @@ -210,7 +211,7 @@ pub(crate) fn target_machine_factory( singlethread = false; } - let triple = SmallCStr::new(&sess.target.llvm_target); + let triple = SmallCStr::new(&versioned_llvm_target(sess)); let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); let features = CString::new(target_features.join(",")).unwrap(); let abi = SmallCStr::new(&sess.target.llvm_abiname); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 81b828404725c..208762b531945 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use std::ffi::{CStr, c_uint}; use std::str; +use rustc_codegen_ssa::apple::versioned_llvm_target; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::*; @@ -165,7 +166,7 @@ pub(crate) unsafe fn create_module<'ll>( llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); } - let llvm_target = SmallCStr::new(&sess.target.llvm_target); + let llvm_target = SmallCStr::new(&versioned_llvm_target(sess)); unsafe { llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 58baf40b5812b..9298835dc8c01 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -37,6 +37,7 @@ rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_type_ir = { path = "../rustc_type_ir" } serde_json = "1.0.59" +serde = { version = "1", features = [ "derive" ]} smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tempfile = "3.2" thin-vec = "0.2.12" diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index f02b0f7267430..b7319ec3cdc2e 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -2,7 +2,116 @@ 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_sdk_error_sdk_path = failed to get {$sdk_name} SDK 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_deployment_target_too_high = + deployment target was set to {$version}, but the maximum supported by the current SDK is {$sdk_max} + + Use the {$env_var} environment variable to set it to something lower. + +codegen_ssa_apple_sdk_error_failed_reading = + failed reading `{$path}` while looking for SDK root: {$error} + +codegen_ssa_apple_sdk_error_invalid_sdk_settings_json = + failed parsing SDK settings from `{$path}`: {$error} + +codegen_ssa_apple_sdk_error_missing = + failed finding SDK for platform `{$sdk_name}`. It looks like you have not installed Xcode? + + You should install Xcode via the App Store, or run `xcode-select --install` if you only intend on developing for macOS. + +codegen_ssa_apple_sdk_error_missing_commandline_tools = + failed finding SDK at `{$sdkroot}` from Command Line Tools installation. + + If cross-compiling for iOS, tvOS, visionOS or watchOS, you will likely need a full installation of Xcode. + +codegen_ssa_apple_sdk_error_missing_cross_compile_non_macos = + failed finding Apple SDK with name `{$sdk_name}`. + + The SDK is needed by the linker to know where to find symbols in system libraries. + + The SDK can be downloaded and extracted from https://developer.apple.com/download/all/?q=xcode (requires an Apple ID). + + You will then need to tell `rustc` about it using the `SDKROOT` environment variables. + + Furthermore, you might need to install a linker capable of linking Mach-O files, or at least ensure that your linker is configured as `lld`. + +codegen_ssa_apple_sdk_error_missing_developer_dir = + failed finding SDK inside active developer path `{$dir}` set by the DEVELOPER_DIR environment variable. Looked in: + - `{$sdkroot}` + - `{$sdkroot_bare}` + +codegen_ssa_apple_sdk_error_missing_mac_catalyst_version = + failed to find {$version} in SDK version map key `macOS_iOSMac`. + + This is probably a bug in your SDK. + +codegen_ssa_apple_sdk_error_missing_sdk_settings = + failed finding `SDKSettings.json` or `SDKSettings.plist` in `{$sdkroot}`. + + Are you sure this is a valid SDK? + +codegen_ssa_apple_sdk_error_missing_xcode = + failed finding SDK at `{$sdkroot}` in Xcode installation. + + Perhaps you need a newer version of Xcode? + +codegen_ssa_apple_sdk_error_missing_xcode_select = + failed finding SDK inside active developer path `{$dir}` set by `xcode-select`. Looked in: + - `{$sdkroot}` + - `{$sdkroot_bare}` + + Consider using `sudo xcode-select --switch path/to/Xcode.app` or `sudo xcode-select --reset` to select a valid path. + +codegen_ssa_apple_sdk_error_must_have_when_using_ld64 = + must know the SDK when linking with ld64 + +codegen_ssa_apple_sdk_error_not_sdk_path = + failed parsing SDK at `{$path}`. + + The SDK did not seem to contain `SDKSettings.json`, and hence `rustc` falled back to parsing required SDK details from the SDK name itself. + + This name must be of the form `[SDKName][major].[minor].[patch].sdk`, for example `MacOSX10.13.sdk` or `iPhoneOS11.0.sdk`. + +codegen_ssa_apple_sdk_error_sdk_does_not_support_arch = + the SDK at `{$sdkroot}` does not support the {$arch} architecture. + +codegen_ssa_apple_sdk_error_sdk_does_not_support_os = + the SDK at `{$sdkroot}` does not support { $abi -> + [macabi] Mac Catalyst + [sim] the {$os} simulator + *[normal] {$os} + }. + + Use `xcode-select --switch` or one of the `SDKROOT` and `DEVELOPER_DIR` environment variables to select { $abi -> + [macabi] a newer version of Xcode that has support for it + *[others] another SDK that has support for it + }. + + { $abi -> + [macabi] Also remember that it is the macOS SDK that supports Mac Catalyst, not the iOS SDK. + *[others] {""} + } + +codegen_ssa_apple_sdk_error_sdk_root_ignored = + the SDKROOT environment variable has been ignored, and `rustc` will attempt to find a suitable SDK + +codegen_ssa_apple_sdk_error_sdk_root_is_root_path = + the path SDKROOT was set to the root path `/`. + + This will work poorly with other tooling, and as such the value has been ignored. + +codegen_ssa_apple_sdk_error_sdk_root_missing = + the path `{$sdkroot}` specified in SDKROOT did not exist, so it has been ignored + +codegen_ssa_apple_sdk_error_sdk_root_not_absolute = + the path `{$sdkroot}` specified in SDKROOT was not an absolute path. + + This will work poorly with other tooling, and as such the value has been ignored. codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} @@ -337,8 +446,6 @@ codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified -codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}` - codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib) diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs new file mode 100644 index 0000000000000..1d6a7dbcd7953 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -0,0 +1,583 @@ +use std::borrow::Cow; +use std::collections::{BTreeMap, BTreeSet}; +use std::io::ErrorKind; +use std::path::{Path, PathBuf}; +use std::{env, fs}; + +use rustc_middle::bug; +use rustc_session::Session; +use rustc_session::config::CrateType; +use rustc_target::spec::{ + AppleOSVersion, Target, apple_deployment_target_env_var, apple_minimum_deployment_target, + apple_os_minimum_deployment_target, apple_sdk_name, +}; +use serde::Deserialize; + +use crate::errors::{AppleDeploymentTarget, AppleSdkError}; + +#[cfg(test)] +mod tests; + +/// 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(env_var) { + match deployment_target.parse::() { + 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: version.pretty().to_string(), + os_min: os_min.pretty().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 + } +} + +fn add_version_to_llvm_target(llvm_target: &str, deployment_target: AppleOSVersion) -> String { + let mut components = llvm_target.split("-"); + let arch = components.next().expect("darwin target should have arch"); + let vendor = components.next().expect("darwin target should have vendor"); + let os = components.next().expect("darwin target should have os"); + let environment = components.next(); + assert_eq!(components.next(), None, "too many LLVM triple components"); + + let AppleOSVersion { major, minor, patch } = deployment_target; + + assert!( + !os.contains(|c: char| c.is_ascii_digit()), + "LLVM target must not already be versioned" + ); + + if let Some(env) = environment { + // Insert version into OS, before environment + format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}-{env}") + } else { + format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}") + } +} + +/// The target triple depends on the deployment target, and is required to +/// enable features such as cross-language LTO, and for picking the right +/// Mach-O commands. +/// +/// Certain optimizations also depend on the deployment target. +pub fn versioned_llvm_target(sess: &Session) -> Cow<'static, str> { + if sess.target.is_like_osx { + add_version_to_llvm_target(&sess.target.llvm_target, deployment_target(sess)).into() + } else { + sess.target.llvm_target.clone() + } +} + +// TOCTOU is not _really_ an issue with our use of `try_exists` in here, we mostly use it for +// diagnostics, and these directories are global state that the user may change anytime anyhow. +fn try_exists(path: &Path) -> Result { + path.try_exists().map_err(|error| AppleSdkError::FailedReading { path: path.to_owned(), error }) +} + +/// Get the SDK path for an SDK under `/Library/Developer/CommandLineTools`. +fn sdk_root_in_sdks_dir(sdks_dir: impl Into, sdk_name: &str) -> PathBuf { + let mut path = sdks_dir.into(); + path.push("SDKs"); + path.push(sdk_name); + path.set_extension("sdk"); + path +} + +/// Get the SDK path for an SDK under `/Applications/Xcode.app/Contents/Developer`. +fn sdk_root_in_developer_dir(developer_dir: impl Into, sdk_name: &str) -> PathBuf { + let mut path = developer_dir.into(); + path.push("Platforms"); + path.push(sdk_name); + // Platform directories are uninteresting to us, we only care about the inner SDK. + path.set_extension("platform"); + path.push("Developer"); + path.push("SDKs"); + path.push(sdk_name); + path.set_extension("sdk"); + path +} + +/// Find a SDK root from the user's environment for the given SDK name. +/// +/// We do this by searching (purely by names in the filesystem, without reading SDKSettings.json) +/// for a matching SDK in the following places: +/// - `DEVELOPER_DIR` +/// - `/var/db/xcode_select_link` +/// - `/Applications/Xcode.app` +/// - `/Library/Developer/CommandLineTools` +/// +/// This does roughly the same thing as `xcrun -sdk $sdk_name -show-sdk-path` (see `man xcrun` for +/// a few details on the search algorithm). +/// +/// The reason why we implement this logic ourselves is: +/// - Reading these directly is faster than spawning a new process. +/// - `xcrun` can be fairly slow to start up after a reboot. +/// - In the future, we will be able to integrate this better with the compiler's change tracking +/// mechanisms, allowing rebuilds when the involved env vars and paths here change. See #118204. +/// - It's easier for us to emit better error messages. +/// +/// Though a downside is that `xcrun` might be expanded in the future to check more places, and then +/// `rustc` would have to be changed to keep up. Furthermore, `xcrun`'s exact algorithm is +/// undocumented, so it might be doing more things than we do here. +fn find_sdk_root(sdk_name: &'static str) -> Result { + // Only try this if host OS is macOS. + if !cfg!(target_os = "macos") { + return Err(AppleSdkError::MissingCrossCompileNonMacOS { sdk_name }); + } + + // NOTE: We could consider walking upwards in `SDKROOT` assuming Xcode directory structure, but + // that isn't what `xcrun` does, and might still not yield the desired result (e.g. if using an + // old SDK to compile for an old ARM iOS arch, we don't want `rustc` to pick a macOS SDK from + // the old Xcode). + + // Try reading from `DEVELOPER_DIR` on all hosts. + if let Some(dir) = std::env::var_os("DEVELOPER_DIR") { + let dir = PathBuf::from(dir); + let sdkroot = sdk_root_in_developer_dir(&dir, sdk_name); + + if try_exists(&sdkroot)? { + return Ok(sdkroot); + } else { + let sdkroot_bare = sdk_root_in_sdks_dir(&dir, sdk_name); + if try_exists(&sdkroot_bare)? { + return Ok(sdkroot_bare); + } else { + return Err(AppleSdkError::MissingDeveloperDir { dir, sdkroot, sdkroot_bare }); + } + } + } + + // Next, try to read the link that `xcode-select` sets. + // + // FIXME(madsmtm): Support cases where `/var/db/xcode_select_link` contains a relative path? + let path = PathBuf::from("/var/db/xcode_select_link"); + match fs::read_link(&path) { + Ok(dir) => { + let sdkroot = sdk_root_in_developer_dir(&dir, sdk_name); + if try_exists(&sdkroot)? { + return Ok(sdkroot); + } else { + let sdkroot_bare = sdk_root_in_sdks_dir(&dir, sdk_name); + if try_exists(&sdkroot_bare)? { + return Ok(sdkroot_bare); + } else { + return Err(AppleSdkError::MissingXcodeSelect { dir, sdkroot, sdkroot_bare }); + } + } + } + Err(err) if err.kind() == ErrorKind::NotFound => { + // Intentionally ignore not found errors, if `xcode-select --reset` is called the + // link will not exist. + } + Err(error) => return Err(AppleSdkError::FailedReading { path, error }), + } + + // Next, fall back to reading from `/Applications/Xcode.app`. + let dir = PathBuf::from("/Applications/Xcode.app/Contents/Developer"); + if try_exists(&dir)? { + let sdkroot = sdk_root_in_developer_dir(&dir, sdk_name); + if try_exists(&sdkroot)? { + return Ok(sdkroot); + } else { + return Err(AppleSdkError::MissingXcode { sdkroot }); + } + } + + // Finally, fall back to reading from `/Library/Developer/CommandLineTools`. + let dir = PathBuf::from("/Library/Developer/CommandLineTools"); + if try_exists(&dir)? { + let sdkroot = sdk_root_in_sdks_dir(&dir, sdk_name); + if try_exists(&sdkroot)? { + return Ok(sdkroot); + } else { + return Err(AppleSdkError::MissingCommandlineTools { sdkroot }); + } + } + + Err(AppleSdkError::Missing { sdk_name }) +} + +/// The architecture name understood by Apple's linker. +/// +/// Supported architecture names can be found in the source: +/// https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648 +pub fn ld64_arch(target: &Target) -> &'static str { + // `target.arch` / `target_arch` is not detailed enough. + let llvm_arch = target.llvm_target.split_once('-').expect("LLVM target must have arch").0; + + // Intentially verbose to ensure that the list always matches correctly + // with the list in the source above. + match llvm_arch { + "armv7k" => "armv7k", + "armv7s" => "armv7s", + "arm64" => "arm64", + "arm64e" => "arm64e", + "arm64_32" => "arm64_32", + // ld64 doesn't understand i686, so fall back to i386 instead. + // + // Same story when linking with cc, since that ends up invoking ld64. + "i386" | "i686" => "i386", + "x86_64" => "x86_64", + "x86_64h" => "x86_64h", + _ => bug!("unsupported architecture {llvm_arch} in Apple target: {}", target.llvm_target), + } +} + +#[derive(Deserialize, Debug, Default)] +struct DefaultProperties { + // Only set in macOS SDK. + #[serde(rename = "IOS_UNZIPPERED_TWIN_PREFIX_PATH")] + mac_catalyst_prefix_path: Option, +} + +#[derive(Deserialize, Debug)] +struct SupportedTargets { + #[serde(rename = "Archs")] + archs: BTreeSet, + + #[serde(rename = "MaximumDeploymentTarget")] + maximum_deployment_target: AppleOSVersion, + // NOTE: We ignore `DefaultDeploymentTarget`, and let `rustc` choose the default instead. This + // makes it easy when not going through Xcode to still support older OS versions. + + // NOTE: We ignore `MinimumDeploymentTarget`, since `rustc` generally has a very low deployment + // target, and we don't want to warn in those common cases. +} + +/// The parsed SDK information. +/// +/// Note that the macOS SDK usually contains information related to Mac Catalyst as well, so if the +/// target is Mac Catalyst, more work is needed to extract the desired information. +/// +/// `DefaultProperties` and `Variants` contain Xcode-specific information like the +/// `/System/iOSSupport` search paths (which we end up coding manually, it's not worth it to try +/// to parse). +/// +/// FIXME(madsmtm): What does `IsBaseSDK` mean, and is it relevant for us? +#[derive(Deserialize, Debug)] +pub(crate) struct SDKSettings { + #[serde(rename = "CanonicalName")] + canonical_name: String, + + #[serde(rename = "Version")] + version: AppleOSVersion, + + #[serde(rename = "MaximumDeploymentTarget")] + maximum_deployment_target: AppleOSVersion, + + #[serde(rename = "DefaultProperties")] + default_properties: DefaultProperties, + + /// Optional to support `SDKSettings.json` converted from an older `SDKSettings.plist`. + #[serde(rename = "SupportedTargets")] + supported_targets: Option>, + + /// Optional to support `SDKSettings.json` converted from an older `SDKSettings.plist`. + /// + /// Could in general be useful in the future for building "zippered" binaries, see: + /// + #[serde(rename = "VersionMap")] + version_map: Option>>, +} + +impl SDKSettings { + /// Attempt to parse required SDK settings from just the SDK's file name. + /// + /// This deliberately does not contain detailed error information, since it's a very rare case + /// anyhow, so spending a lot of effort on nice error messages here is just wasted work. + fn from_just_path(sdkroot: &Path) -> Option { + let Some(extension) = sdkroot.extension() else { + return None; + }; + if extension != "sdk" { + return None; + } + + let file_stem: &str = sdkroot.file_stem()?.try_into().ok()?; + + // Strip e.g. "MacOSX14.0" to "14.0" + let version = file_stem.trim_start_matches(|c: char| !c.is_ascii_digit()); + let version = version.parse().ok()?; + + Some(Self { + // FIXME(madsmtm): Should we do verification of the canonical name too? + canonical_name: file_stem.to_lowercase(), + version, + // The maximum supported version is often `major.minor.99`. + maximum_deployment_target: AppleOSVersion { + major: version.major, + minor: version.minor, + patch: u8::MAX, + }, + default_properties: DefaultProperties::default(), + supported_targets: None, + version_map: None, + }) + } + + /// Parse SDK settings from the given SDK root. + fn from_sdkroot(sdkroot: &Path) -> Result { + let path = sdkroot.join("SDKSettings.json"); + match std::fs::read(&path) { + Ok(bytes) => serde_json::from_slice(&bytes).map_err(|error| { + AppleSdkError::InvalidSDKSettingsJson { path, error: error.into() } + }), + // `SDKSettings.json` is present since macOS 10.14 and iOS 13.0 SDKs, so this must be an old SDK. + Err(err) if err.kind() == ErrorKind::NotFound => { + // Old SDKs must still have `SDKSettings.plist` though. + if !try_exists(&sdkroot.join("SDKSettings.plist"))? { + return Err(AppleSdkError::MissingSDKSettings { sdkroot: sdkroot.to_owned() }); + } + // We don't try to parse SDKSettings.plist though, since that'd require `rustc` to + // contain a PList parser, which is a dependency we don't want. + // + // Clang doesn't do this either. + + // Try to extract SDK settings both from the standard path, and the canonicalized + // path. + let canonical_sdkroot = std::fs::canonicalize(sdkroot).map_err(|error| { + AppleSdkError::FailedReading { path: sdkroot.to_owned(), error } + })?; + Self::from_just_path(sdkroot) + .or_else(|| Self::from_just_path(&canonical_sdkroot)) + .ok_or_else(|| AppleSdkError::NotSdkPath { sdkroot: sdkroot.to_owned() }) + } + Err(error) => Err(AppleSdkError::FailedReading { path, error }), + } + } + + /// The value of settings["DefaultProperties"]["IOS_UNZIPPERED_TWIN_PREFIX_PATH"] or + /// `/System/iOSSupport` if not set. + /// + /// This is only known to be `/System/iOSSupport`, but may change in the future. + pub(crate) fn mac_catalyst_prefix_path(&self) -> &Path { + self.default_properties + .mac_catalyst_prefix_path + .as_deref() + .unwrap_or(Path::new("/System/iOSSupport")) + } + + /// The version of the SDK. + /// + /// This is needed by the linker. + /// + /// settings["Version"] or settings["VersionMap"]["macOS_iOSMac"][settings["Version"]]. + pub(crate) fn sdk_version(&self, target: &Target, sdkroot: &Path) -> Result { + if target.abi == "macabi" { + let map = self + .version_map + .as_ref() + .ok_or(AppleSdkError::SdkDoesNotSupportOS { + sdkroot: sdkroot.to_owned(), + os: target.os.clone(), + abi: target.abi.clone(), + })? + .get("macOS_iOSMac") + .ok_or(AppleSdkError::SdkDoesNotSupportOS { + sdkroot: sdkroot.to_owned(), + os: target.os.clone(), + abi: target.abi.clone(), + })?; + map.get(&self.version).cloned().ok_or(AppleSdkError::MissingMacCatalystVersion { + version: self.version.pretty().to_string(), + }) + } else { + Ok(self.version) + } + } + + fn supports_target(&self, target: &Target, sdkroot: &Path) -> Result<(), AppleSdkError> { + let arch = ld64_arch(target); + + let sdk_name = apple_sdk_name(target).to_lowercase(); + let target_name = if target.abi == "macabi" { "iosmac" } else { &*sdk_name }; + + if let Some(supported_targets) = &self.supported_targets { + let Some(supported_target) = supported_targets.get(target_name) else { + // If `settings["SupportedTargets"][sdk_name]` is not present + return Err(AppleSdkError::SdkDoesNotSupportOS { + sdkroot: sdkroot.to_owned(), + os: target.os.clone(), + abi: target.abi.clone(), + }); + }; + + if !supported_target.archs.contains(arch) { + // If the `Archs` key does not contain the expected architecture. + return Err(AppleSdkError::SdkDoesNotSupportArch { + sdkroot: sdkroot.to_owned(), + arch, + }); + } + } else { + // We try to guess if the SDK is compatible based on `CanonicalName`. + if !self.canonical_name.contains(target_name) { + return Err(AppleSdkError::SdkDoesNotSupportOS { + sdkroot: sdkroot.to_owned(), + os: target.os.clone(), + abi: target.abi.clone(), + }); + } + + // Old SDKs without SupportedTargets do not have support for Aarch64 on macOS. This + // check allows cross-compiling from Aarch64 to i686 by using the macOS 10.13 SDK. + if target.os == "macos" && target.arch == "aarch64" { + return Err(AppleSdkError::SdkDoesNotSupportArch { + sdkroot: sdkroot.to_owned(), + arch, + }); + } + } + + Ok(()) + } + + fn supports_deployment_target( + &self, + target: &Target, + deployment_target: AppleOSVersion, + ) -> Result<(), AppleDeploymentTarget> { + let sdk_name = apple_sdk_name(target).to_lowercase(); + let target_name = if target.abi == "macabi" { "iosmac" } else { &*sdk_name }; + + // settings["SupportedTargets"][target]["MaximumDeploymentTarget"] or + // settings["MaximumDeploymentTarget"]. + let maximum_deployment_target = if let Some(supported_targets) = &self.supported_targets { + if let Some(supported_target) = supported_targets.get(target_name) { + supported_target.maximum_deployment_target + } else { + self.maximum_deployment_target + } + } else { + self.maximum_deployment_target + }; + + if maximum_deployment_target < deployment_target { + let env_var = apple_deployment_target_env_var(&target.os); + return Err(AppleDeploymentTarget::TooHigh { + sdk_max: maximum_deployment_target.pretty().to_string(), + version: deployment_target.pretty().to_string(), + env_var, + }); + } + + Ok(()) + } + + fn try_get_sdkroot_environment( + sess: &Session, + crate_type: CrateType, + ) -> Result, AppleSdkError> { + if let Some(sdkroot) = env::var_os("SDKROOT") { + let sdkroot = PathBuf::from(&sdkroot); + + // Ignore `SDKROOT` if it's not a valid path. This is also what Clang does: + // + if sdkroot == Path::new("/") { + sess.dcx().emit_warn(AppleSdkError::SdkRootIsRootPath); + return Ok(None); + } + if !sdkroot.is_absolute() { + sess.dcx().emit_warn(AppleSdkError::SdkRootNotAbsolute { sdkroot }); + return Ok(None); + } + if !try_exists(&sdkroot)? { + sess.dcx().emit_warn(AppleSdkError::SdkRootMissing { sdkroot }); + return Ok(None); + } + + let settings = Self::from_sdkroot(&sdkroot)?; + + // Check if the SDK root is applicable for the current target, and ignore it if not. + // + // This can happen in many cases, including: + // - When compiling proc-macros or build scripts in cross-compile scenarios with Cargo + // where `SDKROOT` is set for e.g. iOS. + // - When running under bootstrap, which is invoked by the `/usr/bin/python3` binary; + // this is a trampoline that gets `SDKROOT` set to the macOS SDK default. + // - Other invokers originating in trampoline binaries in `/usr/bin/*`. + // - The user has set it and forgotten about it. + if let Err(err) = settings.supports_target(&sess.target, &sdkroot) { + // Best effort check to see if we're linking a build script. + let is_build_script = matches!(&sess.opts.crate_name, Some(crate_name) if crate_name == "build_script_build"); + // Best effort check to see if we're linking a proc-macro + let is_proc_macro = crate_type == CrateType::ProcMacro; + + // If we're likely to be building a build script or a proc macro. + if sess.target.os == sess.host.os && (is_build_script || is_proc_macro) { + // Don't warn in this case. + return Ok(None); + } + + // Report that we ignored the SDK. + // FIXME(madsmtm): Make this diagnostic look nicer. + sess.dcx().emit_warn(err); + sess.dcx().emit_warn(AppleSdkError::SdkRootIgnored); + + return Ok(None); + } + + Ok(Some((sdkroot, settings))) + } else { + Ok(None) + } + } + + pub(crate) fn from_environment( + sess: &Session, + crate_type: CrateType, + ) -> Result<(PathBuf, Self), AppleSdkError> { + // Use `SDKROOT` if given and valid. + let (sdkroot, settings) = if let Some((sdkroot, settings)) = + Self::try_get_sdkroot_environment(sess, crate_type)? + { + (sdkroot, settings) + } else { + // Otherwise search for an SDK root. + let sdkroot = find_sdk_root(apple_sdk_name(&sess.target))?; + + let settings = SDKSettings::from_sdkroot(&sdkroot)?; + (sdkroot, settings) + }; + + // Finally, check that the found SDK matches what we expect. + + if let Err(err) = settings.supports_target(&sess.target, &sdkroot) { + // Emit a warning if the SDK is not supported, but keep going with it (it may still + // work even if unsupported, for example newer SDKs are marked as not supporting the + // armv7/armv7s/armv7k architectures, but their `.tbd` files still support those). + sess.dcx().emit_warn(err); + } + + if let Err(err) = settings.supports_deployment_target(&sess.target, deployment_target(sess)) + { + // Only warn here, the found SDK is probably still usable even if the deployment target + // is not supported. + sess.dcx().emit_warn(err); + } + + Ok((sdkroot, settings)) + } +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphoneos13.0.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphoneos13.0.json new file mode 100644 index 0000000000000..363de10d7e290 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphoneos13.0.json @@ -0,0 +1,99 @@ +{ + "DisplayName": "iOS 13.0", + "DefaultProperties": { + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "AD_HOC_CODE_SIGNING_ALLOWED": "NO", + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "8.0", + "8.1", + "8.2", + "8.3", + "8.4", + "9.0", + "9.1", + "9.2", + "9.3", + "10.0", + "10.1", + "10.2", + "10.3", + "11.0", + "11.1", + "11.2", + "11.3", + "11.4", + "12.0", + "12.1", + "12.2", + "12.3", + "12.4", + "13.0" + ], + "GCC_THUMB_SUPPORT": "YES", + "CODE_SIGN_IDENTITY": "Apple Development", + "CODE_SIGNING_REQUIRED": "YES", + "SUPPORTED_DEVICE_FAMILIES": "1,2", + "ENTITLEMENTS_DESTINATION": "Signature", + "PLATFORM_NAME": "iphoneos", + "ENTITLEMENTS_REQUIRED": "YES", + "CODE_SIGN_ENTITLEMENTS": "", + "IPHONEOS_DEPLOYMENT_TARGET": "13.0", + "KASAN_DEFAULT_CFLAGS": "-DKASAN=1 -fsanitize=address -mllvm -asan-globals-live-support -mllvm -asan-force-dynamic-shadow", + "DEAD_CODE_STRIPPING": "YES" + }, + "MinimalDisplayName": "13.0", + "Version": "13.0", + "IsBaseSDK": "YES", + "SupportedTargets": { + "iphoneos": { + "MinimumDeploymentTarget": "8.0", + "LLVMTargetTripleSys": "ios", + "MaximumDeploymentTarget": "13.0.99", + "LLVMTargetTripleEnvironment": "", + "LLVMTargetTripleVendor": "apple", + "BuildVersionPlatformID": "2", + "DefaultDeploymentTarget": "13.0", + "Archs": [ + "armv7", + "armv7s", + "arm64" + ], + "ValidDeploymentTargets": [ + "8.0", + "8.1", + "8.2", + "8.3", + "8.4", + "9.0", + "9.1", + "9.2", + "9.3", + "10.0", + "10.1", + "10.2", + "10.3", + "11.0", + "11.1", + "11.2", + "11.3", + "11.4", + "12.0", + "12.1", + "12.2", + "12.3", + "12.4", + "13.0" + ] + } + }, + "PropertyConditionFallbackNames": [ + "embedded" + ], + "DefaultDeploymentTarget": "13.0", + "MaximumDeploymentTarget": "13.0.99", + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "iphoneos13.0", + "CustomProperties": {} +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphonesimulator18.0.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphonesimulator18.0.json new file mode 100644 index 0000000000000..8181cd62e2e0b --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphonesimulator18.0.json @@ -0,0 +1,157 @@ +{ + "DisplayName": "Simulator - iOS 18.0", + "DefaultProperties": { + "TAPI_USE_SRCROOT": "YES", + "AD_HOC_CODE_SIGNING_ALLOWED": "YES", + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "TEST_LIBRARY_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/usr\/lib", + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "12.0", + "12.1", + "12.2", + "12.3", + "12.4", + "13.0", + "13.1", + "13.2", + "13.3", + "13.4", + "13.5", + "13.6", + "14.0", + "14.1", + "14.2", + "14.3", + "14.4", + "14.5", + "14.6", + "14.7", + "15.0", + "15.1", + "15.2", + "15.3", + "15.4", + "15.5", + "15.6", + "16.0", + "16.1", + "16.2", + "16.3", + "16.4", + "16.5", + "16.6", + "17.0", + "17.1", + "17.2", + "17.3", + "17.4", + "17.5", + "17.6", + "18.0" + ], + "TEST_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/Library\/Frameworks $(SDKROOT)\/Developer\/Library\/Frameworks", + "CODE_SIGN_IDENTITY": "-", + "CODE_SIGNING_REQUIRED": "YES", + "TAPI_VERIFY_MODE": "Pedantic", + "SUPPORTED_DEVICE_FAMILIES": "1,2", + "PLATFORM_NAME": "iphonesimulator", + "ENTITLEMENTS_DESTINATION": "__entitlements", + "ENTITLEMENTS_REQUIRED": "YES", + "CODE_SIGN_ENTITLEMENTS": "", + "IPHONEOS_DEPLOYMENT_TARGET": "18.0", + "LLVM_TARGET_TRIPLE_SUFFIX": "-simulator", + "DEAD_CODE_STRIPPING": "YES" + }, + "MinimalDisplayName": "Simulator - 18.0", + "Version": "18.0", + "IsBaseSDK": "YES", + "SupportedTargets": { + "iphonesimulator": { + "LLVMTargetTripleVendor": "apple", + "DeploymentTargetSettingName": "IPHONEOS_DEPLOYMENT_TARGET", + "SwiftConcurrencyMinimumDeploymentTarget": "15.0", + "Archs": [ + "arm64", + "x86_64" + ], + "LLVMTargetTripleEnvironment": "simulator", + "ClangRuntimeLibraryPlatformName": "iossim", + "MaximumDeploymentTarget": "18.0.99", + "BuildVersionPlatformID": "7", + "DefaultDeploymentTarget": "18.0", + "LLVMTargetTripleSys": "ios", + "DeviceFamilies": [ + { + "Identifier": "1", + "Name": "phone", + "DisplayName": "iPhone" + }, + { + "Identifier": "2", + "Name": "pad", + "DisplayName": "iPad" + } + ], + "MinimumDeploymentTarget": "12.0", + "SwiftOSRuntimeMinimumDeploymentTarget": "12.2", + "PlatformFamilyDisplayName": "iOS", + "RecommendedDeploymentTarget": "15.0", + "PlatformFamilyName": "iOS", + "ValidDeploymentTargets": [ + "12.0", + "12.1", + "12.2", + "12.3", + "12.4", + "13.0", + "13.1", + "13.2", + "13.3", + "13.4", + "13.5", + "13.6", + "14.0", + "14.1", + "14.2", + "14.3", + "14.4", + "14.5", + "14.6", + "14.7", + "15.0", + "15.1", + "15.2", + "15.3", + "15.4", + "15.5", + "15.6", + "16.0", + "16.1", + "16.2", + "16.3", + "16.4", + "16.5", + "16.6", + "17.0", + "17.1", + "17.2", + "17.3", + "17.4", + "17.5", + "17.6", + "18.0" + ], + "SystemPrefix": "" + } + }, + "PropertyConditionFallbackNames": [ + "embeddedsimulator" + ], + "DefaultDeploymentTarget": "18.0", + "MaximumDeploymentTarget": "18.0.99", + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "iphonesimulator18.0", + "CustomProperties": {} +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.14.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.14.json new file mode 100644 index 0000000000000..d3eed880cc30d --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.14.json @@ -0,0 +1,58 @@ +{ + "DisplayName": "macOS 10.14", + "DefaultProperties": { + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "10.6", + "10.7", + "10.8", + "10.9", + "10.10", + "10.11", + "10.12", + "10.13", + "10.14" + ], + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "KASAN_DEFAULT_CFLAGS": "-DKASAN=1 -fsanitize=address -mllvm -asan-globals-live-support -mllvm -asan-force-dynamic-shadow", + "MACOSX_DEPLOYMENT_TARGET": "10.14", + "PLATFORM_NAME": "macosx" + }, + "MinimalDisplayName": "10.14", + "Version": "10.14", + "IsBaseSDK": "YES", + "SupportedTargets": { + "macosx": { + "MinimumDeploymentTarget": "10.6", + "LLVMTargetTripleSys": "macosx", + "MaximumDeploymentTarget": "10.14.99", + "LLVMTargetTripleEnvironment": "", + "LLVMTargetTripleVendor": "apple", + "BuildVersionPlatformID": "1", + "DefaultDeploymentTarget": "10.14", + "Archs": [ + "x86_64" + ], + "ValidDeploymentTargets": [ + "10.6", + "10.7", + "10.8", + "10.9", + "10.10", + "10.11", + "10.12", + "10.13", + "10.14" + ] + } + }, + "PropertyConditionFallbackNames": [], + "DefaultDeploymentTarget": "10.14", + "MaximumDeploymentTarget": "10.14.99", + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "macosx10.14", + "CustomProperties": { + "KERNEL_EXTENSION_HEADER_SEARCH_PATHS": "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)" + } +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.15.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.15.json new file mode 100644 index 0000000000000..a5dcf9c9a76b6 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.15.json @@ -0,0 +1,134 @@ +{ + "DefaultVariant": "macos", + "DisplayName": "macOS 10.15", + "MinimalDisplayName": "10.15", + "DefaultProperties": { + "CODE_SIGNING_ALLOWED": "YES", + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "IOS_UNZIPPERED_TWIN_PREFIX_PATH": "\/System\/iOSSupport", + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "10.6", + "10.7", + "10.8", + "10.9", + "10.10", + "10.11", + "10.12", + "10.13", + "10.14", + "10.15" + ], + "KASAN_DEFAULT_CFLAGS": "-DKASAN=1 -fsanitize=address -mllvm -asan-globals-live-support -mllvm -asan-force-dynamic-shadow", + "MACOSX_DEPLOYMENT_TARGET": "10.15", + "PLATFORM_NAME": "macosx", + "AD_HOC_CODE_SIGNING_ALLOWED": "YES" + }, + "IsBaseSDK": "YES", + "SupportedTargets": { + "iosmac": { + "MinimumDeploymentTarget": "13.0", + "LLVMTargetTripleEnvironment": "macabi", + "LLVMTargetTripleSys": "ios", + "MaximumDeploymentTarget": "13.0.99", + "LLVMTargetTripleVendor": "apple", + "BuildVersionPlatformID": "6", + "DefaultDeploymentTarget": "13.0", + "Archs": [ + "x86_64" + ], + "ValidDeploymentTargets": [ + "13.0" + ] + }, + "macosx": { + "MinimumDeploymentTarget": "10.6", + "LLVMTargetTripleEnvironment": "", + "LLVMTargetTripleSys": "macosx", + "MaximumDeploymentTarget": "10.15.99", + "LLVMTargetTripleVendor": "apple", + "BuildVersionPlatformID": "1", + "DefaultDeploymentTarget": "10.15", + "Archs": [ + "x86_64" + ], + "ValidDeploymentTargets": [ + "10.6", + "10.7", + "10.8", + "10.9", + "10.10", + "10.11", + "10.12", + "10.13", + "10.14", + "10.15" + ] + } + }, + "Version": "10.15", + "PropertyConditionFallbackNames": [], + "VersionMap": { + "macOS_iOSMac": { + "10.15": "13.0" + }, + "iOSMac_macOS": { + "13.0": "10.15" + } + }, + "DefaultDeploymentTarget": "10.15", + "MaximumDeploymentTarget": "10.15.99", + "Variants": [ + { + "Name": "macos", + "BuildSettings": { + "_BOOL_": "NO", + "_IS_EMPTY_": "YES", + "CODE_SIGN_IDENTITY": "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "macos10.15", + "_DEVELOPMENT_TEAM_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(DEVELOPMENT_TEAM)))", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "macos$(MACOSX_DEPLOYMENT_TARGET)", + "_BOOL_YES": "YES", + "CODE_SIGN_IDENTITY_YES": "-", + "CODE_SIGN_IDENTITY_NO": "Apple Development", + "_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(MACOSX_DEPLOYMENT_TARGET)))", + "_BOOL_NO": "NO", + "IPHONEOS_DEPLOYMENT_TARGET": "13.0", + "LLVM_TARGET_TRIPLE_SUFFIX": "" + } + }, + { + "Name": "iosmac", + "BuildSettings": { + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "ios$(IPHONEOS_DEPLOYMENT_TARGET)", + "_BOOL_NO": "NO", + "SYSTEM_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/System\/Library\/Frameworks", + "SWIFT_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "_BOOL_": "NO", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "ios13.0", + "_IS_EMPTY_": "YES", + "LIBRARY_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/lib $(TOOLCHAIN_DIR)\/usr\/lib\/swift\/iosmac", + "RESOURCES_UI_FRAMEWORK_FAMILY": "uikit", + "LLVM_TARGET_TRIPLE_SUFFIX": "-macabi", + "RESOURCES_MINIMUM_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "SWIFT_PLATFORM_TARGET_PREFIX": "ios", + "_BOOL_YES": "YES", + "_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(IPHONEOS_DEPLOYMENT_TARGET)))", + "IPHONEOS_DEPLOYMENT_TARGET": "13.0", + "CODE_SIGN_IDENTITY": "Apple Development", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY))", + "RESOURCES_PLATFORM_NAME": "macosx", + "RESOURCES_TARGETED_DEVICE_FAMILY": "ipad", + "ENABLE_HARDENED_RUNTIME": "YES", + "SYSTEM_HEADER_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/include" + } + } + ], + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "macosx10.15", + "CustomProperties": { + "KERNEL_EXTENSION_HEADER_SEARCH_PATHS": "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)" + } +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx11.3.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx11.3.json new file mode 100644 index 0000000000000..36e6cf83a16df --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx11.3.json @@ -0,0 +1,180 @@ +{ + "DefaultVariant": "macos", + "DisplayName": "macOS 11.3", + "MinimalDisplayName": "11.3", + "DefaultProperties": { + "ENTITLEMENTS_DESTINATION": "Signature", + "CODE_SIGNING_ALLOWED": "YES", + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "TEST_LIBRARY_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/$(TEST_FRAMEWORK_DEVELOPER_VARIANT_SUBPATH)usr\/lib", + "KASAN_DEFAULT_CFLAGS": "-DKASAN=1 -fsanitize=address -mllvm -asan-globals-live-support -mllvm -asan-force-dynamic-shadow", + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "10.9", + "10.10", + "10.11", + "10.12", + "10.13", + "10.14", + "10.15", + "11.0", + "11.1", + "11.2", + "11.3" + ], + "IOS_UNZIPPERED_TWIN_PREFIX_PATH": "\/System\/iOSSupport", + "MACOSX_DEPLOYMENT_TARGET": "11.3", + "AD_HOC_CODE_SIGNING_ALLOWED": "YES", + "PLATFORM_NAME": "macosx", + "TEST_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/$(TEST_FRAMEWORK_DEVELOPER_VARIANT_SUBPATH)Library\/Frameworks" + }, + "IsBaseSDK": "YES", + "SupportedTargets": { + "iosmac": { + "MinimumDeploymentTarget": "13.1", + "LLVMTargetTripleEnvironment": "macabi", + "LLVMTargetTripleSys": "ios", + "MaximumDeploymentTarget": "14.5.99", + "LLVMTargetTripleVendor": "apple", + "BuildVersionPlatformID": "6", + "DeploymentTargetSettingName": "IPHONEOS_DEPLOYMENT_TARGET", + "Archs": [ + "x86_64", + "x86_64h", + "arm64", + "arm64e" + ], + "DefaultDeploymentTarget": "14.5", + "ValidDeploymentTargets": [ + "13.1", + "13.2", + "13.3", + "13.3.1", + "13.4", + "13.5", + "14.0", + "14.1", + "14.2", + "14.3", + "14.4", + "14.5" + ] + }, + "macosx": { + "MinimumDeploymentTarget": "10.9", + "PlatformFamilyName": "macOS", + "LLVMTargetTripleEnvironment": "", + "LLVMTargetTripleSys": "macosx", + "MaximumDeploymentTarget": "11.3.99", + "LLVMTargetTripleVendor": "apple", + "BuildVersionPlatformID": "1", + "DeploymentTargetSettingName": "MACOSX_DEPLOYMENT_TARGET", + "Archs": [ + "x86_64", + "x86_64h", + "arm64", + "arm64e" + ], + "ValidDeploymentTargets": [ + "10.9", + "10.10", + "10.11", + "10.12", + "10.13", + "10.14", + "10.15", + "11.0", + "11.1", + "11.2", + "11.3" + ], + "DefaultDeploymentTarget": "11.3" + } + }, + "Version": "11.3", + "PropertyConditionFallbackNames": [], + "VersionMap": { + "iOSMac_macOS": { + "13.3.1": "10.15.3", + "13.3": "10.15.2", + "14.2": "11.0", + "13.2": "10.15.1", + "14.5": "11.3", + "14.1": "11.0", + "13.5": "10.15.5", + "13.1": "10.15", + "14.4": "11.2", + "14.0": "11.0", + "13.4": "10.15.4", + "14.3": "11.1" + }, + "macOS_iOSMac": { + "11.0.1": "14.2", + "10.15": "13.1", + "11.2": "14.4", + "10.15.5": "13.5", + "10.15.4": "13.4", + "10.15.3": "13.3.1", + "10.15.2": "13.3", + "11.0": "14.2", + "10.15.1": "13.2", + "11.3": "14.5", + "11.1": "14.3" + } + }, + "DefaultDeploymentTarget": "11.3", + "MaximumDeploymentTarget": "11.3.99", + "Variants": [ + { + "Name": "macos", + "BuildSettings": { + "_BOOL_": "NO", + "_IS_EMPTY_": "YES", + "CODE_SIGN_IDENTITY": "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "macos11.3", + "_DEVELOPMENT_TEAM_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(DEVELOPMENT_TEAM)))", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "macos$(MACOSX_DEPLOYMENT_TARGET)", + "_BOOL_YES": "YES", + "CODE_SIGN_IDENTITY_YES": "-", + "CODE_SIGN_IDENTITY_NO": "Apple Development", + "_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(MACOSX_DEPLOYMENT_TARGET)))", + "_BOOL_NO": "NO", + "IPHONEOS_DEPLOYMENT_TARGET": "14.5", + "LLVM_TARGET_TRIPLE_SUFFIX": "" + } + }, + { + "Name": "iosmac", + "BuildSettings": { + "_BOOL_NO": "NO", + "SYSTEM_HEADER_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/include", + "SYSTEM_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/System\/Library\/Frameworks", + "SWIFT_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "_BOOL_": "NO", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "ios14.5", + "_IS_EMPTY_": "YES", + "LIBRARY_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/lib $(TOOLCHAIN_DIR)\/usr\/lib\/swift\/maccatalyst", + "TARGETED_DEVICE_FAMILY": "2", + "RESOURCES_UI_FRAMEWORK_FAMILY": "uikit", + "LLVM_TARGET_TRIPLE_SUFFIX": "-macabi", + "RESOURCES_MINIMUM_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "SWIFT_PLATFORM_TARGET_PREFIX": "ios", + "_BOOL_YES": "YES", + "_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(IPHONEOS_DEPLOYMENT_TARGET)))", + "IPHONEOS_DEPLOYMENT_TARGET": "14.5", + "CODE_SIGN_IDENTITY": "Apple Development", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY))", + "RESOURCES_PLATFORM_NAME": "macosx", + "ENABLE_HARDENED_RUNTIME": "YES", + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "ios$(IPHONEOS_DEPLOYMENT_TARGET)" + } + } + ], + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "macosx11.3", + "CustomProperties": { + "KERNEL_EXTENSION_HEADER_SEARCH_PATHS": "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)" + } +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx13.3.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx13.3.json new file mode 100644 index 0000000000000..1f239cd885c55 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx13.3.json @@ -0,0 +1,265 @@ +{ + "DefaultVariant": "macos", + "DisplayName": "macOS 13.3", + "MinimalDisplayName": "13.3", + "DefaultProperties": { + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "AD_HOC_CODE_SIGNING_ALLOWED": "YES", + "TEST_LIBRARY_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/$(TEST_FRAMEWORK_DEVELOPER_VARIANT_SUBPATH)usr\/lib", + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "10.13", + "10.14", + "10.15", + "11.0", + "11.1", + "11.2", + "11.3", + "11.4", + "11.5", + "12.0", + "12.2", + "12.3", + "12.4", + "13.0", + "13.1", + "13.2", + "13.3" + ], + "TEST_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/$(TEST_FRAMEWORK_DEVELOPER_VARIANT_SUBPATH)Library\/Frameworks", + "CODE_SIGN_IDENTITY": "Apple Development", + "IOS_UNZIPPERED_TWIN_PREFIX_PATH": "\/System\/iOSSupport", + "CODE_SIGNING_REQUIRED": "YES", + "KASAN_DEFAULT_CFLAGS[arch=arm64e]": "$(KASAN_CFLAGS_TBI)", + "MACOSX_DEPLOYMENT_TARGET": "13.3", + "ENTITLEMENTS_DESTINATION": "Signature", + "PLATFORM_NAME": "macosx", + "ENTITLEMENTS_REQUIRED": "YES", + "CODE_SIGN_ENTITLEMENTS": "", + "KASAN_CFLAGS_TBI": "-DKASAN=1 -DKASAN_TBI=1 -fsanitize=kernel-hwaddress -mllvm -hwasan-recover=0 -mllvm -hwasan-instrument-atomics=0 -mllvm -hwasan-instrument-stack=1 -mllvm -hwasan-uar-retag-to-zero=1 -mllvm -hwasan-generate-tags-with-calls=1 -mllvm -hwasan-instrument-with-calls=1 -mllvm -hwasan-use-short-granules=0 -mllvm -hwasan-memory-access-callback-prefix=__asan_", + "KASAN_DEFAULT_CFLAGS[arch=arm64]": "$(KASAN_CFLAGS_TBI)", + "KASAN_DEFAULT_CFLAGS": "$(KASAN_CFLAGS_CLASSIC)", + "KASAN_CFLAGS_CLASSIC": "-DKASAN=1 -DKASAN_CLASSIC=1 -fsanitize=address -mllvm -asan-globals-live-support -mllvm -asan-force-dynamic-shadow" + }, + "IsBaseSDK": "YES", + "SupportedTargets": { + "iosmac": { + "LLVMTargetTripleVendor": "apple", + "DeploymentTargetSettingName": "IPHONEOS_DEPLOYMENT_TARGET", + "Archs": [ + "x86_64", + "x86_64h", + "arm64", + "arm64e" + ], + "SwiftConcurrencyMinimumDeploymentTarget": "15.0", + "LLVMTargetTripleEnvironment": "macabi", + "ClangRuntimeLibraryPlatformName": "osx", + "MaximumDeploymentTarget": "16.4.99", + "BuildVersionPlatformID": "6", + "DefaultDeploymentTarget": "16.4", + "LLVMTargetTripleSys": "ios", + "DeviceFamilies": [ + { + "Identifier": "2", + "Name": "pad", + "DisplayName": "iPad" + }, + { + "Identifier": "6", + "Name": "mac", + "DisplayName": "Mac" + } + ], + "MinimumDeploymentTarget": "13.1", + "SwiftOSRuntimeMinimumDeploymentTarget": "12.2", + "RecommendedDeploymentTarget": "13.1", + "SystemPrefix": "\/System\/iOSSupport", + "ValidDeploymentTargets": [ + "13.1", + "13.2", + "13.3", + "13.3.1", + "13.4", + "13.5", + "14.0", + "14.1", + "14.2", + "14.3", + "14.4", + "14.5", + "14.6", + "14.7", + "15.0", + "15.2", + "15.3", + "15.4", + "15.5", + "15.6", + "16.0", + "16.1", + "16.2", + "16.3", + "16.4" + ] + }, + "macosx": { + "LLVMTargetTripleVendor": "apple", + "DeploymentTargetSettingName": "MACOSX_DEPLOYMENT_TARGET", + "Archs": [ + "x86_64", + "x86_64h", + "arm64", + "arm64e" + ], + "SwiftConcurrencyMinimumDeploymentTarget": "12.0", + "LLVMTargetTripleEnvironment": "", + "ClangRuntimeLibraryPlatformName": "osx", + "MaximumDeploymentTarget": "13.3.99", + "BuildVersionPlatformID": "1", + "DefaultDeploymentTarget": "13.3", + "LLVMTargetTripleSys": "macos", + "DeviceFamilies": [ + { + "Name": "mac", + "DisplayName": "Mac" + } + ], + "MinimumDeploymentTarget": "10.13", + "SwiftOSRuntimeMinimumDeploymentTarget": "10.14.4", + "RecommendedDeploymentTarget": "10.14.6", + "PlatformFamilyName": "macOS", + "SystemPrefix": "", + "ValidDeploymentTargets": [ + "10.13", + "10.14", + "10.15", + "11.0", + "11.1", + "11.2", + "11.3", + "11.4", + "11.5", + "12.0", + "12.2", + "12.3", + "12.4", + "13.0", + "13.1", + "13.2", + "13.3" + ] + } + }, + "Version": "13.3", + "PropertyConditionFallbackNames": [], + "VersionMap": { + "iOSMac_macOS": { + "15.0": "12.0", + "13.3.1": "10.15.3", + "16.2": "13.1", + "14.3": "11.1", + "15.5": "12.4", + "13.1": "10.15", + "16.0": "13.0", + "14.1": "11.0", + "15.3": "12.2", + "14.6": "11.4", + "13.4": "10.15.4", + "16.3": "13.2", + "15.6": "12.5", + "13.2": "10.15.1", + "14.4": "11.2", + "16.1": "13.0", + "14.2": "11.0", + "15.4": "12.3", + "13.5": "10.15.5", + "14.7": "11.5", + "15.2": "12.1", + "14.0": "11.0", + "16.4": "13.3", + "13.3": "10.15.2", + "14.5": "11.3" + }, + "macOS_iOSMac": { + "11.4": "14.6", + "13.1": "16.2", + "12.4": "15.5", + "11.2": "14.4", + "12.0.1": "15.0", + "10.15.1": "13.2", + "11.0": "14.2", + "10.15": "13.1", + "12.2": "15.3", + "10.15.2": "13.3", + "11.5": "14.7", + "12.0": "15.0", + "13.2": "16.3", + "10.15.3": "13.3.1", + "11.3": "14.5", + "12.5": "15.6", + "13.0": "16.1", + "10.15.4": "13.4", + "11.1": "14.3", + "12.3": "15.4", + "10.15.5": "13.5", + "11.0.1": "14.2", + "12.1": "15.2", + "13.3": "16.4" + } + }, + "DefaultDeploymentTarget": "13.3", + "MaximumDeploymentTarget": "13.3.99", + "Variants": [ + { + "Name": "macos", + "BuildSettings": { + "_BOOL_": "NO", + "_IS_EMPTY_": "YES", + "CODE_SIGN_IDENTITY": "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "macos13.3", + "_DEVELOPMENT_TEAM_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(DEVELOPMENT_TEAM)))", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "macos$(MACOSX_DEPLOYMENT_TARGET)", + "_BOOL_YES": "YES", + "CODE_SIGN_IDENTITY_YES": "-", + "CODE_SIGN_IDENTITY_NO": "Apple Development", + "_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(MACOSX_DEPLOYMENT_TARGET)))", + "_BOOL_NO": "NO", + "IPHONEOS_DEPLOYMENT_TARGET": "16.4", + "LLVM_TARGET_TRIPLE_SUFFIX": "" + } + }, + { + "Name": "iosmac", + "BuildSettings": { + "_BOOL_NO": "NO", + "SYSTEM_HEADER_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/include", + "SYSTEM_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/System\/Library\/Frameworks", + "SWIFT_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "_BOOL_": "NO", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "ios16.4", + "_IS_EMPTY_": "YES", + "LIBRARY_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/lib $(TOOLCHAIN_DIR)\/usr\/lib\/swift\/maccatalyst", + "TARGETED_DEVICE_FAMILY": "2", + "RESOURCES_UI_FRAMEWORK_FAMILY": "uikit", + "LLVM_TARGET_TRIPLE_SUFFIX": "-macabi", + "RESOURCES_MINIMUM_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "_BOOL_YES": "YES", + "_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(IPHONEOS_DEPLOYMENT_TARGET)))", + "IPHONEOS_DEPLOYMENT_TARGET": "16.4", + "CODE_SIGN_IDENTITY": "Apple Development", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY))", + "RESOURCES_PLATFORM_NAME": "macosx", + "ENABLE_HARDENED_RUNTIME": "YES", + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "ios$(IPHONEOS_DEPLOYMENT_TARGET)" + } + } + ], + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "macosx13.3", + "CustomProperties": { + "KERNEL_EXTENSION_HEADER_SEARCH_PATHS": "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)" + } +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx15.0.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx15.0.json new file mode 100644 index 0000000000000..f033c54de971f --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx15.0.json @@ -0,0 +1,318 @@ +{ + "DefaultVariant": "macos", + "DisplayName": "macOS 15.0", + "MinimalDisplayName": "15.0", + "DefaultProperties": { + "CODE_SIGN_ENTITLEMENTS": "", + "ENTITLEMENTS_REQUIRED": "YES", + "KASAN_DEFAULT_CFLAGS": "$(KASAN_CFLAGS_CLASSIC)", + "KASAN_DEFAULT_CFLAGS[arch=arm64]": "$(KASAN_CFLAGS_TBI)", + "KASAN_DEFAULT_CFLAGS[arch=arm64e]": "$(KASAN_CFLAGS_TBI)", + "MACOSX_DEPLOYMENT_TARGET": "15.0", + "IOS_UNZIPPERED_TWIN_PREFIX_PATH": "\/System\/iOSSupport", + "TEST_LIBRARY_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/usr\/lib", + "TAPI_VERIFY_MODE": "Pedantic", + "PLATFORM_NAME": "macosx", + "KASAN_CFLAGS_CLASSIC": "-DKASAN=1 -DKASAN_CLASSIC=1 -fsanitize=address -mllvm -asan-globals-live-support -mllvm -asan-force-dynamic-shadow", + "CODE_SIGNING_REQUIRED": "YES", + "TEST_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/Library\/Frameworks", + "CODE_SIGN_IDENTITY": "Apple Development", + "KASAN_CFLAGS_TBI": "-DKASAN=1 -DKASAN_TBI=1 -fsanitize=kernel-hwaddress -mllvm -hwasan-recover=0 -mllvm -hwasan-instrument-atomics=0 -mllvm -hwasan-instrument-stack=1 -mllvm -hwasan-generate-tags-with-calls=1 -mllvm -hwasan-instrument-with-calls=1 -mllvm -hwasan-use-short-granules=0 -mllvm -hwasan-memory-access-callback-prefix=__asan_", + "TAPI_USE_SRCROOT": "YES", + "ENTITLEMENTS_DESTINATION": "Signature", + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "10.13", + "10.14", + "10.15", + "11.0", + "11.1", + "11.2", + "11.3", + "11.4", + "11.5", + "12.0", + "12.2", + "12.3", + "12.4", + "13.0", + "13.1", + "13.2", + "13.3", + "13.4", + "13.5", + "14.0", + "14.1", + "14.2", + "14.3", + "14.4", + "14.5", + "14.6", + "15.0" + ], + "AD_HOC_CODE_SIGNING_ALLOWED": "YES" + }, + "IsBaseSDK": "YES", + "SupportedTargets": { + "iosmac": { + "LLVMTargetTripleVendor": "apple", + "DeploymentTargetSettingName": "IPHONEOS_DEPLOYMENT_TARGET", + "Archs": [ + "x86_64", + "x86_64h", + "arm64", + "arm64e" + ], + "SwiftConcurrencyMinimumDeploymentTarget": "15.0", + "LLVMTargetTripleEnvironment": "macabi", + "ClangRuntimeLibraryPlatformName": "osx", + "MaximumDeploymentTarget": "18.0.99", + "BuildVersionPlatformID": "6", + "DefaultDeploymentTarget": "18.0", + "LLVMTargetTripleSys": "ios", + "DeviceFamilies": [ + { + "Identifier": "2", + "Name": "pad", + "DisplayName": "iPad" + }, + { + "Identifier": "6", + "Name": "mac", + "DisplayName": "Mac" + } + ], + "MinimumDeploymentTarget": "13.1", + "SwiftOSRuntimeMinimumDeploymentTarget": "12.2", + "RecommendedDeploymentTarget": "14.2", + "SystemPrefix": "\/System\/iOSSupport", + "ValidDeploymentTargets": [ + "13.1", + "13.2", + "13.3", + "13.3.1", + "13.4", + "13.5", + "14.0", + "14.1", + "14.2", + "14.3", + "14.4", + "14.5", + "14.6", + "14.7", + "15.0", + "15.2", + "15.3", + "15.4", + "15.5", + "15.6", + "16.0", + "16.1", + "16.2", + "16.3", + "16.4", + "16.5", + "16.6", + "17.0", + "17.1", + "17.2", + "17.3", + "17.4", + "17.5", + "17.6", + "18.0" + ] + }, + "macosx": { + "LLVMTargetTripleVendor": "apple", + "DeploymentTargetSettingName": "MACOSX_DEPLOYMENT_TARGET", + "PlatformFamilyDisplayName": "macOS", + "Archs": [ + "x86_64", + "x86_64h", + "arm64", + "arm64e" + ], + "LLVMTargetTripleEnvironment": "", + "ClangRuntimeLibraryPlatformName": "osx", + "MaximumDeploymentTarget": "15.0.99", + "BuildVersionPlatformID": "1", + "DefaultDeploymentTarget": "15.0", + "LLVMTargetTripleSys": "macos", + "DeviceFamilies": [ + { + "Name": "mac", + "DisplayName": "Mac" + } + ], + "MinimumDeploymentTarget": "10.13", + "SwiftConcurrencyMinimumDeploymentTarget": "12.0", + "SwiftOSRuntimeMinimumDeploymentTarget": "10.14.4", + "RecommendedDeploymentTarget": "11.0", + "PlatformFamilyName": "macOS", + "SystemPrefix": "", + "ValidDeploymentTargets": [ + "10.13", + "10.14", + "10.15", + "11.0", + "11.1", + "11.2", + "11.3", + "11.4", + "11.5", + "12.0", + "12.2", + "12.3", + "12.4", + "13.0", + "13.1", + "13.2", + "13.3", + "13.4", + "13.5", + "14.0", + "14.1", + "14.2", + "14.3", + "14.4", + "14.5", + "14.6", + "15.0" + ] + } + }, + "Version": "15.0", + "PropertyConditionFallbackNames": [], + "VersionMap": { + "iOSMac_macOS": { + "13.2": "10.15.1", + "14.4": "11.2", + "15.6": "12.5", + "14.0": "11.0", + "15.2": "12.1", + "16.4": "13.3", + "17.6": "14.6", + "16.0": "13.0", + "17.2": "14.2", + "13.3": "10.15.2", + "14.5": "11.3", + "18.0": "15.0", + "14.1": "11.0", + "15.3": "12.2", + "16.5": "13.4", + "16.1": "13.0", + "17.3": "14.3", + "13.4": "10.15.4", + "14.6": "11.4", + "14.2": "11.0", + "15.4": "12.3", + "16.6": "13.5", + "15.0": "12.0", + "16.2": "13.1", + "17.4": "14.4", + "17.0": "14.0", + "13.5": "10.15.5", + "14.7": "11.5", + "13.1": "10.15", + "14.3": "11.1", + "15.5": "12.4", + "16.3": "13.2", + "17.5": "14.5", + "17.1": "14.1", + "13.3.1": "10.15.3" + }, + "macOS_iOSMac": { + "12.0": "15.0", + "13.2": "16.3", + "14.4": "17.4", + "14.0": "17.0", + "11.3": "14.5", + "10.15.3": "13.3.1", + "12.5": "15.6", + "12.1": "15.2", + "13.3": "16.4", + "14.5": "17.5", + "12.0.1": "15.0", + "14.1": "17.1", + "10.15.2": "13.3", + "11.4": "14.6", + "11.0": "14.2", + "12.2": "15.3", + "13.4": "16.5", + "14.6": "17.6", + "10.15.1": "13.2", + "13.0": "16.1", + "14.2": "17.2", + "11.5": "14.7", + "15.0": "18.0", + "11.1": "14.3", + "12.3": "15.4", + "13.5": "16.6", + "13.1": "16.2", + "14.3": "17.3", + "10.15.5": "13.5", + "11.0.1": "14.2", + "10.15": "13.1", + "11.2": "14.4", + "12.4": "15.5", + "10.15.4": "13.4" + } + }, + "DefaultDeploymentTarget": "15.0", + "MaximumDeploymentTarget": "15.0.99", + "Variants": [ + { + "Name": "macos", + "BuildSettings": { + "_BOOL_": "NO", + "_IS_EMPTY_": "YES", + "CODE_SIGN_IDENTITY": "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "macos15.0", + "_DEVELOPMENT_TEAM_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(DEVELOPMENT_TEAM)))", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY))", + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "macos$(MACOSX_DEPLOYMENT_TARGET)", + "_BOOL_YES": "YES", + "CODE_SIGN_IDENTITY_YES": "-", + "CODE_SIGN_IDENTITY_NO": "Apple Development", + "_MACOSX_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(MACOSX_DEPLOYMENT_TARGET)))", + "_BOOL_NO": "NO", + "IPHONEOS_DEPLOYMENT_TARGET": "18.0", + "LLVM_TARGET_TRIPLE_SUFFIX": "" + } + }, + { + "Name": "iosmac", + "BuildSettings": { + "_BOOL_NO": "NO", + "SYSTEM_HEADER_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/include", + "SYSTEM_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/System\/Library\/Frameworks", + "SWIFT_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "_BOOL_": "NO", + "LLVM_TARGET_TRIPLE_OS_VERSION_YES": "ios18.0", + "_IS_EMPTY_": "YES", + "LIBRARY_SEARCH_PATHS": "$(inherited) $(SDKROOT)$(IOS_UNZIPPERED_TWIN_PREFIX_PATH)\/usr\/lib $(TOOLCHAIN_DIR)\/usr\/lib\/swift\/maccatalyst", + "TARGETED_DEVICE_FAMILY": "2", + "RESOURCES_UI_FRAMEWORK_FAMILY": "uikit", + "LLVM_TARGET_TRIPLE_SUFFIX": "-macabi", + "RESOURCES_MINIMUM_DEPLOYMENT_TARGET": "$(IPHONEOS_DEPLOYMENT_TARGET)", + "_BOOL_YES": "YES", + "_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY": "$(_BOOL_$(_IS_EMPTY_$(IPHONEOS_DEPLOYMENT_TARGET)))", + "IPHONEOS_DEPLOYMENT_TARGET": "18.0", + "CODE_SIGN_IDENTITY": "Apple Development", + "LLVM_TARGET_TRIPLE_OS_VERSION": "$(LLVM_TARGET_TRIPLE_OS_VERSION_$(_IPHONEOS_DEPLOYMENT_TARGET_IS_EMPTY))", + "RESOURCES_PLATFORM_NAME": "macosx", + "ENABLE_HARDENED_RUNTIME": "YES", + "LLVM_TARGET_TRIPLE_OS_VERSION_NO": "ios$(IPHONEOS_DEPLOYMENT_TARGET)" + } + } + ], + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "macosx15.0", + "CustomProperties": { + "KERNEL_EXTENSION_HEADER_SEARCH_PATHS": "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)" + } +} diff --git a/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/xros2.0.json b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/xros2.0.json new file mode 100644 index 0000000000000..3b9ec198d373b --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/xros2.0.json @@ -0,0 +1,110 @@ +{ + "DisplayName": "visionOS 2.0", + "DefaultProperties": { + "CODE_SIGN_ENTITLEMENTS": "", + "ENTITLEMENTS_REQUIRED": "YES", + "KASAN_DEFAULT_CFLAGS": "$(KASAN_CFLAGS_CLASSIC)", + "KASAN_DEFAULT_CFLAGS[arch=arm64]": "$(KASAN_CFLAGS_TBI)", + "KASAN_DEFAULT_CFLAGS[arch=arm64e]": "$(KASAN_CFLAGS_TBI)", + "DEAD_CODE_STRIPPING": "YES", + "GCC_THUMB_SUPPORT": "YES", + "SUPPORTED_DEVICE_FAMILIES": "7", + "TAPI_VERIFY_MODE": "Pedantic", + "TEST_LIBRARY_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/usr\/lib", + "PLATFORM_NAME": "xros", + "KASAN_CFLAGS_CLASSIC": "-DKASAN=1 -DKASAN_CLASSIC=1 -fsanitize=address -mllvm -asan-globals-live-support -mllvm -asan-force-dynamic-shadow", + "XROS_DEPLOYMENT_TARGET": "2.0", + "CODE_SIGNING_REQUIRED": "YES", + "CODE_SIGN_IDENTITY": "Apple Development", + "KASAN_CFLAGS_TBI": "-DKASAN=1 -DKASAN_TBI=1 -fsanitize=kernel-hwaddress -mllvm -hwasan-recover=0 -mllvm -hwasan-instrument-atomics=0 -mllvm -hwasan-instrument-stack=1 -mllvm -hwasan-generate-tags-with-calls=1 -mllvm -hwasan-instrument-with-calls=1 -mllvm -hwasan-use-short-granules=0 -mllvm -hwasan-memory-access-callback-prefix=__asan_", + "TEST_FRAMEWORK_SEARCH_PATHS": "$(inherited) $(PLATFORM_DIR)\/Developer\/Library\/Frameworks $(SDKROOT)\/Developer\/Library\/Frameworks", + "TAPI_USE_SRCROOT": "YES", + "ENTITLEMENTS_DESTINATION": "Signature", + "RESOURCES_PLATFORM_NAME": "xros", + "DEFAULT_COMPILER": "com.apple.compilers.llvm.clang.1_0", + "DEPLOYMENT_TARGET_SUGGESTED_VALUES": [ + "1.0", + "1.1", + "1.2", + "1.3", + "2.0" + ], + "AD_HOC_CODE_SIGNING_ALLOWED": "NO" + }, + "MinimalDisplayName": "2.0", + "Version": "2.0", + "IsBaseSDK": "YES", + "SupportedTargets": { + "xros": { + "LLVMTargetTripleVendor": "apple", + "DeploymentTargetSettingName": "XROS_DEPLOYMENT_TARGET", + "PlatformFamilyDisplayName": "visionOS", + "Archs": [ + "arm64e", + "arm64" + ], + "LLVMTargetTripleEnvironment": "", + "ClangRuntimeLibraryPlatformName": "xros", + "MaximumDeploymentTarget": "2.0.99", + "BuildVersionPlatformID": "11", + "DefaultDeploymentTarget": "2.0", + "LLVMTargetTripleSys": "xros", + "DeviceFamilies": [ + { + "Identifier": "7", + "Name": "vision", + "DisplayName": "Apple Vision" + } + ], + "MinimumDeploymentTarget": "1.0", + "SwiftConcurrencyMinimumDeploymentTarget": "1.0", + "SwiftOSRuntimeMinimumDeploymentTarget": "1.0", + "RecommendedDeploymentTarget": "1.0", + "PlatformFamilyName": "xrOS", + "SystemPrefix": "", + "ValidDeploymentTargets": [ + "1.0", + "1.1", + "1.2", + "1.3", + "2.0" + ] + } + }, + "PropertyConditionFallbackNames": [ + "embedded" + ], + "VersionMap": { + "xrOS_iOS": { + "1.2": "17.5", + "1.0": "17.1", + "2.0": "18.0", + "1.1": "17.4" + }, + "iOS_visionOS": { + "17.5": "1.2", + "17.1": "1.0", + "17.4": "1.1", + "18.0": "2.0" + }, + "iOS_xrOS": { + "17.5": "1.2", + "17.1": "1.0", + "17.4": "1.1", + "18.0": "2.0" + }, + "visionOS_iOS": { + "1.2": "17.5", + "1.0": "17.1", + "2.0": "18.0", + "1.1": "17.4" + } + }, + "DefaultDeploymentTarget": "2.0", + "MaximumDeploymentTarget": "2.0.99", + "DebuggerOptions": { + "SupportsViewDebugging": "YES" + }, + "CanonicalName": "xros2.0", + "CustomProperties": {} +} diff --git a/compiler/rustc_codegen_ssa/src/apple/tests.rs b/compiler/rustc_codegen_ssa/src/apple/tests.rs new file mode 100644 index 0000000000000..55b2b47f74635 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/tests.rs @@ -0,0 +1,120 @@ +use std::io; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use rustc_target::spec::AppleOSVersion; + +use super::{SDKSettings, add_version_to_llvm_target, find_sdk_root}; + +#[test] +fn test_add_version_to_llvm_target() { + let version = AppleOSVersion { major: 10, minor: 14, patch: 1 }; + assert_eq!( + add_version_to_llvm_target("aarch64-apple-macosx", version), + "aarch64-apple-macosx10.14.1" + ); + + let version = AppleOSVersion { major: 16, minor: 1, patch: 0 }; + assert_eq!( + add_version_to_llvm_target("aarch64-apple-ios-simulator", version), + "aarch64-apple-ios16.1.0-simulator" + ); +} + +fn find_sdk_root_xcrun(sdk_name: &str) -> io::Result { + let output = Command::new("xcrun") + .arg("-sdk") + .arg(sdk_name.to_lowercase()) + .arg("-show-sdk-path") + .output()?; + if output.status.success() { + // FIXME(madsmtm): If using this for real, we should not error on non-UTF-8 paths. + let output = String::from_utf8(output.stdout).unwrap(); + Ok(PathBuf::from(output.trim())) + } else { + let error = String::from_utf8(output.stderr); + let error = format!("process exit with error: {}", error.unwrap()); + Err(io::Error::new(io::ErrorKind::Other, &error[..])) + } +} + +/// Ensure that our `find_sdk_root` matches `xcrun`'s behaviour. +/// +/// `xcrun` is quite slow the first time it's run after a reboot, so this test may take some time. +#[test] +#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")] +fn test_find_sdk_root() { + let sdks = [ + "MacOSX", + "AppleTVOS", + "AppleTVSimulator", + "iPhoneOS", + "iPhoneSimulator", + "WatchOS", + "WatchSimulator", + "XROS", + "XRSimulator", + ]; + for sdk_name in sdks { + if let Ok(expected) = find_sdk_root_xcrun(sdk_name) { + // `xcrun` prefers `MacOSX14.0.sdk` over `MacOSX.sdk`, so let's compare canonical paths. + let expected = std::fs::canonicalize(expected).unwrap(); + let actual = find_sdk_root(sdk_name).unwrap(); + let actual = std::fs::canonicalize(actual).unwrap(); + assert_eq!(expected, actual); + } else { + // The macOS SDK must always be findable in Rust's CI. + // + // The other SDKs are allowed to not be found in the current developer directory when + // running this test. + if sdk_name == "MacOSX" { + panic!("Could not find macOS SDK with `xcrun -sdk macosx -show-sdk-path`"); + } + } + } +} + +#[test] +fn test_from_just_path() { + let cases = [ + ("", None), + ("MacOSX.sdk", None), + ("MacOSX10.13", None), + ("MacOSX99999.0.sdk", None), + ("MacOSX10.sdk", Some(("macosx10", (10, 0, 0)))), + ("MacOSX10.13.sdk", Some(("macosx10.13", (10, 13, 0)))), + ("MacOSX10.13.4.sdk", Some(("macosx10.13.4", (10, 13, 4)))), + // FIXME(madsmtm): Catch these cases? + ("InvalidSDKName10.0.sdk", Some(("invalidsdkname10.0", (10, 0, 0)))), + ("10.0.sdk", Some(("10.0", (10, 0, 0)))), + ]; + for (path, expected) in cases { + let settings = SDKSettings::from_just_path(Path::new(path)); + match (expected, settings) { + (Some((canonical_name, version)), Some(actual)) => { + assert_eq!(canonical_name, actual.canonical_name); + let (major, minor, patch) = version; + let version = AppleOSVersion { major, minor, patch }; + assert_eq!(version, actual.version); + } + (None, None) => {} + (expected, actual) => panic!("{expected:?} and {actual:?} were not equal"), + } + } +} + +#[test] +fn test_parse_sdk_settings() { + let samples = Path::new(env!("CARGO_MANIFEST_DIR")).join("src/apple/sample_sdk_settings"); + for sample in samples.read_dir().unwrap() { + let sample = sample.unwrap(); + let path = sample.path(); + if path.extension().unwrap() == "json" { + let s = std::fs::read_to_string(path).unwrap(); + + // Parse SDK and test that we can access properties without crashing + let settings: SDKSettings = serde_json::from_str(&s).unwrap(); + let _ = settings.mac_catalyst_prefix_path(); + } + } +} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e7b1c63a82251..c4a1efee88d87 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -38,9 +38,9 @@ use rustc_session::{Session, filesearch}; use rustc_span::symbol::Symbol; use rustc_target::spec::crt_objects::CrtObjects; use rustc_target::spec::{ - Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFeatures, - LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, - SplitDebuginfo, current_apple_deployment_target, + AppleOSVersion, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, + LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, + SanitizerSet, SplitDebuginfo, }; use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; @@ -50,6 +50,7 @@ use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; use super::rpath::{self, RPathConfig}; +use crate::apple::{SDKSettings, deployment_target, ld64_arch, versioned_llvm_target}; use crate::{ CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, looks_like_rust_object_file, @@ -2099,16 +2100,20 @@ fn add_library_search_dirs( cmd: &mut dyn Linker, sess: &Session, self_contained_components: LinkSelfContainedComponents, - apple_sdk_root: Option<&Path>, + apple_sdk_data: &Option<(PathBuf, SDKSettings)>, ) { if !sess.opts.unstable_opts.link_native_libraries { return; } + let apple_sdk_data = apple_sdk_data + .as_ref() + .map(|(sdkroot, settings)| (&**sdkroot, settings.mac_catalyst_prefix_path())); + walk_native_lib_search_dirs( sess, self_contained_components, - apple_sdk_root, + apple_sdk_data, |dir, is_framework| { if is_framework { cmd.framework_path(dir); @@ -2405,9 +2410,9 @@ fn add_order_independent_options( // Take care of the flavors and CLI options requesting the `lld` linker. add_lld_args(cmd, sess, flavor, self_contained_components); - add_apple_link_args(cmd, sess, flavor); + let apple_sdk_data = add_apple_sdk(cmd, sess, crate_type, flavor); - let apple_sdk_root = add_apple_sdk(cmd, sess, flavor); + add_apple_link_args(cmd, sess, flavor, &apple_sdk_data); add_link_script(cmd, sess, tmpdir, crate_type); @@ -2445,7 +2450,7 @@ fn add_order_independent_options( if flavor == LinkerFlavor::Llbc { cmd.link_args(&[ "--target", - sess.target.llvm_target.as_ref(), + &versioned_llvm_target(sess), "--target-cpu", &codegen_results.crate_info.target_cpu, ]); @@ -2463,7 +2468,7 @@ fn add_order_independent_options( cmd.linker_plugin_lto(); - add_library_search_dirs(cmd, sess, self_contained_components, apple_sdk_root.as_deref()); + add_library_search_dirs(cmd, sess, self_contained_components, &apple_sdk_data); cmd.output_filename(out_filename); @@ -2965,7 +2970,12 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool /// - The environment / ABI. /// - The deployment target. /// - The SDK version. -fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { +fn add_apple_link_args( + cmd: &mut dyn Linker, + sess: &Session, + flavor: LinkerFlavor, + settings: &Option<(PathBuf, SDKSettings)>, +) { if !sess.target.is_like_osx { return; } @@ -2973,32 +2983,9 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo return; }; - // `sess.target.arch` (`target_arch`) is not detailed enough. - let llvm_arch = sess.target.llvm_target.split_once('-').expect("LLVM target must have arch").0; let target_os = &*sess.target.os; let target_abi = &*sess.target.abi; - - // The architecture name to forward to the linker. - // - // Supported architecture names can be found in the source: - // https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648 - // - // Intentially verbose to ensure that the list always matches correctly - // with the list in the source above. - let ld64_arch = match llvm_arch { - "armv7k" => "armv7k", - "armv7s" => "armv7s", - "arm64" => "arm64", - "arm64e" => "arm64e", - "arm64_32" => "arm64_32", - // ld64 doesn't understand i686, so fall back to i386 instead. - // - // Same story when linking with cc, since that ends up invoking ld64. - "i386" | "i686" => "i386", - "x86_64" => "x86_64", - "x86_64h" => "x86_64h", - _ => bug!("unsupported architecture in Apple target: {}", sess.target.llvm_target), - }; + let ld64_arch = ld64_arch(&sess.target); if cc == Cc::No { // From the man page for ld64 (`man ld`): @@ -3037,7 +3024,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) = current_apple_deployment_target(&sess.target); + let AppleOSVersion { major, minor, patch } = deployment_target(sess); let min_version = format!("{major}.{minor}.{patch}"); // The SDK version is used at runtime when compiling with a newer SDK / version of Xcode: @@ -3048,31 +3035,41 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // `-[NSView wantsBestResolutionOpenGLSurface]` is `YES` when the SDK version is >= 10.15. // // - // We do not currently know the actual SDK version though, so we have a few options: - // 1. Use the minimum version supported by rustc. - // 2. Use the same as the deployment target. - // 3. Use an arbitary recent version. - // 4. Omit the version. + // So it is important that we pass the correct version here. // - // The first option is too low / too conservative, and means that users will not get the - // same behaviour from a binary compiled with rustc as with one compiled by clang. // - // The second option is similarly conservative, and also wrong since if the user specified a - // higher deployment target than the SDK they're compiling/linking with, the runtime might - // make invalid assumptions about the capabilities of the binary. + // For posterity, insufficient alternatives are listed below: // - // The third option requires that `rustc` is periodically kept up to date with Apple's SDK - // version, and is also wrong for similar reasons as above. + // 1. Use the minimum version supported by rustc. + // Too low / too conservative, and means that users will not get the same behaviour from + // a binary compiled with rustc as with one compiled by clang. // - // The fourth option is bad because while `ld`, `otool`, `vtool` and such understand it to - // mean "absent" or `n/a`, dyld doesn't actually understand it, and will end up interpreting - // it as 0.0, which is again too low/conservative. + // 2. Use the same as the deployment target. + // Similarly conservative, and also wrong since if the user specified a higher deployment + // target than the SDK they're compiling/linking with, the runtime might make invalid + // assumptions about the capabilities of the binary. // - // Currently, we lie about the SDK version, and choose the second option. + // 3. Use an arbitary recent version. + // Requires that `rustc` is periodically kept up to date with Apple's SDK version, and is + // also wrong for similar reasons as above. // - // FIXME(madsmtm): Parse the SDK version from the SDK root instead. - // - let sdk_version = &*min_version; + // 4. Omit the version. + // Bad because while `ld`, `otool`, `vtool` and such understand it to mean "absent" or + // `n/a`, dyld doesn't actually understand it, and will end up interpreting it as 0.0, + // which is again too low/conservative. + let AppleOSVersion { major, minor, patch } = if let Some((sdkroot, settings)) = settings { + settings.sdk_version(&sess.target, &sdkroot).unwrap_or_else(|err| { + sess.dcx().emit_err(err); + AppleOSVersion::MAX + }) + } else { + // If the SDK wasn't read properly, we may have errored already, but we may also only + // have given a warning to support `zig cc` on non-macOS hosts. `ld64` requires the SDK + // version though, so we must actually error here. + sess.dcx().emit_err(errors::AppleSdkError::MustHaveWhenUsingLd64); + AppleOSVersion::MAX + }; + let sdk_version = format!("{major}.{minor}.{patch}"); // From the man page for ld64 (`man ld`): // > This is set to indicate the platform, oldest supported version of @@ -3082,7 +3079,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // Like with `-arch`, the linker can figure out the platform versions // itself from the binaries being linked, but to be safe, we specify // the desired versions here explicitly. - cmd.link_args(&["-platform_version", platform_name, &*min_version, sdk_version]); + cmd.link_args(&["-platform_version", platform_name, &*min_version, &*sdk_version]); } else { // cc == Cc::Yes // @@ -3107,7 +3104,7 @@ 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) = current_apple_deployment_target(&sess.target); + let AppleOSVersion { major, minor, patch } = deployment_target(sess); // 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}")); @@ -3117,134 +3114,69 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`. } else { - cmd.cc_args(&["-target", &sess.target.llvm_target]); + cmd.cc_args(&["-target", &versioned_llvm_target(sess)]); } } } -fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option { - let arch = &sess.target.arch; - let os = &sess.target.os; - let llvm_target = &sess.target.llvm_target; - if sess.target.vendor != "apple" - || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos") - || !matches!(flavor, LinkerFlavor::Darwin(..)) - { +fn add_apple_sdk( + cmd: &mut dyn Linker, + sess: &Session, + crate_type: CrateType, + flavor: LinkerFlavor, +) -> Option<(PathBuf, SDKSettings)> { + if !sess.target.is_like_osx { return None; } - - if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) { + let LinkerFlavor::Darwin(cc, _) = flavor else { return None; - } - - let sdk_name = match (arch.as_ref(), os.as_ref()) { - ("aarch64", "tvos") if llvm_target.ends_with("-simulator") => "appletvsimulator", - ("aarch64", "tvos") => "appletvos", - ("x86_64", "tvos") => "appletvsimulator", - ("arm", "ios") => "iphoneos", - ("aarch64", "ios") if llvm_target.contains("macabi") => "macosx", - ("aarch64", "ios") if llvm_target.ends_with("-simulator") => "iphonesimulator", - ("aarch64", "ios") => "iphoneos", - ("x86", "ios") => "iphonesimulator", - ("x86_64", "ios") if llvm_target.contains("macabi") => "macosx", - ("x86_64", "ios") => "iphonesimulator", - ("x86_64", "watchos") => "watchsimulator", - ("arm64_32", "watchos") => "watchos", - ("aarch64", "watchos") if llvm_target.ends_with("-simulator") => "watchsimulator", - ("aarch64", "watchos") => "watchos", - ("aarch64", "visionos") if llvm_target.ends_with("-simulator") => "xrsimulator", - ("aarch64", "visionos") => "xros", - ("arm", "watchos") => "watchos", - (_, "macos") => "macosx", - _ => { - sess.dcx().emit_err(errors::UnsupportedArch { arch, os }); - return None; - } }; - let sdk_root = match get_apple_sdk_root(sdk_name) { - Ok(s) => s, + + let (sdkroot, settings) = match SDKSettings::from_environment(sess, crate_type) { + Ok((sdkroot, settings)) => (sdkroot, settings), Err(e) => { - sess.dcx().emit_err(e); + // If cross compiling from non-macOS, the user might be using something like `zig cc`. + // + // In that case, we shouldn't error when the SDK is missing, though we still warn. + if cfg!(target_os = "macos") { + sess.dcx().emit_err(e); + } else { + sess.dcx().emit_warn(e); + } return None; } }; - match flavor { - LinkerFlavor::Darwin(Cc::Yes, _) => { - // Use `-isysroot` instead of `--sysroot`, as only the former - // makes Clang treat it as a platform SDK. - // - // This is admittedly a bit strange, as on most targets - // `-isysroot` only applies to include header files, but on Apple - // targets this also applies to libraries and frameworks. - cmd.cc_args(&["-isysroot", &sdk_root]); - } - LinkerFlavor::Darwin(Cc::No, _) => { - cmd.link_args(&["-syslibroot", &sdk_root]); - } - _ => unreachable!(), + if cc == Cc::Yes { + // To pass the SDK root to `cc`, we have a few options: + // 1. `--sysroot` flag. + // 2. `-isysroot` flag. + // 3. `SDKROOT` environment variable. + // + // `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need to + // specify `-isysroot` - this is admittedly a bit strange, as on most targets `-isysroot` + // only applies to include header files, but on Apple targets it also applies to libraries + // and frameworks. + // + // Now, while the `-isysroot` flag is pretty well supported (both Clang and GCC implements + // the desired behaviour), it may not be understood by any `cc`'s that the user might want + // to use. + // + // So to better support such use-cases, we pass the SDK root in the standard environment + // variable instead. This is also supported by GCC since 2019: + // + // + // This also works better with the trampoline `/usr/bin/cc` which calls `xcrun cc` + // internally, since the presence of `SDKROOT` means it won't have to look up the SDK root + // itself. + cmd.cmd().env("SDKROOT", &sdkroot); + } else { + // For `ld64`, we use the `-syslibroot` parameter (and there are no other options). + cmd.link_arg("-syslibroot"); + cmd.link_arg(&sdkroot); } - Some(sdk_root.into()) -} - -fn get_apple_sdk_root(sdk_name: &str) -> Result> { - // Following what clang does - // (https://github.com/llvm/llvm-project/blob/ - // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678) - // to allow the SDK path to be set. (For clang, xcrun sets - // SDKROOT; for rustc, the user or build system can set it, or we - // can fall back to checking for xcrun on PATH.) - if let Ok(sdkroot) = env::var("SDKROOT") { - let p = Path::new(&sdkroot); - match sdk_name { - // Ignore `SDKROOT` if it's clearly set for the wrong platform. - "appletvos" - if sdkroot.contains("TVSimulator.platform") - || sdkroot.contains("MacOSX.platform") => {} - "appletvsimulator" - if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {} - "iphoneos" - if sdkroot.contains("iPhoneSimulator.platform") - || sdkroot.contains("MacOSX.platform") => {} - "iphonesimulator" - if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => { - } - "macosx" - if sdkroot.contains("iPhoneOS.platform") - || sdkroot.contains("iPhoneSimulator.platform") => {} - "watchos" - if sdkroot.contains("WatchSimulator.platform") - || sdkroot.contains("MacOSX.platform") => {} - "watchsimulator" - if sdkroot.contains("WatchOS.platform") || sdkroot.contains("MacOSX.platform") => {} - "xros" - if sdkroot.contains("XRSimulator.platform") - || sdkroot.contains("MacOSX.platform") => {} - "xrsimulator" - if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {} - // Ignore `SDKROOT` if it's not a valid path. - _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} - _ => return Ok(sdkroot), - } - } - let res = - Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then( - |output| { - if output.status.success() { - Ok(String::from_utf8(output.stdout).unwrap()) - } else { - let error = String::from_utf8(output.stderr); - let error = format!("process exit with error: {}", error.unwrap()); - Err(io::Error::new(io::ErrorKind::Other, &error[..])) - } - }, - ); - - match res { - Ok(output) => Ok(output.trim().to_string()), - Err(error) => Err(errors::AppleSdkRootError::SdkPath { sdk_name, error }), - } + Some((sdkroot, settings)) } /// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to @@ -3343,7 +3275,7 @@ fn add_lld_args( // targeting a different linker flavor on macOS, and that's also always // the case when targeting WASM. if sess.target.linker_flavor != sess.host.linker_flavor { - cmd.cc_arg(format!("--target={}", sess.target.llvm_target)); + cmd.cc_arg(format!("--target={}", versioned_llvm_target(sess))); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 8857fda1e9728..2fccf4f2c15a2 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -238,7 +238,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Option object::write::MachOBuildVersion { +fn macho_object_build_version_for_target(sess: &Session) -> object::write::MachOBuildVersion { + use rustc_target::spec::AppleOSVersion; + /// 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(version: AppleOSVersion) -> u32 { + let AppleOSVersion { major, minor, patch } = version; let (major, minor, patch) = (major as u32, minor as u32, patch as u32); (major << 16) | (minor << 8) | patch } let platform = - rustc_target::spec::current_apple_platform(target).expect("unknown Apple target OS"); - let min_os = rustc_target::spec::current_apple_deployment_target(target); + rustc_target::spec::current_apple_platform(&sess.target).expect("unknown Apple target OS"); + let min_os = crate::apple::deployment_target(sess); let mut build_version = object::write::MachOBuildVersion::default(); build_version.platform = platform; diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index ab909abcead8e..586768a606048 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; @@ -533,16 +534,72 @@ pub enum ExtractBundledLibsError<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_unsupported_arch)] -pub(crate) struct UnsupportedArch<'a> { - pub arch: &'a str, - pub os: &'a str, +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 }, + + #[diag(codegen_ssa_apple_deployment_target_too_high)] + TooHigh { sdk_max: String, version: String, env_var: &'static str }, } -#[derive(Diagnostic)] -pub(crate) enum AppleSdkRootError<'a> { - #[diag(codegen_ssa_apple_sdk_error_sdk_path)] - SdkPath { sdk_name: &'a str, error: Error }, +#[derive(Diagnostic, Debug)] +pub(crate) enum AppleSdkError { + #[diag(codegen_ssa_apple_sdk_error_failed_reading)] + FailedReading { path: PathBuf, error: std::io::Error }, + + #[diag(codegen_ssa_apple_sdk_error_invalid_sdk_settings_json)] + InvalidSDKSettingsJson { path: PathBuf, error: Box }, + + #[diag(codegen_ssa_apple_sdk_error_missing)] + Missing { sdk_name: &'static str }, + + #[diag(codegen_ssa_apple_sdk_error_missing_commandline_tools)] + MissingCommandlineTools { sdkroot: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_missing_cross_compile_non_macos)] + MissingCrossCompileNonMacOS { sdk_name: &'static str }, + + #[diag(codegen_ssa_apple_sdk_error_missing_developer_dir)] + MissingDeveloperDir { dir: PathBuf, sdkroot: PathBuf, sdkroot_bare: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_missing_mac_catalyst_version)] + MissingMacCatalystVersion { version: String }, + + #[diag(codegen_ssa_apple_sdk_error_missing_sdk_settings)] + MissingSDKSettings { sdkroot: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_missing_xcode)] + MissingXcode { sdkroot: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_missing_xcode_select)] + MissingXcodeSelect { dir: PathBuf, sdkroot: PathBuf, sdkroot_bare: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_must_have_when_using_ld64)] + MustHaveWhenUsingLd64, + + #[diag(codegen_ssa_apple_sdk_error_not_sdk_path)] + NotSdkPath { sdkroot: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_sdk_does_not_support_arch)] + SdkDoesNotSupportArch { sdkroot: PathBuf, arch: &'static str }, + + #[diag(codegen_ssa_apple_sdk_error_sdk_does_not_support_os)] + SdkDoesNotSupportOS { sdkroot: PathBuf, os: Cow<'static, str>, abi: Cow<'static, str> }, + + #[diag(codegen_ssa_apple_sdk_error_sdk_root_ignored)] + SdkRootIgnored, + + #[diag(codegen_ssa_apple_sdk_error_sdk_root_is_root_path)] + SdkRootIsRootPath, + + #[diag(codegen_ssa_apple_sdk_error_sdk_root_missing)] + SdkRootMissing { sdkroot: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_sdk_root_not_absolute)] + SdkRootNotAbsolute { sdkroot: PathBuf }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index cbd95146294f5..aeae825f30508 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -44,6 +44,7 @@ use rustc_session::cstore::{self, CrateSource}; use rustc_session::utils::NativeLibKind; use rustc_span::symbol::Symbol; +pub mod apple; pub mod assert_module_sources; pub mod back; pub mod base; diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index a59dea557bb96..18422cb3a71f9 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -855,12 +855,10 @@ fn print_crate_info( } } DeploymentTarget => { - use rustc_target::spec::current_apple_deployment_target; + use rustc_codegen_ssa::apple::deployment_target; if sess.target.is_like_osx { - let (major, minor, patch) = current_apple_deployment_target(&sess.target); - let patch = if patch != 0 { format!(".{patch}") } else { String::new() }; - println_info!("deployment_target={major}.{minor}{patch}") + println_info!("deployment_target={}", deployment_target(sess).pretty()) } else { #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("only Apple targets currently support deployment version info") diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index c7953d50406ac..e904808e62735 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -24,7 +24,7 @@ use crate::{errors, fluent_generated}; pub fn walk_native_lib_search_dirs( sess: &Session, self_contained_components: LinkSelfContainedComponents, - apple_sdk_root: Option<&Path>, + apple_sdk_data: Option<(&Path, &Path)>, mut f: impl FnMut(&Path, bool /*is_framework*/) -> ControlFlow, ) -> ControlFlow { // Library search paths explicitly supplied by user (`-L` on the command line). @@ -62,13 +62,17 @@ pub fn walk_native_lib_search_dirs( f(&sess.target_tlib_path.dir, false)?; } - // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks - // we must have the support library stubs in the library search path (#121430). - if let Some(sdk_root) = apple_sdk_root - && sess.target.llvm_target.contains("macabi") + // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks we must have the + // support library stubs under `/System/iOSSupport` in the library search path (#121430). + if let Some((sdkroot, mac_catalyst_prefix_path)) = apple_sdk_data + && sess.target.abi == "macabi" { - f(&sdk_root.join("System/iOSSupport/usr/lib"), false)?; - f(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"), true)?; + // `.join` with a root path replaces the path, while we want to extend the path. + let mac_catalyst_prefix_path = + mac_catalyst_prefix_path.strip_prefix("/").unwrap_or(mac_catalyst_prefix_path); + let root = sdkroot.join(mac_catalyst_prefix_path); + f(&root.join("usr/lib"), false)?; + f(&root.join("System/Library/Frameworks"), true)?; } ControlFlow::Continue(()) diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index c7d24154e8bd4..9f6556b58cd82 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -14,6 +14,7 @@ rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } +serde = "1" serde_json = "1.0.59" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 2121c4110dde6..d282cc183442e 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 73763cf034ca0..ae804afac6399 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,6 +1,9 @@ use std::borrow::Cow; -use std::env; +use std::fmt; use std::num::ParseIntError; +use std::str::FromStr; + +use serde::de; use crate::spec::{ Cc, DebuginfoKind, FramePointer, LinkerFlavor, Lld, SplitDebuginfo, StackProbeType, StaticCow, @@ -158,6 +161,23 @@ pub(crate) fn base( (opts, llvm_target(os, arch, abi), arch.target_arch()) } +pub fn sdk_name(target: &Target) -> &'static str { + match (&*target.os, &*target.abi) { + ("ios", "") => "iPhoneOS", + ("ios", "sim") => "iPhoneSimulator", + // Mac Catalyst uses the macOS SDK + ("ios", "macabi") => "MacOSX", + ("macos", "") => "MacOSX", + ("tvos", "") => "AppleTVOS", + ("tvos", "sim") => "AppleTVSimulator", + ("visionos", "") => "XROS", + ("visionos", "sim") => "XRSimulator", + ("watchos", "") => "WatchOS", + ("watchos", "sim") => "WatchSimulator", + (os, abi) => unreachable!("invalid os '{os}' / abi '{abi}' combination for Apple target"), + } +} + pub fn platform(target: &Target) -> Option { Some(match (&*target.os, &*target.abi) { ("macos", _) => object::macho::PLATFORM_MACOS, @@ -175,37 +195,16 @@ pub fn platform(target: &Target) -> Option { }) } -/// Hack for calling `deployment_target` outside of this module. -pub fn deployment_target_for_target(target: &Target) -> (u16, u8, u8) { - let arch = if target.llvm_target.starts_with("arm64e") { - Arch::Arm64e - } else if target.arch == "aarch64" { - Arch::Arm64 - } else { - // Dummy architecture, only used by `deployment_target` anyhow - Arch::X86_64 - }; - let abi = match &*target.abi { - "macabi" => TargetAbi::MacCatalyst, - "sim" => TargetAbi::Simulator, - "" => TargetAbi::Normal, - abi => unreachable!("invalid abi '{abi}' for Apple target"), - }; - deployment_target(&target.os, arch, abi) -} - -/// Get the deployment target based on the standard environment variables, or -/// fall back to a sane default. -fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) { - // When bumping a version in here, remember to update the platform-support - // docs too. +/// Minimum operating system versions currently supported by `rustc`. +pub fn os_minimum_deployment_target(os: &str) -> OSVersion { + // When bumping a version in here, remember to update the platform-support docs too. // - // NOTE: If you are looking for the default deployment target, prefer - // `rustc --print deployment-target`, as the default here may change in - // future `rustc` versions. - - // Minimum operating system versions currently supported by `rustc`. - let os_min = match os { + // 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), @@ -213,59 +212,47 @@ fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) { "visionos" => (1, 0, 0), _ => unreachable!("tried to get deployment target for non-Apple platform"), }; + OSVersion { major, minor, patch } +} - // On certain targets it makes sense to raise the minimum OS version. - // - // This matches what LLVM does, see: - // - let min = match (os, arch, abi) { - ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0), - ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::MacCatalyst) => (14, 0, 0), - ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), - ("ios", Arch::Arm64e, TargetAbi::Normal) => (14, 0, 0), +/// 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: +/// +pub fn minimum_deployment_target(target: &Target) -> OSVersion { + 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", _, TargetAbi::MacCatalyst) => (13, 1, 0), - ("tvos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), - ("watchos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (7, 0, 0), - _ => os_min, + ("ios", _, "macabi") => (13, 1, 0), + ("tvos", "aarch64", "sim") => (14, 0, 0), + ("watchos", "aarch64", "sim") => (7, 0, 0), + (os, _, _) => return os_minimum_deployment_target(os), }; + OSVersion { major, minor, patch } +} - // The environment variable used to fetch the deployment target. - let env_var = match 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"), - }; - - if let Ok(deployment_target) = env::var(env_var) { - match 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, - } - } else { - min } } /// Generate the target triple that we need to pass to LLVM and/or Clang. +/// +/// See `rustc_codegen_ssa::apple::llvm_target` for the full LLVM target. fn llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow { - // The target triple depends on the deployment target, and is required to - // enable features such as cross-language LTO, and for picking the right - // Mach-O commands. - // - // Certain optimizations also depend on the deployment target. - let (major, minor, patch) = deployment_target(os, arch, abi); let arch = arch.target_name(); // Convert to the "canonical" OS name used by LLVM: // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L236-L282 @@ -282,7 +269,7 @@ fn llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow { TargetAbi::MacCatalyst => "-macabi", TargetAbi::Simulator => "-simulator", }; - format!("{arch}-apple-{os}{major}.{minor}.{patch}{environment}").into() + format!("{arch}-apple-{os}{environment}").into() } fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { @@ -292,29 +279,10 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { // that's only applicable to cross-OS compilation. Always leave anything for the // host OS alone though. if os == "macos" { - let mut env_remove = Vec::with_capacity(2); - // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which - // may occur when we're linking a custom build script while targeting iOS for example. - if let Ok(sdkroot) = env::var("SDKROOT") { - if sdkroot.contains("iPhoneOS.platform") - || sdkroot.contains("iPhoneSimulator.platform") - || sdkroot.contains("AppleTVOS.platform") - || sdkroot.contains("AppleTVSimulator.platform") - || sdkroot.contains("WatchOS.platform") - || sdkroot.contains("WatchSimulator.platform") - || sdkroot.contains("XROS.platform") - || sdkroot.contains("XRSimulator.platform") - { - env_remove.push("SDKROOT".into()) - } - } - // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at + // `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", // although this is apparently ignored when using the linker at "/usr/bin/ld". - env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into()); - env_remove.push("TVOS_DEPLOYMENT_TARGET".into()); - env_remove.push("XROS_DEPLOYMENT_TARGET".into()); - env_remove.into() + cvs!["IPHONEOS_DEPLOYMENT_TARGET", "TVOS_DEPLOYMENT_TARGET", "XROS_DEPLOYMENT_TARGET"] } else { // Otherwise if cross-compiling for a different OS/SDK (including Mac Catalyst), remove any part // of the linking environment that's wrong and reversed. @@ -322,19 +290,71 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { } } -/// Parse an OS version triple (SDK version or deployment target). +/// Deployment target or SDK version. /// -/// The size of the returned numbers here are limited by Mach-O's -/// `LC_BUILD_VERSION`. -fn parse_version(version: &str) -> Result<(u16, u8, u8), 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()?)) +/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct OSVersion { + pub major: u16, + pub minor: u8, + pub patch: u8, +} + +impl OSVersion { + pub const MIN: Self = Self { major: u16::MIN, minor: u8::MIN, patch: u8::MIN }; + + pub const MAX: Self = Self { major: u16::MAX, minor: u8::MAX, patch: u8::MAX }; + + pub fn pretty(self) -> impl fmt::Display { + let OSVersion { major, minor, patch } = self; + fmt::from_fn(move |f| { + write!(f, "{major}.{minor}")?; + if patch != 0 { + write!(f, ".{patch}")?; + } + Ok(()) + }) + } +} + +impl<'de> de::Deserialize<'de> for OSVersion { + fn deserialize>(deserializer: D) -> Result { + struct OSVersionVisitor; + + impl<'de> de::Visitor<'de> for OSVersionVisitor { + type Value = OSVersion; + + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("a valid `major.minor.patch` version") + } + + fn visit_str(self, value: &str) -> Result { + OSVersion::from_str(value).map_err(E::custom) + } + } + + deserializer.deserialize_str(OSVersionVisitor) + } +} + +impl FromStr for OSVersion { + type Err = ParseIntError; + + /// Parse an OS version triple (SDK version or deployment target). + fn from_str(version: &str) -> Result { + if let Some((major, minor)) = version.split_once('.') { + let major = major.parse()?; + if let Some((minor, patch)) = minor.split_once('.') { + let minor = minor.parse()?; + let patch = patch.parse()?; + Ok(Self { major, minor, patch }) + } else { + let minor = minor.parse()?; + Ok(Self { major, minor, patch: 0 }) + } } else { - Ok((major, minor.parse()?, 0)) + let major = version.parse()?; + Ok(Self { major, minor: 0, patch: 0 }) } - } else { - Ok((version.parse()?, 0, 0)) } } diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs index 9435b9a5bad59..b23c04870e1ef 100644 --- a/compiler/rustc_target/src/spec/base/apple/tests.rs +++ b/compiler/rustc_target/src/spec/base/apple/tests.rs @@ -1,4 +1,6 @@ -use super::parse_version; +use std::str::FromStr; + +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, @@ -43,8 +45,14 @@ fn macos_link_environment_unmodified() { #[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))); + let cases = [ + ("10", 10, 0, 0), + ("10.12", 10, 12, 0), + ("10.12.6", 10, 12, 6), + ("9999.99.99", 9999, 99, 99), + ]; + for (str, major, minor, patch) in cases { + let expected = OSVersion { major, minor, patch }; + assert_eq!(Ok(expected), OSVersion::from_str(str)); + } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 82e11a3afce32..b6dee7055f190 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -60,8 +60,10 @@ pub mod crt_objects; mod base; pub use base::apple::{ - deployment_target_for_target as current_apple_deployment_target, - platform as current_apple_platform, + OSVersion as AppleOSVersion, deployment_target_env_var as apple_deployment_target_env_var, + minimum_deployment_target as apple_minimum_deployment_target, + os_minimum_deployment_target as apple_os_minimum_deployment_target, + platform as current_apple_platform, sdk_name as apple_sdk_name, }; pub use base::avr_gnu::ef_avr_arch; @@ -2002,7 +2004,12 @@ impl TargetWarnings { /// Every field here must be specified, and has no default value. #[derive(PartialEq, Clone, Debug)] pub struct Target { - /// Target triple to pass to LLVM. + /// Unversioned target triple to pass to LLVM. + /// + /// Target triples can optionally contain an OS version (notably Apple targets), which rustc + /// cannot know without querying the environment. + /// + /// Use `rustc_codegen_ssa::apple::versioned_llvm_target` if you need the full LLVM target. pub llvm_target: StaticCow, /// Metadata about a target, for example the description or tier. /// Used for generating target documentation. diff --git a/tests/run-make/apple-sdk-version/rmake.rs b/tests/run-make/apple-sdk-version/rmake.rs index 6463ec0040359..9c56e4862d1d0 100644 --- a/tests/run-make/apple-sdk-version/rmake.rs +++ b/tests/run-make/apple-sdk-version/rmake.rs @@ -23,12 +23,6 @@ fn has_sdk_version(file: &str, version: &str) { } fn main() { - // Fetch rustc's inferred deployment target. - let current_deployment_target = - rustc().target(target()).print("deployment-target").run().stdout_utf8(); - let current_deployment_target = - current_deployment_target.strip_prefix("deployment_target=").unwrap().trim(); - // Fetch current SDK version via. xcrun. // // Assumes a standard Xcode distribution, where e.g. the macOS SDK's Mac Catalyst @@ -87,9 +81,6 @@ fn main() { .input("foo.rs") .output(&file_name) .run(); - // FIXME(madsmtm): This uses the current deployment target - // instead of the current SDK version like Clang does. - // https://github.com/rust-lang/rust/issues/129432 - has_sdk_version(&file_name, current_deployment_target); + has_sdk_version(&file_name, current_sdk_version); } }