@@ -2410,10 +2410,10 @@ fn add_order_independent_options(
24102410 // Take care of the flavors and CLI options requesting the `lld` linker.
24112411 add_lld_args ( cmd, sess, flavor, self_contained_components) ;
24122412
2413- add_apple_link_args ( cmd, sess, flavor) ;
2414-
24152413 let apple_sdk_data = add_apple_sdk ( cmd, sess, crate_type, flavor) ;
24162414
2415+ add_apple_link_args ( cmd, sess, flavor, & apple_sdk_data) ;
2416+
24172417 add_link_script ( cmd, sess, tmpdir, crate_type) ;
24182418
24192419 if sess. target . os == "fuchsia"
@@ -2970,7 +2970,12 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool
29702970/// - The environment / ABI.
29712971/// - The deployment target.
29722972/// - The SDK version.
2973- fn add_apple_link_args ( cmd : & mut dyn Linker , sess : & Session , flavor : LinkerFlavor ) {
2973+ fn add_apple_link_args (
2974+ cmd : & mut dyn Linker ,
2975+ sess : & Session ,
2976+ flavor : LinkerFlavor ,
2977+ settings : & Option < ( PathBuf , SDKSettings ) > ,
2978+ ) {
29742979 if !sess. target . is_like_osx {
29752980 return ;
29762981 }
@@ -3030,31 +3035,41 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
30303035 // `-[NSView wantsBestResolutionOpenGLSurface]` is `YES` when the SDK version is >= 10.15.
30313036 // <https://developer.apple.com/documentation/appkit/nsview/1414938-wantsbestresolutionopenglsurface?language=objc>
30323037 //
3033- // We do not currently know the actual SDK version though, so we have a few options:
3034- // 1. Use the minimum version supported by rustc.
3035- // 2. Use the same as the deployment target.
3036- // 3. Use an arbitary recent version.
3037- // 4. Omit the version.
3038+ // So it is important that we pass the correct version here.
30383039 //
3039- // The first option is too low / too conservative, and means that users will not get the
3040- // same behaviour from a binary compiled with rustc as with one compiled by clang.
30413040 //
3042- // The second option is similarly conservative, and also wrong since if the user specified a
3043- // higher deployment target than the SDK they're compiling/linking with, the runtime might
3044- // make invalid assumptions about the capabilities of the binary.
3041+ // For posterity, insufficient alternatives are listed below:
30453042 //
3046- // The third option requires that `rustc` is periodically kept up to date with Apple's SDK
3047- // version, and is also wrong for similar reasons as above.
3043+ // 1. Use the minimum version supported by rustc.
3044+ // Too low / too conservative, and means that users will not get the same behaviour from
3045+ // a binary compiled with rustc as with one compiled by clang.
30483046 //
3049- // The fourth option is bad because while `ld`, `otool`, `vtool` and such understand it to
3050- // mean "absent" or `n/a`, dyld doesn't actually understand it, and will end up interpreting
3051- // it as 0.0, which is again too low/conservative.
3047+ // 2. Use the same as the deployment target.
3048+ // Similarly conservative, and also wrong since if the user specified a higher deployment
3049+ // target than the SDK they're compiling/linking with, the runtime might make invalid
3050+ // assumptions about the capabilities of the binary.
30523051 //
3053- // Currently, we lie about the SDK version, and choose the second option.
3052+ // 3. Use an arbitary recent version.
3053+ // Requires that `rustc` is periodically kept up to date with Apple's SDK version, and is
3054+ // also wrong for similar reasons as above.
30543055 //
3055- // FIXME(madsmtm): Parse the SDK version from the SDK root instead.
3056- // <https://github.com/rust-lang/rust/issues/129432>
3057- let sdk_version = & * min_version;
3056+ // 4. Omit the version.
3057+ // Bad because while `ld`, `otool`, `vtool` and such understand it to mean "absent" or
3058+ // `n/a`, dyld doesn't actually understand it, and will end up interpreting it as 0.0,
3059+ // which is again too low/conservative.
3060+ let AppleOSVersion { major, minor, patch } = if let Some ( ( sdkroot, settings) ) = settings {
3061+ settings. sdk_version ( & sess. target , & sdkroot) . unwrap_or_else ( |err| {
3062+ sess. dcx ( ) . emit_err ( err) ;
3063+ AppleOSVersion :: MAX
3064+ } )
3065+ } else {
3066+ // If the SDK wasn't read properly, we may have errored already, but we may also only
3067+ // have given a warning to support `zig cc` on non-macOS hosts. `ld64` requires the SDK
3068+ // version though, so we must actually error here.
3069+ sess. dcx ( ) . emit_err ( errors:: AppleSdkError :: MustHaveWhenUsingLd64 ) ;
3070+ AppleOSVersion :: MAX
3071+ } ;
3072+ let sdk_version = format ! ( "{major}.{minor}.{patch}" ) ;
30583073
30593074 // From the man page for ld64 (`man ld`):
30603075 // > This is set to indicate the platform, oldest supported version of
@@ -3064,7 +3079,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
30643079 // Like with `-arch`, the linker can figure out the platform versions
30653080 // itself from the binaries being linked, but to be safe, we specify
30663081 // the desired versions here explicitly.
3067- cmd. link_args ( & [ "-platform_version" , platform_name, & * min_version, sdk_version] ) ;
3082+ cmd. link_args ( & [ "-platform_version" , platform_name, & * min_version, & * sdk_version] ) ;
30683083 } else {
30693084 // cc == Cc::Yes
30703085 //
0 commit comments