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`.
This commit is contained in:
@@ -3208,15 +3208,37 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
|
||||
let sdkroot = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
|
||||
|
||||
if cc == Cc::Yes {
|
||||
// Use `-isysroot` instead of `--sysroot`, as only the former
|
||||
// makes Clang treat it as a platform SDK.
|
||||
// There are a few options to pass the SDK root when linking with a C/C++ compiler:
|
||||
// - The `--sysroot` flag.
|
||||
// - The `-isysroot` flag.
|
||||
// - The `SDKROOT` environment variable.
|
||||
//
|
||||
// This is admittedly a bit strange, as on most targets
|
||||
// `-isysroot` only applies to include header files, but on Apple
|
||||
// targets this also applies to libraries and frameworks.
|
||||
cmd.cc_arg("-isysroot");
|
||||
cmd.cc_arg(&sdk_root);
|
||||
// `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need
|
||||
// to specify `-isysroot`. This is admittedly a bit strange, as on most targets `-isysroot`
|
||||
// only applies to include header files, but on Apple targets it also applies to libraries
|
||||
// and frameworks.
|
||||
//
|
||||
// This leaves the choice between `-isysroot` and `SDKROOT`. Both are supported by Clang and
|
||||
// GCC, though they may not be supported by all compiler drivers. We choose `SDKROOT`,
|
||||
// primarily because that is the same interface that is used when invoking the tool under
|
||||
// `xcrun -sdk macosx $tool`.
|
||||
//
|
||||
// In that sense, if a given compiler driver does not support `SDKROOT`, the blame is fairly
|
||||
// clearly in the tool in question, since they also don't support being run under `xcrun`.
|
||||
//
|
||||
// Additionally, `SDKROOT` is an environment variable and thus optional. It also has lower
|
||||
// precedence than `-isysroot`, so a custom compiler driver that does not support it and
|
||||
// instead figures out the SDK on their own can easily do so by using `-isysroot`.
|
||||
//
|
||||
// (This in particular affects Clang built with the `DEFAULT_SYSROOT` CMake flag, such as
|
||||
// the one provided by some versions of Homebrew's `llvm` package. Those will end up
|
||||
// ignoring the value we set here, and instead use their built-in sysroot).
|
||||
cmd.cmd().env("SDKROOT", &sdkroot);
|
||||
} else {
|
||||
// When invoking the linker directly, we use the `-syslibroot` parameter. `SDKROOT` is not
|
||||
// read by the linker, so it's really the only option.
|
||||
//
|
||||
// This is also what Clang does.
|
||||
cmd.link_arg("-syslibroot");
|
||||
cmd.link_arg(&sdkroot);
|
||||
}
|
||||
@@ -3250,7 +3272,13 @@ fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
|
||||
}
|
||||
"macosx"
|
||||
if sdkroot.contains("iPhoneOS.platform")
|
||||
|| sdkroot.contains("iPhoneSimulator.platform") => {}
|
||||
|| sdkroot.contains("iPhoneSimulator.platform")
|
||||
|| sdkroot.contains("AppleTVOS.platform")
|
||||
|| sdkroot.contains("AppleTVSimulator.platform")
|
||||
|| sdkroot.contains("WatchOS.platform")
|
||||
|| sdkroot.contains("WatchSimulator.platform")
|
||||
|| sdkroot.contains("XROS.platform")
|
||||
|| sdkroot.contains("XRSimulator.platform") => {}
|
||||
"watchos"
|
||||
if sdkroot.contains("WatchSimulator.platform")
|
||||
|| sdkroot.contains("MacOSX.platform") => {}
|
||||
|
||||
Reference in New Issue
Block a user