aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-11-26 12:00:30 -0800
committerGitHub <noreply@github.com>2021-11-26 12:00:30 -0800
commit7c2cc45ad87b621831ac4b8cada809c2d88cdf0d (patch)
treed831a33e04f90fb27558bce226985095ef981546 /src
parenta2c546fea30de2caf1efb454d327e70270c07338 (diff)
parente2b6dfa6087f2e63bbc03e0430b73e900c95a193 (diff)
downloadzig-7c2cc45ad87b621831ac4b8cada809c2d88cdf0d.tar.gz
zig-7c2cc45ad87b621831ac4b8cada809c2d88cdf0d.zip
Merge pull request #10226 from ziglang/fix-10217
macos: improved SDK detection and linker integration with _mh_execute_header
Diffstat (limited to 'src')
-rw-r--r--src/Compilation.zig96
-rw-r--r--src/link.zig3
-rw-r--r--src/link/MachO.zig54
-rw-r--r--src/main.zig9
4 files changed, 113 insertions, 49 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 64e08c62be..ac25519190 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -773,6 +773,8 @@ pub const InitOptions = struct {
wasi_exec_model: ?std.builtin.WasiExecModel = null,
/// (Zig compiler development) Enable dumping linker's state as JSON.
enable_link_snapshots: bool = false,
+ /// (Darwin) Path and version of the native SDK if detected.
+ native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
};
fn addPackageTableToCacheHash(
@@ -962,18 +964,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
break :blk false;
};
- const darwin_use_system_sdk = blk: {
- if (comptime !builtin.target.isDarwin()) break :blk false;
- if (!options.is_native_os) break :blk false;
- if (builtin.os.tag != .macos or !options.target.isDarwin()) break :blk false;
- break :blk options.frameworks.len > 0 or options.framework_dirs.len > 0;
- };
-
const sysroot = blk: {
if (options.sysroot) |sysroot| {
break :blk sysroot;
- } else if (darwin_use_system_sdk) {
- break :blk try std.zig.system.darwin.getSDKPath(arena, options.target);
+ } else if (options.native_darwin_sdk) |sdk| {
+ break :blk sdk.path;
} else {
break :blk null;
}
@@ -1060,6 +1055,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
link_libc,
options.system_lib_names.len != 0 or options.frameworks.len != 0,
options.libc_installation,
+ options.native_darwin_sdk != null,
);
const must_pie = target_util.requiresPIE(options.target);
@@ -1496,6 +1492,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.wasi_exec_model = wasi_exec_model,
.use_stage1 = use_stage1,
.enable_link_snapshots = options.enable_link_snapshots,
+ .native_darwin_sdk = options.native_darwin_sdk,
});
errdefer bin_file.destroy();
comp.* = .{
@@ -3776,6 +3773,37 @@ const LibCDirs = struct {
libc_installation: ?*const LibCInstallation,
};
+fn getZigShippedLibCIncludeDirsDarwin(arena: *Allocator, zig_lib_dir: []const u8, target: Target) !LibCDirs {
+ const arch_name = @tagName(target.cpu.arch);
+ const os_name = try std.fmt.allocPrint(arena, "{s}.{d}", .{
+ @tagName(target.os.tag),
+ target.os.version_range.semver.min.major,
+ });
+ const s = std.fs.path.sep_str;
+ const list = try arena.alloc([]const u8, 3);
+
+ list[0] = try std.fmt.allocPrint(
+ arena,
+ "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-gnu",
+ .{ zig_lib_dir, arch_name, os_name },
+ );
+ list[1] = try std.fmt.allocPrint(
+ arena,
+ "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
+ .{ zig_lib_dir, os_name },
+ );
+ list[2] = try std.fmt.allocPrint(
+ arena,
+ "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-macos-any",
+ .{zig_lib_dir},
+ );
+
+ return LibCDirs{
+ .libc_include_dir_list = list,
+ .libc_installation = null,
+ };
+}
+
fn detectLibCIncludeDirs(
arena: *Allocator,
zig_lib_dir: []const u8,
@@ -3784,6 +3812,7 @@ fn detectLibCIncludeDirs(
link_libc: bool,
link_system_libs: bool,
libc_installation: ?*const LibCInstallation,
+ has_macos_sdk: bool,
) !LibCDirs {
if (!link_libc) {
return LibCDirs{
@@ -3800,11 +3829,14 @@ fn detectLibCIncludeDirs(
// using the system libc installation.
if (link_system_libs and is_native_abi and !target.isMinGW()) {
if (target.isDarwin()) {
- // For Darwin/macOS, we are all set with getSDKPath found earlier.
- return LibCDirs{
- .libc_include_dir_list = &[0][]u8{},
- .libc_installation = null,
- };
+ return if (has_macos_sdk)
+ // For Darwin/macOS, we are all set with getDarwinSDK found earlier.
+ LibCDirs{
+ .libc_include_dir_list = &[0][]u8{},
+ .libc_installation = null,
+ }
+ else
+ getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target);
}
const libc = try arena.create(LibCInstallation);
libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true });
@@ -3815,36 +3847,14 @@ fn detectLibCIncludeDirs(
// default if possible.
if (target_util.canBuildLibC(target)) {
switch (target.os.tag) {
- .macos => {
- const arch_name = @tagName(target.cpu.arch);
- const os_name = try std.fmt.allocPrint(arena, "{s}.{d}", .{
- @tagName(target.os.tag),
- target.os.version_range.semver.min.major,
- });
- const s = std.fs.path.sep_str;
- const list = try arena.alloc([]const u8, 3);
-
- list[0] = try std.fmt.allocPrint(
- arena,
- "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-gnu",
- .{ zig_lib_dir, arch_name, os_name },
- );
- list[1] = try std.fmt.allocPrint(
- arena,
- "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
- .{ zig_lib_dir, os_name },
- );
- list[2] = try std.fmt.allocPrint(
- arena,
- "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-macos-any",
- .{zig_lib_dir},
- );
-
- return LibCDirs{
- .libc_include_dir_list = list,
+ .macos => return if (has_macos_sdk)
+ // For Darwin/macOS, we are all set with getDarwinSDK found earlier.
+ LibCDirs{
+ .libc_include_dir_list = &[0][]u8{},
.libc_installation = null,
- };
- },
+ }
+ else
+ getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target),
else => {
const generic_name = target_util.libCGenericName(target);
// Some architectures are handled by the same set of headers.
diff --git a/src/link.zig b/src/link.zig
index 38b91c9e39..77464737b0 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -153,6 +153,9 @@ pub const Options = struct {
/// (Zig compiler development) Enable dumping of linker's state as JSON.
enable_link_snapshots: bool = false,
+ /// (Darwin) Path and version of the native SDK if detected.
+ native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null,
+
pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
return if (options.use_lld) .Obj else options.output_mode;
}
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 4d5133a959..37f905cdd4 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -154,6 +154,7 @@ tentatives: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
locals_free_list: std.ArrayListUnmanaged(u32) = .{},
globals_free_list: std.ArrayListUnmanaged(u32) = .{},
+mh_execute_header_index: ?u32 = null,
dyld_stub_binder_index: ?u32 = null,
dyld_private_atom: ?*Atom = null,
stub_helper_preamble_atom: ?*Atom = null,
@@ -863,6 +864,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
sect.offset = self.tlv_bss_file_offset;
}
+ try self.createMhExecuteHeaderAtom();
for (self.objects.items) |*object, object_id| {
if (object.analyzed) continue;
try self.resolveSymbolsInObject(@intCast(u16, object_id));
@@ -2725,6 +2727,42 @@ fn resolveSymbolsInDylibs(self: *MachO) !void {
}
}
+fn createMhExecuteHeaderAtom(self: *MachO) !void {
+ if (self.mh_execute_header_index != null) return;
+
+ const match: MatchingSection = .{
+ .seg = self.text_segment_cmd_index.?,
+ .sect = self.text_section_index.?,
+ };
+ const n_strx = try self.makeString("__mh_execute_header");
+ const local_sym_index = @intCast(u32, self.locals.items.len);
+ var nlist = macho.nlist_64{
+ .n_strx = n_strx,
+ .n_type = macho.N_SECT,
+ .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1),
+ .n_desc = 0,
+ .n_value = 0,
+ };
+ try self.locals.append(self.base.allocator, nlist);
+
+ nlist.n_type |= macho.N_EXT;
+ const global_sym_index = @intCast(u32, self.globals.items.len);
+ try self.globals.append(self.base.allocator, nlist);
+ try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
+ .where = .global,
+ .where_index = global_sym_index,
+ .local_sym_index = local_sym_index,
+ .file = null,
+ });
+
+ const atom = try self.createEmptyAtom(local_sym_index, 0, 0);
+ const sym = &self.locals.items[local_sym_index];
+ const vaddr = try self.allocateAtom(atom, 0, 1, match);
+ sym.n_value = vaddr;
+ atom.dirty = false;
+ self.mh_execute_header_index = local_sym_index;
+}
+
fn resolveDyldStubBinder(self: *MachO) !void {
if (self.dyld_stub_binder_index != null) return;
@@ -4077,8 +4115,16 @@ pub fn populateMissingMetadata(self: *MachO) !void {
@sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version),
@sizeOf(u64),
));
- const ver = self.base.options.target.os.version_range.semver.min;
- const version = ver.major << 16 | ver.minor << 8 | ver.patch;
+ const platform_version = blk: {
+ const ver = self.base.options.target.os.version_range.semver.min;
+ const platform_version = ver.major << 16 | ver.minor << 8;
+ break :blk platform_version;
+ };
+ const sdk_version = if (self.base.options.native_darwin_sdk) |sdk| blk: {
+ const ver = sdk.version;
+ const sdk_version = ver.major << 16 | ver.minor << 8;
+ break :blk sdk_version;
+ } else platform_version;
const is_simulator_abi = self.base.options.target.abi == .simulator;
var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
.cmd = macho.LC_BUILD_VERSION,
@@ -4090,8 +4136,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
.tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,
else => unreachable,
},
- .minos = version,
- .sdk = version,
+ .minos = platform_version,
+ .sdk = sdk_version,
.ntools = 1,
});
const ld_ver = macho.build_tool_version{
diff --git a/src/main.zig b/src/main.zig
index 20ea5caded..5590e14d0e 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -663,6 +663,7 @@ fn buildOutputType(
var minor_subsystem_version: ?u32 = null;
var wasi_exec_model: ?std.builtin.WasiExecModel = null;
var enable_link_snapshots: bool = false;
+ var native_darwin_sdk: ?std.zig.system.darwin.DarwinSDK = null;
var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa);
defer system_libs.deinit();
@@ -1857,10 +1858,13 @@ fn buildOutputType(
}
const has_sysroot = if (comptime builtin.target.isDarwin()) outer: {
- if (try std.zig.system.darwin.getSDKPath(arena, target_info.target)) |sdk_path| {
+ if (std.zig.system.darwin.isDarwinSDKInstalled(arena)) {
+ const sdk = std.zig.system.darwin.getDarwinSDK(arena, target_info.target) orelse
+ break :outer false;
+ native_darwin_sdk = sdk;
try clang_argv.ensureUnusedCapacity(2);
clang_argv.appendAssumeCapacity("-isysroot");
- clang_argv.appendAssumeCapacity(sdk_path);
+ clang_argv.appendAssumeCapacity(sdk.path);
break :outer true;
} else break :outer false;
} else false;
@@ -2340,6 +2344,7 @@ fn buildOutputType(
.wasi_exec_model = wasi_exec_model,
.debug_compile_errors = debug_compile_errors,
.enable_link_snapshots = enable_link_snapshots,
+ .native_darwin_sdk = native_darwin_sdk,
}) catch |err| {
fatal("unable to create compilation: {s}", .{@errorName(err)});
};