Skip to content

Commit 3fc7413

Browse files
authored
Merge pull request #17069 from squeek502/resinator
Add a `.rc` -> `.res` compiler to the Zig compiler
2 parents 867e61e + 572956c commit 3fc7413

32 files changed

+17043
-13
lines changed

lib/std/Build/Step/Compile.zig

+65
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ is_linking_libc: bool,
9090
is_linking_libcpp: bool,
9191
vcpkg_bin_path: ?[]const u8 = null,
9292

93+
// keep in sync with src/Compilation.zig:RcIncludes
94+
/// Behavior of automatic detection of include directories when compiling .rc files.
95+
/// any: Use MSVC if available, fall back to MinGW.
96+
/// msvc: Use MSVC include paths (must be present on the system).
97+
/// gnu: Use MinGW include paths (distributed with Zig).
98+
/// none: Do not use any autodetected include paths.
99+
rc_includes: enum { any, msvc, gnu, none } = .any,
100+
93101
installed_path: ?[]const u8,
94102

95103
/// Base address for an executable image.
@@ -221,13 +229,34 @@ pub const CSourceFile = struct {
221229
}
222230
};
223231

232+
pub const RcSourceFile = struct {
233+
file: LazyPath,
234+
/// Any option that rc.exe accepts will work here, with the exception of:
235+
/// - `/fo`: The output filename is set by the build system
236+
/// - Any MUI-related option
237+
/// https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line-
238+
///
239+
/// Implicitly defined options:
240+
/// /x (ignore the INCLUDE environment variable)
241+
/// /D_DEBUG or /DNDEBUG depending on the optimization mode
242+
flags: []const []const u8 = &.{},
243+
244+
pub fn dupe(self: RcSourceFile, b: *std.Build) RcSourceFile {
245+
return .{
246+
.file = self.file.dupe(b),
247+
.flags = b.dupeStrings(self.flags),
248+
};
249+
}
250+
};
251+
224252
pub const LinkObject = union(enum) {
225253
static_path: LazyPath,
226254
other_step: *Compile,
227255
system_lib: SystemLib,
228256
assembly_file: LazyPath,
229257
c_source_file: *CSourceFile,
230258
c_source_files: *CSourceFiles,
259+
win32_resource_file: *RcSourceFile,
231260
};
232261

233262
pub const SystemLib = struct {
@@ -910,6 +939,18 @@ pub fn addCSourceFile(self: *Compile, source: CSourceFile) void {
910939
source.file.addStepDependencies(&self.step);
911940
}
912941

942+
pub fn addWin32ResourceFile(self: *Compile, source: RcSourceFile) void {
943+
// Only the PE/COFF format has a Resource Table, so for any other target
944+
// the resource file is just ignored.
945+
if (self.target.getObjectFormat() != .coff) return;
946+
947+
const b = self.step.owner;
948+
const rc_source_file = b.allocator.create(RcSourceFile) catch @panic("OOM");
949+
rc_source_file.* = source.dupe(b);
950+
self.link_objects.append(.{ .win32_resource_file = rc_source_file }) catch @panic("OOM");
951+
source.file.addStepDependencies(&self.step);
952+
}
953+
913954
pub fn setVerboseLink(self: *Compile, value: bool) void {
914955
self.verbose_link = value;
915956
}
@@ -1358,6 +1399,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
13581399
try transitive_deps.add(self.link_objects.items);
13591400

13601401
var prev_has_cflags = false;
1402+
var prev_has_rcflags = false;
13611403
var prev_search_strategy: SystemLib.SearchStrategy = .paths_first;
13621404
var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic;
13631405

@@ -1500,6 +1542,24 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
15001542
try zig_args.append(b.pathFromRoot(file));
15011543
}
15021544
},
1545+
1546+
.win32_resource_file => |rc_source_file| {
1547+
if (rc_source_file.flags.len == 0) {
1548+
if (prev_has_rcflags) {
1549+
try zig_args.append("-rcflags");
1550+
try zig_args.append("--");
1551+
prev_has_rcflags = false;
1552+
}
1553+
} else {
1554+
try zig_args.append("-rcflags");
1555+
for (rc_source_file.flags) |arg| {
1556+
try zig_args.append(arg);
1557+
}
1558+
try zig_args.append("--");
1559+
prev_has_rcflags = true;
1560+
}
1561+
try zig_args.append(rc_source_file.file.getPath(b));
1562+
},
15031563
}
15041564
}
15051565

@@ -1897,6 +1957,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
18971957
}
18981958
}
18991959

1960+
if (self.rc_includes != .any) {
1961+
try zig_args.append("-rcincludes");
1962+
try zig_args.append(@tagName(self.rc_includes));
1963+
}
1964+
19001965
try addFlag(&zig_args, "valgrind", self.valgrind_support);
19011966
try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);
19021967

lib/std/zig/ErrorBundle.zig

+20-2
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ pub const Wip = struct {
421421
_ = try addExtra(wip, rt);
422422
}
423423

424-
pub fn addBundle(wip: *Wip, other: ErrorBundle) !void {
424+
pub fn addBundleAsNotes(wip: *Wip, other: ErrorBundle) !void {
425425
const gpa = wip.gpa;
426426

427427
try wip.string_bytes.ensureUnusedCapacity(gpa, other.string_bytes.len);
@@ -436,6 +436,21 @@ pub const Wip = struct {
436436
}
437437
}
438438

439+
pub fn addBundleAsRoots(wip: *Wip, other: ErrorBundle) !void {
440+
const gpa = wip.gpa;
441+
442+
try wip.string_bytes.ensureUnusedCapacity(gpa, other.string_bytes.len);
443+
try wip.extra.ensureUnusedCapacity(gpa, other.extra.len);
444+
445+
const other_list = other.getMessages();
446+
447+
try wip.root_list.ensureUnusedCapacity(gpa, other_list.len);
448+
for (other_list) |other_msg| {
449+
// The ensureUnusedCapacity calls above guarantees this.
450+
wip.root_list.appendAssumeCapacity(wip.addOtherMessage(other, other_msg) catch unreachable);
451+
}
452+
}
453+
439454
pub fn reserveNotes(wip: *Wip, notes_len: u32) !u32 {
440455
try wip.extra.ensureUnusedCapacity(wip.gpa, notes_len +
441456
notes_len * @typeInfo(ErrorBundle.ErrorMessage).Struct.fields.len);
@@ -474,7 +489,10 @@ pub const Wip = struct {
474489
.span_start = other_sl.span_start,
475490
.span_main = other_sl.span_main,
476491
.span_end = other_sl.span_end,
477-
.source_line = try wip.addString(other.nullTerminatedString(other_sl.source_line)),
492+
.source_line = if (other_sl.source_line != 0)
493+
try wip.addString(other.nullTerminatedString(other_sl.source_line))
494+
else
495+
0,
478496
.reference_trace_len = other_sl.reference_trace_len,
479497
});
480498

0 commit comments

Comments
 (0)