authorgravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2023-09-15 01:05:14-04:00
committergravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2023-09-25 15:53:05-04:00
log5d6521d2814e6768536103c233d2e283051b9f1e
treebccd4d252a4c9849ae31e76258d6e7d83a35f78b
parent15fd7cd154316e7eb3bf254e249072e562fdbe2c
signaturelock-open Commit is signed but in an unrecognized format.

macos: better SDK version detection

SDK version detection: - read SDKSettings.json before inferral from SDK path - vendored libc: add SDKSettings.json for SDK version info resolveLibSystem: - adjust search order to { search_dirs, { sysroot or vendored }} - previous search order was { sysroot, search_dirs, vendored }

6 files changed, 60 insertions(+), 21 deletions(-)

lib/libc/darwin/SDKSettings.json created+1
......@@ -0,0 +1 @@
1{"MinimalDisplayName":"14.0"}
src/Compilation.zig+7
......@@ -1554,6 +1554,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15541554 .use_lld = use_lld,
15551555 .use_llvm = use_llvm,
15561556 .use_lib_llvm = use_lib_llvm,
1557 .libc_provider = libc_dirs.provider,
15571558 .link_libc = link_libc,
15581559 .link_libcpp = link_libcpp,
15591560 .link_libunwind = link_libunwind,
......@@ -5654,6 +5655,7 @@ const LibCDirs = struct {
56545655 libc_installation: ?*const LibCInstallation,
56555656 libc_framework_dir_list: []const []const u8,
56565657 sysroot: ?[]const u8,
5658 provider: link.LibCProvider,
56575659};
56585660
56595661fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8) !LibCDirs {
......@@ -5669,6 +5671,7 @@ fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8)
56695671 .libc_installation = null,
56705672 .libc_framework_dir_list = &.{},
56715673 .sysroot = null,
5674 .provider = .vendored,
56725675 };
56735676}
56745677
......@@ -5686,6 +5689,7 @@ pub fn detectLibCIncludeDirs(
56865689 .libc_installation = null,
56875690 .libc_framework_dir_list = &.{},
56885691 .sysroot = null,
5692 .provider = .none,
56895693 };
56905694 }
56915695
......@@ -5743,6 +5747,7 @@ pub fn detectLibCIncludeDirs(
57435747 .libc_installation = null,
57445748 .libc_framework_dir_list = &.{},
57455749 .sysroot = null,
5750 .provider = .none,
57465751 };
57475752}
57485753
......@@ -5797,6 +5802,7 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const
57975802 .libc_installation = lci,
57985803 .libc_framework_dir_list = framework_list.items,
57995804 .sysroot = sysroot,
5805 .provider = if (sysroot == null) .installation else .sysroot,
58005806 };
58015807}
58025808
......@@ -5858,6 +5864,7 @@ fn detectLibCFromBuilding(
58585864 .libc_installation = null,
58595865 .libc_framework_dir_list = &.{},
58605866 .sysroot = null,
5867 .provider = .vendored,
58615868 };
58625869}
58635870
src/link.zig+8
......@@ -134,6 +134,7 @@ pub const Options = struct {
134134 /// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
135135 use_llvm: bool,
136136 use_lib_llvm: bool,
137 libc_provider: LibCProvider,
137138 link_libc: bool,
138139 link_libcpp: bool,
139140 link_libunwind: bool,
......@@ -282,6 +283,13 @@ pub const HashStyle = enum { sysv, gnu, both };
282283
283284pub const CompressDebugSections = enum { none, zlib };
284285
286pub const LibCProvider = enum {
287 none,
288 installation,
289 sysroot,
290 vendored,
291};
292
285293pub const File = struct {
286294 tag: Tag,
287295 options: Options,
src/link/MachO.zig+13-11
......@@ -558,10 +558,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
558558 });
559559 {
560560 const platform = Platform.fromTarget(self.base.options.target);
561 const sdk_version: ?std.SemanticVersion = if (self.base.options.sysroot) |path|
562 load_commands.inferSdkVersionFromSdkPath(path)
563 else
564 null;
561 const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(comp);
565562 if (platform.isBuildVersionCompatible()) {
566563 try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer);
567564 } else if (platform.isVersionMinCompatible()) {
......@@ -647,11 +644,6 @@ pub fn resolveLibSystem(
647644 var checked_paths = std.ArrayList([]const u8).init(tmp_arena);
648645
649646 success: {
650 if (self.base.options.sysroot) |root| {
651 const dir = try fs.path.join(tmp_arena, &[_][]const u8{ root, "usr", "lib" });
652 if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
653 }
654
655647 for (search_dirs) |dir| if (try accessLibPath(
656648 tmp_arena,
657649 &test_path,
......@@ -660,8 +652,18 @@ pub fn resolveLibSystem(
660652 "libSystem",
661653 )) break :success;
662654
663 const dir = try comp.zig_lib_directory.join(tmp_arena, &[_][]const u8{ "libc", "darwin" });
664 if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
655 switch (self.base.options.libc_provider) {
656 .none => unreachable,
657 .installation => unreachable,
658 .sysroot => {
659 const dir = try fs.path.join(tmp_arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" });
660 if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
661 },
662 .vendored => {
663 const dir = try comp.zig_lib_directory.join(tmp_arena, &[_][]const u8{ "libc", "darwin" });
664 if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
665 },
666 }
665667
666668 try self.reportMissingLibraryError(checked_paths.items, "unable to find libSystem system library", .{});
667669 return;
src/link/MachO/load_commands.zig+29-2
......@@ -467,8 +467,34 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion {
467467 };
468468}
469469
470pub fn inferSdkVersionFromSdkPath(path: []const u8) ?std.SemanticVersion {
471 const stem = std.fs.path.stem(path);
470fn readSdkVersionString(arena: Allocator, dir: []const u8) ![]const u8 {
471 const sdk_path = try std.fs.path.join(arena, &.{ dir, "SDKSettings.json" });
472 const contents = try std.fs.cwd().readFileAlloc(arena, sdk_path, std.math.maxInt(u16));
473 const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{});
474 if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string;
475 return error.SdkVersionFailure;
476}
477
478pub fn inferSdkVersion(comp: *const Compilation) ?std.SemanticVersion {
479 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
480 defer arena_allocator.deinit();
481 const arena = arena_allocator.allocator();
482 const options = comp.bin_file.options;
483
484 const sdk_dir = switch (options.libc_provider) {
485 .none => unreachable,
486 .installation => unreachable,
487 .sysroot => options.sysroot.?,
488 .vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null,
489 };
490
491 // prefer meta information if available
492 if (readSdkVersionString(arena, sdk_dir)) |ver| {
493 return parseSdkVersion(ver);
494 } else |_| {}
495
496 // infer from pathname
497 const stem = std.fs.path.stem(sdk_dir);
472498 const start = for (stem, 0..) |c, i| {
473499 if (std.ascii.isDigit(c)) break i;
474500 } else stem.len;
......@@ -532,3 +558,4 @@ const mem = std.mem;
532558const Allocator = mem.Allocator;
533559const Dylib = @import("Dylib.zig");
534560const MachO = @import("../MachO.zig");
561const Compilation = @import("../../Compilation.zig");
src/link/MachO/zld.zig+2-8
......@@ -241,10 +241,7 @@ pub fn linkWithZld(
241241 try argv.append(@tagName(platform.os_tag));
242242 try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version}));
243243
244 const sdk_version: ?std.SemanticVersion = if (options.sysroot) |path|
245 load_commands.inferSdkVersionFromSdkPath(path)
246 else
247 null;
244 const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(comp);
248245 if (sdk_version) |ver| {
249246 try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));
250247 } else {
......@@ -591,10 +588,7 @@ pub fn linkWithZld(
591588 });
592589 {
593590 const platform = Platform.fromTarget(macho_file.base.options.target);
594 const sdk_version: ?std.SemanticVersion = if (macho_file.base.options.sysroot) |path|
595 load_commands.inferSdkVersionFromSdkPath(path)
596 else
597 null;
591 const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(comp);
598592 if (platform.isBuildVersionCompatible()) {
599593 try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer);
600594 } else {