diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-08-28 21:39:25 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-08-29 06:43:41 +0200 |
| commit | 3b2b9fcbc5e162063febf989883f29e55cc64c65 (patch) | |
| tree | c85bbce50c24a18df10e08889b1cb3cc3f69e335 /lib/std | |
| parent | c429bb5d2feb36f83e33ef95a25dd5bb7455f16c (diff) | |
| download | zig-3b2b9fcbc5e162063febf989883f29e55cc64c65.tar.gz zig-3b2b9fcbc5e162063febf989883f29e55cc64c65.zip | |
darwin: move inference of SDK version into the linker
`std.zig.system.darwin.getSdk` now pulls only the SDK path
so we execute a child process only once and not twice as it was
until now since we parse the SDK version directly from the pulled path.
This is actually how `ld64` does it too.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/zig/system/NativePaths.zig | 6 | ||||
| -rw-r--r-- | lib/std/zig/system/darwin.zig | 101 |
2 files changed, 17 insertions, 90 deletions
diff --git a/lib/std/zig/system/NativePaths.zig b/lib/std/zig/system/NativePaths.zig index 4c8f1286b8..99ff554106 100644 --- a/lib/std/zig/system/NativePaths.zig +++ b/lib/std/zig/system/NativePaths.zig @@ -81,9 +81,9 @@ pub fn detect(arena: Allocator, native_info: NativeTargetInfo) !NativePaths { if (comptime builtin.target.isDarwin()) { if (std.zig.system.darwin.isSdkInstalled(arena)) sdk: { const sdk = std.zig.system.darwin.getSdk(arena, native_target) orelse break :sdk; - try self.addLibDir(try std.fs.path.join(arena, &.{ sdk.path, "usr/lib" })); - try self.addFrameworkDir(try std.fs.path.join(arena, &.{ sdk.path, "System/Library/Frameworks" })); - try self.addIncludeDir(try std.fs.path.join(arena, &.{ sdk.path, "usr/include" })); + try self.addLibDir(try std.fs.path.join(arena, &.{ sdk, "usr/lib" })); + try self.addFrameworkDir(try std.fs.path.join(arena, &.{ sdk, "System/Library/Frameworks" })); + try self.addIncludeDir(try std.fs.path.join(arena, &.{ sdk, "usr/include" })); return self; } return self; diff --git a/lib/std/zig/system/darwin.zig b/lib/std/zig/system/darwin.zig index 992c0d814d..ade3e7c653 100644 --- a/lib/std/zig/system/darwin.zig +++ b/lib/std/zig/system/darwin.zig @@ -30,12 +30,11 @@ pub fn isSdkInstalled(allocator: Allocator) bool { } /// Detect SDK on Darwin. -/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which fetches the path to the SDK sysroot (if any). -/// Subsequently calls `xcrun --sdk <target_sdk> --show-sdk-version` which fetches version of the SDK. -/// The caller needs to deinit the resulting struct. +/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which fetches the path to the SDK. +/// Caller owns the memory. /// stderr from xcrun is ignored. /// If error.OutOfMemory occurs in Allocator, this function returns null. -pub fn getSdk(allocator: Allocator, target: Target) ?Sdk { +pub fn getSdk(allocator: Allocator, target: Target) ?[]const u8 { const is_simulator_abi = target.abi == .simulator; const sdk = switch (target.os.tag) { .macos => "macosx", @@ -44,91 +43,19 @@ pub fn getSdk(allocator: Allocator, target: Target) ?Sdk { .tvos => if (is_simulator_abi) "appletvsimulator" else "appletvos", else => return null, }; - const path = path: { - const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-path" }; - const result = std.process.Child.exec(.{ .allocator = allocator, .argv = argv }) catch return null; - defer { - allocator.free(result.stderr); - allocator.free(result.stdout); - } - switch (result.term) { - .Exited => |code| if (code != 0) return null, - else => return null, - } - const path = allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n")) catch return null; - break :path path; - }; - const version = version: { - const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-version" }; - const result = std.process.Child.exec(.{ .allocator = allocator, .argv = argv }) catch return null; - defer { - allocator.free(result.stderr); - allocator.free(result.stdout); - } - switch (result.term) { - .Exited => |code| if (code != 0) return null, - else => return null, - } - const raw_version = mem.trimRight(u8, result.stdout, "\r\n"); - const version = parseSdkVersion(raw_version) orelse Version{ - .major = 0, - .minor = 0, - .patch = 0, - }; - break :version version; - }; - return Sdk{ - .path = path, - .version = version, - }; -} - -// Versions reported by Apple aren't exactly semantically valid as they usually omit -// the patch component. Hence, we do a simple check for the number of components and -// add the missing patch value if needed. -fn parseSdkVersion(raw: []const u8) ?Version { - var buffer: [128]u8 = undefined; - if (raw.len > buffer.len) return null; - @memcpy(buffer[0..raw.len], raw); - const dots_count = mem.count(u8, raw, "."); - if (dots_count < 1) return null; - const len = if (dots_count < 2) blk: { - const patch_suffix = ".0"; - buffer[raw.len..][0..patch_suffix.len].* = patch_suffix.*; - break :blk raw.len + patch_suffix.len; - } else raw.len; - return Version.parse(buffer[0..len]) catch null; -} - -pub const Sdk = struct { - path: []const u8, - version: Version, - - pub fn deinit(self: Sdk, allocator: Allocator) void { - allocator.free(self.path); + const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-path" }; + const result = std.process.Child.exec(.{ .allocator = allocator, .argv = argv }) catch return null; + defer { + allocator.free(result.stderr); + allocator.free(result.stdout); + } + switch (result.term) { + .Exited => |code| if (code != 0) return null, + else => return null, } -}; + return allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n")) catch null; +} test { _ = macos; } - -const expect = std.testing.expect; -const expectEqual = std.testing.expectEqual; - -fn testParseSdkVersionSuccess(exp: Version, raw: []const u8) !void { - const maybe_ver = parseSdkVersion(raw); - try expect(maybe_ver != null); - const ver = maybe_ver.?; - try expectEqual(exp.major, ver.major); - try expectEqual(exp.minor, ver.minor); - try expectEqual(exp.patch, ver.patch); -} - -test "parseSdkVersion" { - try testParseSdkVersionSuccess(.{ .major = 13, .minor = 4, .patch = 0 }, "13.4"); - try testParseSdkVersionSuccess(.{ .major = 13, .minor = 4, .patch = 1 }, "13.4.1"); - try testParseSdkVersionSuccess(.{ .major = 11, .minor = 15, .patch = 0 }, "11.15"); - - try expect(parseSdkVersion("11") == null); -} |
