mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Merge pull request #16058 from ziglang/frontend-lib-paths
compiler: resolve library paths in the frontend
This commit is contained in:
commit
c4e62be62e
21 changed files with 914 additions and 717 deletions
|
|
@ -204,10 +204,9 @@ pub fn build(b: *std.Build) !void {
|
|||
);
|
||||
|
||||
if (!no_bin) {
|
||||
const install_exe = b.addInstallArtifact(exe, .{});
|
||||
if (flat) {
|
||||
install_exe.dest_dir = .prefix;
|
||||
}
|
||||
const install_exe = b.addInstallArtifact(exe, .{
|
||||
.dest_dir = if (flat) .{ .override = .prefix } else .default,
|
||||
});
|
||||
b.getInstallStep().dependOn(&install_exe.step);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ stage3-debug/bin/zig build test docs \
|
|||
|
||||
# Look for HTML errors.
|
||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
||||
tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
|
||||
tidy --drop-empty-elements no -qe "../zig-out/doc/langref.html"
|
||||
|
||||
# Ensure that updating the wasm binary from this commit will result in a viable build.
|
||||
stage3-debug/bin/zig build update-zig1
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ stage3-release/bin/zig build test docs \
|
|||
|
||||
# Look for HTML errors.
|
||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
||||
tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
|
||||
tidy --drop-empty-elements no -qe "../zig-out/doc/langref.html"
|
||||
|
||||
# Ensure that updating the wasm binary from this commit will result in a viable build.
|
||||
stage3-release/bin/zig build update-zig1
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ stage3-debug/bin/zig build test docs \
|
|||
|
||||
# Look for HTML errors.
|
||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
||||
tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
|
||||
tidy --drop-empty-elements no -qe "../zig-out/doc/langref.html"
|
||||
|
||||
# Ensure that updating the wasm binary from this commit will result in a viable build.
|
||||
stage3-debug/bin/zig build update-zig1
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ stage3-release/bin/zig build test docs \
|
|||
|
||||
# Look for HTML errors.
|
||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
||||
tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
|
||||
tidy --drop-empty-elements no -qe "../zig-out/doc/langref.html"
|
||||
|
||||
# Ensure that stage3 and stage4 are byte-for-byte identical.
|
||||
stage3-release/bin/zig build \
|
||||
|
|
|
|||
|
|
@ -149,13 +149,6 @@ entitlements: ?[]const u8 = null,
|
|||
/// (Darwin) Size of the pagezero segment.
|
||||
pagezero_size: ?u64 = null,
|
||||
|
||||
/// (Darwin) Search strategy for searching system libraries. Either `paths_first` or `dylibs_first`.
|
||||
/// The former lowers to `-search_paths_first` linker option, while the latter to `-search_dylibs_first`
|
||||
/// option.
|
||||
/// By default, if no option is specified, the linker assumes `paths_first` as the default
|
||||
/// search strategy.
|
||||
search_strategy: ?enum { paths_first, dylibs_first } = null,
|
||||
|
||||
/// (Darwin) Set size of the padding between the end of load commands
|
||||
/// and start of `__TEXT,__text` section.
|
||||
headerpad_size: ?u32 = null,
|
||||
|
|
@ -242,7 +235,11 @@ pub const SystemLib = struct {
|
|||
name: []const u8,
|
||||
needed: bool,
|
||||
weak: bool,
|
||||
use_pkg_config: enum {
|
||||
use_pkg_config: UsePkgConfig,
|
||||
preferred_link_mode: std.builtin.LinkMode,
|
||||
search_strategy: SystemLib.SearchStrategy,
|
||||
|
||||
pub const UsePkgConfig = enum {
|
||||
/// Don't use pkg-config, just pass -lfoo where foo is name.
|
||||
no,
|
||||
/// Try to get information on how to link the library from pkg-config.
|
||||
|
|
@ -251,7 +248,9 @@ pub const SystemLib = struct {
|
|||
/// Try to get information on how to link the library from pkg-config.
|
||||
/// If that fails, error out.
|
||||
force,
|
||||
},
|
||||
};
|
||||
|
||||
pub const SearchStrategy = enum { paths_first, mode_first, no_fallback };
|
||||
};
|
||||
|
||||
const FrameworkLinkInfo = struct {
|
||||
|
|
@ -718,74 +717,29 @@ pub fn defineCMacroRaw(self: *Compile, name_and_value: []const u8) void {
|
|||
self.c_macros.append(b.dupe(name_and_value)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// This one has no integration with anything, it just puts -lname on the command line.
|
||||
/// Prefer to use `linkSystemLibrary` instead.
|
||||
/// deprecated: use linkSystemLibrary2
|
||||
pub fn linkSystemLibraryName(self: *Compile, name: []const u8) void {
|
||||
const b = self.step.owner;
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = b.dupe(name),
|
||||
.needed = false,
|
||||
.weak = false,
|
||||
.use_pkg_config = .no,
|
||||
},
|
||||
}) catch @panic("OOM");
|
||||
return linkSystemLibrary2(self, name, .{ .use_pkg_config = .no });
|
||||
}
|
||||
|
||||
/// This one has no integration with anything, it just puts -needed-lname on the command line.
|
||||
/// Prefer to use `linkSystemLibraryNeeded` instead.
|
||||
/// deprecated: use linkSystemLibrary2
|
||||
pub fn linkSystemLibraryNeededName(self: *Compile, name: []const u8) void {
|
||||
const b = self.step.owner;
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = b.dupe(name),
|
||||
.needed = true,
|
||||
.weak = false,
|
||||
.use_pkg_config = .no,
|
||||
},
|
||||
}) catch @panic("OOM");
|
||||
return linkSystemLibrary2(self, name, .{ .needed = true, .use_pkg_config = .no });
|
||||
}
|
||||
|
||||
/// Darwin-only. This one has no integration with anything, it just puts -weak-lname on the
|
||||
/// command line. Prefer to use `linkSystemLibraryWeak` instead.
|
||||
/// deprecated: use linkSystemLibrary2
|
||||
pub fn linkSystemLibraryWeakName(self: *Compile, name: []const u8) void {
|
||||
const b = self.step.owner;
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = b.dupe(name),
|
||||
.needed = false,
|
||||
.weak = true,
|
||||
.use_pkg_config = .no,
|
||||
},
|
||||
}) catch @panic("OOM");
|
||||
return linkSystemLibrary2(self, name, .{ .weak = true, .use_pkg_config = .no });
|
||||
}
|
||||
|
||||
/// This links against a system library, exclusively using pkg-config to find the library.
|
||||
/// Prefer to use `linkSystemLibrary` instead.
|
||||
/// deprecated: use linkSystemLibrary2
|
||||
pub fn linkSystemLibraryPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
|
||||
const b = self.step.owner;
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = b.dupe(lib_name),
|
||||
.needed = false,
|
||||
.weak = false,
|
||||
.use_pkg_config = .force,
|
||||
},
|
||||
}) catch @panic("OOM");
|
||||
return linkSystemLibrary2(self, lib_name, .{ .use_pkg_config = .force });
|
||||
}
|
||||
|
||||
/// This links against a system library, exclusively using pkg-config to find the library.
|
||||
/// Prefer to use `linkSystemLibraryNeeded` instead.
|
||||
/// deprecated: use linkSystemLibrary2
|
||||
pub fn linkSystemLibraryNeededPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
|
||||
const b = self.step.owner;
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = b.dupe(lib_name),
|
||||
.needed = true,
|
||||
.weak = false,
|
||||
.use_pkg_config = .force,
|
||||
},
|
||||
}) catch @panic("OOM");
|
||||
return linkSystemLibrary2(self, lib_name, .{ .needed = true, .use_pkg_config = .force });
|
||||
}
|
||||
|
||||
/// Run pkg-config for the given library name and parse the output, returning the arguments
|
||||
|
|
@ -885,21 +839,32 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {
|
|||
}
|
||||
|
||||
pub fn linkSystemLibrary(self: *Compile, name: []const u8) void {
|
||||
self.linkSystemLibraryInner(name, .{});
|
||||
self.linkSystemLibrary2(name, .{});
|
||||
}
|
||||
|
||||
/// deprecated: use linkSystemLibrary2
|
||||
pub fn linkSystemLibraryNeeded(self: *Compile, name: []const u8) void {
|
||||
self.linkSystemLibraryInner(name, .{ .needed = true });
|
||||
return linkSystemLibrary2(self, name, .{ .needed = true });
|
||||
}
|
||||
|
||||
/// deprecated: use linkSystemLibrary2
|
||||
pub fn linkSystemLibraryWeak(self: *Compile, name: []const u8) void {
|
||||
self.linkSystemLibraryInner(name, .{ .weak = true });
|
||||
return linkSystemLibrary2(self, name, .{ .weak = true });
|
||||
}
|
||||
|
||||
fn linkSystemLibraryInner(self: *Compile, name: []const u8, opts: struct {
|
||||
pub const LinkSystemLibraryOptions = struct {
|
||||
needed: bool = false,
|
||||
weak: bool = false,
|
||||
}) void {
|
||||
use_pkg_config: SystemLib.UsePkgConfig = .yes,
|
||||
preferred_link_mode: std.builtin.LinkMode = .Dynamic,
|
||||
search_strategy: SystemLib.SearchStrategy = .paths_first,
|
||||
};
|
||||
|
||||
pub fn linkSystemLibrary2(
|
||||
self: *Compile,
|
||||
name: []const u8,
|
||||
options: LinkSystemLibraryOptions,
|
||||
) void {
|
||||
const b = self.step.owner;
|
||||
if (isLibCLibrary(name)) {
|
||||
self.linkLibC();
|
||||
|
|
@ -913,9 +878,11 @@ fn linkSystemLibraryInner(self: *Compile, name: []const u8, opts: struct {
|
|||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = b.dupe(name),
|
||||
.needed = opts.needed,
|
||||
.weak = opts.weak,
|
||||
.use_pkg_config = .yes,
|
||||
.needed = options.needed,
|
||||
.weak = options.weak,
|
||||
.use_pkg_config = options.use_pkg_config,
|
||||
.preferred_link_mode = options.preferred_link_mode,
|
||||
.search_strategy = options.search_strategy,
|
||||
},
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
|
@ -1385,6 +1352,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
|||
try transitive_deps.add(self.link_objects.items);
|
||||
|
||||
var prev_has_cflags = false;
|
||||
var prev_search_strategy: SystemLib.SearchStrategy = .paths_first;
|
||||
var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic;
|
||||
|
||||
for (transitive_deps.link_objects.items) |link_object| {
|
||||
switch (link_object) {
|
||||
|
|
@ -1420,6 +1389,28 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
|||
},
|
||||
|
||||
.system_lib => |system_lib| {
|
||||
if ((system_lib.search_strategy != prev_search_strategy or
|
||||
system_lib.preferred_link_mode != prev_preferred_link_mode) and
|
||||
self.linkage != .static)
|
||||
{
|
||||
switch (system_lib.search_strategy) {
|
||||
.no_fallback => switch (system_lib.preferred_link_mode) {
|
||||
.Dynamic => try zig_args.append("-search_dylibs_only"),
|
||||
.Static => try zig_args.append("-search_static_only"),
|
||||
},
|
||||
.paths_first => switch (system_lib.preferred_link_mode) {
|
||||
.Dynamic => try zig_args.append("-search_paths_first"),
|
||||
.Static => try zig_args.append("-search_paths_first_static"),
|
||||
},
|
||||
.mode_first => switch (system_lib.preferred_link_mode) {
|
||||
.Dynamic => try zig_args.append("-search_dylibs_first"),
|
||||
.Static => try zig_args.append("-search_static_first"),
|
||||
},
|
||||
}
|
||||
prev_search_strategy = system_lib.search_strategy;
|
||||
prev_preferred_link_mode = system_lib.preferred_link_mode;
|
||||
}
|
||||
|
||||
const prefix: []const u8 = prefix: {
|
||||
if (system_lib.needed) break :prefix "-needed-l";
|
||||
if (system_lib.weak) break :prefix "-weak-l";
|
||||
|
|
@ -1662,10 +1653,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
|||
const size = try std.fmt.allocPrint(b.allocator, "{x}", .{pagezero_size});
|
||||
try zig_args.appendSlice(&[_][]const u8{ "-pagezero_size", size });
|
||||
}
|
||||
if (self.search_strategy) |strat| switch (strat) {
|
||||
.paths_first => try zig_args.append("-search_paths_first"),
|
||||
.dylibs_first => try zig_args.append("-search_dylibs_first"),
|
||||
};
|
||||
if (self.headerpad_size) |headerpad_size| {
|
||||
const size = try std.fmt.allocPrint(b.allocator, "{x}", .{headerpad_size});
|
||||
try zig_args.appendSlice(&[_][]const u8{ "-headerpad", size });
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
const std = @import("../../std.zig");
|
||||
const builtin = @import("builtin");
|
||||
const ArrayList = std.ArrayList;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const process = std.process;
|
||||
const mem = std.mem;
|
||||
|
|
@ -8,28 +7,18 @@ const mem = std.mem;
|
|||
const NativePaths = @This();
|
||||
const NativeTargetInfo = std.zig.system.NativeTargetInfo;
|
||||
|
||||
include_dirs: ArrayList([:0]u8),
|
||||
lib_dirs: ArrayList([:0]u8),
|
||||
framework_dirs: ArrayList([:0]u8),
|
||||
rpaths: ArrayList([:0]u8),
|
||||
warnings: ArrayList([:0]u8),
|
||||
arena: Allocator,
|
||||
include_dirs: std.ArrayListUnmanaged([]const u8) = .{},
|
||||
lib_dirs: std.ArrayListUnmanaged([]const u8) = .{},
|
||||
framework_dirs: std.ArrayListUnmanaged([]const 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;
|
||||
|
||||
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 self: NativePaths = .{ .arena = arena };
|
||||
var is_nix = false;
|
||||
if (process.getEnvVarOwned(allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
|
||||
defer allocator.free(nix_cflags_compile);
|
||||
|
||||
if (process.getEnvVarOwned(arena, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
|
||||
is_nix = true;
|
||||
var it = mem.tokenizeScalar(u8, nix_cflags_compile, ' ');
|
||||
while (true) {
|
||||
|
|
@ -58,9 +47,7 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
|
|||
error.EnvironmentVariableNotFound => {},
|
||||
error.OutOfMemory => |e| return e,
|
||||
}
|
||||
if (process.getEnvVarOwned(allocator, "NIX_LDFLAGS")) |nix_ldflags| {
|
||||
defer allocator.free(nix_ldflags);
|
||||
|
||||
if (process.getEnvVarOwned(arena, "NIX_LDFLAGS")) |nix_ldflags| {
|
||||
is_nix = true;
|
||||
var it = mem.tokenizeScalar(u8, nix_ldflags, ' ');
|
||||
while (true) {
|
||||
|
|
@ -89,17 +76,16 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
|
|||
return self;
|
||||
}
|
||||
|
||||
// TODO: consider also adding homebrew paths
|
||||
// TODO: consider also adding macports paths
|
||||
if (comptime builtin.target.isDarwin()) {
|
||||
try self.addIncludeDir("/usr/include");
|
||||
try self.addLibDir("/usr/lib");
|
||||
try self.addFrameworkDir("/System/Library/Frameworks");
|
||||
|
||||
if (builtin.target.os.version_range.semver.min.major < 11) {
|
||||
try self.addIncludeDir("/usr/local/include");
|
||||
try self.addLibDir("/usr/local/lib");
|
||||
try self.addFrameworkDir("/Library/Frameworks");
|
||||
if (std.zig.system.darwin.isSdkInstalled(arena)) sdk: {
|
||||
const sdk = std.zig.system.darwin.getSdk(arena, native_target) orelse break :sdk;
|
||||
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" }));
|
||||
try self.addIncludeDir(try std.fs.path.join(arena, &.{ sdk.path, "usr/include" }));
|
||||
return self;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
@ -115,8 +101,7 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
|
|||
}
|
||||
|
||||
if (builtin.os.tag != .windows) {
|
||||
const triple = try native_target.linuxTriple(allocator);
|
||||
defer allocator.free(triple);
|
||||
const triple = try native_target.linuxTriple(arena);
|
||||
|
||||
const qual = native_target.ptrBitWidth();
|
||||
|
||||
|
|
@ -172,69 +157,42 @@ pub fn detect(allocator: Allocator, native_info: NativeTargetInfo) !NativePaths
|
|||
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 {
|
||||
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 {
|
||||
const item = try std.fmt.allocPrintZ(self.include_dirs.allocator, fmt, args);
|
||||
errdefer self.include_dirs.allocator.free(item);
|
||||
try self.include_dirs.append(item);
|
||||
const item = try std.fmt.allocPrint(self.arena, fmt, args);
|
||||
try self.include_dirs.append(self.arena, item);
|
||||
}
|
||||
|
||||
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 {
|
||||
const item = try std.fmt.allocPrintZ(self.lib_dirs.allocator, fmt, args);
|
||||
errdefer self.lib_dirs.allocator.free(item);
|
||||
try self.lib_dirs.append(item);
|
||||
const item = try std.fmt.allocPrint(self.arena, fmt, args);
|
||||
try self.lib_dirs.append(self.arena, item);
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
const item = try std.fmt.allocPrintZ(self.framework_dirs.allocator, fmt, args);
|
||||
errdefer self.framework_dirs.allocator.free(item);
|
||||
try self.framework_dirs.append(item);
|
||||
const item = try std.fmt.allocPrint(self.arena, fmt, args);
|
||||
try self.framework_dirs.append(self.arena, item);
|
||||
}
|
||||
|
||||
pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: anytype) !void {
|
||||
const item = try std.fmt.allocPrintZ(self.warnings.allocator, fmt, args);
|
||||
errdefer self.warnings.allocator.free(item);
|
||||
try self.warnings.append(item);
|
||||
const item = try std.fmt.allocPrint(self.arena, fmt, args);
|
||||
try self.warnings.append(self.arena, item);
|
||||
}
|
||||
|
||||
pub fn addRPath(self: *NativePaths, s: []const u8) !void {
|
||||
return self.appendArray(&self.rpaths, 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);
|
||||
try self.rpaths.append(self.arena, s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,28 +8,34 @@ pub const macos = @import("darwin/macos.zig");
|
|||
|
||||
/// Check if SDK is installed on Darwin without triggering CLT installation popup window.
|
||||
/// Note: simply invoking `xcrun` will inevitably trigger the CLT installation popup.
|
||||
/// Therefore, we resort to the same tool used by Homebrew, namely, invoking `xcode-select --print-path`
|
||||
/// and checking if the status is nonzero or the returned string in nonempty.
|
||||
/// https://github.com/Homebrew/brew/blob/e119bdc571dcb000305411bc1e26678b132afb98/Library/Homebrew/brew.sh#L630
|
||||
pub fn isDarwinSDKInstalled(allocator: Allocator) bool {
|
||||
const argv = &[_][]const u8{ "/usr/bin/xcode-select", "--print-path" };
|
||||
const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return false;
|
||||
/// Therefore, we resort to invoking `xcode-select --print-path` and checking
|
||||
/// if the status is nonzero.
|
||||
/// stderr from xcode-select is ignored.
|
||||
/// If error.OutOfMemory occurs in Allocator, this function returns null.
|
||||
pub fn isSdkInstalled(allocator: Allocator) bool {
|
||||
const result = std.process.Child.exec(.{
|
||||
.allocator = allocator,
|
||||
.argv = &.{ "/usr/bin/xcode-select", "--print-path" },
|
||||
}) catch return false;
|
||||
|
||||
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.
|
||||
return false;
|
||||
}
|
||||
return result.stdout.len > 0;
|
||||
|
||||
return switch (result.term) {
|
||||
.Exited => |code| if (code == 0) result.stdout.len > 0 else false,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// Detect SDK on Darwin.
|
||||
/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which fetches the path to the SDK sysroot (if any).
|
||||
/// Subsequently calls `xcrun --sdk <target_sdk> --show-sdk-version` which fetches version of the SDK.
|
||||
/// The caller needs to deinit the resulting struct.
|
||||
pub fn getDarwinSDK(allocator: Allocator, target: Target) ?DarwinSDK {
|
||||
/// stderr from xcrun is ignored.
|
||||
/// If error.OutOfMemory occurs in Allocator, this function returns null.
|
||||
pub fn getSdk(allocator: Allocator, target: Target) ?Sdk {
|
||||
const is_simulator_abi = target.abi == .simulator;
|
||||
const sdk = switch (target.os.tag) {
|
||||
.macos => "macosx",
|
||||
|
|
@ -40,30 +46,28 @@ pub fn getDarwinSDK(allocator: Allocator, target: Target) ?DarwinSDK {
|
|||
};
|
||||
const path = path: {
|
||||
const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-path" };
|
||||
const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
|
||||
const result = std.process.Child.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
|
||||
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;
|
||||
switch (result.term) {
|
||||
.Exited => |code| if (code != 0) return null,
|
||||
else => return null,
|
||||
}
|
||||
const path = allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n")) catch return null;
|
||||
break :path path;
|
||||
};
|
||||
const version = version: {
|
||||
const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-version" };
|
||||
const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
|
||||
const result = std.process.Child.exec(.{ .allocator = allocator, .argv = argv }) catch return null;
|
||||
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;
|
||||
switch (result.term) {
|
||||
.Exited => |code| if (code != 0) return null,
|
||||
else => return null,
|
||||
}
|
||||
const raw_version = mem.trimRight(u8, result.stdout, "\r\n");
|
||||
const version = parseSdkVersion(raw_version) orelse Version{
|
||||
|
|
@ -73,7 +77,7 @@ pub fn getDarwinSDK(allocator: Allocator, target: Target) ?DarwinSDK {
|
|||
};
|
||||
break :version version;
|
||||
};
|
||||
return DarwinSDK{
|
||||
return Sdk{
|
||||
.path = path,
|
||||
.version = version,
|
||||
};
|
||||
|
|
@ -96,11 +100,11 @@ fn parseSdkVersion(raw: []const u8) ?Version {
|
|||
return Version.parse(buffer[0..len]) catch null;
|
||||
}
|
||||
|
||||
pub const DarwinSDK = struct {
|
||||
pub const Sdk = struct {
|
||||
path: []const u8,
|
||||
version: Version,
|
||||
|
||||
pub fn deinit(self: DarwinSDK, allocator: Allocator) void {
|
||||
pub fn deinit(self: Sdk, allocator: Allocator) void {
|
||||
allocator.free(self.path);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ zig_lib_directory: Directory,
|
|||
local_cache_directory: Directory,
|
||||
global_cache_directory: Directory,
|
||||
libc_include_dir_list: []const []const u8,
|
||||
libc_framework_dir_list: []const []const u8,
|
||||
thread_pool: *ThreadPool,
|
||||
|
||||
/// Populated when we build the libc++ static library. A Job to build this is placed in the queue
|
||||
|
|
@ -448,6 +449,7 @@ pub const ClangPreprocessorMode = enum {
|
|||
stdout,
|
||||
};
|
||||
|
||||
pub const Framework = link.Framework;
|
||||
pub const SystemLib = link.SystemLib;
|
||||
pub const CacheMode = link.CacheMode;
|
||||
|
||||
|
|
@ -505,7 +507,7 @@ pub const InitOptions = struct {
|
|||
c_source_files: []const CSourceFile = &[0]CSourceFile{},
|
||||
link_objects: []LinkObject = &[0]LinkObject{},
|
||||
framework_dirs: []const []const u8 = &[0][]const u8{},
|
||||
frameworks: std.StringArrayHashMapUnmanaged(SystemLib) = .{},
|
||||
frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{},
|
||||
system_lib_names: []const []const u8 = &.{},
|
||||
system_lib_infos: []const SystemLib = &.{},
|
||||
/// These correspond to the WASI libc emulated subcomponents including:
|
||||
|
|
@ -636,16 +638,12 @@ 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,
|
||||
/// (Darwin) Install name of the dylib
|
||||
install_name: ?[]const u8 = null,
|
||||
/// (Darwin) Path to entitlements file
|
||||
entitlements: ?[]const u8 = null,
|
||||
/// (Darwin) size of the __PAGEZERO segment
|
||||
pagezero_size: ?u64 = null,
|
||||
/// (Darwin) search strategy for system libraries
|
||||
search_strategy: ?link.File.MachO.SearchStrategy = null,
|
||||
/// (Darwin) set minimum space for future expansion of the load commands
|
||||
headerpad_size: ?u32 = null,
|
||||
/// (Darwin) set enough space as if all paths were MATPATHLEN
|
||||
|
|
@ -855,16 +853,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||
break :blk false;
|
||||
};
|
||||
|
||||
const sysroot = blk: {
|
||||
if (options.sysroot) |sysroot| {
|
||||
break :blk sysroot;
|
||||
} else if (options.native_darwin_sdk) |sdk| {
|
||||
break :blk sdk.path;
|
||||
} else {
|
||||
break :blk null;
|
||||
}
|
||||
};
|
||||
|
||||
const lto = blk: {
|
||||
if (options.want_lto) |explicit| {
|
||||
if (!use_lld and !options.target.isDarwin())
|
||||
|
|
@ -948,9 +936,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||
options.is_native_abi,
|
||||
link_libc,
|
||||
options.libc_installation,
|
||||
options.native_darwin_sdk != null,
|
||||
);
|
||||
|
||||
const sysroot = options.sysroot orelse libc_dirs.sysroot;
|
||||
|
||||
const must_pie = target_util.requiresPIE(options.target);
|
||||
const pie: bool = if (options.want_pie) |explicit| pie: {
|
||||
if (!explicit and must_pie) {
|
||||
|
|
@ -1563,11 +1552,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||
.wasi_exec_model = wasi_exec_model,
|
||||
.hash_style = options.hash_style,
|
||||
.enable_link_snapshots = options.enable_link_snapshots,
|
||||
.native_darwin_sdk = options.native_darwin_sdk,
|
||||
.install_name = options.install_name,
|
||||
.entitlements = options.entitlements,
|
||||
.pagezero_size = options.pagezero_size,
|
||||
.search_strategy = options.search_strategy,
|
||||
.headerpad_size = options.headerpad_size,
|
||||
.headerpad_max_install_names = options.headerpad_max_install_names,
|
||||
.dead_strip_dylibs = options.dead_strip_dylibs,
|
||||
|
|
@ -1601,6 +1588,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||
.cache_parent = cache,
|
||||
.self_exe_path = options.self_exe_path,
|
||||
.libc_include_dir_list = libc_dirs.libc_include_dir_list,
|
||||
.libc_framework_dir_list = libc_dirs.libc_framework_dir_list,
|
||||
.sanitize_c = sanitize_c,
|
||||
.thread_pool = options.thread_pool,
|
||||
.clang_passthrough_mode = options.clang_passthrough_mode,
|
||||
|
|
@ -1727,15 +1715,18 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||
|
||||
// When linking mingw-w64 there are some import libs we always need.
|
||||
for (mingw.always_link_libs) |name| {
|
||||
try comp.bin_file.options.system_libs.put(comp.gpa, name, .{});
|
||||
try comp.bin_file.options.system_libs.put(comp.gpa, name, .{
|
||||
.needed = false,
|
||||
.weak = false,
|
||||
.path = null,
|
||||
});
|
||||
}
|
||||
}
|
||||
// Generate Windows import libs.
|
||||
if (target.os.tag == .windows) {
|
||||
const count = comp.bin_file.options.system_libs.count();
|
||||
try comp.work_queue.ensureUnusedCapacity(count);
|
||||
var i: usize = 0;
|
||||
while (i < count) : (i += 1) {
|
||||
for (0..count) |i| {
|
||||
comp.work_queue.writeItemAssumeCapacity(.{ .windows_import_lib = i });
|
||||
}
|
||||
}
|
||||
|
|
@ -2367,17 +2358,17 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
|||
if (comp.bin_file.options.link_libc) {
|
||||
man.hash.add(comp.bin_file.options.libc_installation != null);
|
||||
if (comp.bin_file.options.libc_installation) |libc_installation| {
|
||||
man.hash.addBytes(libc_installation.crt_dir.?);
|
||||
man.hash.addOptionalBytes(libc_installation.crt_dir);
|
||||
if (target.abi == .msvc) {
|
||||
man.hash.addBytes(libc_installation.msvc_lib_dir.?);
|
||||
man.hash.addBytes(libc_installation.kernel32_lib_dir.?);
|
||||
man.hash.addOptionalBytes(libc_installation.msvc_lib_dir);
|
||||
man.hash.addOptionalBytes(libc_installation.kernel32_lib_dir);
|
||||
}
|
||||
}
|
||||
man.hash.addOptionalBytes(comp.bin_file.options.dynamic_linker);
|
||||
}
|
||||
man.hash.addOptionalBytes(comp.bin_file.options.soname);
|
||||
man.hash.addOptional(comp.bin_file.options.version);
|
||||
link.hashAddSystemLibs(&man.hash, comp.bin_file.options.system_libs);
|
||||
try link.hashAddSystemLibs(man, comp.bin_file.options.system_libs);
|
||||
man.hash.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys());
|
||||
man.hash.addOptional(comp.bin_file.options.allow_shlib_undefined);
|
||||
man.hash.add(comp.bin_file.options.bind_global_refs_locally);
|
||||
|
|
@ -2395,10 +2386,9 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
|||
|
||||
// Mach-O specific stuff
|
||||
man.hash.addListOfBytes(comp.bin_file.options.framework_dirs);
|
||||
link.hashAddSystemLibs(&man.hash, comp.bin_file.options.frameworks);
|
||||
link.hashAddFrameworks(&man.hash, comp.bin_file.options.frameworks);
|
||||
try man.addOptionalFile(comp.bin_file.options.entitlements);
|
||||
man.hash.addOptional(comp.bin_file.options.pagezero_size);
|
||||
man.hash.addOptional(comp.bin_file.options.search_strategy);
|
||||
man.hash.addOptional(comp.bin_file.options.headerpad_size);
|
||||
man.hash.add(comp.bin_file.options.headerpad_max_install_names);
|
||||
man.hash.add(comp.bin_file.options.dead_strip_dylibs);
|
||||
|
|
@ -4341,6 +4331,14 @@ pub fn addCCArgs(
|
|||
try argv.append("-ObjC++");
|
||||
}
|
||||
|
||||
for (comp.libc_framework_dir_list) |framework_dir| {
|
||||
try argv.appendSlice(&.{ "-iframework", framework_dir });
|
||||
}
|
||||
|
||||
for (comp.bin_file.options.framework_dirs) |framework_dir| {
|
||||
try argv.appendSlice(&.{ "-F", framework_dir });
|
||||
}
|
||||
|
||||
// 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
|
||||
// and other compiler specific items.
|
||||
|
|
@ -4823,6 +4821,8 @@ test "classifyFileExt" {
|
|||
const LibCDirs = struct {
|
||||
libc_include_dir_list: []const []const u8,
|
||||
libc_installation: ?*const LibCInstallation,
|
||||
libc_framework_dir_list: []const []const u8,
|
||||
sysroot: ?[]const u8,
|
||||
};
|
||||
|
||||
fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8, target: Target) !LibCDirs {
|
||||
|
|
@ -4853,6 +4853,8 @@ fn getZigShippedLibCIncludeDirsDarwin(arena: Allocator, zig_lib_dir: []const u8,
|
|||
return LibCDirs{
|
||||
.libc_include_dir_list = list,
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -4863,12 +4865,13 @@ fn detectLibCIncludeDirs(
|
|||
is_native_abi: bool,
|
||||
link_libc: bool,
|
||||
libc_installation: ?*const LibCInstallation,
|
||||
has_macos_sdk: bool,
|
||||
) !LibCDirs {
|
||||
if (!link_libc) {
|
||||
return LibCDirs{
|
||||
.libc_include_dir_list = &[0][]u8{},
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -4879,28 +4882,19 @@ fn detectLibCIncludeDirs(
|
|||
// If linking system libraries and targeting the native abi, default to
|
||||
// using the system libc installation.
|
||||
if (is_native_abi and !target.isMinGW()) {
|
||||
if (target.isDarwin()) {
|
||||
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.* = LibCInstallation.findNative(.{ .allocator = arena }) catch |err| switch (err) {
|
||||
libc.* = LibCInstallation.findNative(.{ .allocator = arena, .target = target }) catch |err| switch (err) {
|
||||
error.CCompilerExitCode,
|
||||
error.CCompilerCrashed,
|
||||
error.CCompilerCannotFindHeaders,
|
||||
error.UnableToSpawnCCompiler,
|
||||
error.DarwinSdkNotFound,
|
||||
=> |e| {
|
||||
// We tried to integrate with the native system C compiler,
|
||||
// however, it is not installed. So we must rely on our bundled
|
||||
// libc files.
|
||||
if (target_util.canBuildLibC(target)) {
|
||||
return detectLibCFromBuilding(arena, zig_lib_dir, target, has_macos_sdk);
|
||||
return detectLibCFromBuilding(arena, zig_lib_dir, target);
|
||||
}
|
||||
return e;
|
||||
},
|
||||
|
|
@ -4912,7 +4906,7 @@ fn detectLibCIncludeDirs(
|
|||
// If not linking system libraries, build and provide our own libc by
|
||||
// default if possible.
|
||||
if (target_util.canBuildLibC(target)) {
|
||||
return detectLibCFromBuilding(arena, zig_lib_dir, target, has_macos_sdk);
|
||||
return detectLibCFromBuilding(arena, zig_lib_dir, target);
|
||||
}
|
||||
|
||||
// If zig can't build the libc for the target and we are targeting the
|
||||
|
|
@ -4926,18 +4920,21 @@ fn detectLibCIncludeDirs(
|
|||
|
||||
if (use_system_abi) {
|
||||
const libc = try arena.create(LibCInstallation);
|
||||
libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true });
|
||||
libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, .target = target });
|
||||
return detectLibCFromLibCInstallation(arena, target, libc);
|
||||
}
|
||||
|
||||
return LibCDirs{
|
||||
.libc_include_dir_list = &[0][]u8{},
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
};
|
||||
}
|
||||
|
||||
fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const LibCInstallation) !LibCDirs {
|
||||
var list = try std.ArrayList([]const u8).initCapacity(arena, 5);
|
||||
var framework_list = std.ArrayList([]const u8).init(arena);
|
||||
|
||||
list.appendAssumeCapacity(lci.include_dir.?);
|
||||
|
||||
|
|
@ -4965,9 +4962,20 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const
|
|||
list.appendAssumeCapacity(config_dir);
|
||||
}
|
||||
|
||||
var sysroot: ?[]const u8 = null;
|
||||
|
||||
if (target.isDarwin()) d: {
|
||||
const down1 = std.fs.path.dirname(lci.sys_include_dir.?) orelse break :d;
|
||||
const down2 = std.fs.path.dirname(down1) orelse break :d;
|
||||
try framework_list.append(try std.fs.path.join(arena, &.{ down2, "System", "Library", "Frameworks" }));
|
||||
sysroot = down2;
|
||||
}
|
||||
|
||||
return LibCDirs{
|
||||
.libc_include_dir_list = list.items,
|
||||
.libc_installation = lci,
|
||||
.libc_framework_dir_list = framework_list.items,
|
||||
.sysroot = sysroot,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -4975,18 +4983,10 @@ fn detectLibCFromBuilding(
|
|||
arena: Allocator,
|
||||
zig_lib_dir: []const u8,
|
||||
target: std.Target,
|
||||
has_macos_sdk: bool,
|
||||
) !LibCDirs {
|
||||
switch (target.os.tag) {
|
||||
.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 => {
|
||||
if (target.isDarwin())
|
||||
return getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target);
|
||||
|
||||
const generic_name = target_util.libCGenericName(target);
|
||||
// Some architectures are handled by the same set of headers.
|
||||
const arch_name = if (target.abi.isMusl())
|
||||
|
|
@ -5035,9 +5035,9 @@ fn detectLibCFromBuilding(
|
|||
return LibCDirs{
|
||||
.libc_include_dir_list = list,
|
||||
.libc_installation = null,
|
||||
.libc_framework_dir_list = &.{},
|
||||
.sysroot = null,
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 {
|
||||
|
|
@ -5618,6 +5618,11 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {
|
|||
// to queue up a work item to produce the DLL import library for this.
|
||||
const gop = try comp.bin_file.options.system_libs.getOrPut(comp.gpa, lib_name);
|
||||
if (!gop.found_existing and comp.getTarget().os.tag == .windows) {
|
||||
gop.value_ptr.* = .{
|
||||
.needed = true,
|
||||
.weak = false,
|
||||
.path = null,
|
||||
};
|
||||
try comp.work_queue.writeItem(.{
|
||||
.windows_import_lib = comp.bin_file.options.system_libs.count() - 1,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ pub const LibCInstallation = struct {
|
|||
LibCKernel32LibNotFound,
|
||||
UnsupportedArchitecture,
|
||||
WindowsSdkNotFound,
|
||||
DarwinSdkNotFound,
|
||||
ZigIsTheCCompiler,
|
||||
};
|
||||
|
||||
|
|
@ -171,6 +172,7 @@ pub const LibCInstallation = struct {
|
|||
|
||||
pub const FindNativeOptions = struct {
|
||||
allocator: Allocator,
|
||||
target: std.Target,
|
||||
|
||||
/// If enabled, will print human-friendly errors to stderr.
|
||||
verbose: bool = false,
|
||||
|
|
@ -181,7 +183,19 @@ pub const LibCInstallation = struct {
|
|||
var self: LibCInstallation = .{};
|
||||
|
||||
if (is_darwin) {
|
||||
@panic("Darwin is handled separately via std.zig.system.darwin module");
|
||||
if (!std.zig.system.darwin.isSdkInstalled(args.allocator))
|
||||
return error.DarwinSdkNotFound;
|
||||
const sdk = std.zig.system.darwin.getSdk(args.allocator, args.target) orelse
|
||||
return error.DarwinSdkNotFound;
|
||||
defer args.allocator.free(sdk.path);
|
||||
|
||||
self.include_dir = try fs.path.join(args.allocator, &.{
|
||||
sdk.path, "usr/include",
|
||||
});
|
||||
self.sys_include_dir = try fs.path.join(args.allocator, &.{
|
||||
sdk.path, "usr/include",
|
||||
});
|
||||
return self;
|
||||
} else if (is_windows) {
|
||||
var sdk: ZigWindowsSDK = ZigWindowsSDK.find(args.allocator) catch |err| switch (err) {
|
||||
error.NotFound => return error.WindowsSdkNotFound,
|
||||
|
|
|
|||
41
src/link.zig
41
src/link.zig
|
|
@ -21,7 +21,20 @@ const Type = @import("type.zig").Type;
|
|||
const TypedValue = @import("TypedValue.zig");
|
||||
|
||||
/// When adding a new field, remember to update `hashAddSystemLibs`.
|
||||
/// These are *always* dynamically linked. Static libraries will be
|
||||
/// provided as positional arguments.
|
||||
pub const SystemLib = struct {
|
||||
needed: bool,
|
||||
weak: bool,
|
||||
/// This can be null in two cases right now:
|
||||
/// 1. Windows DLLs that zig ships such as advapi32.
|
||||
/// 2. extern "foo" fn declarations where we find out about libraries too late
|
||||
/// TODO: make this non-optional and resolve those two cases somehow.
|
||||
path: ?[]const u8,
|
||||
};
|
||||
|
||||
/// When adding a new field, remember to update `hashAddFrameworks`.
|
||||
pub const Framework = struct {
|
||||
needed: bool = false,
|
||||
weak: bool = false,
|
||||
};
|
||||
|
|
@ -31,11 +44,23 @@ pub const SortSection = enum { name, alignment };
|
|||
pub const CacheMode = enum { incremental, whole };
|
||||
|
||||
pub fn hashAddSystemLibs(
|
||||
hh: *Cache.HashHelper,
|
||||
man: *Cache.Manifest,
|
||||
hm: std.StringArrayHashMapUnmanaged(SystemLib),
|
||||
) !void {
|
||||
const keys = hm.keys();
|
||||
man.hash.addListOfBytes(keys);
|
||||
for (hm.values()) |value| {
|
||||
man.hash.add(value.needed);
|
||||
man.hash.add(value.weak);
|
||||
if (value.path) |p| _ = try man.addFile(p, null);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hashAddFrameworks(
|
||||
hh: *Cache.HashHelper,
|
||||
hm: std.StringArrayHashMapUnmanaged(Framework),
|
||||
) void {
|
||||
const keys = hm.keys();
|
||||
hh.add(keys.len);
|
||||
hh.addListOfBytes(keys);
|
||||
for (hm.values()) |value| {
|
||||
hh.add(value.needed);
|
||||
|
|
@ -183,9 +208,12 @@ pub const Options = struct {
|
|||
|
||||
objects: []Compilation.LinkObject,
|
||||
framework_dirs: []const []const u8,
|
||||
frameworks: std.StringArrayHashMapUnmanaged(SystemLib),
|
||||
frameworks: std.StringArrayHashMapUnmanaged(Framework),
|
||||
/// These are *always* dynamically linked. Static libraries will be
|
||||
/// provided as positional arguments.
|
||||
system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
|
||||
wasi_emulated_libs: []const wasi_libc.CRTFile,
|
||||
// TODO: remove this. libraries are resolved by the frontend.
|
||||
lib_dirs: []const []const u8,
|
||||
rpath_list: []const []const u8,
|
||||
|
||||
|
|
@ -203,6 +231,7 @@ pub const Options = struct {
|
|||
|
||||
version: ?std.SemanticVersion,
|
||||
compatibility_version: ?std.SemanticVersion,
|
||||
darwin_sdk_version: ?std.SemanticVersion = null,
|
||||
libc_installation: ?*const LibCInstallation,
|
||||
|
||||
dwarf_format: ?std.dwarf.Format,
|
||||
|
|
@ -213,9 +242,6 @@ 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,
|
||||
|
||||
/// (Darwin) Install name for the dylib
|
||||
install_name: ?[]const u8 = null,
|
||||
|
||||
|
|
@ -225,9 +251,6 @@ pub const Options = struct {
|
|||
/// (Darwin) size of the __PAGEZERO segment
|
||||
pagezero_size: ?u64 = null,
|
||||
|
||||
/// (Darwin) search strategy for system libraries
|
||||
search_strategy: ?File.MachO.SearchStrategy = null,
|
||||
|
||||
/// (Darwin) set minimum space for future expansion of the load commands
|
||||
headerpad_size: ?u32 = null,
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
|||
}
|
||||
}
|
||||
}
|
||||
link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
|
||||
try link.hashAddSystemLibs(&man, self.base.options.system_libs);
|
||||
man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());
|
||||
man.hash.addOptional(self.base.options.subsystem);
|
||||
man.hash.add(self.base.options.is_test);
|
||||
|
|
@ -405,6 +405,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
|||
try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib"));
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "mingwex.lib"));
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "msvcrt-os.lib"));
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "uuid.lib"));
|
||||
|
||||
for (mingw.always_link_libs) |name| {
|
||||
if (!self.base.options.system_libs.contains(name)) {
|
||||
|
|
|
|||
|
|
@ -1428,7 +1428,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
|||
}
|
||||
man.hash.addOptionalBytes(self.base.options.soname);
|
||||
man.hash.addOptional(self.base.options.version);
|
||||
link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
|
||||
try link.hashAddSystemLibs(&man, self.base.options.system_libs);
|
||||
man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());
|
||||
man.hash.add(allow_shlib_undefined);
|
||||
man.hash.add(self.base.options.bind_global_refs_locally);
|
||||
|
|
@ -1824,8 +1824,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
|||
argv.appendAssumeCapacity("--as-needed");
|
||||
var as_needed = true;
|
||||
|
||||
for (system_libs, 0..) |link_lib, i| {
|
||||
const lib_as_needed = !system_libs_values[i].needed;
|
||||
for (system_libs_values) |lib_info| {
|
||||
const lib_as_needed = !lib_info.needed;
|
||||
switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
|
||||
0b00, 0b11 => {},
|
||||
0b01 => {
|
||||
|
|
@ -1842,9 +1842,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
|||
// libraries and not static libraries (the check for that needs to be earlier),
|
||||
// but they could be full paths to .so files, in which case we
|
||||
// want to avoid prepending "-l".
|
||||
const ext = Compilation.classifyFileExt(link_lib);
|
||||
const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{s}", .{link_lib});
|
||||
argv.appendAssumeCapacity(arg);
|
||||
argv.appendAssumeCapacity(lib_info.path.?);
|
||||
}
|
||||
|
||||
if (!as_needed) {
|
||||
|
|
|
|||
|
|
@ -58,11 +58,6 @@ const Rebase = @import("MachO/dyld_info/Rebase.zig");
|
|||
|
||||
pub const base_tag: File.Tag = File.Tag.macho;
|
||||
|
||||
pub const SearchStrategy = enum {
|
||||
paths_first,
|
||||
dylibs_first,
|
||||
};
|
||||
|
||||
/// Mode of operation of the linker.
|
||||
pub const Mode = enum {
|
||||
/// Incremental mode will preallocate segments/sections and is compatible with
|
||||
|
|
@ -834,39 +829,50 @@ pub fn resolveLibSystem(
|
|||
out_libs: anytype,
|
||||
) !void {
|
||||
// If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
|
||||
var libsystem_available = false;
|
||||
if (syslibroot != null) blk: {
|
||||
// Try stub file first. If we hit it, then we're done as the stub file
|
||||
// re-exports every single symbol definition.
|
||||
for (search_dirs) |dir| {
|
||||
if (try resolveLib(arena, dir, "System", ".tbd")) |full_path| {
|
||||
try out_libs.put(full_path, .{ .needed = true });
|
||||
libsystem_available = true;
|
||||
break :blk;
|
||||
if (syslibroot) |root| {
|
||||
const full_dir_path = try std.fs.path.join(arena, &.{ root, "usr", "lib" });
|
||||
if (try resolveLibSystemInDirs(arena, &.{full_dir_path}, out_libs)) return;
|
||||
}
|
||||
}
|
||||
// If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
|
||||
// doesn't export libc.dylib which we'll need to resolve subsequently also.
|
||||
for (search_dirs) |dir| {
|
||||
if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| {
|
||||
if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| {
|
||||
try out_libs.put(libsystem_path, .{ .needed = true });
|
||||
try out_libs.put(libc_path, .{ .needed = true });
|
||||
libsystem_available = true;
|
||||
break :blk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!libsystem_available) {
|
||||
|
||||
// Next, try input search dirs if we are linking on a custom host such as Nix.
|
||||
if (try resolveLibSystemInDirs(arena, search_dirs, out_libs)) return;
|
||||
|
||||
// As a fallback, try linking against Zig shipped stub.
|
||||
const libsystem_name = try std.fmt.allocPrint(arena, "libSystem.{d}.tbd", .{
|
||||
target.os.version_range.semver.min.major,
|
||||
});
|
||||
const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "darwin", libsystem_name,
|
||||
});
|
||||
try out_libs.put(full_path, .{ .needed = true });
|
||||
try out_libs.put(full_path, .{
|
||||
.needed = true,
|
||||
.weak = false,
|
||||
.path = full_path,
|
||||
});
|
||||
}
|
||||
|
||||
fn resolveLibSystemInDirs(arena: Allocator, dirs: []const []const u8, out_libs: anytype) !bool {
|
||||
// Try stub file first. If we hit it, then we're done as the stub file
|
||||
// re-exports every single symbol definition.
|
||||
for (dirs) |dir| {
|
||||
if (try resolveLib(arena, dir, "System", ".tbd")) |full_path| {
|
||||
try out_libs.put(full_path, .{ .needed = true, .weak = false, .path = full_path });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
|
||||
// doesn't export libc.dylib which we'll need to resolve subsequently also.
|
||||
for (dirs) |dir| {
|
||||
if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| {
|
||||
if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| {
|
||||
try out_libs.put(libsystem_path, .{ .needed = true, .weak = false, .path = libsystem_path });
|
||||
try out_libs.put(libc_path, .{ .needed = true, .weak = false, .path = libc_path });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn resolveSearchDir(
|
||||
|
|
|
|||
|
|
@ -278,11 +278,10 @@ pub fn writeBuildVersionLC(options: *const link.Options, lc_writer: anytype) !vo
|
|||
const platform_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8));
|
||||
break :blk platform_version;
|
||||
};
|
||||
const sdk_version = if (options.native_darwin_sdk) |sdk| blk: {
|
||||
const ver = sdk.version;
|
||||
const sdk_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8));
|
||||
break :blk sdk_version;
|
||||
} else platform_version;
|
||||
const sdk_version: u32 = if (options.darwin_sdk_version) |ver|
|
||||
@intCast(ver.major << 16 | ver.minor << 8)
|
||||
else
|
||||
platform_version;
|
||||
const is_simulator_abi = options.target.abi == .simulator;
|
||||
try lc_writer.writeStruct(macho.build_version_command{
|
||||
.cmdsize = cmdsize,
|
||||
|
|
|
|||
|
|
@ -3410,7 +3410,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
|||
// installation sources because they are always a product of the compiler version + target information.
|
||||
man.hash.add(stack_size);
|
||||
man.hash.addOptional(options.pagezero_size);
|
||||
man.hash.addOptional(options.search_strategy);
|
||||
man.hash.addOptional(options.headerpad_size);
|
||||
man.hash.add(options.headerpad_max_install_names);
|
||||
man.hash.add(gc_sections);
|
||||
|
|
@ -3418,13 +3417,13 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
|||
man.hash.add(options.strip);
|
||||
man.hash.addListOfBytes(options.lib_dirs);
|
||||
man.hash.addListOfBytes(options.framework_dirs);
|
||||
link.hashAddSystemLibs(&man.hash, options.frameworks);
|
||||
link.hashAddFrameworks(&man.hash, options.frameworks);
|
||||
man.hash.addListOfBytes(options.rpath_list);
|
||||
if (is_dyn_lib) {
|
||||
man.hash.addOptionalBytes(options.install_name);
|
||||
man.hash.addOptional(options.version);
|
||||
}
|
||||
link.hashAddSystemLibs(&man.hash, options.system_libs);
|
||||
try link.hashAddSystemLibs(&man, options.system_libs);
|
||||
man.hash.addOptionalBytes(options.sysroot);
|
||||
man.hash.addListOfBytes(options.force_undefined_symbols.keys());
|
||||
try man.addOptionalFile(options.entitlements);
|
||||
|
|
@ -3550,84 +3549,15 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
|||
try positionals.append(comp.libcxx_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// Shared and static libraries passed via `-l` flag.
|
||||
var candidate_libs = std.StringArrayHashMap(link.SystemLib).init(arena);
|
||||
|
||||
const system_lib_names = options.system_libs.keys();
|
||||
for (system_lib_names) |system_lib_name| {
|
||||
// By this time, we depend on these libs being dynamically linked libraries and not static libraries
|
||||
// (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
|
||||
// case we want to avoid prepending "-l".
|
||||
if (Compilation.classifyFileExt(system_lib_name) == .shared_library) {
|
||||
try positionals.append(system_lib_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
const system_lib_info = options.system_libs.get(system_lib_name).?;
|
||||
try candidate_libs.put(system_lib_name, .{
|
||||
.needed = system_lib_info.needed,
|
||||
.weak = system_lib_info.weak,
|
||||
});
|
||||
}
|
||||
|
||||
var lib_dirs = std.ArrayList([]const u8).init(arena);
|
||||
for (options.lib_dirs) |dir| {
|
||||
if (try MachO.resolveSearchDir(arena, dir, options.sysroot)) |search_dir| {
|
||||
try lib_dirs.append(search_dir);
|
||||
} else {
|
||||
log.warn("directory not found for '-L{s}'", .{dir});
|
||||
}
|
||||
}
|
||||
|
||||
var libs = std.StringArrayHashMap(link.SystemLib).init(arena);
|
||||
|
||||
// Assume ld64 default -search_paths_first if no strategy specified.
|
||||
const search_strategy = options.search_strategy orelse .paths_first;
|
||||
outer: for (candidate_libs.keys()) |lib_name| {
|
||||
switch (search_strategy) {
|
||||
.paths_first => {
|
||||
// Look in each directory for a dylib (stub first), and then for archive
|
||||
for (lib_dirs.items) |dir| {
|
||||
for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {
|
||||
if (try MachO.resolveLib(arena, dir, lib_name, ext)) |full_path| {
|
||||
try libs.put(full_path, candidate_libs.get(lib_name).?);
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("library not found for '-l{s}'", .{lib_name});
|
||||
lib_not_found = true;
|
||||
}
|
||||
},
|
||||
.dylibs_first => {
|
||||
// First, look for a dylib in each search dir
|
||||
for (lib_dirs.items) |dir| {
|
||||
for (&[_][]const u8{ ".tbd", ".dylib" }) |ext| {
|
||||
if (try MachO.resolveLib(arena, dir, lib_name, ext)) |full_path| {
|
||||
try libs.put(full_path, candidate_libs.get(lib_name).?);
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
} else for (lib_dirs.items) |dir| {
|
||||
if (try MachO.resolveLib(arena, dir, lib_name, ".a")) |full_path| {
|
||||
try libs.put(full_path, candidate_libs.get(lib_name).?);
|
||||
} else {
|
||||
log.warn("library not found for '-l{s}'", .{lib_name});
|
||||
lib_not_found = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
{
|
||||
const vals = options.system_libs.values();
|
||||
try libs.ensureUnusedCapacity(vals.len);
|
||||
for (vals) |v| libs.putAssumeCapacity(v.path.?, v);
|
||||
}
|
||||
|
||||
if (lib_not_found) {
|
||||
log.warn("Library search paths:", .{});
|
||||
for (lib_dirs.items) |dir| {
|
||||
log.warn(" {s}", .{dir});
|
||||
}
|
||||
}
|
||||
|
||||
try MachO.resolveLibSystem(arena, comp, options.sysroot, target, lib_dirs.items, &libs);
|
||||
try MachO.resolveLibSystem(arena, comp, options.sysroot, target, options.lib_dirs, &libs);
|
||||
|
||||
// frameworks
|
||||
var framework_dirs = std.ArrayList([]const u8).init(arena);
|
||||
|
|
@ -3647,6 +3577,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
|||
try libs.put(full_path, .{
|
||||
.needed = info.needed,
|
||||
.weak = info.weak,
|
||||
.path = full_path,
|
||||
});
|
||||
continue :outer;
|
||||
}
|
||||
|
|
@ -3698,11 +3629,6 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
|||
try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{pagezero_size}));
|
||||
}
|
||||
|
||||
if (options.search_strategy) |strat| switch (strat) {
|
||||
.paths_first => try argv.append("-search_paths_first"),
|
||||
.dylibs_first => try argv.append("-search_dylibs_first"),
|
||||
};
|
||||
|
||||
if (options.headerpad_size) |headerpad_size| {
|
||||
try argv.append("-headerpad_size");
|
||||
try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{headerpad_size}));
|
||||
|
|
|
|||
802
src/main.zig
802
src/main.zig
File diff suppressed because it is too large
Load diff
|
|
@ -283,7 +283,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
|||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const def_file_path = findDef(comp, arena, lib_name) catch |err| switch (err) {
|
||||
const def_file_path = findDef(arena, comp.getTarget(), comp.zig_lib_directory, lib_name) catch |err| switch (err) {
|
||||
error.FileNotFound => {
|
||||
log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name });
|
||||
// In this case we will end up putting foo.lib onto the linker line and letting the linker
|
||||
|
|
@ -431,10 +431,28 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
|||
});
|
||||
}
|
||||
|
||||
/// This function body is verbose but all it does is test 3 different paths and see if a .def file exists.
|
||||
fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8 {
|
||||
const target = comp.getTarget();
|
||||
pub fn libExists(
|
||||
allocator: Allocator,
|
||||
target: std.Target,
|
||||
zig_lib_directory: Cache.Directory,
|
||||
lib_name: []const u8,
|
||||
) !bool {
|
||||
const s = findDef(allocator, target, zig_lib_directory, lib_name) catch |err| switch (err) {
|
||||
error.FileNotFound => return false,
|
||||
else => |e| return e,
|
||||
};
|
||||
defer allocator.free(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// This function body is verbose but all it does is test 3 different paths and
|
||||
/// see if a .def file exists.
|
||||
fn findDef(
|
||||
allocator: Allocator,
|
||||
target: std.Target,
|
||||
zig_lib_directory: Cache.Directory,
|
||||
lib_name: []const u8,
|
||||
) ![]u8 {
|
||||
const lib_path = switch (target.cpu.arch) {
|
||||
.x86 => "lib32",
|
||||
.x86_64 => "lib64",
|
||||
|
|
@ -451,7 +469,7 @@ fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8
|
|||
{
|
||||
// Try the archtecture-specific path first.
|
||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def";
|
||||
if (comp.zig_lib_directory.path) |p| {
|
||||
if (zig_lib_directory.path) |p| {
|
||||
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name });
|
||||
} else {
|
||||
try override_path.writer().print(fmt_path, .{ lib_path, lib_name });
|
||||
|
|
@ -468,7 +486,7 @@ fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8
|
|||
// Try the generic version.
|
||||
override_path.shrinkRetainingCapacity(0);
|
||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def";
|
||||
if (comp.zig_lib_directory.path) |p| {
|
||||
if (zig_lib_directory.path) |p| {
|
||||
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
||||
} else {
|
||||
try override_path.writer().print(fmt_path, .{lib_name});
|
||||
|
|
@ -485,7 +503,7 @@ fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8
|
|||
// Try the generic version and preprocess it.
|
||||
override_path.shrinkRetainingCapacity(0);
|
||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in";
|
||||
if (comp.zig_lib_directory.path) |p| {
|
||||
if (zig_lib_directory.path) |p| {
|
||||
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
||||
} else {
|
||||
try override_path.writer().print(fmt_path, .{lib_name});
|
||||
|
|
|
|||
|
|
@ -366,6 +366,15 @@ pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool {
|
|||
if (eqlIgnoreCase(ignore_case, name, "m"))
|
||||
return true;
|
||||
|
||||
if (eqlIgnoreCase(ignore_case, name, "uuid"))
|
||||
return true;
|
||||
if (eqlIgnoreCase(ignore_case, name, "mingw32"))
|
||||
return true;
|
||||
if (eqlIgnoreCase(ignore_case, name, "msvcrt-os"))
|
||||
return true;
|
||||
if (eqlIgnoreCase(ignore_case, name, "mingwex"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub fn build(b: *std.Build) void {
|
|||
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
const target_info = std.zig.system.NativeTargetInfo.detect(target) catch unreachable;
|
||||
const sdk = std.zig.system.darwin.getDarwinSDK(b.allocator, target_info.target) orelse
|
||||
const sdk = std.zig.system.darwin.getSdk(b.allocator, target_info.target) orelse
|
||||
@panic("macOS SDK is required to run the test");
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
|
|||
|
||||
{
|
||||
// -search_dylibs_first
|
||||
const exe = createScenario(b, optimize, target, "search_dylibs_first");
|
||||
exe.search_strategy = .dylibs_first;
|
||||
const exe = createScenario(b, optimize, target, "search_dylibs_first", .mode_first);
|
||||
|
||||
const check = exe.checkObject();
|
||||
check.checkStart();
|
||||
|
|
@ -34,8 +33,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
|
|||
|
||||
{
|
||||
// -search_paths_first
|
||||
const exe = createScenario(b, optimize, target, "search_paths_first");
|
||||
exe.search_strategy = .paths_first;
|
||||
const exe = createScenario(b, optimize, target, "search_paths_first", .paths_first);
|
||||
|
||||
const run = b.addRunArtifact(exe);
|
||||
run.skip_foreign_checks = true;
|
||||
|
|
@ -49,6 +47,7 @@ fn createScenario(
|
|||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
name: []const u8,
|
||||
search_strategy: std.Build.Step.Compile.SystemLib.SearchStrategy,
|
||||
) *std.Build.Step.Compile {
|
||||
const static = b.addStaticLibrary(.{
|
||||
.name = name,
|
||||
|
|
@ -73,7 +72,10 @@ fn createScenario(
|
|||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} });
|
||||
exe.linkSystemLibraryName(name);
|
||||
exe.linkSystemLibrary2(name, .{
|
||||
.use_pkg_config = .no,
|
||||
.search_strategy = search_strategy,
|
||||
});
|
||||
exe.linkLibC();
|
||||
exe.addLibraryPath(static.getEmittedBinDirectory());
|
||||
exe.addLibraryPath(dylib.getEmittedBinDirectory());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue