@@ -3101,47 +3101,60 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
3101
3101
}
3102
3102
3103
3103
fn add_apple_sdk ( cmd : & mut dyn Linker , sess : & Session , flavor : LinkerFlavor ) -> Option < PathBuf > {
3104
- let os = & sess. target . os ;
3105
- if sess. target . vendor != "apple"
3106
- || !matches ! ( os. as_ref( ) , "ios" | "tvos" | "watchos" | "visionos" | "macos" )
3107
- || !matches ! ( flavor, LinkerFlavor :: Darwin ( ..) )
3108
- {
3104
+ if !sess. target . is_like_osx {
3109
3105
return None ;
3110
3106
}
3111
-
3112
- if os == "macos" && !matches ! ( flavor, LinkerFlavor :: Darwin ( Cc :: No , _) ) {
3107
+ let LinkerFlavor :: Darwin ( cc, _) = flavor else {
3113
3108
return None ;
3114
- }
3109
+ } ;
3115
3110
3116
3111
let sdk_name = rustc_target:: spec:: apple_sdk_name ( & sess. target ) ;
3117
3112
3118
- let sdk_root = match get_apple_sdk_root ( sdk_name) {
3113
+ let sdkroot = match get_apple_sdk_root ( sdk_name) {
3119
3114
Ok ( s) => s,
3120
3115
Err ( e) => {
3121
- sess. dcx ( ) . emit_err ( e) ;
3116
+ // If cross compiling from non-macOS, the user might be using something like `zig cc`.
3117
+ //
3118
+ // In that case, we shouldn't error when the SDK is missing, though we still warn.
3119
+ if cfg ! ( target_os = "macos" ) {
3120
+ sess. dcx ( ) . emit_err ( e) ;
3121
+ } else {
3122
+ sess. dcx ( ) . emit_warn ( e) ;
3123
+ }
3122
3124
return None ;
3123
3125
}
3124
3126
} ;
3125
3127
3126
- match flavor {
3127
- LinkerFlavor :: Darwin ( Cc :: Yes , _) => {
3128
- // Use `-isysroot` instead of `--sysroot`, as only the former
3129
- // makes Clang treat it as a platform SDK.
3130
- //
3131
- // This is admittedly a bit strange, as on most targets
3132
- // `-isysroot` only applies to include header files, but on Apple
3133
- // targets this also applies to libraries and frameworks.
3134
- cmd. cc_arg ( "-isysroot" ) ;
3135
- cmd. cc_arg ( & sdk_root) ;
3136
- }
3137
- LinkerFlavor :: Darwin ( Cc :: No , _) => {
3138
- cmd. link_arg ( "-syslibroot" ) ;
3139
- cmd. link_arg ( & sdk_root) ;
3140
- }
3141
- _ => unreachable ! ( ) ,
3128
+ if cc == Cc :: Yes {
3129
+ // To pass the SDK root to `cc`, we have a few options:
3130
+ // 1. `--sysroot` flag.
3131
+ // 2. `-isysroot` flag.
3132
+ // 3. `SDKROOT` environment variable.
3133
+ //
3134
+ // `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need to
3135
+ // specify `-isysroot` - this is admittedly a bit strange, as on most targets `-isysroot`
3136
+ // only applies to include header files, but on Apple targets it also applies to libraries
3137
+ // and frameworks.
3138
+ //
3139
+ // Now, while the `-isysroot` flag is pretty well supported (both Clang and GCC implements
3140
+ // the desired behaviour), it may not be understood by any `cc`'s that the user might want
3141
+ // to use.
3142
+ //
3143
+ // So to better support such use-cases, we pass the SDK root in the standard environment
3144
+ // variable instead. This is also supported by GCC since 2019:
3145
+ // <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87243>
3146
+ //
3147
+ // This also works better with the trampoline `/usr/bin/cc` which calls `xcrun cc`
3148
+ // internally, since the presence of `SDKROOT` means it won't have to look up the SDK root
3149
+ // itself.
3150
+ cmd. cmd ( ) . env ( "SDKROOT" , & sdkroot) ;
3151
+ } else {
3152
+ // For `ld64`, we use the `-syslibroot` parameter (and there are no other options).
3153
+ cmd. link_arg ( "-syslibroot" ) ;
3154
+ cmd. link_arg ( & sdkroot) ;
3142
3155
}
3143
3156
3144
- Some ( sdk_root )
3157
+ Some ( sdkroot )
3145
3158
}
3146
3159
3147
3160
fn get_apple_sdk_root ( sdk_name : & ' static str ) -> Result < PathBuf , errors:: AppleSdkError > {
0 commit comments