From 3a2f4dbe6435a1a1dd750ea8aae28bb00a893a38 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 3 Oct 2024 16:49:39 +0200 Subject: [PATCH 1/9] Move versioned LLVM target creation to rustc_codegen_ssa The OS version depends on the deployment target environment variables, the access of which we want to move to later in the compilation pipeline that has access to more information, for example `env_depinfo`. --- compiler/rustc_codegen_cranelift/src/lib.rs | 5 +- compiler/rustc_codegen_llvm/src/back/write.rs | 3 +- compiler/rustc_codegen_llvm/src/context.rs | 3 +- compiler/rustc_codegen_ssa/src/apple.rs | 69 +++++++++++ compiler/rustc_codegen_ssa/src/apple/tests.rs | 13 ++ compiler/rustc_codegen_ssa/src/back/link.rs | 13 +- .../rustc_codegen_ssa/src/back/metadata.rs | 8 +- compiler/rustc_codegen_ssa/src/lib.rs | 1 + compiler/rustc_driver_impl/src/lib.rs | 4 +- .../rustc_target/src/spec/base/apple/mod.rs | 117 +++++++----------- compiler/rustc_target/src/spec/mod.rs | 13 +- 11 files changed, 155 insertions(+), 94 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/apple.rs create mode 100644 compiler/rustc_codegen_ssa/src/apple/tests.rs 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 2b8912d1db2ab..903e55e67346e 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/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs new file mode 100644 index 0000000000000..23acfde5fd4f5 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -0,0 +1,69 @@ +use std::borrow::Cow; +use std::env; + +use rustc_session::Session; +use rustc_target::spec::{ + AppleOSVersion, apple_deployment_target_env_var, apple_minimum_deployment_target, + apple_parse_version, +}; + +#[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 min = apple_minimum_deployment_target(&sess.target); + + if let Ok(deployment_target) = env::var(apple_deployment_target_env_var(&sess.target.os)) { + match apple_parse_version(&deployment_target) { + // It is common that the deployment target is set too low, e.g. on macOS Aarch64 to also + // target older x86_64, the user may set a lower deployment target than supported. + // + // To avoid such issues, we silently raise the deployment target here. + // FIXME: We want to show a warning when `version < os_min`. + Ok(version) => version.max(min), + // FIXME: Report erroneous environment variable to user. + Err(_) => min, + } + } 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 (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() + } +} 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..1edf0f0034fbf --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/tests.rs @@ -0,0 +1,13 @@ +use super::add_version_to_llvm_target; + +#[test] +fn test_add_version_to_llvm_target() { + assert_eq!( + add_version_to_llvm_target("aarch64-apple-macosx", (10, 14, 1)), + "aarch64-apple-macosx10.14.1" + ); + assert_eq!( + add_version_to_llvm_target("aarch64-apple-ios-simulator", (16, 1, 0)), + "aarch64-apple-ios16.1.0-simulator" + ); +} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e7b1c63a82251..878cdff9300b9 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -40,7 +40,7 @@ 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, + 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::{deployment_target, versioned_llvm_target}; use crate::{ CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, looks_like_rust_object_file, @@ -2445,7 +2446,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, ]); @@ -3037,7 +3038,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 (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: @@ -3107,7 +3108,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 (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,7 +3118,7 @@ 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)]); } } } @@ -3343,7 +3344,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..4cfda916ec24f 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 { /// 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 { @@ -400,8 +400,8 @@ fn macho_object_build_version_for_target(target: &Target) -> object::write::Mach } 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/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 162d14272a555..cae753ae50cee 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 76b7270d4b815..2ebcb245ed112 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -856,10 +856,8 @@ fn print_crate_info( } } DeploymentTarget => { - use rustc_target::spec::current_apple_deployment_target; - if sess.target.is_like_osx { - let (major, minor, patch) = current_apple_deployment_target(&sess.target); + let (major, minor, patch) = rustc_codegen_ssa::apple::deployment_target(sess); let patch = if patch != 0 { format!(".{patch}") } else { String::new() }; println_info!("deployment_target={major}.{minor}{patch}") } else { diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 73763cf034ca0..5ea77a29351c0 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -175,97 +175,62 @@ 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 + // ``` + match os { "macos" => (10, 12, 0), "ios" => (10, 0, 0), "tvos" => (10, 0, 0), "watchos" => (5, 0, 0), "visionos" => (1, 0, 0), _ => unreachable!("tried to get deployment target for non-Apple platform"), - }; + } +} - // 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 { + 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, _, _) => os_minimum_deployment_target(os), + } +} - // 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 +247,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]> { @@ -322,11 +287,13 @@ 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> { +/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. +pub type OSVersion = (u16, u8, u8); + +/// Parse an OS version triple (SDK version or deployment target). +pub fn parse_version(version: &str) -> Result { if let Some((major, minor)) = version.split_once('.') { let major = major.parse()?; if let Some((minor, patch)) = minor.split_once('.') { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c557091242e98..6401806fdf9df 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, + parse_version as apple_parse_version, platform as current_apple_platform, }; pub use base::avr_gnu::ef_avr_arch; @@ -1997,7 +1999,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. From 7750660e57fd1ed4302d4d12cbd76514e15e6a64 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 29 Sep 2024 22:14:55 +0200 Subject: [PATCH 2/9] Emit diagnostics for incorrect deployment targets --- compiler/rustc_codegen_ssa/messages.ftl | 6 +++ compiler/rustc_codegen_ssa/src/apple.rs | 48 +++++++++++++++++++----- compiler/rustc_codegen_ssa/src/errors.rs | 9 +++++ compiler/rustc_codegen_ssa/src/lib.rs | 1 + compiler/rustc_driver_impl/src/lib.rs | 6 +-- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 9091602d75b71..7c6ace84ee1ae 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -2,6 +2,12 @@ codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not imp codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} +codegen_ssa_apple_deployment_target_invalid = + failed to parse deployment target specified in {$env_var}: {$error} + +codegen_ssa_apple_deployment_target_too_low = + deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} + codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs index 23acfde5fd4f5..21ef509553182 100644 --- a/compiler/rustc_codegen_ssa/src/apple.rs +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -1,30 +1,58 @@ use std::borrow::Cow; use std::env; +use std::fmt::{Display, from_fn}; use rustc_session::Session; use rustc_target::spec::{ AppleOSVersion, apple_deployment_target_env_var, apple_minimum_deployment_target, - apple_parse_version, + apple_os_minimum_deployment_target, apple_parse_version, }; +use crate::errors::AppleDeploymentTarget; + #[cfg(test)] mod tests; +pub fn pretty_version(version: AppleOSVersion) -> impl Display { + let (major, minor, patch) = version; + from_fn(move |f| { + write!(f, "{major}.{minor}")?; + if patch != 0 { + write!(f, ".{patch}")?; + } + Ok(()) + }) +} + /// Get the deployment target based on the standard environment variables, or fall back to the /// minimum version supported by `rustc`. pub fn deployment_target(sess: &Session) -> AppleOSVersion { + let os_min = apple_os_minimum_deployment_target(&sess.target.os); let min = apple_minimum_deployment_target(&sess.target); + let env_var = apple_deployment_target_env_var(&sess.target.os); - if let Ok(deployment_target) = env::var(apple_deployment_target_env_var(&sess.target.os)) { + if let Ok(deployment_target) = env::var(env_var) { match apple_parse_version(&deployment_target) { - // It is common that the deployment target is set too low, e.g. on macOS Aarch64 to also - // target older x86_64, the user may set a lower deployment target than supported. - // - // To avoid such issues, we silently raise the deployment target here. - // FIXME: We want to show a warning when `version < os_min`. - Ok(version) => version.max(min), - // FIXME: Report erroneous environment variable to user. - Err(_) => min, + Ok(version) => { + // It is common that the deployment target is set a bit too low, for example on + // macOS Aarch64 to also target older x86_64. So we only want to warn when variable + // is lower than the minimum OS supported by rustc, not when the variable is lower + // than the minimum for a specific target. + if version < os_min { + sess.dcx().emit_warn(AppleDeploymentTarget::TooLow { + env_var, + version: pretty_version(version).to_string(), + os_min: pretty_version(os_min).to_string(), + }); + } + + // Raise the deployment target to the minimum supported. + version.max(min) + } + Err(error) => { + sess.dcx().emit_err(AppleDeploymentTarget::Invalid { env_var, error }); + min + } } } else { // If no deployment target variable is set, default to the minimum found above. diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 08b326e3ac3c6..5dadfdc66a2bc 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::io::Error; +use std::num::ParseIntError; use std::path::{Path, PathBuf}; use std::process::ExitStatus; @@ -539,6 +540,14 @@ pub(crate) struct UnsupportedArch<'a> { pub os: &'a str, } +#[derive(Diagnostic)] +pub(crate) enum AppleDeploymentTarget { + #[diag(codegen_ssa_apple_deployment_target_invalid)] + Invalid { env_var: &'static str, error: ParseIntError }, + #[diag(codegen_ssa_apple_deployment_target_too_low)] + TooLow { env_var: &'static str, version: String, os_min: String }, +} + #[derive(Diagnostic)] pub(crate) enum AppleSdkRootError<'a> { #[diag(codegen_ssa_apple_sdk_error_sdk_path)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index cae753ae50cee..a79424e28c6e1 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2ebcb245ed112..d743148f316df 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -856,10 +856,10 @@ fn print_crate_info( } } DeploymentTarget => { + use rustc_codegen_ssa::apple::{deployment_target, pretty_version}; + if sess.target.is_like_osx { - let (major, minor, patch) = rustc_codegen_ssa::apple::deployment_target(sess); - let patch = if patch != 0 { format!(".{patch}") } else { String::new() }; - println_info!("deployment_target={major}.{minor}{patch}") + println_info!("deployment_target={}", pretty_version(deployment_target(sess))) } else { #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("only Apple targets currently support deployment version info") From 80551911e3755e6669aade75253c374f26ec8458 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 9 Oct 2024 05:40:55 +0200 Subject: [PATCH 3/9] Move knowledge of SDK names to rustc_target Also make the SDK name be the same casing as used in the file system. --- compiler/rustc_codegen_ssa/messages.ftl | 2 - compiler/rustc_codegen_ssa/src/back/link.rs | 57 ++++++------------- compiler/rustc_codegen_ssa/src/errors.rs | 7 --- .../rustc_target/src/spec/base/apple/mod.rs | 17 ++++++ compiler/rustc_target/src/spec/mod.rs | 2 +- 5 files changed, 36 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index f02b0f7267430..5e83cab6b2636 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -337,8 +337,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/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e7b1c63a82251..566fe7e6ea080 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3123,9 +3123,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo } 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(..)) @@ -3137,30 +3135,8 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> 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_name = rustc_target::spec::apple_sdk_name(&sess.target); + let sdk_root = match get_apple_sdk_root(sdk_name) { Ok(s) => s, Err(e) => { @@ -3197,7 +3173,7 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result Result 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[..])) - } - }, - ); + + let res = Command::new("xcrun") + .arg("--show-sdk-path") + .arg("-sdk") + .arg(sdk_name.to_lowercase()) + .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()), diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index ab909abcead8e..4ec95d11c6848 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -532,13 +532,6 @@ pub enum ExtractBundledLibsError<'a> { ExtractSection { rlib: &'a Path, error: Box }, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_unsupported_arch)] -pub(crate) struct UnsupportedArch<'a> { - pub arch: &'a str, - pub os: &'a str, -} - #[derive(Diagnostic)] pub(crate) enum AppleSdkRootError<'a> { #[diag(codegen_ssa_apple_sdk_error_sdk_path)] diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 73763cf034ca0..50a16a9078bac 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -158,6 +158,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, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 82e11a3afce32..a8cfc3ff80fff 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -61,7 +61,7 @@ pub mod crt_objects; mod base; pub use base::apple::{ deployment_target_for_target as current_apple_deployment_target, - platform as current_apple_platform, + platform as current_apple_platform, sdk_name as apple_sdk_name, }; pub use base::avr_gnu::ef_avr_arch; From f91a3b860d10caeb1f7edf3fbe09b15230a85c0f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 9 Oct 2024 04:57:56 +0200 Subject: [PATCH 4/9] Re-implement SDK discovery instead of using xcrun --- compiler/rustc_codegen_ssa/messages.ftl | 41 +++++- compiler/rustc_codegen_ssa/src/apple.rs | 136 ++++++++++++++++++ compiler/rustc_codegen_ssa/src/apple/tests.rs | 58 ++++++++ compiler/rustc_codegen_ssa/src/back/link.rs | 39 ++--- compiler/rustc_codegen_ssa/src/errors.rs | 26 +++- compiler/rustc_codegen_ssa/src/lib.rs | 1 + 6 files changed, 268 insertions(+), 33 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/apple.rs create mode 100644 compiler/rustc_codegen_ssa/src/apple/tests.rs diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 5e83cab6b2636..c55c57105f524 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -2,7 +2,46 @@ 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_sdk_error_failed_reading = + failed reading `{$path}` while looking for SDK root: {$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_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_archive_build_failure = failed to build archive at `{$path}`: {$error} diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs new file mode 100644 index 0000000000000..9518a1cc1f894 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -0,0 +1,136 @@ +use std::fs; +use std::io::ErrorKind; +use std::path::{Path, PathBuf}; + +use crate::errors::AppleSdkError; + +#[cfg(test)] +mod tests; + +// 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); + 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. +pub(crate) 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 }) +} 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..fed942866b9f2 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/apple/tests.rs @@ -0,0 +1,58 @@ +use std::io; +use std::path::PathBuf; +use std::process::Command; + +use super::find_sdk_root; + +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`"); + } + } + } +} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 566fe7e6ea080..fef54e90402d5 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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::find_sdk_root; use crate::{ CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, looks_like_rust_object_file, @@ -3153,26 +3154,26 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> // 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]); + cmd.cc_arg("-isysroot"); + cmd.cc_arg(&sdk_root); } LinkerFlavor::Darwin(Cc::No, _) => { - cmd.link_args(&["-syslibroot", &sdk_root]); + cmd.link_arg("-syslibroot"); + cmd.link_arg(&sdk_root); } _ => unreachable!(), } - Some(sdk_root.into()) + Some(sdk_root) } -fn get_apple_sdk_root(sdk_name: &str) -> Result> { +fn get_apple_sdk_root(sdk_name: &'static 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.) + // to allow the SDK path to be set. if let Ok(sdkroot) = env::var("SDKROOT") { - let p = Path::new(&sdkroot); + let p = PathBuf::from(&sdkroot); match &*sdk_name.to_lowercase() { // Ignore `SDKROOT` if it's clearly set for the wrong platform. "appletvos" @@ -3201,29 +3202,11 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result {} // Ignore `SDKROOT` if it's not a valid path. _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} - _ => return Ok(sdkroot), + _ => return Ok(p), } } - let res = Command::new("xcrun") - .arg("--show-sdk-path") - .arg("-sdk") - .arg(sdk_name.to_lowercase()) - .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 }), - } + find_sdk_root(sdk_name) } /// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 4ec95d11c6848..635da6b422e94 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -532,10 +532,28 @@ pub enum ExtractBundledLibsError<'a> { ExtractSection { rlib: &'a Path, error: Box }, } -#[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_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_xcode)] + MissingXcode { sdkroot: PathBuf }, + + #[diag(codegen_ssa_apple_sdk_error_missing_xcode_select)] + MissingXcodeSelect { dir: PathBuf, sdkroot: PathBuf, sdkroot_bare: 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; From 6d94e37b38792ccbccb661a73e4e6da801be8a5f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 00:31:48 +0200 Subject: [PATCH 5/9] Always attempt to get SDK root, and pass it to Clang via env var The exact reasoning why we do not always pass the SDK root with `-isysroot` to `cc` when linking on macOS eludes me (the git history dead ends in #100286), but I suspect it's because we want to support `cc`s which do not support this option. So instead, we pass the SDK root via the environment variable SDKROOT. This way, compiler drivers that support setting the SDK root (such as Clang and GCC) can use it, while compiler drivers that don't (presumably because they figure out the SDK root in some other way) can just ignore it. This fixes https://github.com/rust-lang/rust/issues/80817 (by always passing the SDK root, even when linking with cc on macOS). --- compiler/rustc_codegen_ssa/src/back/link.rs | 67 +++++++++++-------- .../rustc_target/src/spec/base/apple/mod.rs | 24 +------ 2 files changed, 42 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d218e78b31f1e..620699f883f03 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3124,47 +3124,60 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo } fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option { - let os = &sess.target.os; - if sess.target.vendor != "apple" - || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos") - || !matches!(flavor, LinkerFlavor::Darwin(..)) - { + 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 = rustc_target::spec::apple_sdk_name(&sess.target); - let sdk_root = match get_apple_sdk_root(sdk_name) { + let sdkroot = match get_apple_sdk_root(sdk_name) { Ok(s) => s, 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_arg("-isysroot"); - cmd.cc_arg(&sdk_root); - } - LinkerFlavor::Darwin(Cc::No, _) => { - cmd.link_arg("-syslibroot"); - cmd.link_arg(&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) + Some(sdkroot) } fn get_apple_sdk_root(sdk_name: &'static str) -> Result { diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 7eb5d626e34f1..a88e1a655dd61 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::env; use std::num::ParseIntError; use crate::spec::{ @@ -274,29 +273,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. From 51204a98116a8f693f7de4c317fb04c6c28fd21f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 02:48:52 +0200 Subject: [PATCH 6/9] Convert OSVersion to a struct that implements traits Instead of being a type-alias to a tuple. This allows us to implement Deserialize for OSVersion, which will be useful when parsing SDK settings. --- Cargo.lock | 1 + compiler/rustc_codegen_ssa/src/apple.rs | 25 ++---- compiler/rustc_codegen_ssa/src/apple/tests.rs | 9 +- compiler/rustc_codegen_ssa/src/back/link.rs | 10 +-- .../rustc_codegen_ssa/src/back/metadata.rs | 5 +- compiler/rustc_codegen_ssa/src/lib.rs | 1 - compiler/rustc_driver_impl/src/lib.rs | 4 +- compiler/rustc_target/Cargo.toml | 1 + compiler/rustc_target/src/lib.rs | 1 + .../rustc_target/src/spec/base/apple/mod.rs | 88 +++++++++++++++---- .../rustc_target/src/spec/base/apple/tests.rs | 18 ++-- compiler/rustc_target/src/spec/mod.rs | 3 +- 12 files changed, 113 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 502920350d5c5..4648774b8b13f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4450,6 +4450,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "serde", "serde_json", "tracing", ] diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs index c34a912366b75..33450bec328c8 100644 --- a/compiler/rustc_codegen_ssa/src/apple.rs +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -1,14 +1,12 @@ use std::borrow::Cow; -use std::env; -use std::fs; use std::io::ErrorKind; -use std::fmt::{Display, from_fn}; use std::path::{Path, PathBuf}; +use std::{env, fs}; use rustc_session::Session; use rustc_target::spec::{ AppleOSVersion, apple_deployment_target_env_var, apple_minimum_deployment_target, - apple_os_minimum_deployment_target, apple_parse_version, + apple_os_minimum_deployment_target, }; use crate::errors::{AppleDeploymentTarget, AppleSdkError}; @@ -16,17 +14,6 @@ use crate::errors::{AppleDeploymentTarget, AppleSdkError}; #[cfg(test)] mod tests; -pub fn pretty_version(version: AppleOSVersion) -> impl Display { - let (major, minor, patch) = version; - from_fn(move |f| { - write!(f, "{major}.{minor}")?; - if patch != 0 { - write!(f, ".{patch}")?; - } - Ok(()) - }) -} - /// Get the deployment target based on the standard environment variables, or fall back to the /// minimum version supported by `rustc`. pub fn deployment_target(sess: &Session) -> AppleOSVersion { @@ -35,7 +22,7 @@ pub fn deployment_target(sess: &Session) -> AppleOSVersion { let env_var = apple_deployment_target_env_var(&sess.target.os); if let Ok(deployment_target) = env::var(env_var) { - match apple_parse_version(&deployment_target) { + 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 @@ -44,8 +31,8 @@ pub fn deployment_target(sess: &Session) -> AppleOSVersion { if version < os_min { sess.dcx().emit_warn(AppleDeploymentTarget::TooLow { env_var, - version: pretty_version(version).to_string(), - os_min: pretty_version(os_min).to_string(), + version: version.pretty().to_string(), + os_min: os_min.pretty().to_string(), }); } @@ -71,7 +58,7 @@ fn add_version_to_llvm_target(llvm_target: &str, deployment_target: AppleOSVersi let environment = components.next(); assert_eq!(components.next(), None, "too many LLVM triple components"); - let (major, minor, patch) = deployment_target; + let AppleOSVersion { major, minor, patch } = deployment_target; assert!( !os.contains(|c: char| c.is_ascii_digit()), diff --git a/compiler/rustc_codegen_ssa/src/apple/tests.rs b/compiler/rustc_codegen_ssa/src/apple/tests.rs index cac186c4d2f1c..eeaf8776022ca 100644 --- a/compiler/rustc_codegen_ssa/src/apple/tests.rs +++ b/compiler/rustc_codegen_ssa/src/apple/tests.rs @@ -2,16 +2,21 @@ use std::io; use std::path::PathBuf; use std::process::Command; +use rustc_target::spec::AppleOSVersion; + use super::{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", (10, 14, 1)), + 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", (16, 1, 0)), + add_version_to_llvm_target("aarch64-apple-ios-simulator", version), "aarch64-apple-ios16.1.0-simulator" ); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 620699f883f03..e2316179aaa7e 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, + AppleOSVersion, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, + LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, + SanitizerSet, SplitDebuginfo, }; use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; @@ -3038,7 +3038,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) = deployment_target(sess); + 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: @@ -3108,7 +3108,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) = deployment_target(sess); + 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}")); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 4cfda916ec24f..2fccf4f2c15a2 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -392,9 +392,12 @@ pub(crate) fn create_object_file(sess: &Session) -> Option 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 } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 5310c2295ed0f..aeae825f30508 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -6,7 +6,6 @@ #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] -#![feature(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d99633e1baa37..18422cb3a71f9 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -855,10 +855,10 @@ fn print_crate_info( } } DeploymentTarget => { - use rustc_codegen_ssa::apple::{deployment_target, pretty_version}; + use rustc_codegen_ssa::apple::deployment_target; if sess.target.is_like_osx { - println_info!("deployment_target={}", pretty_version(deployment_target(sess))) + 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_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 a88e1a655dd61..ae804afac6399 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,5 +1,9 @@ use std::borrow::Cow; +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, @@ -200,14 +204,15 @@ pub fn os_minimum_deployment_target(os: &str) -> OSVersion { // ``` // $ rustc --print deployment-target // ``` - match os { + let (major, minor, patch) = match os { "macos" => (10, 12, 0), "ios" => (10, 0, 0), "tvos" => (10, 0, 0), "watchos" => (5, 0, 0), "visionos" => (1, 0, 0), _ => unreachable!("tried to get deployment target for non-Apple platform"), - } + }; + OSVersion { major, minor, patch } } /// The deployment target for the given target. @@ -218,7 +223,7 @@ pub fn os_minimum_deployment_target(os: &str) -> OSVersion { /// This matches what LLVM does, see in part: /// pub fn minimum_deployment_target(target: &Target) -> OSVersion { - match (&*target.os, &*target.arch, &*target.abi) { + 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), @@ -227,8 +232,9 @@ pub fn minimum_deployment_target(target: &Target) -> OSVersion { ("ios", _, "macabi") => (13, 1, 0), ("tvos", "aarch64", "sim") => (14, 0, 0), ("watchos", "aarch64", "sim") => (7, 0, 0), - (os, _, _) => os_minimum_deployment_target(os), - } + (os, _, _) => return os_minimum_deployment_target(os), + }; + OSVersion { major, minor, patch } } /// Name of the environment variable used to fetch the deployment target on the given OS. @@ -287,18 +293,68 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { /// Deployment target or SDK version. /// /// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. -pub type OSVersion = (u16, u8, u8); - -/// Parse an OS version triple (SDK version or deployment target). -pub fn parse_version(version: &str) -> Result { - 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()?)) +#[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 93a7555c66554..b6dee7055f190 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -63,8 +63,7 @@ pub use base::apple::{ 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, - parse_version as apple_parse_version, platform as current_apple_platform, - sdk_name as apple_sdk_name, + platform as current_apple_platform, sdk_name as apple_sdk_name, }; pub use base::avr_gnu::ef_avr_arch; From 05457b9c2af8d236dc159bf3e94452300035fffc Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 00:29:47 +0200 Subject: [PATCH 7/9] Refactor ld64 arch determination --- compiler/rustc_codegen_ssa/src/apple.rs | 29 ++++++++++++++++++++- compiler/rustc_codegen_ssa/src/back/link.rs | 27 ++----------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs index 33450bec328c8..0ff2b7fb79c20 100644 --- a/compiler/rustc_codegen_ssa/src/apple.rs +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -3,9 +3,10 @@ use std::io::ErrorKind; use std::path::{Path, PathBuf}; use std::{env, fs}; +use rustc_middle::bug; use rustc_session::Session; use rustc_target::spec::{ - AppleOSVersion, apple_deployment_target_env_var, apple_minimum_deployment_target, + AppleOSVersion, Target, apple_deployment_target_env_var, apple_minimum_deployment_target, apple_os_minimum_deployment_target, }; @@ -213,3 +214,29 @@ pub(crate) fn find_sdk_root(sdk_name: &'static str) -> Result &'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), + } +} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e2316179aaa7e..3966172242ece 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -50,7 +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::{deployment_target, find_sdk_root, versioned_llvm_target}; +use crate::apple::{deployment_target, find_sdk_root, ld64_arch, versioned_llvm_target}; use crate::{ CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, looks_like_rust_object_file, @@ -2974,32 +2974,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`): From 7111bec1db5ea26202c2badee4138f7b228ebf47 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 03:30:53 +0200 Subject: [PATCH 8/9] Parse SDK settings Previously, we did a simplistic check against the SDKROOT path to try to figure out whether we should use the environment variable, or try to find a better matching SDK instead. This is brittle since the user might want their SDK to be in a different place in the file system (that's kinda the whole idea of the SDKROOT variable), and also didn't work properly with SDKs in the Xcode Command Line Tools. Instead, we now: 1. Parse the SDKSettings.json file under the SDKROOT, to determine whether it is suitable for the target we're compiling for (which it might not be when using Cargo, and targetting iOS but compiling build scripts on macOS). 2. If it's not, attempt to find another SDK. This allows us to give much more detailed error messages, to better support cross-compile scenarios, and allows using parameters from the SDK (such as the SDK version) elsewhere in the future. --- Cargo.lock | 1 + compiler/rustc_codegen_ssa/Cargo.toml | 1 + compiler/rustc_codegen_ssa/messages.ftl | 56 +++ compiler/rustc_codegen_ssa/src/apple.rs | 309 ++++++++++++++++- .../sample_sdk_settings/iphoneos13.0.json | 99 ++++++ .../iphonesimulator18.0.json | 157 +++++++++ .../sample_sdk_settings/macosx10.14.json | 58 ++++ .../sample_sdk_settings/macosx10.15.json | 134 ++++++++ .../apple/sample_sdk_settings/macosx11.3.json | 180 ++++++++++ .../apple/sample_sdk_settings/macosx13.3.json | 265 +++++++++++++++ .../apple/sample_sdk_settings/macosx15.0.json | 318 ++++++++++++++++++ .../apple/sample_sdk_settings/xros2.0.json | 110 ++++++ compiler/rustc_codegen_ssa/src/apple/tests.rs | 49 ++- compiler/rustc_codegen_ssa/src/back/link.rs | 71 +--- compiler/rustc_codegen_ssa/src/errors.rs | 31 ++ compiler/rustc_metadata/src/native_libs.rs | 18 +- 16 files changed, 1793 insertions(+), 64 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphoneos13.0.json create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/iphonesimulator18.0.json create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.14.json create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx10.15.json create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx11.3.json create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx13.3.json create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/macosx15.0.json create mode 100644 compiler/rustc_codegen_ssa/src/apple/sample_sdk_settings/xros2.0.json diff --git a/Cargo.lock b/Cargo.lock index 4648774b8b13f..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", 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 fc7bea195e4c1..9d39fba8d340a 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -8,9 +8,17 @@ codegen_ssa_apple_deployment_target_invalid = 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? @@ -37,6 +45,11 @@ codegen_ssa_apple_sdk_error_missing_developer_dir = - `{$sdkroot}` - `{$sdkroot_bare}` +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. @@ -49,6 +62,49 @@ codegen_ssa_apple_sdk_error_missing_xcode_select = 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_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} codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs index 0ff2b7fb79c20..297227f519fb0 100644 --- a/compiler/rustc_codegen_ssa/src/apple.rs +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -1,14 +1,17 @@ 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_os_minimum_deployment_target, apple_sdk_name, }; +use serde::Deserialize; use crate::errors::{AppleDeploymentTarget, AppleSdkError}; @@ -107,6 +110,7 @@ fn sdk_root_in_developer_dir(developer_dir: impl Into, sdk_name: &str) 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"); @@ -137,7 +141,7 @@ fn sdk_root_in_developer_dir(developer_dir: impl Into, sdk_name: &str) /// 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. -pub(crate) fn find_sdk_root(sdk_name: &'static str) -> Result { +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 }); @@ -240,3 +244,304 @@ pub fn ld64_arch(target: &Target) -> &'static str { _ => 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")] + #[allow(dead_code)] + 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>, +} + +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, + }) + } + + /// 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")) + } + + 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 index eeaf8776022ca..55b2b47f74635 100644 --- a/compiler/rustc_codegen_ssa/src/apple/tests.rs +++ b/compiler/rustc_codegen_ssa/src/apple/tests.rs @@ -1,10 +1,10 @@ use std::io; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; use rustc_target::spec::AppleOSVersion; -use super::{add_version_to_llvm_target, find_sdk_root}; +use super::{SDKSettings, add_version_to_llvm_target, find_sdk_root}; #[test] fn test_add_version_to_llvm_target() { @@ -73,3 +73,48 @@ fn test_find_sdk_root() { } } } + +#[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 3966172242ece..5ae3dd81548ac 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -50,7 +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::{deployment_target, find_sdk_root, ld64_arch, versioned_llvm_target}; +use crate::apple::{SDKSettings, deployment_target, ld64_arch, versioned_llvm_target}; use crate::{ CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, looks_like_rust_object_file, @@ -2100,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); @@ -2408,7 +2412,7 @@ fn add_order_independent_options( add_apple_link_args(cmd, sess, flavor); - let apple_sdk_root = add_apple_sdk(cmd, sess, flavor); + let apple_sdk_data = add_apple_sdk(cmd, sess, crate_type, flavor); add_link_script(cmd, sess, tmpdir, crate_type); @@ -2464,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); @@ -3100,7 +3104,12 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo } } -fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option { +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; } @@ -3108,10 +3117,8 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> return None; }; - let sdk_name = rustc_target::spec::apple_sdk_name(&sess.target); - - let sdkroot = 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) => { // If cross compiling from non-macOS, the user might be using something like `zig cc`. // @@ -3154,49 +3161,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> cmd.link_arg(&sdkroot); } - Some(sdkroot) -} - -fn get_apple_sdk_root(sdk_name: &'static 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. - if let Ok(sdkroot) = env::var("SDKROOT") { - let p = PathBuf::from(&sdkroot); - match &*sdk_name.to_lowercase() { - // 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(p), - } - } - - find_sdk_root(sdk_name) + Some((sdkroot, settings)) } /// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 64ccb0f0ac3ed..67164b0cceb9a 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -537,8 +537,12 @@ pub enum ExtractBundledLibsError<'a> { 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, Debug)] @@ -546,6 +550,9 @@ 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 }, @@ -558,11 +565,35 @@ pub(crate) enum AppleSdkError { #[diag(codegen_ssa_apple_sdk_error_missing_developer_dir)] MissingDeveloperDir { dir: PathBuf, sdkroot: PathBuf, sdkroot_bare: PathBuf }, + #[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_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_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(()) From 1960f3b302472ba520ec87f164a85b365c78716f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 00:26:31 +0200 Subject: [PATCH 9/9] Pass SDK version to ld64 when linking This is an important property of the binary that we were previously setting incorrectly, and is a big step towards making binaries linked with cc and ld64 equal. --- compiler/rustc_codegen_ssa/messages.ftl | 8 +++ compiler/rustc_codegen_ssa/src/apple.rs | 38 ++++++++++++- compiler/rustc_codegen_ssa/src/back/link.rs | 61 +++++++++++++-------- compiler/rustc_codegen_ssa/src/errors.rs | 6 ++ tests/run-make/apple-sdk-version/rmake.rs | 11 +--- 5 files changed, 90 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 9d39fba8d340a..b7319ec3cdc2e 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -45,6 +45,11 @@ codegen_ssa_apple_sdk_error_missing_developer_dir = - `{$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}`. @@ -62,6 +67,9 @@ codegen_ssa_apple_sdk_error_missing_xcode_select = 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}`. diff --git a/compiler/rustc_codegen_ssa/src/apple.rs b/compiler/rustc_codegen_ssa/src/apple.rs index 297227f519fb0..1d6a7dbcd7953 100644 --- a/compiler/rustc_codegen_ssa/src/apple.rs +++ b/compiler/rustc_codegen_ssa/src/apple.rs @@ -282,7 +282,6 @@ pub(crate) struct SDKSettings { canonical_name: String, #[serde(rename = "Version")] - #[allow(dead_code)] version: AppleOSVersion, #[serde(rename = "MaximumDeploymentTarget")] @@ -294,6 +293,13 @@ pub(crate) struct SDKSettings { /// 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 { @@ -327,6 +333,7 @@ impl SDKSettings { }, default_properties: DefaultProperties::default(), supported_targets: None, + version_map: None, }) } @@ -372,6 +379,35 @@ impl SDKSettings { .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); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 5ae3dd81548ac..c4a1efee88d87 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2410,10 +2410,10 @@ 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); + add_apple_link_args(cmd, sess, flavor, &apple_sdk_data); + add_link_script(cmd, sess, tmpdir, crate_type); if sess.target.os == "fuchsia" @@ -2970,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; } @@ -3030,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 @@ -3064,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 // diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 67164b0cceb9a..586768a606048 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -565,6 +565,9 @@ pub(crate) enum AppleSdkError { #[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 }, @@ -574,6 +577,9 @@ pub(crate) enum AppleSdkError { #[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 }, 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); } }