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 }
This commit is contained in:
1
lib/libc/darwin/SDKSettings.json
vendored
Normal file
1
lib/libc/darwin/SDKSettings.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"MinimalDisplayName":"14.0"}
|
||||
@@ -1554,6 +1554,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
.use_lld = use_lld,
|
||||
.use_llvm = use_llvm,
|
||||
.use_lib_llvm = use_lib_llvm,
|
||||
.libc_provider = libc_dirs.provider,
|
||||
.link_libc = link_libc,
|
||||
.link_libcpp = link_libcpp,
|
||||
.link_libunwind = link_libunwind,
|
||||
@@ -5654,6 +5655,7 @@ const LibCDirs = struct {
|
||||
libc_installation: ?*const LibCInstallation,
|
||||
libc_framework_dir_list: []const []const u8,
|
||||
sysroot: ?[]const u8,
|
||||
provider: link.LibCProvider,
|
||||
};
|
||||
|
||||
fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8) !LibCDirs {
|
||||
@@ -5669,6 +5671,7 @@ fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8)
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
.provider = .vendored,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5686,6 +5689,7 @@ pub fn detectLibCIncludeDirs(
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
.provider = .none,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5743,6 +5747,7 @@ pub fn detectLibCIncludeDirs(
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
.provider = .none,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5797,6 +5802,7 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const
|
||||
.libc_installation = lci,
|
||||
.libc_framework_dir_list = framework_list.items,
|
||||
.sysroot = sysroot,
|
||||
.provider = if (sysroot == null) .installation else .sysroot,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5858,6 +5864,7 @@ fn detectLibCFromBuilding(
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
.provider = .vendored,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ pub const Options = struct {
|
||||
/// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
|
||||
use_llvm: bool,
|
||||
use_lib_llvm: bool,
|
||||
libc_provider: LibCProvider,
|
||||
link_libc: bool,
|
||||
link_libcpp: bool,
|
||||
link_libunwind: bool,
|
||||
@@ -282,6 +283,13 @@ pub const HashStyle = enum { sysv, gnu, both };
|
||||
|
||||
pub const CompressDebugSections = enum { none, zlib };
|
||||
|
||||
pub const LibCProvider = enum {
|
||||
none,
|
||||
installation,
|
||||
sysroot,
|
||||
vendored,
|
||||
};
|
||||
|
||||
pub const File = struct {
|
||||
tag: Tag,
|
||||
options: Options,
|
||||
|
||||
@@ -558,10 +558,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
||||
});
|
||||
{
|
||||
const platform = Platform.fromTarget(self.base.options.target);
|
||||
const sdk_version: ?std.SemanticVersion = if (self.base.options.sysroot) |path|
|
||||
load_commands.inferSdkVersionFromSdkPath(path)
|
||||
else
|
||||
null;
|
||||
const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(comp);
|
||||
if (platform.isBuildVersionCompatible()) {
|
||||
try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer);
|
||||
} else if (platform.isVersionMinCompatible()) {
|
||||
@@ -647,11 +644,6 @@ pub fn resolveLibSystem(
|
||||
var checked_paths = std.ArrayList([]const u8).init(tmp_arena);
|
||||
|
||||
success: {
|
||||
if (self.base.options.sysroot) |root| {
|
||||
const dir = try fs.path.join(tmp_arena, &[_][]const u8{ root, "usr", "lib" });
|
||||
if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
|
||||
}
|
||||
|
||||
for (search_dirs) |dir| if (try accessLibPath(
|
||||
tmp_arena,
|
||||
&test_path,
|
||||
@@ -660,8 +652,18 @@ pub fn resolveLibSystem(
|
||||
"libSystem",
|
||||
)) break :success;
|
||||
|
||||
const dir = try comp.zig_lib_directory.join(tmp_arena, &[_][]const u8{ "libc", "darwin" });
|
||||
if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
|
||||
switch (self.base.options.libc_provider) {
|
||||
.none => unreachable,
|
||||
.installation => unreachable,
|
||||
.sysroot => {
|
||||
const dir = try fs.path.join(tmp_arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" });
|
||||
if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
|
||||
},
|
||||
.vendored => {
|
||||
const dir = try comp.zig_lib_directory.join(tmp_arena, &[_][]const u8{ "libc", "darwin" });
|
||||
if (try accessLibPath(tmp_arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
|
||||
},
|
||||
}
|
||||
|
||||
try self.reportMissingLibraryError(checked_paths.items, "unable to find libSystem system library", .{});
|
||||
return;
|
||||
|
||||
@@ -467,8 +467,34 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn inferSdkVersionFromSdkPath(path: []const u8) ?std.SemanticVersion {
|
||||
const stem = std.fs.path.stem(path);
|
||||
fn readSdkVersionString(arena: Allocator, dir: []const u8) ![]const u8 {
|
||||
const sdk_path = try std.fs.path.join(arena, &.{ dir, "SDKSettings.json" });
|
||||
const contents = try std.fs.cwd().readFileAlloc(arena, sdk_path, std.math.maxInt(u16));
|
||||
const parsed = try std.json.parseFromSlice(std.json.Value, arena, contents, .{});
|
||||
if (parsed.value.object.get("MinimalDisplayName")) |ver| return ver.string;
|
||||
return error.SdkVersionFailure;
|
||||
}
|
||||
|
||||
pub fn inferSdkVersion(comp: *const Compilation) ?std.SemanticVersion {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
const options = comp.bin_file.options;
|
||||
|
||||
const sdk_dir = switch (options.libc_provider) {
|
||||
.none => unreachable,
|
||||
.installation => unreachable,
|
||||
.sysroot => options.sysroot.?,
|
||||
.vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null,
|
||||
};
|
||||
|
||||
// prefer meta information if available
|
||||
if (readSdkVersionString(arena, sdk_dir)) |ver| {
|
||||
return parseSdkVersion(ver);
|
||||
} else |_| {}
|
||||
|
||||
// infer from pathname
|
||||
const stem = std.fs.path.stem(sdk_dir);
|
||||
const start = for (stem, 0..) |c, i| {
|
||||
if (std.ascii.isDigit(c)) break i;
|
||||
} else stem.len;
|
||||
@@ -532,3 +558,4 @@ const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
const Dylib = @import("Dylib.zig");
|
||||
const MachO = @import("../MachO.zig");
|
||||
const Compilation = @import("../../Compilation.zig");
|
||||
|
||||
@@ -241,10 +241,7 @@ pub fn linkWithZld(
|
||||
try argv.append(@tagName(platform.os_tag));
|
||||
try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version}));
|
||||
|
||||
const sdk_version: ?std.SemanticVersion = if (options.sysroot) |path|
|
||||
load_commands.inferSdkVersionFromSdkPath(path)
|
||||
else
|
||||
null;
|
||||
const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(comp);
|
||||
if (sdk_version) |ver| {
|
||||
try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor }));
|
||||
} else {
|
||||
@@ -591,10 +588,7 @@ pub fn linkWithZld(
|
||||
});
|
||||
{
|
||||
const platform = Platform.fromTarget(macho_file.base.options.target);
|
||||
const sdk_version: ?std.SemanticVersion = if (macho_file.base.options.sysroot) |path|
|
||||
load_commands.inferSdkVersionFromSdkPath(path)
|
||||
else
|
||||
null;
|
||||
const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(comp);
|
||||
if (platform.isBuildVersionCompatible()) {
|
||||
try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user