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) {
|
if (!no_bin) {
|
||||||
const install_exe = b.addInstallArtifact(exe, .{});
|
const install_exe = b.addInstallArtifact(exe, .{
|
||||||
if (flat) {
|
.dest_dir = if (flat) .{ .override = .prefix } else .default,
|
||||||
install_exe.dest_dir = .prefix;
|
});
|
||||||
}
|
|
||||||
b.getInstallStep().dependOn(&install_exe.step);
|
b.getInstallStep().dependOn(&install_exe.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ stage3-debug/bin/zig build test docs \
|
||||||
|
|
||||||
# Look for HTML errors.
|
# Look for HTML errors.
|
||||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
# 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.
|
# Ensure that updating the wasm binary from this commit will result in a viable build.
|
||||||
stage3-debug/bin/zig build update-zig1
|
stage3-debug/bin/zig build update-zig1
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ stage3-release/bin/zig build test docs \
|
||||||
|
|
||||||
# Look for HTML errors.
|
# Look for HTML errors.
|
||||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
# 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.
|
# Ensure that updating the wasm binary from this commit will result in a viable build.
|
||||||
stage3-release/bin/zig build update-zig1
|
stage3-release/bin/zig build update-zig1
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ stage3-debug/bin/zig build test docs \
|
||||||
|
|
||||||
# Look for HTML errors.
|
# Look for HTML errors.
|
||||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
# 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.
|
# Ensure that updating the wasm binary from this commit will result in a viable build.
|
||||||
stage3-debug/bin/zig build update-zig1
|
stage3-debug/bin/zig build update-zig1
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ stage3-release/bin/zig build test docs \
|
||||||
|
|
||||||
# Look for HTML errors.
|
# Look for HTML errors.
|
||||||
# TODO: move this to a build.zig flag (-Denable-tidy)
|
# 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.
|
# Ensure that stage3 and stage4 are byte-for-byte identical.
|
||||||
stage3-release/bin/zig build \
|
stage3-release/bin/zig build \
|
||||||
|
|
|
||||||
|
|
@ -149,13 +149,6 @@ entitlements: ?[]const u8 = null,
|
||||||
/// (Darwin) Size of the pagezero segment.
|
/// (Darwin) Size of the pagezero segment.
|
||||||
pagezero_size: ?u64 = null,
|
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
|
/// (Darwin) Set size of the padding between the end of load commands
|
||||||
/// and start of `__TEXT,__text` section.
|
/// and start of `__TEXT,__text` section.
|
||||||
headerpad_size: ?u32 = null,
|
headerpad_size: ?u32 = null,
|
||||||
|
|
@ -242,7 +235,11 @@ pub const SystemLib = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
needed: bool,
|
needed: bool,
|
||||||
weak: 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.
|
/// Don't use pkg-config, just pass -lfoo where foo is name.
|
||||||
no,
|
no,
|
||||||
/// Try to get information on how to link the library from pkg-config.
|
/// 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.
|
/// Try to get information on how to link the library from pkg-config.
|
||||||
/// If that fails, error out.
|
/// If that fails, error out.
|
||||||
force,
|
force,
|
||||||
},
|
};
|
||||||
|
|
||||||
|
pub const SearchStrategy = enum { paths_first, mode_first, no_fallback };
|
||||||
};
|
};
|
||||||
|
|
||||||
const FrameworkLinkInfo = struct {
|
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");
|
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.
|
/// deprecated: use linkSystemLibrary2
|
||||||
/// Prefer to use `linkSystemLibrary` instead.
|
|
||||||
pub fn linkSystemLibraryName(self: *Compile, name: []const u8) void {
|
pub fn linkSystemLibraryName(self: *Compile, name: []const u8) void {
|
||||||
const b = self.step.owner;
|
return linkSystemLibrary2(self, name, .{ .use_pkg_config = .no });
|
||||||
self.link_objects.append(.{
|
|
||||||
.system_lib = .{
|
|
||||||
.name = b.dupe(name),
|
|
||||||
.needed = false,
|
|
||||||
.weak = false,
|
|
||||||
.use_pkg_config = .no,
|
|
||||||
},
|
|
||||||
}) catch @panic("OOM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This one has no integration with anything, it just puts -needed-lname on the command line.
|
/// deprecated: use linkSystemLibrary2
|
||||||
/// Prefer to use `linkSystemLibraryNeeded` instead.
|
|
||||||
pub fn linkSystemLibraryNeededName(self: *Compile, name: []const u8) void {
|
pub fn linkSystemLibraryNeededName(self: *Compile, name: []const u8) void {
|
||||||
const b = self.step.owner;
|
return linkSystemLibrary2(self, name, .{ .needed = true, .use_pkg_config = .no });
|
||||||
self.link_objects.append(.{
|
|
||||||
.system_lib = .{
|
|
||||||
.name = b.dupe(name),
|
|
||||||
.needed = true,
|
|
||||||
.weak = false,
|
|
||||||
.use_pkg_config = .no,
|
|
||||||
},
|
|
||||||
}) catch @panic("OOM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Darwin-only. This one has no integration with anything, it just puts -weak-lname on the
|
/// deprecated: use linkSystemLibrary2
|
||||||
/// command line. Prefer to use `linkSystemLibraryWeak` instead.
|
|
||||||
pub fn linkSystemLibraryWeakName(self: *Compile, name: []const u8) void {
|
pub fn linkSystemLibraryWeakName(self: *Compile, name: []const u8) void {
|
||||||
const b = self.step.owner;
|
return linkSystemLibrary2(self, name, .{ .weak = true, .use_pkg_config = .no });
|
||||||
self.link_objects.append(.{
|
|
||||||
.system_lib = .{
|
|
||||||
.name = b.dupe(name),
|
|
||||||
.needed = false,
|
|
||||||
.weak = true,
|
|
||||||
.use_pkg_config = .no,
|
|
||||||
},
|
|
||||||
}) catch @panic("OOM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This links against a system library, exclusively using pkg-config to find the library.
|
/// deprecated: use linkSystemLibrary2
|
||||||
/// Prefer to use `linkSystemLibrary` instead.
|
|
||||||
pub fn linkSystemLibraryPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
|
pub fn linkSystemLibraryPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
|
||||||
const b = self.step.owner;
|
return linkSystemLibrary2(self, lib_name, .{ .use_pkg_config = .force });
|
||||||
self.link_objects.append(.{
|
|
||||||
.system_lib = .{
|
|
||||||
.name = b.dupe(lib_name),
|
|
||||||
.needed = false,
|
|
||||||
.weak = false,
|
|
||||||
.use_pkg_config = .force,
|
|
||||||
},
|
|
||||||
}) catch @panic("OOM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This links against a system library, exclusively using pkg-config to find the library.
|
/// deprecated: use linkSystemLibrary2
|
||||||
/// Prefer to use `linkSystemLibraryNeeded` instead.
|
|
||||||
pub fn linkSystemLibraryNeededPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
|
pub fn linkSystemLibraryNeededPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
|
||||||
const b = self.step.owner;
|
return linkSystemLibrary2(self, lib_name, .{ .needed = true, .use_pkg_config = .force });
|
||||||
self.link_objects.append(.{
|
|
||||||
.system_lib = .{
|
|
||||||
.name = b.dupe(lib_name),
|
|
||||||
.needed = true,
|
|
||||||
.weak = false,
|
|
||||||
.use_pkg_config = .force,
|
|
||||||
},
|
|
||||||
}) catch @panic("OOM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run pkg-config for the given library name and parse the output, returning the arguments
|
/// 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 {
|
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 {
|
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 {
|
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,
|
needed: bool = false,
|
||||||
weak: 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;
|
const b = self.step.owner;
|
||||||
if (isLibCLibrary(name)) {
|
if (isLibCLibrary(name)) {
|
||||||
self.linkLibC();
|
self.linkLibC();
|
||||||
|
|
@ -913,9 +878,11 @@ fn linkSystemLibraryInner(self: *Compile, name: []const u8, opts: struct {
|
||||||
self.link_objects.append(.{
|
self.link_objects.append(.{
|
||||||
.system_lib = .{
|
.system_lib = .{
|
||||||
.name = b.dupe(name),
|
.name = b.dupe(name),
|
||||||
.needed = opts.needed,
|
.needed = options.needed,
|
||||||
.weak = opts.weak,
|
.weak = options.weak,
|
||||||
.use_pkg_config = .yes,
|
.use_pkg_config = options.use_pkg_config,
|
||||||
|
.preferred_link_mode = options.preferred_link_mode,
|
||||||
|
.search_strategy = options.search_strategy,
|
||||||
},
|
},
|
||||||
}) catch @panic("OOM");
|
}) 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);
|
try transitive_deps.add(self.link_objects.items);
|
||||||
|
|
||||||
var prev_has_cflags = false;
|
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| {
|
for (transitive_deps.link_objects.items) |link_object| {
|
||||||
switch (link_object) {
|
switch (link_object) {
|
||||||
|
|
@ -1420,6 +1389,28 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
||||||
},
|
},
|
||||||
|
|
||||||
.system_lib => |system_lib| {
|
.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: {
|
const prefix: []const u8 = prefix: {
|
||||||
if (system_lib.needed) break :prefix "-needed-l";
|
if (system_lib.needed) break :prefix "-needed-l";
|
||||||
if (system_lib.weak) break :prefix "-weak-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});
|
const size = try std.fmt.allocPrint(b.allocator, "{x}", .{pagezero_size});
|
||||||
try zig_args.appendSlice(&[_][]const u8{ "-pagezero_size", 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| {
|
if (self.headerpad_size) |headerpad_size| {
|
||||||
const size = try std.fmt.allocPrint(b.allocator, "{x}", .{headerpad_size});
|
const size = try std.fmt.allocPrint(b.allocator, "{x}", .{headerpad_size});
|
||||||
try zig_args.appendSlice(&[_][]const u8{ "-headerpad", size });
|
try zig_args.appendSlice(&[_][]const u8{ "-headerpad", size });
|
||||||
|
|
|
||||||
|
|
@ -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,16 @@ 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.isSdkInstalled(arena)) sdk: {
|
||||||
try self.addLibDir("/usr/lib");
|
const sdk = std.zig.system.darwin.getSdk(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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,8 +101,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 +157,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);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,34 @@ pub const macos = @import("darwin/macos.zig");
|
||||||
|
|
||||||
/// Check if SDK is installed on Darwin without triggering CLT installation popup window.
|
/// Check if SDK is installed on Darwin without triggering CLT installation popup window.
|
||||||
/// Note: simply invoking `xcrun` will inevitably trigger the CLT installation popup.
|
/// 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`
|
/// Therefore, we resort to invoking `xcode-select --print-path` and checking
|
||||||
/// and checking if the status is nonzero or the returned string in nonempty.
|
/// if the status is nonzero.
|
||||||
/// https://github.com/Homebrew/brew/blob/e119bdc571dcb000305411bc1e26678b132afb98/Library/Homebrew/brew.sh#L630
|
/// stderr from xcode-select is ignored.
|
||||||
pub fn isDarwinSDKInstalled(allocator: Allocator) bool {
|
/// If error.OutOfMemory occurs in Allocator, this function returns null.
|
||||||
const argv = &[_][]const u8{ "/usr/bin/xcode-select", "--print-path" };
|
pub fn isSdkInstalled(allocator: Allocator) bool {
|
||||||
const result = std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv }) catch return false;
|
const result = std.process.Child.exec(.{
|
||||||
|
.allocator = allocator,
|
||||||
|
.argv = &.{ "/usr/bin/xcode-select", "--print-path" },
|
||||||
|
}) catch return false;
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
allocator.free(result.stderr);
|
allocator.free(result.stderr);
|
||||||
allocator.free(result.stdout);
|
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 switch (result.term) {
|
||||||
return false;
|
.Exited => |code| if (code == 0) result.stdout.len > 0 else false,
|
||||||
}
|
else => false,
|
||||||
return result.stdout.len > 0;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Detect SDK on Darwin.
|
/// Detect SDK on Darwin.
|
||||||
/// Calls `xcrun --sdk <target_sdk> --show-sdk-path` which fetches the path to the SDK sysroot (if any).
|
/// 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.
|
/// Subsequently calls `xcrun --sdk <target_sdk> --show-sdk-version` which fetches version of the SDK.
|
||||||
/// The caller needs to deinit the resulting struct.
|
/// 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 is_simulator_abi = target.abi == .simulator;
|
||||||
const sdk = switch (target.os.tag) {
|
const sdk = switch (target.os.tag) {
|
||||||
.macos => "macosx",
|
.macos => "macosx",
|
||||||
|
|
@ -40,30 +46,28 @@ pub fn getDarwinSDK(allocator: Allocator, target: Target) ?DarwinSDK {
|
||||||
};
|
};
|
||||||
const path = path: {
|
const path = path: {
|
||||||
const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-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 {
|
defer {
|
||||||
allocator.free(result.stderr);
|
allocator.free(result.stderr);
|
||||||
allocator.free(result.stdout);
|
allocator.free(result.stdout);
|
||||||
}
|
}
|
||||||
if (result.stderr.len != 0 or result.term.Exited != 0) {
|
switch (result.term) {
|
||||||
// We don't actually care if there were errors as this is best-effort check anyhow
|
.Exited => |code| if (code != 0) return null,
|
||||||
// and in the worst case the user can specify the sysroot manually.
|
else => return null,
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
const path = allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n")) catch return null;
|
const path = allocator.dupe(u8, mem.trimRight(u8, result.stdout, "\r\n")) catch return null;
|
||||||
break :path path;
|
break :path path;
|
||||||
};
|
};
|
||||||
const version = version: {
|
const version = version: {
|
||||||
const argv = &[_][]const u8{ "/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-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 {
|
defer {
|
||||||
allocator.free(result.stderr);
|
allocator.free(result.stderr);
|
||||||
allocator.free(result.stdout);
|
allocator.free(result.stdout);
|
||||||
}
|
}
|
||||||
if (result.stderr.len != 0 or result.term.Exited != 0) {
|
switch (result.term) {
|
||||||
// We don't actually care if there were errors as this is best-effort check anyhow
|
.Exited => |code| if (code != 0) return null,
|
||||||
// and in the worst case the user can specify the sysroot manually.
|
else => return null,
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
const raw_version = mem.trimRight(u8, result.stdout, "\r\n");
|
const raw_version = mem.trimRight(u8, result.stdout, "\r\n");
|
||||||
const version = parseSdkVersion(raw_version) orelse Version{
|
const version = parseSdkVersion(raw_version) orelse Version{
|
||||||
|
|
@ -73,7 +77,7 @@ pub fn getDarwinSDK(allocator: Allocator, target: Target) ?DarwinSDK {
|
||||||
};
|
};
|
||||||
break :version version;
|
break :version version;
|
||||||
};
|
};
|
||||||
return DarwinSDK{
|
return Sdk{
|
||||||
.path = path,
|
.path = path,
|
||||||
.version = version,
|
.version = version,
|
||||||
};
|
};
|
||||||
|
|
@ -96,11 +100,11 @@ fn parseSdkVersion(raw: []const u8) ?Version {
|
||||||
return Version.parse(buffer[0..len]) catch null;
|
return Version.parse(buffer[0..len]) catch null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DarwinSDK = struct {
|
pub const Sdk = struct {
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
version: Version,
|
version: Version,
|
||||||
|
|
||||||
pub fn deinit(self: DarwinSDK, allocator: Allocator) void {
|
pub fn deinit(self: Sdk, allocator: Allocator) void {
|
||||||
allocator.free(self.path);
|
allocator.free(self.path);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,7 @@ zig_lib_directory: Directory,
|
||||||
local_cache_directory: Directory,
|
local_cache_directory: Directory,
|
||||||
global_cache_directory: Directory,
|
global_cache_directory: Directory,
|
||||||
libc_include_dir_list: []const []const u8,
|
libc_include_dir_list: []const []const u8,
|
||||||
|
libc_framework_dir_list: []const []const u8,
|
||||||
thread_pool: *ThreadPool,
|
thread_pool: *ThreadPool,
|
||||||
|
|
||||||
/// Populated when we build the libc++ static library. A Job to build this is placed in the queue
|
/// 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,
|
stdout,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Framework = link.Framework;
|
||||||
pub const SystemLib = link.SystemLib;
|
pub const SystemLib = link.SystemLib;
|
||||||
pub const CacheMode = link.CacheMode;
|
pub const CacheMode = link.CacheMode;
|
||||||
|
|
||||||
|
|
@ -505,7 +507,7 @@ pub const InitOptions = struct {
|
||||||
c_source_files: []const CSourceFile = &[0]CSourceFile{},
|
c_source_files: []const CSourceFile = &[0]CSourceFile{},
|
||||||
link_objects: []LinkObject = &[0]LinkObject{},
|
link_objects: []LinkObject = &[0]LinkObject{},
|
||||||
framework_dirs: []const []const u8 = &[0][]const u8{},
|
framework_dirs: []const []const u8 = &[0][]const u8{},
|
||||||
frameworks: std.StringArrayHashMapUnmanaged(SystemLib) = .{},
|
frameworks: std.StringArrayHashMapUnmanaged(Framework) = .{},
|
||||||
system_lib_names: []const []const u8 = &.{},
|
system_lib_names: []const []const u8 = &.{},
|
||||||
system_lib_infos: []const SystemLib = &.{},
|
system_lib_infos: []const SystemLib = &.{},
|
||||||
/// These correspond to the WASI libc emulated subcomponents including:
|
/// These correspond to the WASI libc emulated subcomponents including:
|
||||||
|
|
@ -636,16 +638,12 @@ pub const InitOptions = struct {
|
||||||
wasi_exec_model: ?std.builtin.WasiExecModel = null,
|
wasi_exec_model: ?std.builtin.WasiExecModel = null,
|
||||||
/// (Zig compiler development) Enable dumping linker's state as JSON.
|
/// (Zig compiler development) Enable dumping linker's state as JSON.
|
||||||
enable_link_snapshots: bool = false,
|
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
|
/// (Darwin) Install name of the dylib
|
||||||
install_name: ?[]const u8 = null,
|
install_name: ?[]const u8 = null,
|
||||||
/// (Darwin) Path to entitlements file
|
/// (Darwin) Path to entitlements file
|
||||||
entitlements: ?[]const u8 = null,
|
entitlements: ?[]const u8 = null,
|
||||||
/// (Darwin) size of the __PAGEZERO segment
|
/// (Darwin) size of the __PAGEZERO segment
|
||||||
pagezero_size: ?u64 = null,
|
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
|
/// (Darwin) set minimum space for future expansion of the load commands
|
||||||
headerpad_size: ?u32 = null,
|
headerpad_size: ?u32 = null,
|
||||||
/// (Darwin) set enough space as if all paths were MATPATHLEN
|
/// (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;
|
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: {
|
const lto = blk: {
|
||||||
if (options.want_lto) |explicit| {
|
if (options.want_lto) |explicit| {
|
||||||
if (!use_lld and !options.target.isDarwin())
|
if (!use_lld and !options.target.isDarwin())
|
||||||
|
|
@ -948,9 +936,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||||
options.is_native_abi,
|
options.is_native_abi,
|
||||||
link_libc,
|
link_libc,
|
||||||
options.libc_installation,
|
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 must_pie = target_util.requiresPIE(options.target);
|
||||||
const pie: bool = if (options.want_pie) |explicit| pie: {
|
const pie: bool = if (options.want_pie) |explicit| pie: {
|
||||||
if (!explicit and must_pie) {
|
if (!explicit and must_pie) {
|
||||||
|
|
@ -1563,11 +1552,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||||
.wasi_exec_model = wasi_exec_model,
|
.wasi_exec_model = wasi_exec_model,
|
||||||
.hash_style = options.hash_style,
|
.hash_style = options.hash_style,
|
||||||
.enable_link_snapshots = options.enable_link_snapshots,
|
.enable_link_snapshots = options.enable_link_snapshots,
|
||||||
.native_darwin_sdk = options.native_darwin_sdk,
|
|
||||||
.install_name = options.install_name,
|
.install_name = options.install_name,
|
||||||
.entitlements = options.entitlements,
|
.entitlements = options.entitlements,
|
||||||
.pagezero_size = options.pagezero_size,
|
.pagezero_size = options.pagezero_size,
|
||||||
.search_strategy = options.search_strategy,
|
|
||||||
.headerpad_size = options.headerpad_size,
|
.headerpad_size = options.headerpad_size,
|
||||||
.headerpad_max_install_names = options.headerpad_max_install_names,
|
.headerpad_max_install_names = options.headerpad_max_install_names,
|
||||||
.dead_strip_dylibs = options.dead_strip_dylibs,
|
.dead_strip_dylibs = options.dead_strip_dylibs,
|
||||||
|
|
@ -1601,6 +1588,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||||
.cache_parent = cache,
|
.cache_parent = cache,
|
||||||
.self_exe_path = options.self_exe_path,
|
.self_exe_path = options.self_exe_path,
|
||||||
.libc_include_dir_list = libc_dirs.libc_include_dir_list,
|
.libc_include_dir_list = libc_dirs.libc_include_dir_list,
|
||||||
|
.libc_framework_dir_list = libc_dirs.libc_framework_dir_list,
|
||||||
.sanitize_c = sanitize_c,
|
.sanitize_c = sanitize_c,
|
||||||
.thread_pool = options.thread_pool,
|
.thread_pool = options.thread_pool,
|
||||||
.clang_passthrough_mode = options.clang_passthrough_mode,
|
.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.
|
// When linking mingw-w64 there are some import libs we always need.
|
||||||
for (mingw.always_link_libs) |name| {
|
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.
|
// Generate Windows import libs.
|
||||||
if (target.os.tag == .windows) {
|
if (target.os.tag == .windows) {
|
||||||
const count = comp.bin_file.options.system_libs.count();
|
const count = comp.bin_file.options.system_libs.count();
|
||||||
try comp.work_queue.ensureUnusedCapacity(count);
|
try comp.work_queue.ensureUnusedCapacity(count);
|
||||||
var i: usize = 0;
|
for (0..count) |i| {
|
||||||
while (i < count) : (i += 1) {
|
|
||||||
comp.work_queue.writeItemAssumeCapacity(.{ .windows_import_lib = 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) {
|
if (comp.bin_file.options.link_libc) {
|
||||||
man.hash.add(comp.bin_file.options.libc_installation != null);
|
man.hash.add(comp.bin_file.options.libc_installation != null);
|
||||||
if (comp.bin_file.options.libc_installation) |libc_installation| {
|
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) {
|
if (target.abi == .msvc) {
|
||||||
man.hash.addBytes(libc_installation.msvc_lib_dir.?);
|
man.hash.addOptionalBytes(libc_installation.msvc_lib_dir);
|
||||||
man.hash.addBytes(libc_installation.kernel32_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.dynamic_linker);
|
||||||
}
|
}
|
||||||
man.hash.addOptionalBytes(comp.bin_file.options.soname);
|
man.hash.addOptionalBytes(comp.bin_file.options.soname);
|
||||||
man.hash.addOptional(comp.bin_file.options.version);
|
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.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys());
|
||||||
man.hash.addOptional(comp.bin_file.options.allow_shlib_undefined);
|
man.hash.addOptional(comp.bin_file.options.allow_shlib_undefined);
|
||||||
man.hash.add(comp.bin_file.options.bind_global_refs_locally);
|
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
|
// Mach-O specific stuff
|
||||||
man.hash.addListOfBytes(comp.bin_file.options.framework_dirs);
|
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);
|
try man.addOptionalFile(comp.bin_file.options.entitlements);
|
||||||
man.hash.addOptional(comp.bin_file.options.pagezero_size);
|
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.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.headerpad_max_install_names);
|
||||||
man.hash.add(comp.bin_file.options.dead_strip_dylibs);
|
man.hash.add(comp.bin_file.options.dead_strip_dylibs);
|
||||||
|
|
@ -4341,6 +4331,14 @@ pub fn addCCArgs(
|
||||||
try argv.append("-ObjC++");
|
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.
|
// 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.
|
||||||
|
|
@ -4823,6 +4821,8 @@ test "classifyFileExt" {
|
||||||
const LibCDirs = struct {
|
const LibCDirs = struct {
|
||||||
libc_include_dir_list: []const []const u8,
|
libc_include_dir_list: []const []const u8,
|
||||||
libc_installation: ?*const LibCInstallation,
|
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 {
|
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{
|
return LibCDirs{
|
||||||
.libc_include_dir_list = list,
|
.libc_include_dir_list = list,
|
||||||
.libc_installation = null,
|
.libc_installation = null,
|
||||||
|
.libc_framework_dir_list = &.{},
|
||||||
|
.sysroot = null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4863,12 +4865,13 @@ fn detectLibCIncludeDirs(
|
||||||
is_native_abi: bool,
|
is_native_abi: bool,
|
||||||
link_libc: bool,
|
link_libc: bool,
|
||||||
libc_installation: ?*const LibCInstallation,
|
libc_installation: ?*const LibCInstallation,
|
||||||
has_macos_sdk: bool,
|
|
||||||
) !LibCDirs {
|
) !LibCDirs {
|
||||||
if (!link_libc) {
|
if (!link_libc) {
|
||||||
return LibCDirs{
|
return LibCDirs{
|
||||||
.libc_include_dir_list = &[0][]u8{},
|
.libc_include_dir_list = &[0][]u8{},
|
||||||
.libc_installation = null,
|
.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
|
// If linking system libraries and targeting the native abi, default to
|
||||||
// using the system libc installation.
|
// using the system libc installation.
|
||||||
if (is_native_abi and !target.isMinGW()) {
|
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);
|
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.CCompilerExitCode,
|
||||||
error.CCompilerCrashed,
|
error.CCompilerCrashed,
|
||||||
error.CCompilerCannotFindHeaders,
|
error.CCompilerCannotFindHeaders,
|
||||||
error.UnableToSpawnCCompiler,
|
error.UnableToSpawnCCompiler,
|
||||||
|
error.DarwinSdkNotFound,
|
||||||
=> |e| {
|
=> |e| {
|
||||||
// We tried to integrate with the native system C compiler,
|
// We tried to integrate with the native system C compiler,
|
||||||
// however, it is not installed. So we must rely on our bundled
|
// however, it is not installed. So we must rely on our bundled
|
||||||
// libc files.
|
// libc files.
|
||||||
if (target_util.canBuildLibC(target)) {
|
if (target_util.canBuildLibC(target)) {
|
||||||
return detectLibCFromBuilding(arena, zig_lib_dir, target, has_macos_sdk);
|
return detectLibCFromBuilding(arena, zig_lib_dir, target);
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
},
|
},
|
||||||
|
|
@ -4912,7 +4906,7 @@ fn detectLibCIncludeDirs(
|
||||||
// If not linking system libraries, build and provide our own libc by
|
// If not linking system libraries, build and provide our own libc by
|
||||||
// default if possible.
|
// default if possible.
|
||||||
if (target_util.canBuildLibC(target)) {
|
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
|
// 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) {
|
if (use_system_abi) {
|
||||||
const libc = try arena.create(LibCInstallation);
|
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 detectLibCFromLibCInstallation(arena, target, libc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LibCDirs{
|
return LibCDirs{
|
||||||
.libc_include_dir_list = &[0][]u8{},
|
.libc_include_dir_list = &[0][]u8{},
|
||||||
.libc_installation = null,
|
.libc_installation = null,
|
||||||
|
.libc_framework_dir_list = &.{},
|
||||||
|
.sysroot = null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const LibCInstallation) !LibCDirs {
|
fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const LibCInstallation) !LibCDirs {
|
||||||
var list = try std.ArrayList([]const u8).initCapacity(arena, 5);
|
var list = try std.ArrayList([]const u8).initCapacity(arena, 5);
|
||||||
|
var framework_list = std.ArrayList([]const u8).init(arena);
|
||||||
|
|
||||||
list.appendAssumeCapacity(lci.include_dir.?);
|
list.appendAssumeCapacity(lci.include_dir.?);
|
||||||
|
|
||||||
|
|
@ -4965,9 +4962,20 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const
|
||||||
list.appendAssumeCapacity(config_dir);
|
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{
|
return LibCDirs{
|
||||||
.libc_include_dir_list = list.items,
|
.libc_include_dir_list = list.items,
|
||||||
.libc_installation = lci,
|
.libc_installation = lci,
|
||||||
|
.libc_framework_dir_list = framework_list.items,
|
||||||
|
.sysroot = sysroot,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4975,69 +4983,61 @@ fn detectLibCFromBuilding(
|
||||||
arena: Allocator,
|
arena: Allocator,
|
||||||
zig_lib_dir: []const u8,
|
zig_lib_dir: []const u8,
|
||||||
target: std.Target,
|
target: std.Target,
|
||||||
has_macos_sdk: bool,
|
|
||||||
) !LibCDirs {
|
) !LibCDirs {
|
||||||
switch (target.os.tag) {
|
if (target.isDarwin())
|
||||||
.macos => return if (has_macos_sdk)
|
return getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target);
|
||||||
// For Darwin/macOS, we are all set with getDarwinSDK found earlier.
|
|
||||||
LibCDirs{
|
|
||||||
.libc_include_dir_list = &[0][]u8{},
|
|
||||||
.libc_installation = null,
|
|
||||||
}
|
|
||||||
else
|
|
||||||
getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target),
|
|
||||||
else => {
|
|
||||||
const generic_name = target_util.libCGenericName(target);
|
|
||||||
// Some architectures are handled by the same set of headers.
|
|
||||||
const arch_name = if (target.abi.isMusl())
|
|
||||||
musl.archNameHeaders(target.cpu.arch)
|
|
||||||
else if (target.cpu.arch.isThumb())
|
|
||||||
// ARM headers are valid for Thumb too.
|
|
||||||
switch (target.cpu.arch) {
|
|
||||||
.thumb => "arm",
|
|
||||||
.thumbeb => "armeb",
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
else
|
|
||||||
@tagName(target.cpu.arch);
|
|
||||||
const os_name = @tagName(target.os.tag);
|
|
||||||
// Musl's headers are ABI-agnostic and so they all have the "musl" ABI name.
|
|
||||||
const abi_name = if (target.abi.isMusl()) "musl" else @tagName(target.abi);
|
|
||||||
const s = std.fs.path.sep_str;
|
|
||||||
const arch_include_dir = try std.fmt.allocPrint(
|
|
||||||
arena,
|
|
||||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}",
|
|
||||||
.{ zig_lib_dir, arch_name, os_name, abi_name },
|
|
||||||
);
|
|
||||||
const generic_include_dir = try std.fmt.allocPrint(
|
|
||||||
arena,
|
|
||||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}",
|
|
||||||
.{ zig_lib_dir, generic_name },
|
|
||||||
);
|
|
||||||
const generic_arch_name = target_util.osArchName(target);
|
|
||||||
const arch_os_include_dir = try std.fmt.allocPrint(
|
|
||||||
arena,
|
|
||||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any",
|
|
||||||
.{ zig_lib_dir, generic_arch_name, os_name },
|
|
||||||
);
|
|
||||||
const generic_os_include_dir = try std.fmt.allocPrint(
|
|
||||||
arena,
|
|
||||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
|
|
||||||
.{ zig_lib_dir, os_name },
|
|
||||||
);
|
|
||||||
|
|
||||||
const list = try arena.alloc([]const u8, 4);
|
const generic_name = target_util.libCGenericName(target);
|
||||||
list[0] = arch_include_dir;
|
// Some architectures are handled by the same set of headers.
|
||||||
list[1] = generic_include_dir;
|
const arch_name = if (target.abi.isMusl())
|
||||||
list[2] = arch_os_include_dir;
|
musl.archNameHeaders(target.cpu.arch)
|
||||||
list[3] = generic_os_include_dir;
|
else if (target.cpu.arch.isThumb())
|
||||||
|
// ARM headers are valid for Thumb too.
|
||||||
|
switch (target.cpu.arch) {
|
||||||
|
.thumb => "arm",
|
||||||
|
.thumbeb => "armeb",
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
@tagName(target.cpu.arch);
|
||||||
|
const os_name = @tagName(target.os.tag);
|
||||||
|
// Musl's headers are ABI-agnostic and so they all have the "musl" ABI name.
|
||||||
|
const abi_name = if (target.abi.isMusl()) "musl" else @tagName(target.abi);
|
||||||
|
const s = std.fs.path.sep_str;
|
||||||
|
const arch_include_dir = try std.fmt.allocPrint(
|
||||||
|
arena,
|
||||||
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}",
|
||||||
|
.{ zig_lib_dir, arch_name, os_name, abi_name },
|
||||||
|
);
|
||||||
|
const generic_include_dir = try std.fmt.allocPrint(
|
||||||
|
arena,
|
||||||
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}",
|
||||||
|
.{ zig_lib_dir, generic_name },
|
||||||
|
);
|
||||||
|
const generic_arch_name = target_util.osArchName(target);
|
||||||
|
const arch_os_include_dir = try std.fmt.allocPrint(
|
||||||
|
arena,
|
||||||
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any",
|
||||||
|
.{ zig_lib_dir, generic_arch_name, os_name },
|
||||||
|
);
|
||||||
|
const generic_os_include_dir = try std.fmt.allocPrint(
|
||||||
|
arena,
|
||||||
|
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
|
||||||
|
.{ zig_lib_dir, os_name },
|
||||||
|
);
|
||||||
|
|
||||||
return LibCDirs{
|
const list = try arena.alloc([]const u8, 4);
|
||||||
.libc_include_dir_list = list,
|
list[0] = arch_include_dir;
|
||||||
.libc_installation = null,
|
list[1] = generic_include_dir;
|
||||||
};
|
list[2] = arch_os_include_dir;
|
||||||
},
|
list[3] = generic_os_include_dir;
|
||||||
}
|
|
||||||
|
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 {
|
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.
|
// 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);
|
const gop = try comp.bin_file.options.system_libs.getOrPut(comp.gpa, lib_name);
|
||||||
if (!gop.found_existing and comp.getTarget().os.tag == .windows) {
|
if (!gop.found_existing and comp.getTarget().os.tag == .windows) {
|
||||||
|
gop.value_ptr.* = .{
|
||||||
|
.needed = true,
|
||||||
|
.weak = false,
|
||||||
|
.path = null,
|
||||||
|
};
|
||||||
try comp.work_queue.writeItem(.{
|
try comp.work_queue.writeItem(.{
|
||||||
.windows_import_lib = comp.bin_file.options.system_libs.count() - 1,
|
.windows_import_lib = comp.bin_file.options.system_libs.count() - 1,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ pub const LibCInstallation = struct {
|
||||||
LibCKernel32LibNotFound,
|
LibCKernel32LibNotFound,
|
||||||
UnsupportedArchitecture,
|
UnsupportedArchitecture,
|
||||||
WindowsSdkNotFound,
|
WindowsSdkNotFound,
|
||||||
|
DarwinSdkNotFound,
|
||||||
ZigIsTheCCompiler,
|
ZigIsTheCCompiler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -171,6 +172,7 @@ pub const LibCInstallation = struct {
|
||||||
|
|
||||||
pub const FindNativeOptions = struct {
|
pub const FindNativeOptions = struct {
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
|
target: std.Target,
|
||||||
|
|
||||||
/// If enabled, will print human-friendly errors to stderr.
|
/// If enabled, will print human-friendly errors to stderr.
|
||||||
verbose: bool = false,
|
verbose: bool = false,
|
||||||
|
|
@ -181,7 +183,19 @@ pub const LibCInstallation = struct {
|
||||||
var self: LibCInstallation = .{};
|
var self: LibCInstallation = .{};
|
||||||
|
|
||||||
if (is_darwin) {
|
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) {
|
} else if (is_windows) {
|
||||||
var sdk: ZigWindowsSDK = ZigWindowsSDK.find(args.allocator) catch |err| switch (err) {
|
var sdk: ZigWindowsSDK = ZigWindowsSDK.find(args.allocator) catch |err| switch (err) {
|
||||||
error.NotFound => return error.WindowsSdkNotFound,
|
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");
|
const TypedValue = @import("TypedValue.zig");
|
||||||
|
|
||||||
/// When adding a new field, remember to update `hashAddSystemLibs`.
|
/// 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 {
|
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,
|
needed: bool = false,
|
||||||
weak: bool = false,
|
weak: bool = false,
|
||||||
};
|
};
|
||||||
|
|
@ -31,11 +44,23 @@ pub const SortSection = enum { name, alignment };
|
||||||
pub const CacheMode = enum { incremental, whole };
|
pub const CacheMode = enum { incremental, whole };
|
||||||
|
|
||||||
pub fn hashAddSystemLibs(
|
pub fn hashAddSystemLibs(
|
||||||
hh: *Cache.HashHelper,
|
man: *Cache.Manifest,
|
||||||
hm: std.StringArrayHashMapUnmanaged(SystemLib),
|
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 {
|
) void {
|
||||||
const keys = hm.keys();
|
const keys = hm.keys();
|
||||||
hh.add(keys.len);
|
|
||||||
hh.addListOfBytes(keys);
|
hh.addListOfBytes(keys);
|
||||||
for (hm.values()) |value| {
|
for (hm.values()) |value| {
|
||||||
hh.add(value.needed);
|
hh.add(value.needed);
|
||||||
|
|
@ -183,9 +208,12 @@ pub const Options = struct {
|
||||||
|
|
||||||
objects: []Compilation.LinkObject,
|
objects: []Compilation.LinkObject,
|
||||||
framework_dirs: []const []const u8,
|
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),
|
system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
|
||||||
wasi_emulated_libs: []const wasi_libc.CRTFile,
|
wasi_emulated_libs: []const wasi_libc.CRTFile,
|
||||||
|
// TODO: remove this. libraries are resolved by the frontend.
|
||||||
lib_dirs: []const []const u8,
|
lib_dirs: []const []const u8,
|
||||||
rpath_list: []const []const u8,
|
rpath_list: []const []const u8,
|
||||||
|
|
||||||
|
|
@ -203,6 +231,7 @@ pub const Options = struct {
|
||||||
|
|
||||||
version: ?std.SemanticVersion,
|
version: ?std.SemanticVersion,
|
||||||
compatibility_version: ?std.SemanticVersion,
|
compatibility_version: ?std.SemanticVersion,
|
||||||
|
darwin_sdk_version: ?std.SemanticVersion = null,
|
||||||
libc_installation: ?*const LibCInstallation,
|
libc_installation: ?*const LibCInstallation,
|
||||||
|
|
||||||
dwarf_format: ?std.dwarf.Format,
|
dwarf_format: ?std.dwarf.Format,
|
||||||
|
|
@ -213,9 +242,6 @@ pub const Options = struct {
|
||||||
/// (Zig compiler development) Enable dumping of linker's state as JSON.
|
/// (Zig compiler development) Enable dumping of linker's state as JSON.
|
||||||
enable_link_snapshots: bool = false,
|
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
|
/// (Darwin) Install name for the dylib
|
||||||
install_name: ?[]const u8 = null,
|
install_name: ?[]const u8 = null,
|
||||||
|
|
||||||
|
|
@ -225,9 +251,6 @@ pub const Options = struct {
|
||||||
/// (Darwin) size of the __PAGEZERO segment
|
/// (Darwin) size of the __PAGEZERO segment
|
||||||
pagezero_size: ?u64 = null,
|
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
|
/// (Darwin) set minimum space for future expansion of the load commands
|
||||||
headerpad_size: ?u32 = null,
|
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.addListOfBytes(self.base.options.force_undefined_symbols.keys());
|
||||||
man.hash.addOptional(self.base.options.subsystem);
|
man.hash.addOptional(self.base.options.subsystem);
|
||||||
man.hash.add(self.base.options.is_test);
|
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, "mingw32.lib"));
|
||||||
try argv.append(try comp.get_libc_crt_file(arena, "mingwex.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, "msvcrt-os.lib"));
|
||||||
|
try argv.append(try comp.get_libc_crt_file(arena, "uuid.lib"));
|
||||||
|
|
||||||
for (mingw.always_link_libs) |name| {
|
for (mingw.always_link_libs) |name| {
|
||||||
if (!self.base.options.system_libs.contains(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.addOptionalBytes(self.base.options.soname);
|
||||||
man.hash.addOptional(self.base.options.version);
|
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.addListOfBytes(self.base.options.force_undefined_symbols.keys());
|
||||||
man.hash.add(allow_shlib_undefined);
|
man.hash.add(allow_shlib_undefined);
|
||||||
man.hash.add(self.base.options.bind_global_refs_locally);
|
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");
|
argv.appendAssumeCapacity("--as-needed");
|
||||||
var as_needed = true;
|
var as_needed = true;
|
||||||
|
|
||||||
for (system_libs, 0..) |link_lib, i| {
|
for (system_libs_values) |lib_info| {
|
||||||
const lib_as_needed = !system_libs_values[i].needed;
|
const lib_as_needed = !lib_info.needed;
|
||||||
switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
|
switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) {
|
||||||
0b00, 0b11 => {},
|
0b00, 0b11 => {},
|
||||||
0b01 => {
|
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),
|
// 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
|
// but they could be full paths to .so files, in which case we
|
||||||
// want to avoid prepending "-l".
|
// want to avoid prepending "-l".
|
||||||
const ext = Compilation.classifyFileExt(link_lib);
|
argv.appendAssumeCapacity(lib_info.path.?);
|
||||||
const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{s}", .{link_lib});
|
|
||||||
argv.appendAssumeCapacity(arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!as_needed) {
|
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 base_tag: File.Tag = File.Tag.macho;
|
||||||
|
|
||||||
pub const SearchStrategy = enum {
|
|
||||||
paths_first,
|
|
||||||
dylibs_first,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Mode of operation of the linker.
|
/// Mode of operation of the linker.
|
||||||
pub const Mode = enum {
|
pub const Mode = enum {
|
||||||
/// Incremental mode will preallocate segments/sections and is compatible with
|
/// Incremental mode will preallocate segments/sections and is compatible with
|
||||||
|
|
@ -834,39 +829,50 @@ pub fn resolveLibSystem(
|
||||||
out_libs: anytype,
|
out_libs: anytype,
|
||||||
) !void {
|
) !void {
|
||||||
// If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
|
// If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
|
||||||
var libsystem_available = false;
|
if (syslibroot) |root| {
|
||||||
if (syslibroot != null) blk: {
|
const full_dir_path = try std.fs.path.join(arena, &.{ root, "usr", "lib" });
|
||||||
// Try stub file first. If we hit it, then we're done as the stub file
|
if (try resolveLibSystemInDirs(arena, &.{full_dir_path}, out_libs)) return;
|
||||||
// re-exports every single symbol definition.
|
}
|
||||||
for (search_dirs) |dir| {
|
|
||||||
if (try resolveLib(arena, dir, "System", ".tbd")) |full_path| {
|
// Next, try input search dirs if we are linking on a custom host such as Nix.
|
||||||
try out_libs.put(full_path, .{ .needed = true });
|
if (try resolveLibSystemInDirs(arena, search_dirs, out_libs)) return;
|
||||||
libsystem_available = true;
|
|
||||||
break :blk;
|
// 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,
|
||||||
|
.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.
|
// If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
|
||||||
for (search_dirs) |dir| {
|
// doesn't export libc.dylib which we'll need to resolve subsequently also.
|
||||||
if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| {
|
for (dirs) |dir| {
|
||||||
if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| {
|
if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| {
|
||||||
try out_libs.put(libsystem_path, .{ .needed = true });
|
if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| {
|
||||||
try out_libs.put(libc_path, .{ .needed = true });
|
try out_libs.put(libsystem_path, .{ .needed = true, .weak = false, .path = libsystem_path });
|
||||||
libsystem_available = true;
|
try out_libs.put(libc_path, .{ .needed = true, .weak = false, .path = libc_path });
|
||||||
break :blk;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!libsystem_available) {
|
|
||||||
const libsystem_name = try std.fmt.allocPrint(arena, "libSystem.{d}.tbd", .{
|
return false;
|
||||||
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 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolveSearchDir(
|
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));
|
const platform_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8));
|
||||||
break :blk platform_version;
|
break :blk platform_version;
|
||||||
};
|
};
|
||||||
const sdk_version = if (options.native_darwin_sdk) |sdk| blk: {
|
const sdk_version: u32 = if (options.darwin_sdk_version) |ver|
|
||||||
const ver = sdk.version;
|
@intCast(ver.major << 16 | ver.minor << 8)
|
||||||
const sdk_version = @as(u32, @intCast(ver.major << 16 | ver.minor << 8));
|
else
|
||||||
break :blk sdk_version;
|
platform_version;
|
||||||
} else platform_version;
|
|
||||||
const is_simulator_abi = options.target.abi == .simulator;
|
const is_simulator_abi = options.target.abi == .simulator;
|
||||||
try lc_writer.writeStruct(macho.build_version_command{
|
try lc_writer.writeStruct(macho.build_version_command{
|
||||||
.cmdsize = cmdsize,
|
.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.
|
// installation sources because they are always a product of the compiler version + target information.
|
||||||
man.hash.add(stack_size);
|
man.hash.add(stack_size);
|
||||||
man.hash.addOptional(options.pagezero_size);
|
man.hash.addOptional(options.pagezero_size);
|
||||||
man.hash.addOptional(options.search_strategy);
|
|
||||||
man.hash.addOptional(options.headerpad_size);
|
man.hash.addOptional(options.headerpad_size);
|
||||||
man.hash.add(options.headerpad_max_install_names);
|
man.hash.add(options.headerpad_max_install_names);
|
||||||
man.hash.add(gc_sections);
|
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.add(options.strip);
|
||||||
man.hash.addListOfBytes(options.lib_dirs);
|
man.hash.addListOfBytes(options.lib_dirs);
|
||||||
man.hash.addListOfBytes(options.framework_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);
|
man.hash.addListOfBytes(options.rpath_list);
|
||||||
if (is_dyn_lib) {
|
if (is_dyn_lib) {
|
||||||
man.hash.addOptionalBytes(options.install_name);
|
man.hash.addOptionalBytes(options.install_name);
|
||||||
man.hash.addOptional(options.version);
|
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.addOptionalBytes(options.sysroot);
|
||||||
man.hash.addListOfBytes(options.force_undefined_symbols.keys());
|
man.hash.addListOfBytes(options.force_undefined_symbols.keys());
|
||||||
try man.addOptionalFile(options.entitlements);
|
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);
|
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);
|
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;
|
const vals = options.system_libs.values();
|
||||||
outer: for (candidate_libs.keys()) |lib_name| {
|
try libs.ensureUnusedCapacity(vals.len);
|
||||||
switch (search_strategy) {
|
for (vals) |v| libs.putAssumeCapacity(v.path.?, v);
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lib_not_found) {
|
try MachO.resolveLibSystem(arena, comp, options.sysroot, target, options.lib_dirs, &libs);
|
||||||
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);
|
|
||||||
|
|
||||||
// frameworks
|
// frameworks
|
||||||
var framework_dirs = std.ArrayList([]const u8).init(arena);
|
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, .{
|
try libs.put(full_path, .{
|
||||||
.needed = info.needed,
|
.needed = info.needed,
|
||||||
.weak = info.weak,
|
.weak = info.weak,
|
||||||
|
.path = full_path,
|
||||||
});
|
});
|
||||||
continue :outer;
|
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}));
|
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| {
|
if (options.headerpad_size) |headerpad_size| {
|
||||||
try argv.append("-headerpad_size");
|
try argv.append("-headerpad_size");
|
||||||
try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{headerpad_size}));
|
try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{headerpad_size}));
|
||||||
|
|
|
||||||
810
src/main.zig
810
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();
|
defer arena_allocator.deinit();
|
||||||
const arena = arena_allocator.allocator();
|
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 => {
|
error.FileNotFound => {
|
||||||
log.debug("no {s}.def file available to make a DLL import {s}.lib", .{ lib_name, lib_name });
|
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
|
// 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.
|
pub fn libExists(
|
||||||
fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8 {
|
allocator: Allocator,
|
||||||
const target = comp.getTarget();
|
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) {
|
const lib_path = switch (target.cpu.arch) {
|
||||||
.x86 => "lib32",
|
.x86 => "lib32",
|
||||||
.x86_64 => "lib64",
|
.x86_64 => "lib64",
|
||||||
|
|
@ -451,7 +469,7 @@ fn findDef(comp: *Compilation, allocator: Allocator, lib_name: []const u8) ![]u8
|
||||||
{
|
{
|
||||||
// Try the archtecture-specific path first.
|
// Try the archtecture-specific path first.
|
||||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def";
|
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 });
|
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name });
|
||||||
} else {
|
} else {
|
||||||
try override_path.writer().print(fmt_path, .{ lib_path, lib_name });
|
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.
|
// Try the generic version.
|
||||||
override_path.shrinkRetainingCapacity(0);
|
override_path.shrinkRetainingCapacity(0);
|
||||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def";
|
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 });
|
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
||||||
} else {
|
} else {
|
||||||
try override_path.writer().print(fmt_path, .{lib_name});
|
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.
|
// Try the generic version and preprocess it.
|
||||||
override_path.shrinkRetainingCapacity(0);
|
override_path.shrinkRetainingCapacity(0);
|
||||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in";
|
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 });
|
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
||||||
} else {
|
} else {
|
||||||
try override_path.writer().print(fmt_path, .{lib_name});
|
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"))
|
if (eqlIgnoreCase(ignore_case, name, "m"))
|
||||||
return true;
|
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;
|
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 {
|
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: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||||
const target_info = std.zig.system.NativeTargetInfo.detect(target) catch unreachable;
|
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");
|
@panic("macOS SDK is required to run the test");
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
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
|
// -search_dylibs_first
|
||||||
const exe = createScenario(b, optimize, target, "search_dylibs_first");
|
const exe = createScenario(b, optimize, target, "search_dylibs_first", .mode_first);
|
||||||
exe.search_strategy = .dylibs_first;
|
|
||||||
|
|
||||||
const check = exe.checkObject();
|
const check = exe.checkObject();
|
||||||
check.checkStart();
|
check.checkStart();
|
||||||
|
|
@ -34,8 +33,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
|
||||||
|
|
||||||
{
|
{
|
||||||
// -search_paths_first
|
// -search_paths_first
|
||||||
const exe = createScenario(b, optimize, target, "search_paths_first");
|
const exe = createScenario(b, optimize, target, "search_paths_first", .paths_first);
|
||||||
exe.search_strategy = .paths_first;
|
|
||||||
|
|
||||||
const run = b.addRunArtifact(exe);
|
const run = b.addRunArtifact(exe);
|
||||||
run.skip_foreign_checks = true;
|
run.skip_foreign_checks = true;
|
||||||
|
|
@ -49,6 +47,7 @@ fn createScenario(
|
||||||
optimize: std.builtin.OptimizeMode,
|
optimize: std.builtin.OptimizeMode,
|
||||||
target: std.zig.CrossTarget,
|
target: std.zig.CrossTarget,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
|
search_strategy: std.Build.Step.Compile.SystemLib.SearchStrategy,
|
||||||
) *std.Build.Step.Compile {
|
) *std.Build.Step.Compile {
|
||||||
const static = b.addStaticLibrary(.{
|
const static = b.addStaticLibrary(.{
|
||||||
.name = name,
|
.name = name,
|
||||||
|
|
@ -73,7 +72,10 @@ fn createScenario(
|
||||||
.target = target,
|
.target = target,
|
||||||
});
|
});
|
||||||
exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} });
|
exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} });
|
||||||
exe.linkSystemLibraryName(name);
|
exe.linkSystemLibrary2(name, .{
|
||||||
|
.use_pkg_config = .no,
|
||||||
|
.search_strategy = search_strategy,
|
||||||
|
});
|
||||||
exe.linkLibC();
|
exe.linkLibC();
|
||||||
exe.addLibraryPath(static.getEmittedBinDirectory());
|
exe.addLibraryPath(static.getEmittedBinDirectory());
|
||||||
exe.addLibraryPath(dylib.getEmittedBinDirectory());
|
exe.addLibraryPath(dylib.getEmittedBinDirectory());
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue