From 761783f54d1f5ecfaaefc466693f8912ed2e83f5 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Sat, 28 Jun 2025 19:37:24 -0700 Subject: [PATCH 1/2] resinator: Only preprocess when the input is an .rc file --- lib/compiler/resinator/main.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index a96289ceecf0..bedea2c16825 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -121,7 +121,7 @@ pub fn main() !void { }; const full_input = full_input: { - if (options.preprocess != .no) { + if (options.input_format == .rc and options.preprocess != .no) { var preprocessed_buf = std.ArrayList(u8).init(allocator); errdefer preprocessed_buf.deinit(); From 09f4e2d9d138d313b93ab10cbac1fee2a8f4e9f0 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Sat, 28 Jun 2025 19:43:16 -0700 Subject: [PATCH 2/2] resinator: Fix include directory detection when cross-compiling from certain host archs Previously, resinator would use the host arch as the target arch when looking for windows-gnu include directories. However, Zig only thinks it can provide a libc for targets specified in the `std.zig.target.available_libcs` array, which only includes a few for windows-gnu. Therefore, when cross-compiling from a host architecture that doesn't have a windows-gnu target in the available_libcs list, resinator would fail to detect the MinGW include directories. Now, the custom option `/:target` is passed to `zig rc` which is intended for the COFF object file target, but can be re-used for the include directory target as well. For the include directory target, resinator will convert the MachineType to the relevant arch, or fail if there is no equivalent arch/no support for detecting the includes for the MachineType (currently 64-bit Itanium and EBC). Fixes the `windows_resources` standalone test failing when the host is, for example, `riscv64-linux`. --- lib/compiler/resinator/main.zig | 82 +++++++++++++++++++++++++-------- src/Compilation.zig | 4 ++ 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/lib/compiler/resinator/main.zig b/lib/compiler/resinator/main.zig index bedea2c16825..8344a16b25ea 100644 --- a/lib/compiler/resinator/main.zig +++ b/lib/compiler/resinator/main.zig @@ -104,20 +104,11 @@ pub fn main() !void { } const maybe_dependencies_list: ?*std.ArrayList([]const u8) = if (options.depfile_path != null) &dependencies_list else null; - const include_paths = getIncludePaths(arena, options.auto_includes, zig_lib_dir) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => |e| { - switch (e) { - error.MsvcIncludesNotFound => { - try error_handler.emitMessage(allocator, .err, "MSVC include paths could not be automatically detected", .{}); - }, - error.MingwIncludesNotFound => { - try error_handler.emitMessage(allocator, .err, "MinGW include paths could not be automatically detected", .{}); - }, - } - try error_handler.emitMessage(allocator, .note, "to disable auto includes, use the option /:auto-includes none", .{}); - std.process.exit(1); - }, + var include_paths = LazyIncludePaths{ + .arena = arena, + .auto_includes_option = options.auto_includes, + .zig_lib_dir = zig_lib_dir, + .target_machine_type = options.coff_options.target, }; const full_input = full_input: { @@ -138,7 +129,8 @@ pub fn main() !void { defer argv.deinit(); try argv.append("arocc"); // dummy command name - try preprocess.appendAroArgs(aro_arena, &argv, options, include_paths); + const resolved_include_paths = try include_paths.get(&error_handler); + try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths); try argv.append(switch (options.input_source) { .stdio => "-", .filename => |filename| filename, @@ -264,7 +256,7 @@ pub fn main() !void { .dependencies_list = maybe_dependencies_list, .ignore_include_env_var = options.ignore_include_env_var, .extra_include_paths = options.extra_include_paths.items, - .system_include_paths = include_paths, + .system_include_paths = try include_paths.get(&error_handler), .default_language_id = options.default_language_id, .default_code_page = default_code_page, .disjoint_code_page = has_disjoint_code_page, @@ -498,21 +490,71 @@ const IoStream = struct { }; }; -fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8) ![]const []const u8 { +const LazyIncludePaths = struct { + arena: std.mem.Allocator, + auto_includes_option: cli.Options.AutoIncludes, + zig_lib_dir: []const u8, + target_machine_type: std.coff.MachineType, + resolved_include_paths: ?[]const []const u8 = null, + + pub fn get(self: *LazyIncludePaths, error_handler: *ErrorHandler) ![]const []const u8 { + if (self.resolved_include_paths) |include_paths| + return include_paths; + + return getIncludePaths(self.arena, self.auto_includes_option, self.zig_lib_dir, self.target_machine_type) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => |e| { + switch (e) { + error.UnsupportedAutoIncludesMachineType => { + try error_handler.emitMessage(self.arena, .err, "automatic include path detection is not supported for target '{s}'", .{@tagName(self.target_machine_type)}); + }, + error.MsvcIncludesNotFound => { + try error_handler.emitMessage(self.arena, .err, "MSVC include paths could not be automatically detected", .{}); + }, + error.MingwIncludesNotFound => { + try error_handler.emitMessage(self.arena, .err, "MinGW include paths could not be automatically detected", .{}); + }, + } + try error_handler.emitMessage(self.arena, .note, "to disable auto includes, use the option /:auto-includes none", .{}); + std.process.exit(1); + }, + }; + } +}; + +fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8, target_machine_type: std.coff.MachineType) ![]const []const u8 { + if (auto_includes_option == .none) return &[_][]const u8{}; + + const includes_arch: std.Target.Cpu.Arch = switch (target_machine_type) { + .X64 => .x86_64, + .I386 => .x86, + .ARMNT => .thumb, + .ARM64 => .aarch64, + .ARM64EC => .aarch64, + .ARM64X => .aarch64, + .IA64, .EBC => { + return error.UnsupportedAutoIncludesMachineType; + }, + // The above cases are exhaustive of all the `MachineType`s supported (see supported_targets in cvtres.zig) + // This is enforced by the argument parser in cli.zig. + else => unreachable, + }; + var includes = auto_includes_option; if (builtin.target.os.tag != .windows) { switch (includes) { + .none => unreachable, // MSVC can't be found when the host isn't Windows, so short-circuit. .msvc => return error.MsvcIncludesNotFound, // Skip straight to gnu since we won't be able to detect MSVC on non-Windows hosts. .any => includes = .gnu, - .none, .gnu => {}, + .gnu => {}, } } while (true) { switch (includes) { - .none => return &[_][]const u8{}, + .none => unreachable, .any, .msvc => { // MSVC is only detectable on Windows targets. This unreachable is to signify // that .any and .msvc should be dealt with on non-Windows targets before this point, @@ -521,6 +563,7 @@ fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.A const target_query: std.Target.Query = .{ .os_tag = .windows, + .cpu_arch = includes_arch, .abi = .msvc, }; const target = std.zig.resolveTargetQueryOrFatal(target_query); @@ -546,6 +589,7 @@ fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.A .gnu => { const target_query: std.Target.Query = .{ .os_tag = .windows, + .cpu_arch = includes_arch, .abi = .gnu, }; const target = std.zig.resolveTargetQueryOrFatal(target_query); diff --git a/src/Compilation.zig b/src/Compilation.zig index 4136b21f6137..fb9ee617f53b 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6058,6 +6058,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 self_exe_path, "rc", "--zig-integration", + "/:target", + @tagName(comp.getTarget().cpu.arch), "/:no-preprocess", "/x", // ignore INCLUDE environment variable "/c65001", // UTF-8 codepage @@ -6115,6 +6117,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 self_exe_path, "rc", "--zig-integration", + "/:target", + @tagName(comp.getTarget().cpu.arch), "/:depfile", out_dep_path, "/:depfile-fmt",