From 23cdb50e4f1c91ad76a3023e8a8c325e98c6348c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 5 Sep 2024 06:47:11 +0200 Subject: [PATCH] Apple: Improve comments for `-arch` linker argument --- .../rustc_target/src/spec/base/apple/mod.rs | 40 ++++++++++++++++--- .../src/spec/targets/i686_apple_darwin.rs | 7 +--- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index b752a344395..aef35ff6162 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -39,6 +39,25 @@ fn target_name(self) -> &'static str { } } + /// The architecture name to forward to the linker. + fn ld_arch(self) -> &'static str { + // 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 + match self { + 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", + } + } + pub(crate) fn target_arch(self) -> Cow<'static, str> { Cow::Borrowed(match self { Armv7k | Armv7s => "arm", @@ -116,20 +135,29 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { }; let sdk_version = min_version.clone(); - let mut args = TargetOptions::link_args( - LinkerFlavor::Darwin(Cc::No, Lld::No), - &["-arch", arch.target_name(), "-platform_version"], - ); + // From the man page for ld64 (`man ld`): + // > The linker accepts universal (multiple-architecture) input files, + // > but always creates a "thin" (single-architecture), standard Mach-O + // > output file. The architecture for the output file is specified using + // > the -arch option. + // + // The linker has heuristics to determine the desired architecture, but to + // be safe, and to avoid a warning, we set the architecture explicitly. + let mut args = + TargetOptions::link_args(LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch.ld_arch()]); + add_link_args_iter( &mut args, LinkerFlavor::Darwin(Cc::No, Lld::No), - [platform_name, min_version, sdk_version].into_iter(), + ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(), ); if abi != TargetAbi::MacCatalyst { + // CC forwards the `-arch` to the linker, so we use the same value + // here intentionally. add_link_args( &mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), - &["-arch", arch.target_name()], + &["-arch", arch.ld_arch()], ); } else { add_link_args_iter( diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index f173e8b7e4a..f7045a97bbb 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -2,8 +2,7 @@ use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; pub(crate) fn target() -> Target { - // ld64 only understands i386 and not i686 - let arch = Arch::I386; + let arch = Arch::I686; let mut base = opts("macos", arch, TargetAbi::Normal); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); @@ -13,9 +12,7 @@ pub(crate) fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - // - // While ld64 doesn't understand i686, LLVM does. - llvm_target: macos_llvm_target(Arch::I686).into(), + llvm_target: macos_llvm_target(arch).into(), metadata: crate::spec::TargetMetadata { description: Some("32-bit macOS (10.12+, Sierra+)".into()), tier: Some(3),