Skip to content

Commit 430ae4d

Browse files
committed
std.zig.system.darwin.isSdkInstalled: fix implementation
* don't assert that the child process doesn't crash * don't give a false negative on warnings printed to stderr Also fix getSdk from the same file in the same way
1 parent c63ca42 commit 430ae4d

File tree

1 file changed

+24
-20
lines changed

1 file changed

+24
-20
lines changed

lib/std/zig/system/darwin.zig

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,33 @@ pub const macos = @import("darwin/macos.zig");
88

99
/// Check if SDK is installed on Darwin without triggering CLT installation popup window.
1010
/// Note: simply invoking `xcrun` will inevitably trigger the CLT installation popup.
11-
/// Therefore, we resort to the same tool used by Homebrew, namely, invoking `xcode-select --print-path`
12-
/// and checking if the status is nonzero or the returned string in nonempty.
13-
/// https://github.com/Homebrew/brew/blob/e119bdc571dcb000305411bc1e26678b132afb98/Library/Homebrew/brew.sh#L630
11+
/// Therefore, we resort to invoking `xcode-select --print-path` and checking
12+
/// if the status is nonzero.
13+
/// stderr from xcode-select is ignored.
14+
/// If error.OutOfMemory occurs in Allocator, this function returns null.
1415
pub fn isSdkInstalled(allocator: Allocator) bool {
15-
const argv = &[_][]const u8{ "/usr/bin/xcode-select", "--print-path" };
16-
const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return false;
16+
const result = std.process.Child.exec(.{
17+
.allocator = allocator,
18+
.argv = &.{ "/usr/bin/xcode-select", "--print-path" },
19+
}) catch return false;
20+
1721
defer {
1822
allocator.free(result.stderr);
1923
allocator.free(result.stdout);
2024
}
21-
if (result.stderr.len != 0 or result.term.Exited != 0) {
22-
// We don't actually care if there were errors as this is best-effort check anyhow.
23-
return false;
24-
}
25-
return result.stdout.len > 0;
25+
26+
return switch (result.term) {
27+
.Exited => |code| if (code == 0) result.stdout.len > 0 else false,
28+
else => false,
29+
};
2630
}
2731

2832
/// Detect SDK on Darwin.
2933
/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which fetches the path to the SDK sysroot (if any).
3034
/// Subsequently calls `xcrun --sdk <target_sdk> --show-sdk-version` which fetches version of the SDK.
3135
/// The caller needs to deinit the resulting struct.
36+
/// stderr from xcrun is ignored.
37+
/// If error.OutOfMemory occurs in Allocator, this function returns null.
3238
pub fn getSdk(allocator: Allocator, target: Target) ?Sdk {
3339
const is_simulator_abi = target.abi == .simulator;
3440
const sdk = switch (target.os.tag) {
@@ -40,30 +46,28 @@ pub fn getSdk(allocator: Allocator, target: Target) ?Sdk {
4046
};
4147
const path = path: {
4248
const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-path" };
43-
const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
49+
const result = std.process.Child.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
4450
defer {
4551
allocator.free(result.stderr);
4652
allocator.free(result.stdout);
4753
}
48-
if (result.stderr.len != 0 or result.term.Exited != 0) {
49-
// We don't actually care if there were errors as this is best-effort check anyhow
50-
// and in the worst case the user can specify the sysroot manually.
51-
return null;
54+
switch (result.term) {
55+
.Exited => |code| if (code != 0) return null,
56+
else => return null,
5257
}
5358
const path = allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n")) catch return null;
5459
break :path path;
5560
};
5661
const version = version: {
5762
const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-version" };
58-
const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
63+
const result = std.process.Child.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
5964
defer {
6065
allocator.free(result.stderr);
6166
allocator.free(result.stdout);
6267
}
63-
if (result.stderr.len != 0 or result.term.Exited != 0) {
64-
// We don't actually care if there were errors as this is best-effort check anyhow
65-
// and in the worst case the user can specify the sysroot manually.
66-
return null;
68+
switch (result.term) {
69+
.Exited => |code| if (code != 0) return null,
70+
else => return null,
6771
}
6872
const raw_version = mem.trimRight(u8, result.stdout, "\r\n");
6973
const version = parseSdkVersion(raw_version) orelse Version{

0 commit comments

Comments
 (0)