From dd35398545006f5ad4da8fc2ef0190c55ffda29c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 21 Aug 2024 17:23:50 +0200 Subject: [PATCH] Pass deployment target when linking with cc on Apple targets When linking macOS targets with cc, pass the `-mmacosx-version-min=.` option to specify the desired deployment target. Also, no longer pass `-m32`/`-m64`, these are redundant since we already pass `-arch`. When linking with cc on other Apple targets, always pass `-target`. (We assume for these targets that cc => clang). --- .../rustc_target/src/spec/base/apple/mod.rs | 30 ++++++++++++++++++- .../src/spec/targets/i686_apple_darwin.rs | 6 ++-- .../src/spec/targets/x86_64_apple_darwin.rs | 5 ++-- .../src/spec/targets/x86_64h_apple_darwin.rs | 3 +- .../run-make/apple-deployment-target/rmake.rs | 10 +++---- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index b1fe49f76ca..d2886a89b53 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -168,7 +168,26 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(), ); - if abi != TargetAbi::MacCatalyst { + // We need to communicate four things to the C compiler to be able to link: + // - The architecture. + // - The operating system (and that it's an Apple platform). + // - The deployment target. + // - The environment / ABI. + // + // We'd like to use `-target` everywhere, since that can uniquely + // communicate all of these, but that doesn't work on GCC, and since we + // don't know whether the `cc` compiler is Clang, GCC, or something else, + // we fall back to other options that also work on GCC when compiling for + // macOS. + // + // Targets other than macOS are ill-supported by GCC (it doesn't even + // support e.g. `-miphoneos-version-min`), so in those cases we can fairly + // safely use `-target`. See also the following, where it is made explicit + // that the recommendation by LLVM developers is to use `-target`: + // + if os == "macos" { + // `-arch` communicates the architecture. + // // CC forwards the `-arch` to the linker, so we use the same value // here intentionally. add_link_args( @@ -176,6 +195,15 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch.ld_arch()], ); + // The presence of `-mmacosx-version-min` makes CC default to macOS, + // and it sets the deployment target. + let (major, minor, patch) = deployment_target(os, arch, abi); + let opt = format!("-mmacosx-version-min={major}.{minor}.{patch}").into(); + add_link_args_iter(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), [opt].into_iter()); + // macOS has no environment, so with these two, we've told CC all the + // desired parameters. + // + // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`. } else { add_link_args_iter( &mut args, 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 67afe35bee4..3e27f1f899b 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,10 +1,8 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub(crate) fn target() -> Target { - let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - + let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); Target { llvm_target, metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index e7f14aa9209..4304dfc3f68 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,9 +1,8 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); + let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); Target { llvm_target, metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index f44bc660a62..9fb5a46187a 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,11 +1,10 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal); opts.max_atomic_width = Some(128); opts.frame_pointer = FramePointer::Always; - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); opts.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index b2d1af65177..304b0085631 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -81,9 +81,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("libfoo.dylib", example_version); - // FIXME(madsmtm): Deployment target is not currently passed properly to linker - // rustc().env_remove(env_var).run(); - // minos("libfoo.dylib", default_version); + rustc().env_remove(env_var).run(); + minos("libfoo.dylib", default_version); // Test with ld64 instead @@ -110,9 +109,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("foo", example_version); - // FIXME(madsmtm): Deployment target is not currently passed properly to linker - // rustc().env_remove(env_var).run(); - // minos("foo", default_version); + rustc().env_remove(env_var).run(); + minos("foo", default_version); } // Test with ld64 instead