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