@@ -3124,47 +3124,65 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
3124
3124
}
3125
3125
3126
3126
fn add_apple_sdk ( cmd : & mut dyn Linker , sess : & Session , flavor : LinkerFlavor ) -> Option < PathBuf > {
3127
- let os = & sess. target . os ;
3128
- if sess. target . vendor != "apple"
3129
- || !matches ! ( os. as_ref( ) , "ios" | "tvos" | "watchos" | "visionos" | "macos" )
3130
- || !matches ! ( flavor, LinkerFlavor :: Darwin ( ..) )
3131
- {
3127
+ if !sess. target . is_like_osx {
3132
3128
return None ;
3133
3129
}
3134
-
3135
- if os == "macos" && !matches ! ( flavor, LinkerFlavor :: Darwin ( Cc :: No , _) ) {
3130
+ let LinkerFlavor :: Darwin ( cc, _) = flavor else {
3136
3131
return None ;
3137
- }
3132
+ } ;
3138
3133
3139
3134
let sdk_name = apple:: sdk_name ( & sess. target ) ;
3140
3135
3141
- let sdk_root = match get_apple_sdk_root ( sdk_name) {
3136
+ let sdkroot = match get_apple_sdk_root ( sdk_name) {
3142
3137
Ok ( s) => s,
3143
3138
Err ( e) => {
3144
- sess. dcx ( ) . emit_err ( e) ;
3139
+ // If cross compiling from non-macOS, the user might be using something like `zig cc`.
3140
+ //
3141
+ // In that case, we shouldn't error when the SDK is missing, though we still warn.
3142
+ if cfg ! ( target_os = "macos" ) {
3143
+ sess. dcx ( ) . emit_err ( e) ;
3144
+ } else {
3145
+ sess. dcx ( ) . emit_warn ( e) ;
3146
+ }
3145
3147
return None ;
3146
3148
}
3147
3149
} ;
3148
3150
3149
- match flavor {
3150
- LinkerFlavor :: Darwin ( Cc :: Yes , _) => {
3151
- // Use `-isysroot` instead of `--sysroot`, as only the former
3152
- // makes Clang treat it as a platform SDK.
3153
- //
3154
- // This is admittedly a bit strange, as on most targets
3155
- // `-isysroot` only applies to include header files, but on Apple
3156
- // targets this also applies to libraries and frameworks.
3157
- cmd. cc_arg ( "-isysroot" ) ;
3158
- cmd. cc_arg ( & sdk_root) ;
3159
- }
3160
- LinkerFlavor :: Darwin ( Cc :: No , _) => {
3161
- cmd. link_arg ( "-syslibroot" ) ;
3162
- cmd. link_arg ( & sdk_root) ;
3163
- }
3164
- _ => unreachable ! ( ) ,
3151
+ if cc == Cc :: Yes {
3152
+ // To pass the SDK root to `cc`, we have a few options:
3153
+ // 1. `--sysroot` flag.
3154
+ // 2. `-isysroot` flag.
3155
+ // 3. `SDKROOT` environment variable.
3156
+ //
3157
+ // `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need to
3158
+ // specify `-isysroot` - this is admittedly a bit strange, as on most targets `-isysroot`
3159
+ // only applies to include header files, but on Apple targets it also applies to libraries
3160
+ // and frameworks.
3161
+ //
3162
+ // Now, while the `-isysroot` flag is pretty well supported (both Clang and GCC implements
3163
+ // the desired behaviour), it may not be understood by any `cc`'s that the user might want
3164
+ // to use.
3165
+ //
3166
+ // So to better support such use-cases, we pass the SDK root in the standard environment
3167
+ // variable instead. This is also supported by GCC since 2019:
3168
+ // <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87243>
3169
+ //
3170
+ // This also works better with the trampoline `/usr/bin/cc` which calls `xcrun cc`
3171
+ // internally, since the presence of `SDKROOT` means it won't have to look up the SDK root
3172
+ // itself.
3173
+ //
3174
+ // A final note about precedence: Clang seems to treats `SDKROOT` and `-isysroot` the same,
3175
+ // with the latter having precedence. But for the purpose of linking, Clang seems to prefer
3176
+ // the value from `--sysroot`.
3177
+ cmd. cmd ( ) . env ( "SDKROOT" , & sdkroot) ;
3178
+ } else {
3179
+ // For `ld64`, we use the `-syslibroot` parameter (this is what Clang passes, and `SDKROOT`
3180
+ // is not read by `ld64` so it's really the only option).
3181
+ cmd. link_arg ( "-syslibroot" ) ;
3182
+ cmd. link_arg ( & sdkroot) ;
3165
3183
}
3166
3184
3167
- Some ( sdk_root )
3185
+ Some ( sdkroot )
3168
3186
}
3169
3187
3170
3188
fn get_apple_sdk_root ( sdk_name : & ' static str ) -> Result < PathBuf , errors:: AppleSdkError > {
@@ -3189,7 +3207,13 @@ fn get_apple_sdk_root(sdk_name: &'static str) -> Result<PathBuf, errors::AppleSd
3189
3207
}
3190
3208
"macosx"
3191
3209
if sdkroot. contains ( "iPhoneOS.platform" )
3192
- || sdkroot. contains ( "iPhoneSimulator.platform" ) => { }
3210
+ || sdkroot. contains ( "iPhoneSimulator.platform" )
3211
+ || sdkroot. contains ( "AppleTVOS.platform" )
3212
+ || sdkroot. contains ( "AppleTVSimulator.platform" )
3213
+ || sdkroot. contains ( "WatchOS.platform" )
3214
+ || sdkroot. contains ( "WatchSimulator.platform" )
3215
+ || sdkroot. contains ( "XROS.platform" )
3216
+ || sdkroot. contains ( "XRSimulator.platform" ) => { }
3193
3217
"watchos"
3194
3218
if sdkroot. contains ( "WatchSimulator.platform" )
3195
3219
|| sdkroot. contains ( "MacOSX.platform" ) => { }
0 commit comments