commit fb18f2096aaff3a26c309da635472a2fb8b303cd (tree)
parent f061c0dc2851e5fab34dca1991ebe64cfd156bd5
Author: antme0 <anthonyem@gmail.com>
Date: Sun, 8 Feb 2026 18:48:54 +0100
Allow build.zig scripts to define module definition files (.def) when building win32 dlls.
Diffstat:
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
@@ -832,6 +832,8 @@ pub const LibraryOptions = struct {
/// Can be set regardless of target. The `.manifest` file will be ignored
/// if the target object format does not support embedded manifests.
win32_manifest: ?LazyPath = null,
+ /// Win32 module definition file (.def).
+ win32_module_definition: ?LazyPath = null,
};
pub fn addLibrary(b: *Build, options: LibraryOptions) *Step.Compile {
@@ -846,6 +848,7 @@ pub fn addLibrary(b: *Build, options: LibraryOptions) *Step.Compile {
.use_lld = options.use_lld,
.zig_lib_dir = options.zig_lib_dir,
.win32_manifest = options.win32_manifest,
+ .win32_module_definition = options.win32_module_definition,
});
}
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
@@ -79,6 +79,10 @@ rc_includes: std.zig.RcIncludes = .any,
/// Set via options; intended to be read-only after that.
win32_manifest: ?LazyPath = null,
+/// (Windows) .def file to embed in the compilation (dll)
+/// Set via options; intended to be read-only after that.
+win32_module_definition: ?LazyPath = null,
+
installed_path: ?[]const u8,
/// Base address for an executable image.
@@ -284,6 +288,8 @@ pub const Options = struct {
/// Can be set regardless of target. The `.manifest` file will be ignored
/// if the target object format does not support embedded manifests.
win32_manifest: ?LazyPath = null,
+ /// Win32 module definition file.
+ win32_module_definition: ?LazyPath = null,
};
pub const Kind = enum {
@@ -467,6 +473,13 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
compile.win32_manifest = lp.dupe(compile.step.owner);
lp.addStepDependencies(&compile.step);
}
+ if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
+ // Building a Win32 DLL, check for win32 .def file.
+ if (options.win32_module_definition) |lp| {
+ compile.win32_module_definition = lp.dupe(compile.step.owner);
+ lp.addStepDependencies(&compile.step);
+ }
+ }
}
if (compile.kind == .lib) {
@@ -1332,6 +1345,10 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
try zig_args.append(manifest_file.getPath2(b, step));
}
+ if (compile.win32_module_definition) |module_file| {
+ try zig_args.append(module_file.getPath2(b, step));
+ }
+
if (compile.image_base) |image_base| {
try zig_args.append("--image-base");
try zig_args.append(b.fmt("0x{x}", .{image_base}));
diff --git a/src/main.zig b/src/main.zig
@@ -1809,6 +1809,9 @@ fn buildOutputType(
fatal("only one manifest file can be specified, found '{s}' after '{s}'", .{ arg, other });
} else manifest_file = arg;
},
+ .def => {
+ linker_module_definition_file = arg;
+ },
.assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm => {
dev.check(.c_compiler);
try create_module.c_source_files.append(arena, .{
@@ -1834,7 +1837,7 @@ fn buildOutputType(
fatal("found another zig file '{s}' after root source file '{s}'", .{ arg, other });
} else root_src_file = arg;
},
- .def, .unknown => {
+ .unknown => {
if (std.ascii.eqlIgnoreCase(".xml", fs.path.extension(arg))) {
warn("embedded manifest files must have the extension '.manifest'", .{});
}