Function detect [src]

Detect macOS version. target_os is not modified in case of error.

Prototype

pub fn detect(target_os: *Target.Os) !void

Parameters

target_os: *Target.Os

Source

pub fn detect(target_os: *Target.Os) !void { // Drop use of osproductversion sysctl because: // 1. only available 10.13.4 High Sierra and later // 2. when used from a binary built against < SDK 11.0 it returns 10.16 and masks Big Sur 11.x version // // NEW APPROACH, STEP 1, parse file: // // /System/Library/CoreServices/SystemVersion.plist // // NOTE: Historically `SystemVersion.plist` first appeared circa '2003 // with the release of Mac OS X 10.3.0 Panther. // // and if it contains a `10.16` value where the `16` is `>= 16` then it is non-canonical, // discarded, and we move on to next step. Otherwise we accept the version. // // BACKGROUND: `10.(16+)` is not a proper version and does not have enough fidelity to // indicate minor/point version of Big Sur and later. It is a context-sensitive result // issued by the kernel for backwards compatibility purposes. Likely the kernel checks // if the executable was linked against an SDK older than Big Sur. // // STEP 2, parse next file: // // /System/Library/CoreServices/.SystemVersionPlatform.plist // // NOTE: Historically `SystemVersionPlatform.plist` first appeared circa '2020 // with the release of macOS 11.0 Big Sur. // // Accessing the content via this path circumvents a context-sensitive result and // yields a canonical Big Sur version. // // At this time there is no other known way for a < SDK 11.0 executable to obtain a // canonical Big Sur version. // // This implementation uses a reasonably simplified approach to parse .plist file // that while it is an xml document, we have good history on the file and its format // such that I am comfortable with implementing a minimalistic parser. // Things like string and general escapes are not supported. const prefixSlash = "/System/Library/CoreServices/"; const paths = [_][]const u8{ prefixSlash ++ "SystemVersion.plist", prefixSlash ++ ".SystemVersionPlatform.plist", }; for (paths) |path| { // approx. 4 times historical file size var buf: [2048]u8 = undefined; if (std.fs.cwd().readFile(path, &buf)) |bytes| { if (parseSystemVersion(bytes)) |ver| { // never return non-canonical `10.(16+)` if (!(ver.major == 10 and ver.minor >= 16)) { target_os.version_range.semver.min = ver; target_os.version_range.semver.max = ver; return; } continue; } else |_| { return error.OSVersionDetectionFail; } } else |_| { return error.OSVersionDetectionFail; } } return error.OSVersionDetectionFail; }