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.
|
// 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 = undefined,
|
||||||
|
};
|
||||||
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,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
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 crash_report = @import("crash_report.zig");
|
||||||
const Module = @import("Module.zig");
|
const Module = @import("Module.zig");
|
||||||
const AstGen = @import("AstGen.zig");
|
const AstGen = @import("AstGen.zig");
|
||||||
|
const mingw = @import("mingw.zig");
|
||||||
const Server = std.zig.Server;
|
const Server = std.zig.Server;
|
||||||
|
|
||||||
pub const std_options = struct {
|
pub const std_options = struct {
|
||||||
|
|
@ -477,6 +478,8 @@ const usage_build_generic =
|
||||||
\\ -needed-l[lib], Link against system library (even if unused)
|
\\ -needed-l[lib], Link against system library (even if unused)
|
||||||
\\ --needed-library [lib]
|
\\ --needed-library [lib]
|
||||||
\\ -L[d], --library-directory [d] Add a directory to the library search path
|
\\ -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
|
\\ -T[script], --script [script] Use a custom linker script
|
||||||
\\ --version-script [path] Provide a version .map file
|
\\ --version-script [path] Provide a version .map file
|
||||||
\\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
|
\\ --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
|
\\ -install_name=[value] (Darwin) add dylib's install name
|
||||||
\\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature
|
\\ --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
|
\\ -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 [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
|
\\ -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
|
\\ -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.
|
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
|
// 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
|
// are part of libc or libc++. We remove them from the list and communicate their
|
||||||
// existence via flags instead.
|
// 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)) {
|
if (fs.path.isAbsolute(lib_name)) {
|
||||||
fatal("cannot use absolute path as a system library: {s}", .{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) {
|
if (failed_libs.items.len > 0) {
|
||||||
for (failed_libs.items) |f| {
|
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}", .{
|
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);
|
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;
|
var thread_pool: ThreadPool = undefined;
|
||||||
try thread_pool.init(.{ .allocator = gpa });
|
try thread_pool.init(.{ .allocator = gpa });
|
||||||
defer thread_pool.deinit();
|
defer thread_pool.deinit();
|
||||||
|
|
|
||||||
|
|
@ -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});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue