Skip to content

Commit ca690ff

Browse files
authored
Merge pull request #17448 from squeek502/win32-manifest
Add preliminary support for Windows `.manifest` files
2 parents ebde525 + b511478 commit ca690ff

File tree

4 files changed

+231
-32
lines changed

4 files changed

+231
-32
lines changed

lib/std/Build.zig

+14
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,12 @@ pub const ExecutableOptions = struct {
635635
use_lld: ?bool = null,
636636
zig_lib_dir: ?LazyPath = null,
637637
main_mod_path: ?LazyPath = null,
638+
/// Embed a `.manifest` file in the compilation if the object format supports it.
639+
/// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
640+
/// Manifest files must have the extension `.manifest`.
641+
/// Can be set regardless of target. The `.manifest` file will be ignored
642+
/// if the target object format does not support embedded manifests.
643+
win32_manifest: ?LazyPath = null,
638644

639645
/// Deprecated; use `main_mod_path`.
640646
main_pkg_path: ?LazyPath = null,
@@ -656,6 +662,7 @@ pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile {
656662
.use_lld = options.use_lld,
657663
.zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
658664
.main_mod_path = options.main_mod_path orelse options.main_pkg_path,
665+
.win32_manifest = options.win32_manifest,
659666
});
660667
}
661668

@@ -706,6 +713,12 @@ pub const SharedLibraryOptions = struct {
706713
use_lld: ?bool = null,
707714
zig_lib_dir: ?LazyPath = null,
708715
main_mod_path: ?LazyPath = null,
716+
/// Embed a `.manifest` file in the compilation if the object format supports it.
717+
/// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
718+
/// Manifest files must have the extension `.manifest`.
719+
/// Can be set regardless of target. The `.manifest` file will be ignored
720+
/// if the target object format does not support embedded manifests.
721+
win32_manifest: ?LazyPath = null,
709722

710723
/// Deprecated; use `main_mod_path`.
711724
main_pkg_path: ?LazyPath = null,
@@ -727,6 +740,7 @@ pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile
727740
.use_lld = options.use_lld,
728741
.zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
729742
.main_mod_path = options.main_mod_path orelse options.main_pkg_path,
743+
.win32_manifest = options.win32_manifest,
730744
});
731745
}
732746

lib/std/Build/Step/Compile.zig

+26
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ vcpkg_bin_path: ?[]const u8 = null,
9898
/// none: Do not use any autodetected include paths.
9999
rc_includes: enum { any, msvc, gnu, none } = .any,
100100

101+
/// (Windows) .manifest file to embed in the compilation
102+
/// Set via options; intended to be read-only after that.
103+
win32_manifest: ?LazyPath = null,
104+
101105
installed_path: ?[]const u8,
102106

103107
/// Base address for an executable image.
@@ -319,6 +323,12 @@ pub const Options = struct {
319323
use_lld: ?bool = null,
320324
zig_lib_dir: ?LazyPath = null,
321325
main_mod_path: ?LazyPath = null,
326+
/// Embed a `.manifest` file in the compilation if the object format supports it.
327+
/// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
328+
/// Manifest files must have the extension `.manifest`.
329+
/// Can be set regardless of target. The `.manifest` file will be ignored
330+
/// if the target object format does not support embedded manifests.
331+
win32_manifest: ?LazyPath = null,
322332

323333
/// deprecated; use `main_mod_path`.
324334
main_pkg_path: ?LazyPath = null,
@@ -525,6 +535,15 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
525535
lp.addStepDependencies(&self.step);
526536
}
527537

538+
// Only the PE/COFF format has a Resource Table which is where the manifest
539+
// gets embedded, so for any other target the manifest file is just ignored.
540+
if (self.target.getObjectFormat() == .coff) {
541+
if (options.win32_manifest) |lp| {
542+
self.win32_manifest = lp.dupe(self.step.owner);
543+
lp.addStepDependencies(&self.step);
544+
}
545+
}
546+
528547
if (self.kind == .lib) {
529548
if (self.linkage != null and self.linkage.? == .static) {
530549
self.out_lib_filename = self.out_filename;
@@ -957,6 +976,9 @@ pub fn addCSourceFile(self: *Compile, source: CSourceFile) void {
957976
source.file.addStepDependencies(&self.step);
958977
}
959978

979+
/// Resource files must have the extension `.rc`.
980+
/// Can be called regardless of target. The .rc file will be ignored
981+
/// if the target object format does not support embedded resources.
960982
pub fn addWin32ResourceFile(self: *Compile, source: RcSourceFile) void {
961983
// Only the PE/COFF format has a Resource Table, so for any other target
962984
// the resource file is just ignored.
@@ -1593,6 +1615,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
15931615
}
15941616
}
15951617

1618+
if (self.win32_manifest) |manifest_file| {
1619+
try zig_args.append(manifest_file.getPath(b));
1620+
}
1621+
15961622
if (transitive_deps.is_linking_libcpp) {
15971623
try zig_args.append("-lc++");
15981624
}

0 commit comments

Comments
 (0)