Skip to content

Commit e837765

Browse files
authored
zig rc: Fix include directory detection when cross-compiling from certain host archs (ziglang#24288)
* resinator: Only preprocess when the input is an .rc file * 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`.
2 parents d3363b7 + 09f4e2d commit e837765

File tree

2 files changed

+68
-20
lines changed

2 files changed

+68
-20
lines changed

lib/compiler/resinator/main.zig

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -104,24 +104,15 @@ pub fn main() !void {
104104
}
105105
const maybe_dependencies_list: ?*std.ArrayList([]const u8) = if (options.depfile_path != null) &dependencies_list else null;
106106

107-
const include_paths = getIncludePaths(arena, options.auto_includes, zig_lib_dir) catch |err| switch (err) {
108-
error.OutOfMemory => |e| return e,
109-
else => |e| {
110-
switch (e) {
111-
error.MsvcIncludesNotFound => {
112-
try error_handler.emitMessage(allocator, .err, "MSVC include paths could not be automatically detected", .{});
113-
},
114-
error.MingwIncludesNotFound => {
115-
try error_handler.emitMessage(allocator, .err, "MinGW include paths could not be automatically detected", .{});
116-
},
117-
}
118-
try error_handler.emitMessage(allocator, .note, "to disable auto includes, use the option /:auto-includes none", .{});
119-
std.process.exit(1);
120-
},
107+
var include_paths = LazyIncludePaths{
108+
.arena = arena,
109+
.auto_includes_option = options.auto_includes,
110+
.zig_lib_dir = zig_lib_dir,
111+
.target_machine_type = options.coff_options.target,
121112
};
122113

123114
const full_input = full_input: {
124-
if (options.preprocess != .no) {
115+
if (options.input_format == .rc and options.preprocess != .no) {
125116
var preprocessed_buf = std.ArrayList(u8).init(allocator);
126117
errdefer preprocessed_buf.deinit();
127118

@@ -138,7 +129,8 @@ pub fn main() !void {
138129
defer argv.deinit();
139130

140131
try argv.append("arocc"); // dummy command name
141-
try preprocess.appendAroArgs(aro_arena, &argv, options, include_paths);
132+
const resolved_include_paths = try include_paths.get(&error_handler);
133+
try preprocess.appendAroArgs(aro_arena, &argv, options, resolved_include_paths);
142134
try argv.append(switch (options.input_source) {
143135
.stdio => "-",
144136
.filename => |filename| filename,
@@ -264,7 +256,7 @@ pub fn main() !void {
264256
.dependencies_list = maybe_dependencies_list,
265257
.ignore_include_env_var = options.ignore_include_env_var,
266258
.extra_include_paths = options.extra_include_paths.items,
267-
.system_include_paths = include_paths,
259+
.system_include_paths = try include_paths.get(&error_handler),
268260
.default_language_id = options.default_language_id,
269261
.default_code_page = default_code_page,
270262
.disjoint_code_page = has_disjoint_code_page,
@@ -498,21 +490,71 @@ const IoStream = struct {
498490
};
499491
};
500492

501-
fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, zig_lib_dir: []const u8) ![]const []const u8 {
493+
const LazyIncludePaths = struct {
494+
arena: std.mem.Allocator,
495+
auto_includes_option: cli.Options.AutoIncludes,
496+
zig_lib_dir: []const u8,
497+
target_machine_type: std.coff.MachineType,
498+
resolved_include_paths: ?[]const []const u8 = null,
499+
500+
pub fn get(self: *LazyIncludePaths, error_handler: *ErrorHandler) ![]const []const u8 {
501+
if (self.resolved_include_paths) |include_paths|
502+
return include_paths;
503+
504+
return getIncludePaths(self.arena, self.auto_includes_option, self.zig_lib_dir, self.target_machine_type) catch |err| switch (err) {
505+
error.OutOfMemory => |e| return e,
506+
else => |e| {
507+
switch (e) {
508+
error.UnsupportedAutoIncludesMachineType => {
509+
try error_handler.emitMessage(self.arena, .err, "automatic include path detection is not supported for target '{s}'", .{@tagName(self.target_machine_type)});
510+
},
511+
error.MsvcIncludesNotFound => {
512+
try error_handler.emitMessage(self.arena, .err, "MSVC include paths could not be automatically detected", .{});
513+
},
514+
error.MingwIncludesNotFound => {
515+
try error_handler.emitMessage(self.arena, .err, "MinGW include paths could not be automatically detected", .{});
516+
},
517+
}
518+
try error_handler.emitMessage(self.arena, .note, "to disable auto includes, use the option /:auto-includes none", .{});
519+
std.process.exit(1);
520+
},
521+
};
522+
}
523+
};
524+
525+
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 {
526+
if (auto_includes_option == .none) return &[_][]const u8{};
527+
528+
const includes_arch: std.Target.Cpu.Arch = switch (target_machine_type) {
529+
.X64 => .x86_64,
530+
.I386 => .x86,
531+
.ARMNT => .thumb,
532+
.ARM64 => .aarch64,
533+
.ARM64EC => .aarch64,
534+
.ARM64X => .aarch64,
535+
.IA64, .EBC => {
536+
return error.UnsupportedAutoIncludesMachineType;
537+
},
538+
// The above cases are exhaustive of all the `MachineType`s supported (see supported_targets in cvtres.zig)
539+
// This is enforced by the argument parser in cli.zig.
540+
else => unreachable,
541+
};
542+
502543
var includes = auto_includes_option;
503544
if (builtin.target.os.tag != .windows) {
504545
switch (includes) {
546+
.none => unreachable,
505547
// MSVC can't be found when the host isn't Windows, so short-circuit.
506548
.msvc => return error.MsvcIncludesNotFound,
507549
// Skip straight to gnu since we won't be able to detect MSVC on non-Windows hosts.
508550
.any => includes = .gnu,
509-
.none, .gnu => {},
551+
.gnu => {},
510552
}
511553
}
512554

513555
while (true) {
514556
switch (includes) {
515-
.none => return &[_][]const u8{},
557+
.none => unreachable,
516558
.any, .msvc => {
517559
// MSVC is only detectable on Windows targets. This unreachable is to signify
518560
// 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
521563

522564
const target_query: std.Target.Query = .{
523565
.os_tag = .windows,
566+
.cpu_arch = includes_arch,
524567
.abi = .msvc,
525568
};
526569
const target = std.zig.resolveTargetQueryOrFatal(target_query);
@@ -546,6 +589,7 @@ fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.A
546589
.gnu => {
547590
const target_query: std.Target.Query = .{
548591
.os_tag = .windows,
592+
.cpu_arch = includes_arch,
549593
.abi = .gnu,
550594
};
551595
const target = std.zig.resolveTargetQueryOrFatal(target_query);

src/Compilation.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6058,6 +6058,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
60586058
self_exe_path,
60596059
"rc",
60606060
"--zig-integration",
6061+
"/:target",
6062+
@tagName(comp.getTarget().cpu.arch),
60616063
"/:no-preprocess",
60626064
"/x", // ignore INCLUDE environment variable
60636065
"/c65001", // UTF-8 codepage
@@ -6115,6 +6117,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
61156117
self_exe_path,
61166118
"rc",
61176119
"--zig-integration",
6120+
"/:target",
6121+
@tagName(comp.getTarget().cpu.arch),
61186122
"/:depfile",
61196123
out_dep_path,
61206124
"/:depfile-fmt",

0 commit comments

Comments
 (0)