Commit a1e21ceec8
Changed files (3)
src/Compilation.zig
@@ -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 = undefined,
+ };
try comp.work_queue.writeItem(.{
.windows_import_lib = comp.bin_file.options.system_libs.count() - 1,
});
src/main.zig
@@ -28,6 +28,7 @@ const target_util = @import("target.zig");
const crash_report = @import("crash_report.zig");
const Module = @import("Module.zig");
const AstGen = @import("AstGen.zig");
+const mingw = @import("mingw.zig");
const Server = std.zig.Server;
pub const std_options = struct {
@@ -477,6 +478,8 @@ const usage_build_generic =
\\ -needed-l[lib], Link against system library (even if unused)
\\ --needed-library [lib]
\\ -L[d], --library-directory [d] Add a directory to the library search path
+ \\ -search_paths_first Search each library search path for dynamic libs then static libs
+ \\ -search_dylibs_first Search for dynamic libs in each library search path, then static libs.
\\ -T[script], --script [script] Use a custom linker script
\\ --version-script [path] Provide a version .map file
\\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
@@ -537,8 +540,6 @@ const usage_build_generic =
\\ -install_name=[value] (Darwin) add dylib's install name
\\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature
\\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation
- \\ -search_paths_first (Darwin) search each dir in library search paths for `libx.dylib` then `libx.a`
- \\ -search_dylibs_first (Darwin) search `libx.dylib` in each dir in library search paths, then `libx.a`
\\ -headerpad [value] (Darwin) set minimum space for future expansion of the load commands in hexadecimal notation
\\ -headerpad_max_install_names (Darwin) set enough space as if all paths were MAXPATHLEN
\\ -dead_strip (Darwin) remove functions and data that are unreachable by the entry point or exported symbols
@@ -2567,6 +2568,34 @@ fn buildOutputType(
}
lib_dir_args = undefined; // From here we use lib_dirs instead.
+ const self_exe_path: ?[]const u8 = if (!process.can_spawn)
+ null
+ else
+ introspect.findZigExePath(arena) catch |err| {
+ fatal("unable to find zig self exe path: {s}", .{@errorName(err)});
+ };
+
+ var zig_lib_directory: Compilation.Directory = d: {
+ if (override_lib_dir) |unresolved_lib_dir| {
+ const lib_dir = try introspect.resolvePath(arena, unresolved_lib_dir);
+ break :d .{
+ .path = lib_dir,
+ .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| {
+ fatal("unable to open zig lib directory '{s}': {s}", .{ lib_dir, @errorName(err) });
+ },
+ };
+ } else if (builtin.os.tag == .wasi) {
+ break :d getWasiPreopen("/lib");
+ } else if (self_exe_path) |p| {
+ break :d introspect.findZigLibDirFromSelfExe(arena, p) catch |err| {
+ fatal("unable to find zig installation directory: {s}", .{@errorName(err)});
+ };
+ } else {
+ unreachable;
+ }
+ };
+ defer zig_lib_directory.handle.close();
+
// Now that we have target info, we can find out if any of the system libraries
// are part of libc or libc++. We remove them from the list and communicate their
// existence via flags instead.
@@ -2612,6 +2641,25 @@ fn buildOutputType(
},
}
+ if (target_info.target.os.tag == .windows) {
+ const exists = mingw.libExists(arena, target_info.target, zig_lib_directory, lib_name) catch |err| {
+ fatal("failed to check zig installation for DLL import libs: {s}", .{
+ @errorName(err),
+ });
+ };
+ if (exists) {
+ try resolved_system_libs.append(arena, .{
+ .name = lib_name,
+ .lib = .{
+ .needed = true,
+ .weak = false,
+ .path = undefined,
+ },
+ });
+ continue;
+ }
+ }
+
if (fs.path.isAbsolute(lib_name)) {
fatal("cannot use absolute path as a system library: {s}", .{lib_name});
}
@@ -2758,9 +2806,13 @@ fn buildOutputType(
if (failed_libs.items.len > 0) {
for (failed_libs.items) |f| {
+ const searched_paths = if (f.checked_paths.len == 0) " none" else f.checked_paths;
std.log.err("unable to find {s} system library '{s}' using strategy '{s}'. searched paths:{s}", .{
- @tagName(f.preferred_mode), f.name, @tagName(f.strategy), f.checked_paths,
+ @tagName(f.preferred_mode), f.name, @tagName(f.strategy), searched_paths,
});
+ if (f.preferred_mode == .Dynamic and f.strategy == .no_fallback) {
+ std.log.info("to link statically, pass the library as a positional argument", .{});
+ }
}
process.exit(1);
}
@@ -3079,35 +3131,6 @@ fn buildOutputType(
}
}
- const self_exe_path: ?[]const u8 = if (!process.can_spawn)
- null
- else
- introspect.findZigExePath(arena) catch |err| {
- fatal("unable to find zig self exe path: {s}", .{@errorName(err)});
- };
-
- var zig_lib_directory: Compilation.Directory = d: {
- if (override_lib_dir) |unresolved_lib_dir| {
- const lib_dir = try introspect.resolvePath(arena, unresolved_lib_dir);
- break :d .{
- .path = lib_dir,
- .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| {
- fatal("unable to open zig lib directory '{s}': {s}", .{ lib_dir, @errorName(err) });
- },
- };
- } else if (builtin.os.tag == .wasi) {
- break :d getWasiPreopen("/lib");
- } else if (self_exe_path) |p| {
- break :d introspect.findZigLibDirFromSelfExe(arena, p) catch |err| {
- fatal("unable to find zig installation directory: {s}", .{@errorName(err)});
- };
- } else {
- unreachable;
- }
- };
-
- defer zig_lib_directory.handle.close();
-
var thread_pool: ThreadPool = undefined;
try thread_pool.init(.{ .allocator = gpa });
defer thread_pool.deinit();
src/mingw.zig
@@ -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});