From ea9d817a905ae19dcf27db4f380270485f9e26d2 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Thu, 2 May 2024 18:57:34 -0700 Subject: [PATCH] Build system: Allow specifying Win32 resource include paths using LazyPath Adds an `include_paths` field to RcSourceFile that takes a slice of LazyPaths. The paths are resolved and subsequently appended to the -rcflags as `/I `. This fixes an accidental regression from https://github.com/ziglang/zig/pull/19174. Before that PR, all Win32 resource compilation would inherit the CC flags (via `addCCArgs`), which included things like include directories. After that PR, though, that is no longer the case. However, this commit intentionally does not restore the previous behavior (inheriting the C include paths). Instead, each .rc file will need to have its include paths specified directly and the include paths only apply to one particular resource script. This allows more fine-grained control and has less potentially surprising behavior (at the cost of some convenience). Closes #19605 --- lib/std/Build/Module.zig | 10 ++++++++++ lib/std/Build/Step/Compile.zig | 6 +++++- test/standalone/windows_resources/build.zig | 14 ++++++++++---- test/standalone/windows_resources/res/zig.rc | 4 ++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index d19f0a781e30..a142bbd40539 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -110,11 +110,18 @@ pub const RcSourceFile = struct { /// /x (ignore the INCLUDE environment variable) /// /D_DEBUG or /DNDEBUG depending on the optimization mode flags: []const []const u8 = &.{}, + /// Include paths that may or may not exist yet and therefore need to be + /// specified as a LazyPath. Each path will be appended to the flags + /// as `/I `. + include_paths: []const LazyPath = &.{}, pub fn dupe(self: RcSourceFile, b: *std.Build) RcSourceFile { + const include_paths = b.allocator.alloc(LazyPath, self.include_paths.len) catch @panic("OOM"); + for (include_paths, self.include_paths) |*dest, lazy_path| dest.* = lazy_path.dupe(b); return .{ .file = self.file.dupe(b), .flags = b.dupeStrings(self.flags), + .include_paths = include_paths, }; } }; @@ -503,6 +510,9 @@ pub fn addWin32ResourceFile(m: *Module, source: RcSourceFile) void { rc_source_file.* = source.dupe(b); m.link_objects.append(allocator, .{ .win32_resource_file = rc_source_file }) catch @panic("OOM"); addLazyPathDependenciesOnly(m, source.file); + for (source.include_paths) |include_path| { + addLazyPathDependenciesOnly(m, include_path); + } } pub fn addAssemblyFile(m: *Module, source: LazyPath) void { diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 79bade4963f0..b89a240fbf94 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -1281,7 +1281,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { .win32_resource_file => |rc_source_file| l: { if (!my_responsibility) break :l; - if (rc_source_file.flags.len == 0) { + if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) { if (prev_has_rcflags) { try zig_args.append("-rcflags"); try zig_args.append("--"); @@ -1292,6 +1292,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { for (rc_source_file.flags) |arg| { try zig_args.append(arg); } + for (rc_source_file.include_paths) |include_path| { + try zig_args.append("/I"); + try zig_args.append(include_path.getPath2(module.owner, step)); + } try zig_args.append("--"); prev_has_rcflags = true; } diff --git a/test/standalone/windows_resources/build.zig b/test/standalone/windows_resources/build.zig index 6a72dee2a61e..15130d3b8765 100644 --- a/test/standalone/windows_resources/build.zig +++ b/test/standalone/windows_resources/build.zig @@ -10,11 +10,13 @@ pub fn build(b: *std.Build) void { .abi = .gnu, }); - add(b, b.host, .any, test_step); - add(b, target, .any, test_step); + const generated_h_step = b.addWriteFile("generated.h", "#define GENERATED_DEFINE \"foo\""); - add(b, b.host, .gnu, test_step); - add(b, target, .gnu, test_step); + add(b, b.host, .any, test_step, generated_h_step); + add(b, target, .any, test_step, generated_h_step); + + add(b, b.host, .gnu, test_step, generated_h_step); + add(b, target, .gnu, test_step, generated_h_step); } fn add( @@ -22,6 +24,7 @@ fn add( target: std.Build.ResolvedTarget, rc_includes: enum { any, gnu }, test_step: *std.Build.Step, + generated_h_step: *std.Build.Step.WriteFile, ) void { const exe = b.addExecutable(.{ .name = "zig_resource_test", @@ -32,6 +35,9 @@ fn add( exe.addWin32ResourceFile(.{ .file = b.path("res/zig.rc"), .flags = &.{"/c65001"}, // UTF-8 code page + .include_paths = &.{ + .{ .generated = &generated_h_step.generated_directory }, + }, }); exe.rc_includes = switch (rc_includes) { .any => .any, diff --git a/test/standalone/windows_resources/res/zig.rc b/test/standalone/windows_resources/res/zig.rc index 88503a0f6ad7..ae2ad99027f3 100644 --- a/test/standalone/windows_resources/res/zig.rc +++ b/test/standalone/windows_resources/res/zig.rc @@ -1,3 +1,7 @@ +// This include file is generated via build.zig, and it #defines GENERATED_DEFINE +#include "generated.h" +FOO RCDATA { GENERATED_DEFINE } + #define ICO_ID 1 // Nothing from windows.h is used in this .rc file,