rust/library/std/src
León Orell Valerian Liehr 349fbba24f
Rollup merge of #138944 - madsmtm:apple_os_version_check, r=tgross35
Add `__isPlatformVersionAtLeast` and `__isOSVersionAtLeast` symbols

## Motivation

When Objective-C code uses ```@available(...)`,`` Clang inserts a call to [`__isPlatformVersionAtLeast`](https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/compiler-rt/lib/builtins/os_version_check.c#L276) (`__isOSVersionAtLeast` in older Clang versions). These symbols not being available sometimes ends up causing linker errors. See the new test `tests/run-make/apple-c-available-links` for a minimal reproducer.

The workaround is to link `libclang_rt.osx.a`, see e.g. https://github.com/alexcrichton/curl-rust/issues/279. But that's very difficult for users to figure out (and the backreferences to that issue indicates that people are still running into this in their own projects every so often).

For another recent example, this is preventing `rustc` from using LLVM assertions on macOS, see https://github.com/rust-lang/rust/pull/62592#issuecomment-510670657 and https://github.com/rust-lang/rust/pull/134275#issuecomment-2543067830.

It is also a blocker for [setting the correct minimum OS version in `cc-rs`](https://github.com/rust-lang/rust/issues/136113), since fixing this in `cc-rs` might end up introducing linker errors in places where we weren't before (by default, if using e.g. ```@available(macos`` 10.15, *)`, the symbol usually happens to be left out, since `clang` defaults to compiling for the host macOS version, and thus things _seem_ to work - but the availability check actually compiles down to nothing, which is a huge correctness footgun for running on older OSes).

(My super secret evil agenda is also to expose some variant of ```@available``` in Rust's `std` after https://github.com/rust-lang/rfcs/pull/3750 progresses further, will probably file an ACP for this later. But I believe this PR has value regardless of those future plans, since we'd be making C/Objective-C/Swift interop easier).

## Solution

Implement `__isPlatformVersionAtLeast` and `__isOSVersionAtLeast` as part of the "public ABI" that `std` exposes.

**This is insta-stable**, in the same sense that additions to `compiler-builtins` are insta-stable, though the availability of these symbols can probably be considered a "quality of implementation" detail rather than a stable promise.

I originally proposed to implement this in `compiler-builtins`, see https://github.com/rust-lang/compiler-builtins/pull/794, but we discussed moving it to `std` instead ([Zulip thread](https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/Provide.20.60__isPlatformVersionAtLeast.60.20in.20.60std.60.3F/with/507880717)), which makes the implementation substantially simpler, and we avoid gnarly issues with requiring the user to link `libSystem.dylib` (since `std` unconditionally does that).

Note that this does not solve the linker errors for (pure) `#![no_std]` users, but that's _probably_ fine, if you are using ```@available``` to test the OS version on Apple platforms, you're likely also using `std` (and it is still possible to work around by linking `libclang_rt.*.a`).

A thing to note about the implementation, I've choosen to stray a bit from LLVM's upstream implementation, and not use `_availability_version_check` since [it has problems when compiling with an older SDK](https://github.com/llvm/llvm-project/issues/64227). Instead, we use `sysctl kern.osproductversion` when available to still avoid the costly PList lookup in most cases, but still with a fall back to the PList lookup when that is not available (with the PList fallback being is similar to LLVM's implementation).

## Testing

Apple has a lot of different "modes" that they can run binaries in, which can be a bit difficult to find your bearings in, but I've tried to be as thorough as I could in testing them all.

Tested using roughly the equivalent of `./x test library/std -- platform_version` on the following configurations:
- macOS 14.7.3 on a Macbook Pro M2
    - `aarch64-apple-darwin`
    - `x86_64-apple-darwin` (under Rosetta)
    - `aarch64-apple-ios-macabi`
    - `x86_64-apple-ios-macabi` (under Rosetta)
    - `aarch64-apple-ios` (using Xcode's "Designed for iPad" setting)
    - `aarch64-apple-ios-sim` (in iOS Simulator, as iPhone with iOS 17.5)
    - `aarch64-apple-ios-sim` (in iOS Simulator, as iPad with iOS 18.2)
    - `aarch64-apple-tvos-sim` (in tvOS Simulator)
    - `aarch64-apple-watchos-sim` (in watchOS Simulator)
    - `aarch64-apple-ios-sim` (in visionOS simulator, using Xcode's "Designed for iPad" setting)
    - `aarch64-apple-visionos-sim` (in visionOS Simulator)
- macOS 15.3.1 VM
    - `aarch64-apple-darwin`
    - `aarch64-apple-ios-macabi`
- macOS 10.12.6 on an Intel Macbook from 2013
    - `x86_64-apple-darwin`
    - `i686-apple-darwin`
    - `x86_64-apple-ios` (in iOS Simulator)
- iOS 9.3.6 on a 1st generation iPad Mini
    - `armv7-apple-ios` with an older compiler

Along with manually inspecting the output of `version_from_sysctl()` and `version_from_plist()`, and verifying that they actually match what's expected.

I believe the only real omissions here would be:
- `aarch64-apple-ios` on a newer iPhone that has `sysctl` available (iOS 11.4 or above).
- `aarch64-apple-ios` on a Vision Pro using Xcode's "Designed for iPad" setting.

But I don't have the hardware available to test those.

``@rustbot`` label O-apple A-linkage -T-compiler -A-meta -A-run-make

try-job: aarch64-apple
2025-09-05 22:47:17 +02:00
..
backtrace remove redundant imports 2023-12-10 10:56:22 +08:00
collections remove deprecated Error::description in impls 2025-08-26 06:36:53 +00:00
ffi Constify conversion traits 2025-09-01 21:38:26 -04:00
fs Rollup merge of #140459 - niklasf:feature/read-buf-at, r=tgross35 2025-09-04 10:01:51 +10:00
hash remove const_hash feature leftovers 2024-11-02 11:27:14 +01:00
io remove deprecated Error::description in impls 2025-08-26 06:36:53 +00:00
net Set MSG_NOSIGNAL for UnixSteam 2025-06-16 09:15:17 +02:00
num Revert "Rollup merge of #143906 - LorrensP-2158466:miri-float-nondet-foreign-items, r=RalfJung" 2025-08-08 19:16:48 +02:00
os Rollup merge of #140459 - niklasf:feature/read-buf-at, r=tgross35 2025-09-04 10:01:51 +10:00
prelude Make derive_const usable within libcore again 2025-07-17 15:42:54 +00:00
process std: Apply deprecated_safe_2024 2025-02-13 13:10:28 -08:00
sync Rollup merge of #144651 - connortsui20:nonpoison_condvar, r=joboet 2025-08-30 20:29:06 +10:00
sys Rollup merge of #138944 - madsmtm:apple_os_version_check, r=tgross35 2025-09-05 22:47:17 +02:00
sys_common Move WTF-8 code from std to core/alloc 2025-08-20 20:31:33 -04:00
thread Tweak wording again 2025-08-19 19:05:19 -04:00
alloc.rs Make __rust_alloc_error_handler_should_panic a function 2025-07-03 10:52:21 -07:00
ascii.rs Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
backtrace.rs use generic Atomic type where possible 2025-04-27 02:18:08 +03:00
bstr.rs Implement ByteStr and ByteString types 2025-01-11 06:35:21 +02:00
env.rs remove deprecated Error::description in impls 2025-08-26 06:36:53 +00:00
error.rs Move std::error unit tests to integration tests 2025-01-26 10:28:04 +00:00
fs.rs Rollup merge of #144964 - 0xdeafbeef:fix-open-options, r=ibraheemdev 2025-08-30 18:49:48 -05:00
keyword_docs.rs unsafe keyword docs: emphasize that an unsafe fn in a trait does not get to choose its safety contract 2025-06-06 22:34:10 +02:00
lib.miri.rs add 'x.py miri', and make it work for 'library/{core,alloc,std}' 2024-04-03 20:27:20 +02:00
lib.rs Rollup merge of #138944 - madsmtm:apple_os_version_check, r=tgross35 2025-09-05 22:47:17 +02:00
macros.rs feat: implement hash_map! macro 2025-08-02 01:32:52 +02:00
panic.rs Link to payload_as_str() from payload(). 2025-08-12 12:50:48 +02:00
panicking.rs improve process::abort rendering in Miri backtraces 2025-09-02 12:19:06 +02:00
pat.rs Add pattern types to parser 2024-04-08 11:57:17 +00:00
path.rs fix 2025-09-04 18:33:47 +07:00
process.rs improve process::abort rendering in Miri backtraces 2025-09-02 12:19:06 +02:00
random.rs random: Provide a Distribution<T> trait 2025-07-11 10:21:34 -07:00
rt.rs deduplicate abort implementations 2025-05-15 11:20:13 +02:00
test_helpers.rs std: get rid of sys_common::io 2025-02-07 16:54:07 +01:00
time.rs remove deprecated Error::description in impls 2025-08-26 06:36:53 +00:00