mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
frontend: fix linking to Windows DLLs as system libs
This commit is contained in:
parent
a08cc7d2ae
commit
a1e21ceec8
3 changed files with 85 additions and 39 deletions
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
87
src/main.zig
87
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();
|
||||
|
|
|
|||
|
|
@ -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});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue