Skip to content

Commit 31e60ea

Browse files
committed
Revert to always passing --target to Clang
1 parent 58cf61b commit 31e60ea

File tree

3 files changed

+70
-31
lines changed

3 files changed

+70
-31
lines changed

src/lib.rs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,21 +2194,31 @@ 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/llvm/llvm-project/blob/llvmorg-19.1.7/clang/lib/Driver/Driver.cpp#L6347-L6532
22002201
//
2201-
// Instead, we specify `-arch` along with `-mmacosx-version-min=`, `-mtargetos=`
2202-
// and similar flags in `.apple_flags()`.
2202+
// This can be confusing, because on e.g. host macOS, you can usually get by
2203+
// with `-arch` and `-mtargetos=`. But that only works because the _default_
2204+
// toolchain is `Darwin`, which enables parsing of darwin-specific options.
22032205
//
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-
}
2206+
// NOTE: In the past, we passed the deployment version in here on all Apple
2207+
// targets, but versioned targets were found to have poor compatibility with
2208+
// older versions of Clang, especially when it comes to configuration files:
2209+
// https://github.com/rust-lang/cc-rs/issues/1278
2210+
//
2211+
// So instead, we pass the deployment target with `-m*-version-min=`, and only
2212+
// pass it here on visionOS and Mac Catalyst where that option does not exist.
2213+
let clang_target = if target.os == "visionos" || target.abi == "macabi" {
2214+
Cow::Owned(
2215+
target.versioned_llvm_target(&self.apple_deployment_target(target)),
2216+
)
2217+
} else {
2218+
Cow::Borrowed(target.llvm_target)
2219+
};
2220+
2221+
cmd.push_cc_arg(format!("--target={clang_target}").into());
22122222
}
22132223
}
22142224
ToolFamily::Msvc { clang_cl } => {
@@ -2648,21 +2658,23 @@ impl Build {
26482658
fn apple_flags(&self, cmd: &mut Tool) -> Result<(), Error> {
26492659
let target = self.get_target()?;
26502660

2651-
// Add `-arch` on all compilers. This is a Darwin/Apple-specific flag
2652-
// that works both on GCC and Clang.
2661+
// This is a Darwin/Apple-specific flag that works both on GCC and Clang, but it is only
2662+
// necessary on GCC since we specify `-target` on Clang.
26532663
// https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html#:~:text=arch
26542664
// 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());
2665+
if cmd.is_like_gnu() {
2666+
let arch = map_darwin_target_from_rust_to_compiler_architecture(&target);
2667+
cmd.args.push("-arch".into());
2668+
cmd.args.push(arch.into());
2669+
}
26582670

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
2671+
// Pass the deployment target via `-mmacosx-version-min=`, `-miphoneos-version-min=` and
2672+
// similar. Also necessary on GCC, as it forces a compilation error if the compiler is not
26622673
// configured for Darwin: https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html
26632674
let min_version = self.apple_deployment_target(&target);
2664-
cmd.args
2665-
.push(target.apple_version_flag(&min_version).into());
2675+
if let Some(flag) = target.apple_version_flag(&min_version) {
2676+
cmd.args.push(flag.into());
2677+
}
26662678

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

src/target/apple.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl TargetInfo<'_> {
1717
}
1818
}
1919

20-
pub(crate) fn apple_version_flag(&self, min_version: &str) -> String {
20+
pub(crate) fn apple_version_flag(&self, min_version: &str) -> Option<String> {
2121
// There are many aliases for these, and `-mtargetos=` is preferred on Clang nowadays, but
2222
// for compatibility with older Clang, we use the earliest supported name here.
2323
//
@@ -30,20 +30,24 @@ impl TargetInfo<'_> {
3030
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mmacos-version-min
3131
// https://clang.llvm.org/docs/AttributeReference.html#availability
3232
// https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html#index-mmacosx-version-min
33-
match (self.os, self.abi) {
33+
//
34+
// On visionOS and Mac Catalyst, there is no -m*-version-min= flag:
35+
// https://github.com/llvm/llvm-project/issues/88271
36+
//
37+
// And the workaround to use `-mtargetos=` cannot be used with the `--target` flag that we
38+
// otherwise specify. So we avoid emitting that, and put the version in `--target` instead.
39+
Some(match (self.os, self.abi) {
3440
("macos", "") => format!("-mmacosx-version-min={min_version}"),
3541
("ios", "") => format!("-miphoneos-version-min={min_version}"),
3642
("ios", "sim") => format!("-mios-simulator-version-min={min_version}"),
37-
("ios", "macabi") => format!("-mtargetos=ios{min_version}-macabi"),
43+
("ios", "macabi") => return None, // format!("-mtargetos=ios{min_version}-macabi")
3844
("tvos", "") => format!("-mappletvos-version-min={min_version}"),
3945
("tvos", "sim") => format!("-mappletvsimulator-version-min={min_version}"),
4046
("watchos", "") => format!("-mwatchos-version-min={min_version}"),
4147
("watchos", "sim") => format!("-mwatchsimulator-version-min={min_version}"),
42-
// `-mxros-version-min` does not exist
43-
// https://github.com/llvm/llvm-project/issues/88271
44-
("visionos", "") => format!("-mtargetos=xros{min_version}"),
45-
("visionos", "sim") => format!("-mtargetos=xros{min_version}-simulator"),
48+
("visionos", "") => return None, // format!("-mtargetos=xros{min_version}"),
49+
("visionos", "sim") => return None, // format!("-mtargetos=xros{min_version}-simulator"),
4650
(os, _) => panic!("invalid Apple target OS {}", os),
47-
}
51+
})
4852
}
4953
}

src/target/llvm.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
use super::TargetInfo;
2+
3+
impl<'a> TargetInfo<'a> {
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(

0 commit comments

Comments
 (0)