mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 01:53:16 +00:00
Merge pull request #9532 from ziglang/basic-ios-support
Add minimal support to Zig toolchain to support building iOS binaries
This commit is contained in:
commit
60a5552d41
@ -2672,7 +2672,11 @@ pub const LibExeObjStep = struct {
|
||||
try zig_args.append(self.builder.pathFromRoot(include_path));
|
||||
},
|
||||
.raw_path_system => |include_path| {
|
||||
try zig_args.append("-isystem");
|
||||
if (builder.sysroot != null) {
|
||||
try zig_args.append("-iwithsysroot");
|
||||
} else {
|
||||
try zig_args.append("-isystem");
|
||||
}
|
||||
try zig_args.append(self.builder.pathFromRoot(include_path));
|
||||
},
|
||||
.other_step => |other| if (other.emit_h) {
|
||||
@ -2700,6 +2704,12 @@ pub const LibExeObjStep = struct {
|
||||
|
||||
if (self.target.isDarwin()) {
|
||||
for (self.framework_dirs.items) |dir| {
|
||||
if (builder.sysroot != null) {
|
||||
try zig_args.append("-iframeworkwithsysroot");
|
||||
} else {
|
||||
try zig_args.append("-iframework");
|
||||
}
|
||||
try zig_args.append(dir);
|
||||
try zig_args.append("-F");
|
||||
try zig_args.append(dir);
|
||||
}
|
||||
|
||||
@ -116,6 +116,21 @@ pub const build_tool_version = extern struct {
|
||||
version: u32,
|
||||
};
|
||||
|
||||
pub const PLATFORM_MACOS: u32 = 0x1;
|
||||
pub const PLATFORM_IOS: u32 = 0x2;
|
||||
pub const PLATFORM_TVOS: u32 = 0x3;
|
||||
pub const PLATFORM_WATCHOS: u32 = 0x4;
|
||||
pub const PLATFORM_BRIDGEOS: u32 = 0x5;
|
||||
pub const PLATFORM_MACCATALYST: u32 = 0x6;
|
||||
pub const PLATFORM_IOSSIMULATOR: u32 = 0x7;
|
||||
pub const PLATFORM_TVOSSIMULATOR: u32 = 0x8;
|
||||
pub const PLATFORM_WATCHOSSIMULATOR: u32 = 0x9;
|
||||
pub const PLATFORM_DRIVERKIT: u32 = 0x10;
|
||||
|
||||
pub const TOOL_CLANG: u32 = 0x1;
|
||||
pub const TOOL_SWIFT: u32 = 0x2;
|
||||
pub const TOOL_LD: u32 = 0x3;
|
||||
|
||||
/// The entry_point_command is a replacement for thread_command.
|
||||
/// It is used for main executables to specify the location (file offset)
|
||||
/// of main(). If -stack_size was used at link time, the stacksize
|
||||
|
||||
@ -13,12 +13,10 @@ const assert = std.debug.assert;
|
||||
const process = std.process;
|
||||
const Target = std.Target;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
const macos = @import("system/macos.zig");
|
||||
const native_endian = std.Target.current.cpu.arch.endian();
|
||||
const linux = @import("system/linux.zig");
|
||||
pub const windows = @import("system/windows.zig");
|
||||
|
||||
pub const getSDKPath = macos.getSDKPath;
|
||||
pub const darwin = @import("system/darwin.zig");
|
||||
|
||||
pub const NativePaths = struct {
|
||||
include_dirs: ArrayList([:0]u8),
|
||||
@ -255,7 +253,7 @@ pub const NativeTargetInfo = struct {
|
||||
os.version_range.windows.min = detected_version;
|
||||
os.version_range.windows.max = detected_version;
|
||||
},
|
||||
.macos => try macos.detect(&os),
|
||||
.macos => try darwin.macos.detect(&os),
|
||||
.freebsd, .netbsd, .dragonfly => {
|
||||
const key = switch (Target.current.os.tag) {
|
||||
.freebsd => "kern.osreldate",
|
||||
@ -972,7 +970,7 @@ pub const NativeTargetInfo = struct {
|
||||
|
||||
switch (std.Target.current.os.tag) {
|
||||
.linux => return linux.detectNativeCpuAndFeatures(),
|
||||
.macos => return macos.detectNativeCpuAndFeatures(),
|
||||
.macos => return darwin.macos.detectNativeCpuAndFeatures(),
|
||||
else => {},
|
||||
}
|
||||
|
||||
@ -983,6 +981,6 @@ pub const NativeTargetInfo = struct {
|
||||
};
|
||||
|
||||
test {
|
||||
_ = @import("system/macos.zig");
|
||||
_ = @import("system/darwin.zig");
|
||||
_ = @import("system/linux.zig");
|
||||
}
|
||||
|
||||
44
lib/std/zig/system/darwin.zig
Normal file
44
lib/std/zig/system/darwin.zig
Normal file
@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2015-2021 Zig Contributors
|
||||
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
|
||||
// The MIT license requires this copyright notice to be included in all copies
|
||||
// and substantial portions of the software.
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
const Target = std.Target;
|
||||
|
||||
pub const macos = @import("darwin/macos.zig");
|
||||
|
||||
/// Detect SDK path on Darwin.
|
||||
/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which result can be used to specify
|
||||
/// `--sysroot` of the compiler.
|
||||
/// The caller needs to free the resulting path slice.
|
||||
pub fn getSDKPath(allocator: *Allocator, target: Target) !?[]u8 {
|
||||
const is_simulator_abi = target.abi == .simulator;
|
||||
const sdk = switch (target.os.tag) {
|
||||
.macos => "macosx",
|
||||
.ios => if (is_simulator_abi) "iphonesimulator" else "iphoneos",
|
||||
.watchos => if (is_simulator_abi) "watchsimulator" else "watchos",
|
||||
.tvos => if (is_simulator_abi) "appletvsimulator" else "appletvos",
|
||||
else => return null,
|
||||
};
|
||||
|
||||
const argv = &[_][]const u8{ "xcrun", "--sdk", sdk, "--show-sdk-path" };
|
||||
const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });
|
||||
defer {
|
||||
allocator.free(result.stderr);
|
||||
allocator.free(result.stdout);
|
||||
}
|
||||
if (result.stderr.len != 0 or result.term.Exited != 0) {
|
||||
// We don't actually care if there were errors as this is best-effort check anyhow
|
||||
// and in the worst case the user can specify the sysroot manually.
|
||||
return null;
|
||||
}
|
||||
const sysroot = try allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n"));
|
||||
return sysroot;
|
||||
}
|
||||
|
||||
test "" {
|
||||
_ = @import("darwin/macos.zig");
|
||||
}
|
||||
@ -408,28 +408,6 @@ fn testVersionEquality(expected: std.builtin.Version, got: std.builtin.Version)
|
||||
try testing.expectEqualStrings(s_expected, s_got);
|
||||
}
|
||||
|
||||
/// Detect SDK path on Darwin.
|
||||
/// Calls `xcrun --show-sdk-path` which result can be used to specify
|
||||
/// `-syslibroot` param of the linker.
|
||||
/// The caller needs to free the resulting path slice.
|
||||
pub fn getSDKPath(allocator: *mem.Allocator) ![]u8 {
|
||||
assert(Target.current.isDarwin());
|
||||
const argv = &[_][]const u8{ "xcrun", "--show-sdk-path" };
|
||||
const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv });
|
||||
defer {
|
||||
allocator.free(result.stderr);
|
||||
allocator.free(result.stdout);
|
||||
}
|
||||
if (result.stderr.len != 0) {
|
||||
std.log.err("unexpected 'xcrun --show-sdk-path' stderr: {s}", .{result.stderr});
|
||||
}
|
||||
if (result.term.Exited != 0) {
|
||||
return error.ProcessTerminated;
|
||||
}
|
||||
const syslibroot = mem.trimRight(u8, result.stdout, "\r\n");
|
||||
return mem.dupe(allocator, u8, syslibroot);
|
||||
}
|
||||
|
||||
pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
|
||||
var cpu_family: os.CPUFAMILY = undefined;
|
||||
var len: usize = @sizeOf(os.CPUFAMILY);
|
||||
@ -944,8 +944,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
if (options.sysroot) |sysroot| {
|
||||
break :blk sysroot;
|
||||
} else if (darwin_can_use_system_sdk) {
|
||||
const at_least_big_sur = options.target.os.getVersionRange().semver.min.major >= 11;
|
||||
break :blk if (at_least_big_sur) try std.zig.system.getSDKPath(arena) else null;
|
||||
break :blk try std.zig.system.darwin.getSDKPath(arena, options.target);
|
||||
} else {
|
||||
break :blk null;
|
||||
}
|
||||
|
||||
@ -82,8 +82,8 @@ data_in_code_cmd_index: ?u16 = null,
|
||||
function_starts_cmd_index: ?u16 = null,
|
||||
main_cmd_index: ?u16 = null,
|
||||
dylib_id_cmd_index: ?u16 = null,
|
||||
version_min_cmd_index: ?u16 = null,
|
||||
source_version_cmd_index: ?u16 = null,
|
||||
build_version_cmd_index: ?u16 = null,
|
||||
uuid_cmd_index: ?u16 = null,
|
||||
code_signature_cmd_index: ?u16 = null,
|
||||
/// Path to libSystem
|
||||
@ -794,15 +794,14 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
|
||||
}
|
||||
}
|
||||
|
||||
// If we're compiling native and we can find libSystem.B.{dylib, tbd},
|
||||
// we link against that instead of embedded libSystem.B.tbd file.
|
||||
var native_libsystem_available = false;
|
||||
if (self.base.options.is_native_os) blk: {
|
||||
// If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
|
||||
var libsystem_available = false;
|
||||
if (self.base.options.sysroot != null) blk: {
|
||||
// Try stub file first. If we hit it, then we're done as the stub file
|
||||
// re-exports every single symbol definition.
|
||||
if (try resolveLib(arena, lib_dirs.items, "System", ".tbd")) |full_path| {
|
||||
try libs.append(full_path);
|
||||
native_libsystem_available = true;
|
||||
libsystem_available = true;
|
||||
break :blk;
|
||||
}
|
||||
// If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
|
||||
@ -811,12 +810,12 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
|
||||
if (try resolveLib(arena, lib_dirs.items, "c", ".dylib")) |libc_path| {
|
||||
try libs.append(libsystem_path);
|
||||
try libs.append(libc_path);
|
||||
native_libsystem_available = true;
|
||||
libsystem_available = true;
|
||||
break :blk;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!native_libsystem_available) {
|
||||
if (!libsystem_available) {
|
||||
const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "darwin", "libSystem.B.tbd",
|
||||
});
|
||||
@ -841,7 +840,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
log.warn("framework not found for '-f{s}'", .{framework});
|
||||
log.warn("framework not found for '-framework {s}'", .{framework});
|
||||
framework_not_found = true;
|
||||
}
|
||||
}
|
||||
@ -901,10 +900,8 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
|
||||
try argv.append("-o");
|
||||
try argv.append(full_out_path);
|
||||
|
||||
if (native_libsystem_available) {
|
||||
try argv.append("-lSystem");
|
||||
try argv.append("-lc");
|
||||
}
|
||||
try argv.append("-lSystem");
|
||||
try argv.append("-lc");
|
||||
|
||||
for (search_lib_names.items) |l_name| {
|
||||
try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{l_name}));
|
||||
@ -914,6 +911,14 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
|
||||
try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir}));
|
||||
}
|
||||
|
||||
for (self.base.options.frameworks) |framework| {
|
||||
try argv.append(try std.fmt.allocPrint(arena, "-framework {s}", .{framework}));
|
||||
}
|
||||
|
||||
for (self.base.options.framework_dirs) |framework_dir| {
|
||||
try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir}));
|
||||
}
|
||||
|
||||
Compilation.dump_argv(argv.items);
|
||||
}
|
||||
|
||||
@ -990,7 +995,6 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const u8) !void {
|
||||
const arch = self.base.options.target.cpu.arch;
|
||||
for (files) |file_name| {
|
||||
const full_path = full_path: {
|
||||
var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
@ -999,17 +1003,17 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
|
||||
};
|
||||
defer self.base.allocator.free(full_path);
|
||||
|
||||
if (try Object.createAndParseFromPath(self.base.allocator, arch, full_path)) |object| {
|
||||
if (try Object.createAndParseFromPath(self.base.allocator, self.base.options.target, full_path)) |object| {
|
||||
try self.objects.append(self.base.allocator, object);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (try Archive.createAndParseFromPath(self.base.allocator, arch, full_path)) |archive| {
|
||||
if (try Archive.createAndParseFromPath(self.base.allocator, self.base.options.target, full_path)) |archive| {
|
||||
try self.archives.append(self.base.allocator, archive);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (try Dylib.createAndParseFromPath(self.base.allocator, arch, full_path, .{
|
||||
if (try Dylib.createAndParseFromPath(self.base.allocator, self.base.options.target, full_path, .{
|
||||
.syslibroot = syslibroot,
|
||||
})) |dylibs| {
|
||||
defer self.base.allocator.free(dylibs);
|
||||
@ -1027,9 +1031,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const
|
||||
}
|
||||
|
||||
fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !void {
|
||||
const arch = self.base.options.target.cpu.arch;
|
||||
for (libs) |lib| {
|
||||
if (try Dylib.createAndParseFromPath(self.base.allocator, arch, lib, .{
|
||||
if (try Dylib.createAndParseFromPath(self.base.allocator, self.base.options.target, lib, .{
|
||||
.syslibroot = syslibroot,
|
||||
})) |dylibs| {
|
||||
defer self.base.allocator.free(dylibs);
|
||||
@ -1042,7 +1045,7 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v
|
||||
continue;
|
||||
}
|
||||
|
||||
if (try Archive.createAndParseFromPath(self.base.allocator, arch, lib)) |archive| {
|
||||
if (try Archive.createAndParseFromPath(self.base.allocator, self.base.options.target, lib)) |archive| {
|
||||
try self.archives.append(self.base.allocator, archive);
|
||||
continue;
|
||||
}
|
||||
@ -2231,11 +2234,7 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
|
||||
const object_id = @intCast(u16, self.objects.items.len);
|
||||
const object = try self.objects.addOne(self.base.allocator);
|
||||
object.* = try archive.parseObject(
|
||||
self.base.allocator,
|
||||
self.base.options.target.cpu.arch,
|
||||
offsets.items[0],
|
||||
);
|
||||
object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]);
|
||||
try self.resolveSymbolsInObject(object_id);
|
||||
|
||||
continue :loop;
|
||||
@ -2717,27 +2716,6 @@ fn populateMetadata(self: *MachO) !void {
|
||||
try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
|
||||
}
|
||||
|
||||
if (self.version_min_cmd_index == null) {
|
||||
self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
const cmd: u32 = switch (self.base.options.target.os.tag) {
|
||||
.macos => macho.LC_VERSION_MIN_MACOSX,
|
||||
.ios => macho.LC_VERSION_MIN_IPHONEOS,
|
||||
.tvos => macho.LC_VERSION_MIN_TVOS,
|
||||
.watchos => macho.LC_VERSION_MIN_WATCHOS,
|
||||
else => unreachable, // wrong OS
|
||||
};
|
||||
const ver = self.base.options.target.os.version_range.semver.min;
|
||||
const version = ver.major << 16 | ver.minor << 8 | ver.patch;
|
||||
try self.load_commands.append(self.base.allocator, .{
|
||||
.VersionMin = .{
|
||||
.cmd = cmd,
|
||||
.cmdsize = @sizeOf(macho.version_min_command),
|
||||
.version = version,
|
||||
.sdk = version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (self.source_version_cmd_index == null) {
|
||||
self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
try self.load_commands.append(self.base.allocator, .{
|
||||
@ -2749,6 +2727,40 @@ fn populateMetadata(self: *MachO) !void {
|
||||
});
|
||||
}
|
||||
|
||||
if (self.build_version_cmd_index == null) {
|
||||
self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
const cmdsize = @intCast(u32, mem.alignForwardGeneric(
|
||||
u64,
|
||||
@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 is_simulator_abi = self.base.options.target.abi == .simulator;
|
||||
var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
|
||||
.cmd = macho.LC_BUILD_VERSION,
|
||||
.cmdsize = cmdsize,
|
||||
.platform = switch (self.base.options.target.os.tag) {
|
||||
.macos => macho.PLATFORM_MACOS,
|
||||
.ios => if (is_simulator_abi) macho.PLATFORM_IOSSIMULATOR else macho.PLATFORM_IOS,
|
||||
.watchos => if (is_simulator_abi) macho.PLATFORM_WATCHOSSIMULATOR else macho.PLATFORM_WATCHOS,
|
||||
.tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,
|
||||
else => unreachable,
|
||||
},
|
||||
.minos = version,
|
||||
.sdk = version,
|
||||
.ntools = 1,
|
||||
});
|
||||
const ld_ver = macho.build_tool_version{
|
||||
.tool = macho.TOOL_LD,
|
||||
.version = 0x0,
|
||||
};
|
||||
cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command));
|
||||
mem.set(u8, cmd.data, 0);
|
||||
mem.copy(u8, cmd.data, mem.asBytes(&ld_ver));
|
||||
try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd });
|
||||
}
|
||||
|
||||
if (self.uuid_cmd_index == null) {
|
||||
self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
var uuid_cmd: macho.uuid_command = .{
|
||||
@ -2880,11 +2892,6 @@ fn flushZld(self: *MachO) !void {
|
||||
if (self.base.options.target.cpu.arch == .aarch64) {
|
||||
try self.writeCodeSignature();
|
||||
}
|
||||
|
||||
// if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
|
||||
// const out_path = self.output.?.path;
|
||||
// try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
|
||||
// }
|
||||
}
|
||||
|
||||
fn writeGotEntries(self: *MachO) !void {
|
||||
@ -4340,26 +4347,38 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
});
|
||||
self.load_commands_dirty = true;
|
||||
}
|
||||
if (self.version_min_cmd_index == null) {
|
||||
self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
const cmd: u32 = switch (self.base.options.target.os.tag) {
|
||||
.macos => macho.LC_VERSION_MIN_MACOSX,
|
||||
.ios => macho.LC_VERSION_MIN_IPHONEOS,
|
||||
.tvos => macho.LC_VERSION_MIN_TVOS,
|
||||
.watchos => macho.LC_VERSION_MIN_WATCHOS,
|
||||
else => unreachable, // wrong OS
|
||||
};
|
||||
if (self.build_version_cmd_index == null) {
|
||||
self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
const cmdsize = @intCast(u32, mem.alignForwardGeneric(
|
||||
u64,
|
||||
@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;
|
||||
try self.load_commands.append(self.base.allocator, .{
|
||||
.VersionMin = .{
|
||||
.cmd = cmd,
|
||||
.cmdsize = @sizeOf(macho.version_min_command),
|
||||
.version = version,
|
||||
.sdk = version,
|
||||
const is_simulator_abi = self.base.options.target.abi == .simulator;
|
||||
var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{
|
||||
.cmd = macho.LC_BUILD_VERSION,
|
||||
.cmdsize = cmdsize,
|
||||
.platform = switch (self.base.options.target.os.tag) {
|
||||
.macos => macho.PLATFORM_MACOS,
|
||||
.ios => if (is_simulator_abi) macho.PLATFORM_IOSSIMULATOR else macho.PLATFORM_IOS,
|
||||
.watchos => if (is_simulator_abi) macho.PLATFORM_WATCHOSSIMULATOR else macho.PLATFORM_WATCHOS,
|
||||
.tvos => if (is_simulator_abi) macho.PLATFORM_TVOSSIMULATOR else macho.PLATFORM_TVOS,
|
||||
else => unreachable,
|
||||
},
|
||||
.minos = version,
|
||||
.sdk = version,
|
||||
.ntools = 1,
|
||||
});
|
||||
self.load_commands_dirty = true;
|
||||
const ld_ver = macho.build_tool_version{
|
||||
.tool = macho.TOOL_LD,
|
||||
.version = 0x0,
|
||||
};
|
||||
cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command));
|
||||
mem.set(u8, cmd.data, 0);
|
||||
mem.copy(u8, cmd.data, mem.asBytes(&ld_ver));
|
||||
try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd });
|
||||
}
|
||||
if (self.source_version_cmd_index == null) {
|
||||
self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||
|
||||
@ -9,7 +9,6 @@ const mem = std.mem;
|
||||
const fat = @import("fat.zig");
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const Arch = std.Target.Cpu.Arch;
|
||||
const Object = @import("Object.zig");
|
||||
|
||||
file: fs.File,
|
||||
@ -104,7 +103,7 @@ pub fn deinit(self: *Archive, allocator: *Allocator) void {
|
||||
allocator.free(self.name);
|
||||
}
|
||||
|
||||
pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?Archive {
|
||||
pub fn createAndParseFromPath(allocator: *Allocator, target: std.Target, path: []const u8) !?Archive {
|
||||
const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => return null,
|
||||
else => |e| return e,
|
||||
@ -119,7 +118,7 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
|
||||
.file = file,
|
||||
};
|
||||
|
||||
archive.parse(allocator, arch) catch |err| switch (err) {
|
||||
archive.parse(allocator, target) catch |err| switch (err) {
|
||||
error.EndOfStream, error.NotArchive => {
|
||||
archive.deinit(allocator);
|
||||
return null;
|
||||
@ -130,9 +129,9 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
|
||||
return archive;
|
||||
}
|
||||
|
||||
pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void {
|
||||
pub fn parse(self: *Archive, allocator: *Allocator, target: std.Target) !void {
|
||||
const reader = self.file.reader();
|
||||
self.library_offset = try fat.getLibraryOffset(reader, arch);
|
||||
self.library_offset = try fat.getLibraryOffset(reader, target);
|
||||
try self.file.seekTo(self.library_offset);
|
||||
|
||||
const magic = try reader.readBytesNoEof(SARMAG);
|
||||
@ -215,7 +214,7 @@ fn parseTableOfContents(self: *Archive, allocator: *Allocator, reader: anytype)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parseObject(self: Archive, allocator: *Allocator, arch: Arch, offset: u32) !Object {
|
||||
pub fn parseObject(self: Archive, allocator: *Allocator, target: std.Target, offset: u32) !Object {
|
||||
const reader = self.file.reader();
|
||||
try reader.context.seekTo(offset + self.library_offset);
|
||||
|
||||
@ -244,7 +243,7 @@ pub fn parseObject(self: Archive, allocator: *Allocator, arch: Arch, offset: u32
|
||||
.mtime = try self.header.?.date(),
|
||||
};
|
||||
|
||||
try object.parse(allocator, arch);
|
||||
try object.parse(allocator, target);
|
||||
try reader.context.seekTo(0);
|
||||
|
||||
return object;
|
||||
|
||||
@ -12,7 +12,6 @@ const fat = @import("fat.zig");
|
||||
const commands = @import("commands.zig");
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const Arch = std.Target.Cpu.Arch;
|
||||
const LibStub = @import("../tapi.zig").LibStub;
|
||||
const LoadCommand = commands.LoadCommand;
|
||||
const MachO = @import("../MachO.zig");
|
||||
@ -139,11 +138,12 @@ pub const Error = error{
|
||||
pub const CreateOpts = struct {
|
||||
syslibroot: ?[]const u8 = null,
|
||||
id: ?Id = null,
|
||||
target: ?std.Target = null,
|
||||
};
|
||||
|
||||
pub fn createAndParseFromPath(
|
||||
allocator: *Allocator,
|
||||
arch: Arch,
|
||||
target: std.Target,
|
||||
path: []const u8,
|
||||
opts: CreateOpts,
|
||||
) Error!?[]Dylib {
|
||||
@ -161,7 +161,7 @@ pub fn createAndParseFromPath(
|
||||
.file = file,
|
||||
};
|
||||
|
||||
dylib.parse(allocator, arch) catch |err| switch (err) {
|
||||
dylib.parse(allocator, target) catch |err| switch (err) {
|
||||
error.EndOfStream, error.NotDylib => {
|
||||
try file.seekTo(0);
|
||||
|
||||
@ -171,7 +171,7 @@ pub fn createAndParseFromPath(
|
||||
};
|
||||
defer lib_stub.deinit();
|
||||
|
||||
try dylib.parseFromStub(allocator, arch, lib_stub);
|
||||
try dylib.parseFromStub(allocator, target, lib_stub);
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
@ -195,7 +195,7 @@ pub fn createAndParseFromPath(
|
||||
try dylibs.append(dylib);
|
||||
// TODO this should not be performed if the user specifies `-flat_namespace` flag.
|
||||
// See ld64 manpages.
|
||||
try dylib.parseDependentLibs(allocator, arch, &dylibs, opts.syslibroot);
|
||||
try dylib.parseDependentLibs(allocator, target, &dylibs, opts.syslibroot);
|
||||
|
||||
return dylibs.toOwnedSlice();
|
||||
}
|
||||
@ -222,10 +222,10 @@ pub fn deinit(self: *Dylib, allocator: *Allocator) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(self: *Dylib, allocator: *Allocator, arch: Arch) !void {
|
||||
pub fn parse(self: *Dylib, allocator: *Allocator, target: std.Target) !void {
|
||||
log.debug("parsing shared library '{s}'", .{self.name});
|
||||
|
||||
self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch);
|
||||
self.library_offset = try fat.getLibraryOffset(self.file.reader(), target);
|
||||
|
||||
try self.file.seekTo(self.library_offset);
|
||||
|
||||
@ -237,10 +237,10 @@ pub fn parse(self: *Dylib, allocator: *Allocator, arch: Arch) !void {
|
||||
return error.NotDylib;
|
||||
}
|
||||
|
||||
const this_arch: Arch = try fat.decodeArch(self.header.?.cputype, true);
|
||||
const this_arch: std.Target.Cpu.Arch = try fat.decodeArch(self.header.?.cputype, true);
|
||||
|
||||
if (this_arch != arch) {
|
||||
log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
|
||||
if (this_arch != target.cpu.arch) {
|
||||
log.err("mismatched cpu architecture: expected {s}, found {s}", .{ target.cpu.arch, this_arch });
|
||||
return error.MismatchedCpuArchitecture;
|
||||
}
|
||||
|
||||
@ -334,7 +334,61 @@ fn addObjCClassSymbols(self: *Dylib, allocator: *Allocator, sym_name: []const u8
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub: LibStub) !void {
|
||||
fn targetToAppleString(allocator: *Allocator, target: std.Target) ![]const u8 {
|
||||
const arch = switch (target.cpu.arch) {
|
||||
.aarch64 => "arm64",
|
||||
.x86_64 => "x86_64",
|
||||
else => unreachable,
|
||||
};
|
||||
const os = @tagName(target.os.tag);
|
||||
const abi: ?[]const u8 = switch (target.abi) {
|
||||
.gnu => null,
|
||||
.simulator => "simulator",
|
||||
else => unreachable,
|
||||
};
|
||||
if (abi) |x| {
|
||||
return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ arch, os, x });
|
||||
}
|
||||
return std.fmt.allocPrint(allocator, "{s}-{s}", .{ arch, os });
|
||||
}
|
||||
|
||||
const TargetMatcher = struct {
|
||||
allocator: *Allocator,
|
||||
target_strings: std.ArrayListUnmanaged([]const u8) = .{},
|
||||
|
||||
fn init(allocator: *Allocator, target: std.Target) !TargetMatcher {
|
||||
var self = TargetMatcher{ .allocator = allocator };
|
||||
try self.target_strings.append(allocator, try targetToAppleString(allocator, target));
|
||||
|
||||
if (target.abi == .simulator) {
|
||||
// For Apple simulator targets, linking gets tricky as we need to link against the simulator
|
||||
// hosts dylibs too.
|
||||
const host_target = try targetToAppleString(allocator, (std.zig.CrossTarget{
|
||||
.cpu_arch = target.cpu.arch,
|
||||
.os_tag = .macos,
|
||||
}).toTarget());
|
||||
try self.target_strings.append(allocator, host_target);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
fn deinit(self: *TargetMatcher) void {
|
||||
for (self.target_strings.items) |t| {
|
||||
self.allocator.free(t);
|
||||
}
|
||||
self.target_strings.deinit(self.allocator);
|
||||
}
|
||||
|
||||
fn matches(self: TargetMatcher, targets: []const []const u8) bool {
|
||||
for (self.target_strings.items) |t| {
|
||||
if (hasTarget(targets, t)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn parseFromStub(self: *Dylib, allocator: *Allocator, target: std.Target, lib_stub: LibStub) !void {
|
||||
if (lib_stub.inner.len == 0) return error.EmptyStubFile;
|
||||
|
||||
log.debug("parsing shared library from stub '{s}'", .{self.name});
|
||||
@ -350,17 +404,14 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub:
|
||||
}
|
||||
self.id = id;
|
||||
|
||||
const target_string: []const u8 = switch (arch) {
|
||||
.aarch64 => "arm64-macos",
|
||||
.x86_64 => "x86_64-macos",
|
||||
else => unreachable,
|
||||
};
|
||||
var matcher = try TargetMatcher.init(allocator, target);
|
||||
defer matcher.deinit();
|
||||
|
||||
var umbrella_libs = std.StringHashMap(void).init(allocator);
|
||||
defer umbrella_libs.deinit();
|
||||
|
||||
for (lib_stub.inner) |stub, stub_index| {
|
||||
if (!hasTarget(stub.targets, target_string)) continue;
|
||||
if (!matcher.matches(stub.targets)) continue;
|
||||
|
||||
if (stub_index > 0) {
|
||||
// TODO I thought that we could switch on presence of `parent-umbrella` map;
|
||||
@ -371,7 +422,7 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub:
|
||||
|
||||
if (stub.exports) |exports| {
|
||||
for (exports) |exp| {
|
||||
if (!hasTarget(exp.targets, target_string)) continue;
|
||||
if (!matcher.matches(exp.targets)) continue;
|
||||
|
||||
if (exp.symbols) |symbols| {
|
||||
for (symbols) |sym_name| {
|
||||
@ -390,7 +441,7 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub:
|
||||
|
||||
if (stub.reexports) |reexports| {
|
||||
for (reexports) |reexp| {
|
||||
if (!hasTarget(reexp.targets, target_string)) continue;
|
||||
if (!matcher.matches(reexp.targets)) continue;
|
||||
|
||||
if (reexp.symbols) |symbols| {
|
||||
for (symbols) |sym_name| {
|
||||
@ -418,11 +469,11 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub:
|
||||
|
||||
// TODO track which libs were already parsed in different steps
|
||||
for (lib_stub.inner) |stub| {
|
||||
if (!hasTarget(stub.targets, target_string)) continue;
|
||||
if (!matcher.matches(stub.targets)) continue;
|
||||
|
||||
if (stub.reexported_libraries) |reexports| {
|
||||
for (reexports) |reexp| {
|
||||
if (!hasTarget(reexp.targets, target_string)) continue;
|
||||
if (!matcher.matches(reexp.targets)) continue;
|
||||
|
||||
for (reexp.libraries) |lib| {
|
||||
if (umbrella_libs.contains(lib)) {
|
||||
@ -443,7 +494,7 @@ pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub:
|
||||
pub fn parseDependentLibs(
|
||||
self: *Dylib,
|
||||
allocator: *Allocator,
|
||||
arch: Arch,
|
||||
target: std.Target,
|
||||
out: *std.ArrayList(Dylib),
|
||||
syslibroot: ?[]const u8,
|
||||
) !void {
|
||||
@ -475,7 +526,7 @@ pub fn parseDependentLibs(
|
||||
|
||||
const dylibs = (try createAndParseFromPath(
|
||||
allocator,
|
||||
arch,
|
||||
target,
|
||||
full_path,
|
||||
.{
|
||||
.id = id,
|
||||
|
||||
@ -15,7 +15,6 @@ const segmentName = commands.segmentName;
|
||||
const sectionName = commands.sectionName;
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const Arch = std.Target.Cpu.Arch;
|
||||
const LoadCommand = commands.LoadCommand;
|
||||
const MachO = @import("../MachO.zig");
|
||||
const TextBlock = @import("TextBlock.zig");
|
||||
@ -154,7 +153,7 @@ pub fn deinit(self: *Object, allocator: *Allocator) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?Object {
|
||||
pub fn createAndParseFromPath(allocator: *Allocator, target: std.Target, path: []const u8) !?Object {
|
||||
const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => return null,
|
||||
else => |e| return e,
|
||||
@ -169,7 +168,7 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
|
||||
.file = file,
|
||||
};
|
||||
|
||||
object.parse(allocator, arch) catch |err| switch (err) {
|
||||
object.parse(allocator, target) catch |err| switch (err) {
|
||||
error.EndOfStream, error.NotObject => {
|
||||
object.deinit(allocator);
|
||||
return null;
|
||||
@ -180,7 +179,7 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u
|
||||
return object;
|
||||
}
|
||||
|
||||
pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
|
||||
pub fn parse(self: *Object, allocator: *Allocator, target: std.Target) !void {
|
||||
const reader = self.file.reader();
|
||||
if (self.file_offset) |offset| {
|
||||
try reader.context.seekTo(offset);
|
||||
@ -195,7 +194,7 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
|
||||
return error.NotObject;
|
||||
}
|
||||
|
||||
const this_arch: Arch = switch (header.cputype) {
|
||||
const this_arch: std.Target.Cpu.Arch = switch (header.cputype) {
|
||||
macho.CPU_TYPE_ARM64 => .aarch64,
|
||||
macho.CPU_TYPE_X86_64 => .x86_64,
|
||||
else => |value| {
|
||||
@ -203,8 +202,8 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void {
|
||||
return error.UnsupportedCpuArchitecture;
|
||||
},
|
||||
};
|
||||
if (this_arch != arch) {
|
||||
log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
|
||||
if (this_arch != target.cpu.arch) {
|
||||
log.err("mismatched cpu architecture: expected {s}, found {s}", .{ target.cpu.arch, this_arch });
|
||||
return error.MismatchedCpuArchitecture;
|
||||
}
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@ pub const LoadCommand = union(enum) {
|
||||
Main: macho.entry_point_command,
|
||||
VersionMin: macho.version_min_command,
|
||||
SourceVersion: macho.source_version_command,
|
||||
BuildVersion: GenericCommandWithData(macho.build_version_command),
|
||||
Uuid: macho.uuid_command,
|
||||
LinkeditData: macho.linkedit_data_command,
|
||||
Rpath: GenericCommandWithData(macho.rpath_command),
|
||||
@ -97,6 +98,9 @@ pub const LoadCommand = union(enum) {
|
||||
macho.LC_SOURCE_VERSION => LoadCommand{
|
||||
.SourceVersion = try stream.reader().readStruct(macho.source_version_command),
|
||||
},
|
||||
macho.LC_BUILD_VERSION => LoadCommand{
|
||||
.BuildVersion = try GenericCommandWithData(macho.build_version_command).read(allocator, stream.reader()),
|
||||
},
|
||||
macho.LC_UUID => LoadCommand{
|
||||
.Uuid = try stream.reader().readStruct(macho.uuid_command),
|
||||
},
|
||||
@ -129,6 +133,7 @@ pub const LoadCommand = union(enum) {
|
||||
.Dylinker => |x| x.write(writer),
|
||||
.Dylib => |x| x.write(writer),
|
||||
.Rpath => |x| x.write(writer),
|
||||
.BuildVersion => |x| x.write(writer),
|
||||
.Unknown => |x| x.write(writer),
|
||||
};
|
||||
}
|
||||
@ -147,6 +152,7 @@ pub const LoadCommand = union(enum) {
|
||||
.Dylinker => |x| x.inner.cmd,
|
||||
.Dylib => |x| x.inner.cmd,
|
||||
.Rpath => |x| x.inner.cmd,
|
||||
.BuildVersion => |x| x.inner.cmd,
|
||||
.Unknown => |x| x.inner.cmd,
|
||||
};
|
||||
}
|
||||
@ -165,6 +171,7 @@ pub const LoadCommand = union(enum) {
|
||||
.Dylinker => |x| x.inner.cmdsize,
|
||||
.Dylib => |x| x.inner.cmdsize,
|
||||
.Rpath => |x| x.inner.cmdsize,
|
||||
.BuildVersion => |x| x.inner.cmdsize,
|
||||
.Unknown => |x| x.inner.cmdsize,
|
||||
};
|
||||
}
|
||||
@ -175,6 +182,7 @@ pub const LoadCommand = union(enum) {
|
||||
.Dylinker => |*x| x.deinit(allocator),
|
||||
.Dylib => |*x| x.deinit(allocator),
|
||||
.Rpath => |*x| x.deinit(allocator),
|
||||
.BuildVersion => |*x| x.deinit(allocator),
|
||||
.Unknown => |*x| x.deinit(allocator),
|
||||
else => {},
|
||||
};
|
||||
@ -193,6 +201,7 @@ pub const LoadCommand = union(enum) {
|
||||
.Main => |x| meta.eql(x, other.Main),
|
||||
.VersionMin => |x| meta.eql(x, other.VersionMin),
|
||||
.SourceVersion => |x| meta.eql(x, other.SourceVersion),
|
||||
.BuildVersion => |x| x.eql(other.BuildVersion),
|
||||
.Uuid => |x| meta.eql(x, other.Uuid),
|
||||
.LinkeditData => |x| meta.eql(x, other.LinkeditData),
|
||||
.Segment => |x| x.eql(other.Segment),
|
||||
|
||||
@ -5,10 +5,8 @@ const macho = std.macho;
|
||||
const mem = std.mem;
|
||||
const native_endian = builtin.target.cpu.arch.endian();
|
||||
|
||||
const Arch = std.Target.Cpu.Arch;
|
||||
|
||||
pub fn decodeArch(cputype: macho.cpu_type_t, comptime logError: bool) !std.Target.Cpu.Arch {
|
||||
const arch: Arch = switch (cputype) {
|
||||
const arch: std.Target.Cpu.Arch = switch (cputype) {
|
||||
macho.CPU_TYPE_ARM64 => .aarch64,
|
||||
macho.CPU_TYPE_X86_64 => .x86_64,
|
||||
else => {
|
||||
@ -31,7 +29,7 @@ fn readFatStruct(reader: anytype, comptime T: type) !T {
|
||||
return res;
|
||||
}
|
||||
|
||||
pub fn getLibraryOffset(reader: anytype, arch: Arch) !u64 {
|
||||
pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 {
|
||||
const fat_header = try readFatStruct(reader, macho.fat_header);
|
||||
if (fat_header.magic != macho.FAT_MAGIC) return 0;
|
||||
|
||||
@ -44,12 +42,12 @@ pub fn getLibraryOffset(reader: anytype, arch: Arch) !u64 {
|
||||
error.UnsupportedCpuArchitecture => continue,
|
||||
else => |e| return e,
|
||||
};
|
||||
if (lib_arch == arch) {
|
||||
if (lib_arch == target.cpu.arch) {
|
||||
// We have found a matching architecture!
|
||||
return fat_arch.offset;
|
||||
}
|
||||
} else {
|
||||
log.err("Could not find matching cpu architecture in fat library: expected {s}", .{arch});
|
||||
log.err("Could not find matching cpu architecture in fat library: expected {s}", .{target.cpu.arch});
|
||||
return error.MismatchedCpuArchitecture;
|
||||
}
|
||||
}
|
||||
|
||||
25
src/main.zig
25
src/main.zig
@ -830,7 +830,10 @@ fn buildOutputType(
|
||||
} else if (mem.eql(u8, arg, "-D") or
|
||||
mem.eql(u8, arg, "-isystem") or
|
||||
mem.eql(u8, arg, "-I") or
|
||||
mem.eql(u8, arg, "-dirafter"))
|
||||
mem.eql(u8, arg, "-dirafter") or
|
||||
mem.eql(u8, arg, "-iwithsysroot") or
|
||||
mem.eql(u8, arg, "-iframework") or
|
||||
mem.eql(u8, arg, "-iframeworkwithsysroot"))
|
||||
{
|
||||
if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
|
||||
i += 1;
|
||||
@ -873,6 +876,8 @@ fn buildOutputType(
|
||||
if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
|
||||
i += 1;
|
||||
sysroot = args[i];
|
||||
try clang_argv.append("-isysroot");
|
||||
try clang_argv.append(args[i]);
|
||||
} else if (mem.eql(u8, arg, "--libc")) {
|
||||
if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
|
||||
i += 1;
|
||||
@ -1673,7 +1678,9 @@ fn buildOutputType(
|
||||
want_native_include_dirs = true;
|
||||
}
|
||||
|
||||
if (sysroot == null and cross_target.isNativeOs() and
|
||||
const is_darwin_on_darwin = (comptime std.Target.current.isDarwin()) and cross_target.isDarwin();
|
||||
|
||||
if (sysroot == null and (cross_target.isNativeOs() or is_darwin_on_darwin) and
|
||||
(system_libs.items.len != 0 or want_native_include_dirs))
|
||||
{
|
||||
const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| {
|
||||
@ -1684,16 +1691,18 @@ fn buildOutputType(
|
||||
}
|
||||
|
||||
const has_sysroot = if (comptime std.Target.current.isDarwin()) outer: {
|
||||
const min = target_info.target.os.getVersionRange().semver.min;
|
||||
const at_least_mojave = min.major >= 11 or (min.major >= 10 and min.minor >= 14);
|
||||
if (at_least_mojave) {
|
||||
const sdk_path = try std.zig.system.getSDKPath(arena);
|
||||
const should_get_sdk_path = if (cross_target.isNativeOs() and target_info.target.os.tag == .macos) inner: {
|
||||
const min = target_info.target.os.getVersionRange().semver.min;
|
||||
const at_least_mojave = min.major >= 11 or (min.major >= 10 and min.minor >= 14);
|
||||
break :inner at_least_mojave;
|
||||
} else true;
|
||||
if (!should_get_sdk_path) break :outer false;
|
||||
if (try std.zig.system.darwin.getSDKPath(arena, target_info.target)) |sdk_path| {
|
||||
try clang_argv.ensureCapacity(clang_argv.items.len + 2);
|
||||
clang_argv.appendAssumeCapacity("-isysroot");
|
||||
clang_argv.appendAssumeCapacity(sdk_path);
|
||||
break :outer true;
|
||||
}
|
||||
break :outer false;
|
||||
} else break :outer false;
|
||||
} else false;
|
||||
|
||||
try clang_argv.ensureCapacity(clang_argv.items.len + paths.include_dirs.items.len * 2);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user