Skip to content

Commit c60c0c4

Browse files
committed
Revert to always passing --target to Clang
1 parent 353566c commit c60c0c4

File tree

3 files changed

+75
-32
lines changed

3 files changed

+75
-32
lines changed

src/lib.rs

+45-24
Original file line numberDiff line numberDiff line change
@@ -2194,21 +2194,34 @@ impl Build {
21942194

21952195
// Pass `--target` with the LLVM target to configure Clang for cross-compiling.
21962196
//
2197-
// NOTE: In the past, we passed this, along with the deployment version in here
2198-
// on Apple targets, but versioned targets were found to have poor compatibility
2199-
// with older versions of Clang, especially around comes to configuration files.
2197+
// This is **required** for cross-compilation, as it's the only flag that
2198+
// consistently forces Clang to change the "toolchain" that is responsible for
2199+
// parsing target-specific flags:
2200+
// https://github.com/rust-lang/cc-rs/issues/1388
2201+
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.7/clang/lib/Driver/Driver.cpp#L1359-L1360
2202+
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.7/clang/lib/Driver/Driver.cpp#L6347-L6532
22002203
//
2201-
// Instead, we specify `-arch` along with `-mmacosx-version-min=`, `-mtargetos=`
2202-
// and similar flags in `.apple_flags()`.
2204+
// This can be confusing, because on e.g. host macOS, you can usually get by
2205+
// with `-arch` and `-mtargetos=`. But that only works because the _default_
2206+
// toolchain is `Darwin`, which enables parsing of darwin-specific options.
22032207
//
2204-
// Note that Clang errors when both `-mtargetos=` and `-target` are specified,
2205-
// so we omit this entirely on Apple targets (it's redundant when specifying
2206-
// both the `-arch` and the deployment target / OS flag) (in theory we _could_
2207-
// specify this on some of the Apple targets that use the older
2208-
// `-m*-version-min=`, but for consistency we omit it entirely).
2209-
if target.vendor != "apple" {
2210-
cmd.push_cc_arg(format!("--target={}", target.llvm_target).into());
2211-
}
2208+
// NOTE: In the past, we passed the deployment version in here on all Apple
2209+
// targets, but versioned targets were found to have poor compatibility with
2210+
// older versions of Clang, especially when it comes to configuration files:
2211+
// https://github.com/rust-lang/cc-rs/issues/1278
2212+
//
2213+
// So instead, we pass the deployment target with `-m*-version-min=`, and only
2214+
// pass it here on visionOS and Mac Catalyst where that option does not exist:
2215+
// https://github.com/rust-lang/cc-rs/issues/1383
2216+
let clang_target = if target.os == "visionos" || target.abi == "macabi" {
2217+
Cow::Owned(
2218+
target.versioned_llvm_target(&self.apple_deployment_target(target)),
2219+
)
2220+
} else {
2221+
Cow::Borrowed(target.llvm_target)
2222+
};
2223+
2224+
cmd.push_cc_arg(format!("--target={clang_target}").into());
22122225
}
22132226
}
22142227
ToolFamily::Msvc { clang_cl } => {
@@ -2648,21 +2661,29 @@ impl Build {
26482661
fn apple_flags(&self, cmd: &mut Tool) -> Result<(), Error> {
26492662
let target = self.get_target()?;
26502663

2651-
// Add `-arch` on all compilers. This is a Darwin/Apple-specific flag
2652-
// that works both on GCC and Clang.
2664+
// This is a Darwin/Apple-specific flag that works both on GCC and Clang, but it is only
2665+
// necessary on GCC since we specify `-target` on Clang.
26532666
// https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html#:~:text=arch
26542667
// https://clang.llvm.org/docs/CommandGuide/clang.html#cmdoption-arch
2655-
let arch = map_darwin_target_from_rust_to_compiler_architecture(&target);
2656-
cmd.args.push("-arch".into());
2657-
cmd.args.push(arch.into());
2668+
if cmd.is_like_gnu() {
2669+
let arch = map_darwin_target_from_rust_to_compiler_architecture(&target);
2670+
cmd.args.push("-arch".into());
2671+
cmd.args.push(arch.into());
2672+
}
26582673

2659-
// Pass the deployment target via `-mmacosx-version-min=`, `-mtargetos=` and similar.
2660-
//
2661-
// It is also necessary on GCC, as it forces a compilation error if the compiler is not
2674+
// Pass the deployment target via `-mmacosx-version-min=`, `-miphoneos-version-min=` and
2675+
// similar. Also necessary on GCC, as it forces a compilation error if the compiler is not
26622676
// configured for Darwin: https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html
2663-
let min_version = self.apple_deployment_target(&target);
2664-
cmd.args
2665-
.push(target.apple_version_flag(&min_version).into());
2677+
//
2678+
// On visionOS and Mac Catalyst, there is no -m*-version-min= flag:
2679+
// https://github.com/llvm/llvm-project/issues/88271
2680+
// And the workaround to use `-mtargetos=` cannot be used with the `--target` flag that we
2681+
// otherwise specify. So we avoid emitting that, and put the version in `--target` instead.
2682+
if cmd.is_like_gnu() || target.os != "visionos" || target.abi != "macabi" {
2683+
let min_version = self.apple_deployment_target(&target);
2684+
cmd.args
2685+
.push(target.apple_version_flag(&min_version).into());
2686+
}
26662687

26672688
// AppleClang sometimes requires sysroot even on macOS
26682689
if cmd.is_xctoolchain_clang() || target.os != "macos" {

src/target/llvm.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
use super::TargetInfo;
2+
3+
impl TargetInfo<'_> {
4+
/// The versioned LLVM/Clang target triple.
5+
pub(crate) fn versioned_llvm_target(&self, version: &str) -> String {
6+
// Only support versioned Apple targets for now.
7+
assert_eq!(self.vendor, "apple");
8+
9+
let mut components = self.llvm_target.split("-");
10+
let arch = components.next().expect("llvm_target should have arch");
11+
let vendor = components.next().expect("llvm_target should have vendor");
12+
let os = components.next().expect("LLVM target should have os");
13+
let environment = components.next();
14+
assert_eq!(components.next(), None, "too many LLVM target components");
15+
16+
if let Some(env) = environment {
17+
format!("{arch}-{vendor}-{os}{version}-{env}")
18+
} else {
19+
format!("{arch}-{vendor}-{os}{version}")
20+
}
21+
}
22+
}
23+
124
/// Rust and Clang don't really agree on naming, so do a best-effort
225
/// conversion to support out-of-tree / custom target-spec targets.
326
pub(crate) fn guess_llvm_target_triple(

tests/test.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ fn clang_apple_tvos() {
616616
.file("foo.c")
617617
.compile("foo");
618618

619-
test.cmd(0).must_have_in_order("-arch", "arm64");
619+
test.cmd(0).must_have("--target=arm64-apple-tvos");
620620
test.cmd(0).must_have("-mappletvos-version-min=9.0");
621621
}
622622

@@ -640,10 +640,9 @@ fn clang_apple_mac_catalyst() {
640640
.compile("foo");
641641
let execution = test.cmd(0);
642642

643-
execution.must_have_in_order("-arch", "arm64");
643+
execution.must_have("--target=arm64-apple-ios15.0-macabi");
644644
// --target and -mtargetos= don't mix
645-
execution.must_not_have("--target=arm64-apple-ios-macabi");
646-
execution.must_have("-mtargetos=ios15.0-macabi");
645+
execution.must_not_have("-mtargetos=");
647646
execution.must_have_in_order("-isysroot", sdkroot);
648647
execution.must_have_in_order(
649648
"-isystem",
@@ -672,7 +671,8 @@ fn clang_apple_tvsimulator() {
672671
.file("foo.c")
673672
.compile("foo");
674673

675-
test.cmd(0).must_have_in_order("-arch", "x86_64");
674+
test.cmd(0)
675+
.must_have("--target=x86_64-apple-tvos-simulator");
676676
test.cmd(0).must_have("-mappletvsimulator-version-min=9.0");
677677
}
678678

@@ -697,10 +697,9 @@ fn clang_apple_visionos() {
697697

698698
dbg!(test.cmd(0).args);
699699

700-
test.cmd(0).must_have_in_order("-arch", "arm64");
700+
test.cmd(0).must_have("--target=arm64-apple-xros1.0");
701701
// --target and -mtargetos= don't mix.
702-
test.cmd(0).must_not_have("--target=arm64-apple-xros");
703-
test.cmd(0).must_have("-mtargetos=xros1.0");
702+
test.cmd(0).must_not_have("-mtargetos=");
704703

705704
// Flags that don't exist.
706705
test.cmd(0).must_not_have("-mxros-version-min=1.0");

0 commit comments

Comments
 (0)