Skip to content

Commit e41a543

Browse files
committed
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).
1 parent 23bd0d5 commit e41a543

File tree

5 files changed

+37
-16
lines changed

5 files changed

+37
-16
lines changed

compiler/rustc_target/src/spec/base/apple/mod.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,35 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
165165
["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(),
166166
);
167167

168-
if abi != TargetAbi::MacCatalyst {
168+
// We need to communicate four things to the C compiler to be able to link:
169+
// - The architecture.
170+
// - The operating system (and that it's an Apple platform).
171+
// - The deployment target.
172+
// - The environment / ABI.
173+
//
174+
// We'd like to use `-target` everywhere, since that can uniquely
175+
// communicate all of these, but that doesn't work on GCC, and since we
176+
// don't know whether the `cc` compiler is Clang, GCC, or something else,
177+
// we fall back to other options that also work on GCC when compiling for
178+
// macOS.
179+
//
180+
// Targets other than macOS are ill-supported by GCC (it doesn't even
181+
// support e.g. `-miphoneos-version-min`), so in those cases we can fairly
182+
// safely use `-target`. See also the following, where it is made explicit
183+
// that the recommendation by LLVM developers is to use `-target`:
184+
// <https://github.com/llvm/llvm-project/issues/88271>
185+
if os == "macos" {
186+
// `-arch` communicates the architecture.
169187
add_link_args(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", ld_arch]);
188+
// The presence of `-mmacosx-version-min` makes CC default to macOS,
189+
// and it sets the deployment target.
190+
let (major, minor, patch) = deployment_target(os, arch, abi);
191+
let opt = format!("-mmacosx-version-min={major}.{minor}.{patch}").into();
192+
add_link_args_iter(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), [opt].into_iter());
193+
// macOS has no environment, so with these two, we've told CC all the
194+
// desired parameters.
195+
//
196+
// We avoid `-m32`/`-m64`, as this is already encoded by `-arch`.
170197
} else {
171198
add_link_args_iter(
172199
&mut args,

compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use crate::spec::base::apple::{base, Arch, TargetAbi};
2-
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
2+
use crate::spec::{FramePointer, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
6-
opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
7-
5+
let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
86
Target {
97
llvm_target,
108
metadata: crate::spec::TargetMetadata {

compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use crate::spec::base::apple::{base, Arch, TargetAbi};
2-
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
2+
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
6-
opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
5+
let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
76
Target {
87
llvm_target,
98
metadata: crate::spec::TargetMetadata {

compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use crate::spec::base::apple::{base, Arch, TargetAbi};
2-
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
2+
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
33

44
pub fn target() -> Target {
55
let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
66
opts.max_atomic_width = Some(128);
77
opts.frame_pointer = FramePointer::Always;
8-
opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
98
opts.supported_sanitizers =
109
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
1110

tests/run-make/apple-deployment-target/rmake.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,8 @@ fn main() {
7575
rustc.env(env_var, example_version).run();
7676
minos("libfoo.dylib", example_version);
7777

78-
// FIXME(madsmtm): Deployment target is not currently passed properly to linker
79-
// rustc.env_remove(env_var).run();
80-
// minos("libfoo.dylib", default_version);
78+
rustc.env_remove(env_var).run();
79+
minos("libfoo.dylib", default_version);
8180

8281
// Test with ld64 instead
8382
rustc.arg("-Clinker-flavor=ld");
@@ -102,9 +101,8 @@ fn main() {
102101
rustc.env(env_var, example_version).run();
103102
minos("foo", example_version);
104103

105-
// FIXME(madsmtm): Deployment target is not currently passed properly to linker
106-
// rustc.env_remove(env_var).run();
107-
// minos("foo", default_version);
104+
rustc.env_remove(env_var).run();
105+
minos("foo", default_version);
108106
}
109107

110108
// Test with ld64 instead

0 commit comments

Comments
 (0)