os_version_check.zig (2988B) - Raw
1 const std = @import("std"); 2 const testing = std.testing; 3 const builtin = @import("builtin"); 4 const common = @import("common.zig"); 5 const panic = @import("common.zig").panic; 6 7 const have_availability_version_check = builtin.os.tag.isDarwin() and 8 builtin.os.version_range.semver.min.order(.{ .major = 10, .minor = 15, .patch = 0 }).compare(.gte); 9 10 comptime { 11 if (have_availability_version_check) { 12 @export(&__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = common.linkage, .visibility = common.visibility }); 13 } 14 } 15 16 // Ported from llvm-project 13.0.0 d7b669b3a30345cfcdb2fde2af6f48aa4b94845d 17 // 18 // https://github.com/llvm/llvm-project/blob/llvmorg-13.0.0/compiler-rt/lib/builtins/os_version_check.c 19 20 // The compiler generates calls to __isPlatformVersionAtLeast() when Objective-C's @available 21 // function is invoked. 22 // 23 // Old versions of clang would instead emit calls to __isOSVersionAtLeast(), which is still 24 // supported in clang's compiler-rt implementation today in case anyone tries to link an object file 25 // produced with an old clang version. This requires dynamically loading frameworks, parsing a 26 // system plist file, and generally adds a fair amount of complexity to the implementation and so 27 // our implementation differs by simply removing that backwards compatability support. We only use 28 // the newer codepath, which merely calls out to the Darwin _availability_version_check API which is 29 // available on macOS 10.15+, iOS 13+, tvOS 13+ and watchOS 6+. 30 31 const __isPlatformVersionAtLeast = if (have_availability_version_check) struct { 32 inline fn constructVersion(major: u32, minor: u32, subminor: u32) u32 { 33 return ((major & 0xffff) << 16) | ((minor & 0xff) << 8) | (subminor & 0xff); 34 } 35 36 // Darwin-only 37 fn __isPlatformVersionAtLeast(platform: u32, major: u32, minor: u32, subminor: u32) callconv(.c) i32 { 38 const build_version = dyld_build_version_t{ 39 .platform = platform, 40 .version = constructVersion(major, minor, subminor), 41 }; 42 return @intFromBool(_availability_version_check(1, &[_]dyld_build_version_t{build_version})); 43 } 44 45 // _availability_version_check darwin API support. 46 const dyld_platform_t = u32; 47 const dyld_build_version_t = extern struct { 48 platform: dyld_platform_t, 49 version: u32, 50 }; 51 // Darwin-only 52 extern "c" fn _availability_version_check(count: u32, versions: [*c]const dyld_build_version_t) bool; 53 }.__isPlatformVersionAtLeast else struct {}; 54 55 test "isPlatformVersionAtLeast" { 56 if (!have_availability_version_check) return error.SkipZigTest; 57 58 // Note: this test depends on the actual host OS version since it is merely calling into the 59 // native Darwin API. 60 const macos_platform_constant = 1; 61 try testing.expect(__isPlatformVersionAtLeast(macos_platform_constant, 10, 0, 15) == 1); 62 try testing.expect(__isPlatformVersionAtLeast(macos_platform_constant, 99, 0, 0) == 0); 63 }