Always attempt to invoke xcrun to get the Apple SDK

The exact reasoning why we do not always pass the SDK root when linking
on macOS eludes me, but I suspect it's because we want to support
compiler drivers which do not support the `-isysroot` option.

Since we now pass the SDK root via the environment variable SDKROOT,
compiler drivers that don't support it can just ignore it.

Similarly, since we only warn when xcrun fails, users that expect their
compiler driver to provide the SDK location can do so now.
This commit is contained in:
Mads Marquart 2025-08-11 20:46:31 +02:00
parent f4a911031d
commit 1d1316240f
3 changed files with 41 additions and 4 deletions

View file

@ -3200,11 +3200,15 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
let LinkerFlavor::Darwin(cc, _) = flavor else {
return None;
};
if os == "macos" && cc != Cc::No {
// FIXME(madsmtm): Remove this branch.
return None;
}
// The default compiler driver on macOS is at `/usr/bin/cc`. This is a trampoline binary that
// effectively invokes `xcrun cc` internally to look up both the compiler binary and the SDK
// root from the current Xcode installation. When cross-compiling, when `rustc` is invoked
// inside Xcode, or when invoking the linker directly, this default logic is unsuitable, so
// instead we invoke `xcrun` manually.
//
// (Note that this doesn't mean we get a duplicate lookup here - passing `SDKROOT` below will
// cause the trampoline binary to skip looking up the SDK itself).
let sdkroot = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
if cc == Cc::Yes {

View file

@ -0,0 +1 @@
fn main() {}

View file

@ -0,0 +1,32 @@
//! Test that linking works under an environment similar to what Xcode sets up.
//!
//! Regression test for https://github.com/rust-lang/rust/issues/80817.
//@ only-apple
use run_make_support::{cmd, rustc, target};
fn main() {
// Fetch toolchain `/usr/bin` directory. Usually:
// /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
let clang_bin = cmd("xcrun").arg("--find").arg("clang").run().stdout_utf8();
let toolchain_bin = clang_bin.trim().strip_suffix("/clang").unwrap();
// Put toolchain directory at the front of PATH.
let path = format!("{}:{}", toolchain_bin, std::env::var("PATH").unwrap());
// Check that compiling and linking still works.
//
// Removing `SDKROOT` is necessary for the test to excercise what we want, since bootstrap runs
// under `/usr/bin/python3`, which will set SDKROOT for us.
rustc().target(target()).env_remove("SDKROOT").env("PATH", &path).input("foo.rs").run();
// Also check linking directly with the system linker.
rustc()
.target(target())
.env_remove("SDKROOT")
.env("PATH", &path)
.input("foo.rs")
.arg("-Clinker-flavor=ld")
.run();
}