std.zig.system.NativePaths: simplify and integrate with Darwin SDK

This commit is contained in:
Andrew Kelley 2023-08-02 18:35:18 -07:00
parent ea0e6e737b
commit c94bbebb91
3 changed files with 40 additions and 99 deletions

View File

@ -1,6 +1,5 @@
const std = @import("../../std.zig"); const std = @import("../../std.zig");
const builtin = @import("builtin"); const builtin = @import("builtin");
const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const process = std.process; const process = std.process;
const mem = std.mem; const mem = std.mem;
@ -8,28 +7,18 @@ const mem = std.mem;
const NativePaths = @This(); const NativePaths = @This();
const NativeTargetInfo = std.zig.system.NativeTargetInfo; const NativeTargetInfo = std.zig.system.NativeTargetInfo;
include_dirs: ArrayList([:0]u8), arena: Allocator,
lib_dirs: ArrayList([:0]u8), include_dirs: std.ArrayListUnmanaged([]const u8) = .{},
framework_dirs: ArrayList([:0]u8), lib_dirs: std.ArrayListUnmanaged([]const u8) = .{},
rpaths: ArrayList([:0]u8), framework_dirs: std.ArrayListUnmanaged([]const u8) = .{},
warnings: ArrayList([:0]u8), rpaths: std.ArrayListUnmanaged([]const u8) = .{},
warnings: std.ArrayListUnmanaged([]const u8) = .{},
pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths { pub fn detect(arena: Allocator, native_info: NativeTargetInfo) !NativePaths {
const native_target = native_info.target; const native_target = native_info.target;
var self: NativePaths = .{ .arena = arena };
var self: NativePaths = .{
.include_dirs = ArrayList([:0]u8).init(allocator),
.lib_dirs = ArrayList([:0]u8).init(allocator),
.framework_dirs = ArrayList([:0]u8).init(allocator),
.rpaths = ArrayList([:0]u8).init(allocator),
.warnings = ArrayList([:0]u8).init(allocator),
};
errdefer self.deinit();
var is_nix = false; var is_nix = false;
if (process.getEnvVarOwned(allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { if (process.getEnvVarOwned(arena, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
defer allocator.free(nix_cflags_compile);
is_nix = true; is_nix = true;
var it = mem.tokenizeScalar(u8, nix_cflags_compile, ' '); var it = mem.tokenizeScalar(u8, nix_cflags_compile, ' ');
while (true) { while (true) {
@ -58,9 +47,7 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
error.EnvironmentVariableNotFound => {}, error.EnvironmentVariableNotFound => {},
error.OutOfMemory => |e| return e, error.OutOfMemory => |e| return e,
} }
if (process.getEnvVarOwned(allocator, "NIX_LDFLAGS")) |nix_ldflags| { if (process.getEnvVarOwned(arena, "NIX_LDFLAGS")) |nix_ldflags| {
defer allocator.free(nix_ldflags);
is_nix = true; is_nix = true;
var it = mem.tokenizeScalar(u8, nix_ldflags, ' '); var it = mem.tokenizeScalar(u8, nix_ldflags, ' ');
while (true) { while (true) {
@ -89,17 +76,18 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
return self; return self;
} }
// TODO: consider also adding homebrew paths
// TODO: consider also adding macports paths
if (comptime builtin.target.isDarwin()) { if (comptime builtin.target.isDarwin()) {
try self.addIncludeDir("/usr/include"); if (std.zig.system.darwin.isDarwinSDKInstalled(arena)) sdk: {
try self.addLibDir("/usr/lib"); const sdk = std.zig.system.darwin.getDarwinSDK(arena, native_target) orelse break :sdk;
try self.addFrameworkDir("/System/Library/Frameworks"); try self.addLibDir(try std.fs.path.join(arena, &.{ sdk.path, "usr/lib" }));
try self.addFrameworkDir(try std.fs.path.join(arena, &.{ sdk.path, "System/Library/Frameworks" }));
if (builtin.target.os.version_range.semver.min.major < 11) { try self.addIncludeDir(try std.fs.path.join(arena, &.{ sdk.path, "usr/include" }));
try self.addIncludeDir("/usr/local/include"); return self;
try self.addLibDir("/usr/local/lib");
try self.addFrameworkDir("/Library/Frameworks");
} }
// These do not include headers, so the ones that come with the SDK are preferred.
try self.addFrameworkDir("/System/Library/Frameworks");
return self; return self;
} }
@ -115,8 +103,7 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
} }
if (builtin.os.tag != .windows) { if (builtin.os.tag != .windows) {
const triple = try native_target.linuxTriple(allocator); const triple = try native_target.linuxTriple(arena);
defer allocator.free(triple);
const qual = native_target.ptrBitWidth(); const qual = native_target.ptrBitWidth();
@ -172,69 +159,42 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
return self; return self;
} }
pub fn deinit(self: *NativePaths) void {
deinitArray(&self.include_dirs);
deinitArray(&self.lib_dirs);
deinitArray(&self.framework_dirs);
deinitArray(&self.rpaths);
deinitArray(&self.warnings);
self.* = undefined;
}
fn deinitArray(array: *ArrayList([:0]u8)) void {
for (array.items) |item| {
array.allocator.free(item);
}
array.deinit();
}
pub fn addIncludeDir(self: *NativePaths, s: []const u8) !void { pub fn addIncludeDir(self: *NativePaths, s: []const u8) !void {
return self.appendArray(&self.include_dirs, s); return self.include_dirs.append(self.arena, s);
} }
pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void {
const item = try std.fmt.allocPrintZ(self.include_dirs.allocator, fmt, args); const item = try std.fmt.allocPrint(self.arena, fmt, args);
errdefer self.include_dirs.allocator.free(item); try self.include_dirs.append(self.arena, item);
try self.include_dirs.append(item);
} }
pub fn addLibDir(self: *NativePaths, s: []const u8) !void { pub fn addLibDir(self: *NativePaths, s: []const u8) !void {
return self.appendArray(&self.lib_dirs, s); try self.lib_dirs.append(self.arena, s);
} }
pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void {
const item = try std.fmt.allocPrintZ(self.lib_dirs.allocator, fmt, args); const item = try std.fmt.allocPrint(self.arena, fmt, args);
errdefer self.lib_dirs.allocator.free(item); try self.lib_dirs.append(self.arena, item);
try self.lib_dirs.append(item);
} }
pub fn addWarning(self: *NativePaths, s: []const u8) !void { pub fn addWarning(self: *NativePaths, s: []const u8) !void {
return self.appendArray(&self.warnings, s); return self.warnings.append(self.arena, s);
} }
pub fn addFrameworkDir(self: *NativePaths, s: []const u8) !void { pub fn addFrameworkDir(self: *NativePaths, s: []const u8) !void {
return self.appendArray(&self.framework_dirs, s); return self.framework_dirs.append(self.arena, s);
} }
pub fn addFrameworkDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { pub fn addFrameworkDirFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void {
const item = try std.fmt.allocPrintZ(self.framework_dirs.allocator, fmt, args); const item = try std.fmt.allocPrint(self.arena, fmt, args);
errdefer self.framework_dirs.allocator.free(item); try self.framework_dirs.append(self.arena, item);
try self.framework_dirs.append(item);
} }
pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void { pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void {
const item = try std.fmt.allocPrintZ(self.warnings.allocator, fmt, args); const item = try std.fmt.allocPrint(self.arena, fmt, args);
errdefer self.warnings.allocator.free(item); try self.warnings.append(self.arena, item);
try self.warnings.append(item);
} }
pub fn addRPath(self: *NativePaths, s: []const u8) !void { pub fn addRPath(self: *NativePaths, s: []const u8) !void {
return self.appendArray(&self.rpaths, s); try self.rpaths.append(self.arena, s);
}
fn appendArray(self: *NativePaths, array: *ArrayList([:0]u8), s: []const u8) !void {
_ = self;
const item = try array.allocator.dupeZ(u8, s);
errdefer array.allocator.free(item);
try array.append(item);
} }

View File

@ -857,8 +857,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
const sysroot = blk: { const sysroot = blk: {
if (options.sysroot) |sysroot| { if (options.sysroot) |sysroot| {
break :blk sysroot; break :blk sysroot;
} else if (options.native_darwin_sdk) |sdk| {
break :blk sdk.path;
} else { } else {
break :blk null; break :blk null;
} }
@ -4341,6 +4339,10 @@ pub fn addCCArgs(
try argv.append("-ObjC++"); try argv.append("-ObjC++");
} }
for (comp.bin_file.options.framework_dirs) |framework_dir| {
try argv.appendSlice(&.{ "-isystem", framework_dir });
}
// According to Rich Felker libc headers are supposed to go before C language headers. // According to Rich Felker libc headers are supposed to go before C language headers.
// However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics // However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics
// and other compiler specific items. // and other compiler specific items.

View File

@ -2685,34 +2685,13 @@ fn buildOutputType(
warn("{s}", .{warning}); warn("{s}", .{warning});
} }
const has_sysroot = if (comptime builtin.target.isDarwin()) outer: {
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);
break :outer true;
} else break :outer false;
} else false;
try clang_argv.ensureUnusedCapacity(paths.include_dirs.items.len * 2); try clang_argv.ensureUnusedCapacity(paths.include_dirs.items.len * 2);
const isystem_flag = if (has_sysroot) "-iwithsysroot" else "-isystem";
for (paths.include_dirs.items) |include_dir| { for (paths.include_dirs.items) |include_dir| {
clang_argv.appendAssumeCapacity(isystem_flag); clang_argv.appendAssumeCapacity("-isystem");
clang_argv.appendAssumeCapacity(include_dir); clang_argv.appendAssumeCapacity(include_dir);
} }
try clang_argv.ensureUnusedCapacity(paths.framework_dirs.items.len * 2); try framework_dirs.appendSlice(paths.framework_dirs.items);
try framework_dirs.ensureUnusedCapacity(paths.framework_dirs.items.len);
const iframework_flag = if (has_sysroot) "-iframeworkwithsysroot" else "-iframework";
for (paths.framework_dirs.items) |framework_dir| {
clang_argv.appendAssumeCapacity(iframework_flag);
clang_argv.appendAssumeCapacity(framework_dir);
framework_dirs.appendAssumeCapacity(framework_dir);
}
try lib_dirs.appendSlice(paths.lib_dirs.items); try lib_dirs.appendSlice(paths.lib_dirs.items);
try rpath_list.appendSlice(paths.rpaths.items); try rpath_list.appendSlice(paths.rpaths.items);
} }