Skip to content

Commit 1cc44bf

Browse files
committed
Pass Apple SDK root to compiler driver via SDKROOT env var
This is more in-line with what Apple's tooling expects, and allows us to better support custom compiler drivers (such as certain Homebrew and Nixpkgs compilers) that prefer their own `-isysroot` flag. Effectively, we now invoke the compiler driver as-if it was invoked as `xcrun -sdk $sdk_name $tool`.
1 parent 1dc37df commit 1cc44bf

File tree

3 files changed

+39
-31
lines changed
  • compiler
    • rustc_codegen_ssa/src/back
    • rustc_target/src/spec/base/apple
  • src/doc/unstable-book/src/compiler-environment-variables

3 files changed

+39
-31
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,15 +3208,37 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
32083208
let sdkroot = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
32093209

32103210
if cc == Cc::Yes {
3211-
// Use `-isysroot` instead of `--sysroot`, as only the former
3212-
// makes Clang treat it as a platform SDK.
3211+
// There are a few options to pass the SDK root when linking with a C/C++ compiler:
3212+
// - The `--sysroot` flag.
3213+
// - The `-isysroot` flag.
3214+
// - The `SDKROOT` environment variable.
32133215
//
3214-
// This is admittedly a bit strange, as on most targets
3215-
// `-isysroot` only applies to include header files, but on Apple
3216-
// targets this also applies to libraries and frameworks.
3217-
cmd.cc_arg("-isysroot");
3218-
cmd.cc_arg(&sdk_root);
3216+
// `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need
3217+
// to specify `-isysroot`. This is admittedly a bit strange, as on most targets `-isysroot`
3218+
// only applies to include header files, but on Apple targets it also applies to libraries
3219+
// and frameworks.
3220+
//
3221+
// This leaves the choice between `-isysroot` and `SDKROOT`. Both are supported by Clang and
3222+
// GCC, though they may not be supported by all compiler drivers. We choose `SDKROOT`,
3223+
// primarily because that is the same interface that is used when invoking the tool under
3224+
// `xcrun -sdk macosx $tool`.
3225+
//
3226+
// In that sense, if a given compiler driver does not support `SDKROOT`, the blame is fairly
3227+
// clearly in the tool in question, since they also don't support being run under `xcrun`.
3228+
//
3229+
// Additionally, `SDKROOT` is an environment variable and thus optional. It also has lower
3230+
// precedence than `-isysroot`, so a custom compiler driver that does not support it and
3231+
// instead figures out the SDK on their own can easily do so by using `-isysroot`.
3232+
//
3233+
// (This in particular affects Clang built with the `DEFAULT_SYSROOT` CMake flag, such as
3234+
// the one provided by some versions of Homebrew's `llvm` package. Those will end up
3235+
// ignoring the value we set here, and instead use their built-in sysroot).
3236+
cmd.cmd().env("SDKROOT", &sdkroot);
32193237
} else {
3238+
// When invoking the linker directly, we use the `-syslibroot` parameter. `SDKROOT` is not
3239+
// read by the linker, so it's really the only option.
3240+
//
3241+
// This is also what Clang does.
32203242
cmd.link_arg("-syslibroot");
32213243
cmd.link_arg(&sdkroot);
32223244
}
@@ -3250,7 +3272,13 @@ fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
32503272
}
32513273
"macosx"
32523274
if sdkroot.contains("iPhoneOS.platform")
3253-
|| sdkroot.contains("iPhoneSimulator.platform") => {}
3275+
|| sdkroot.contains("iPhoneSimulator.platform")
3276+
|| sdkroot.contains("AppleTVOS.platform")
3277+
|| sdkroot.contains("AppleTVSimulator.platform")
3278+
|| sdkroot.contains("WatchOS.platform")
3279+
|| sdkroot.contains("WatchSimulator.platform")
3280+
|| sdkroot.contains("XROS.platform")
3281+
|| sdkroot.contains("XRSimulator.platform") => {}
32543282
"watchos"
32553283
if sdkroot.contains("WatchSimulator.platform")
32563284
|| sdkroot.contains("MacOSX.platform") => {}

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

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::borrow::Cow;
2-
use std::env;
32
use std::fmt::{Display, from_fn};
43
use std::num::ParseIntError;
54
use std::str::FromStr;
@@ -209,29 +208,10 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
209208
// that's only applicable to cross-OS compilation. Always leave anything for the
210209
// host OS alone though.
211210
if os == "macos" {
212-
let mut env_remove = Vec::with_capacity(2);
213-
// Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
214-
// may occur when we're linking a custom build script while targeting iOS for example.
215-
if let Ok(sdkroot) = env::var("SDKROOT") {
216-
if sdkroot.contains("iPhoneOS.platform")
217-
|| sdkroot.contains("iPhoneSimulator.platform")
218-
|| sdkroot.contains("AppleTVOS.platform")
219-
|| sdkroot.contains("AppleTVSimulator.platform")
220-
|| sdkroot.contains("WatchOS.platform")
221-
|| sdkroot.contains("WatchSimulator.platform")
222-
|| sdkroot.contains("XROS.platform")
223-
|| sdkroot.contains("XRSimulator.platform")
224-
{
225-
env_remove.push("SDKROOT".into())
226-
}
227-
}
228-
// Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
211+
// `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
229212
// "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
230213
// although this is apparently ignored when using the linker at "/usr/bin/ld".
231-
env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into());
232-
env_remove.push("TVOS_DEPLOYMENT_TARGET".into());
233-
env_remove.push("XROS_DEPLOYMENT_TARGET".into());
234-
env_remove.into()
214+
cvs!["IPHONEOS_DEPLOYMENT_TARGET", "TVOS_DEPLOYMENT_TARGET", "XROS_DEPLOYMENT_TARGET"]
235215
} else {
236216
// Otherwise if cross-compiling for a different OS/SDK (including Mac Catalyst), remove any part
237217
// of the linking environment that's wrong and reversed.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# `SDKROOT`
22

33
This environment variable is used on Apple targets.
4-
It is passed through to the linker (currently either as `-isysroot` or `-syslibroot`).
4+
It is passed through to the linker (currently either directly or via the `-syslibroot` flag).
55

66
Note that this variable is not always respected. When the SDKROOT is clearly wrong (e.g. when the platform of the SDK does not match the `--target` used by rustc), this is ignored and rustc does its own detection.

0 commit comments

Comments
 (0)