Files
zig/tools/check_mingw.zig
Ryan Liptak a851256a98 mingw: Only preprocess .def.in files
The .def files don't have any preprocessor commands so running them through the preprocessor is useless work.
2026-06-17 20:07:43 -07:00

125 lines
4.4 KiB
Zig

const std = @import("std");
const Io = std.Io;
const Dir = Io.Dir;
const Preprocessor = @import("preprocessor");
pub fn main(init: std.process.Init) !void {
const arena = init.arena.allocator();
const io = init.io;
const args = try init.minimal.args.toSlice(arena);
const zig_src_mingw_lib_path = args[1];
const mingw_include_path = try Dir.path.join(arena, &.{
zig_src_mingw_lib_path, "def-include",
});
const mingw_libcommon_path = try Dir.path.join(arena, &.{
zig_src_mingw_lib_path, "lib-common",
});
var mingw_libcommon_dir = Dir.cwd().openDir(io, mingw_libcommon_path, .{ .iterate = true }) catch |err| {
std.log.err("unable to open directory {s}: {t}", .{ mingw_libcommon_path, err });
std.process.exit(1);
};
defer mingw_libcommon_dir.close(io);
var walker = try mingw_libcommon_dir.walk(arena);
defer walker.deinit();
while (try walker.next(io)) |entry| {
if (entry.kind != .file) continue;
// Only .def.in files need preprocessing
if (!std.mem.endsWith(u8, entry.basename, ".def.in")) continue;
var fail = false;
for (&targets) |*target| {
var target_arena: std.heap.ArenaAllocator = .init(init.gpa);
defer target_arena.deinit();
const pp_arena = target_arena.allocator();
const file_path = try Dir.path.join(pp_arena, &.{ mingw_libcommon_path, entry.path });
const aro = pp: {
const target_triple = try target.zigTriple(pp_arena);
const target_arg = try std.fmt.allocPrint(pp_arena, "--target={s}", .{target_triple});
const result = std.process.run(pp_arena, io, .{
.argv = &.{
"arocc",
"-E",
target_arg,
"--no-line-commands",
"-nostdinc",
"-I",
mingw_include_path,
file_path,
},
}) catch |err| {
std.log.err("unable to execute arocc: {t}", .{err});
std.process.exit(1);
};
if (result.term.exited != 0) {
std.log.err("error executing arocc: {s}", .{result.stderr});
std.process.exit(result.term.exited);
}
break :pp result.stdout;
};
const native = pp: {
var aw: Io.Writer.Allocating = .init(pp_arena);
errdefer aw.deinit();
var pp: Preprocessor = .{
.io = io,
.arena = pp_arena,
.include_dir = mingw_include_path,
.target = target,
};
pp.preprocess(file_path) catch |err| {
std.log.err("error preprocessing file {s} for target {t}: {t}", .{ entry.path, target.cpu.arch, err });
fail = true;
continue;
};
pp.prettyPrintTokens(&aw.writer) catch |err| {
std.log.err("error printing tokens for file {s} for target {t}: {t}", .{ entry.path, target.cpu.arch, err });
fail = true;
continue;
};
break :pp try aw.toOwnedSliceSentinel(0);
};
try std.testing.expectEqualStrings(aro, native);
}
if (fail) std.process.exit(1);
}
}
const targets = [_]std.Target{
.{
.ofmt = .coff,
.abi = .gnu,
.os = .{ .tag = .windows, .version_range = .default(.thumb, .windows, .gnu) },
.cpu = .{ .arch = .thumb, .model = .generic(.thumb), .features = .empty },
},
.{
.ofmt = .coff,
.abi = .gnu,
.os = .{ .tag = .windows, .version_range = .default(.aarch64, .windows, .gnu) },
.cpu = .{ .arch = .aarch64, .model = .generic(.aarch64), .features = .empty },
},
.{
.ofmt = .coff,
.abi = .gnu,
.os = .{ .tag = .windows, .version_range = .default(.x86, .windows, .gnu) },
.cpu = .{ .arch = .x86, .model = .generic(.x86), .features = .empty },
},
.{
.ofmt = .coff,
.abi = .gnu,
.os = .{ .tag = .windows, .version_range = .default(.x86_64, .windows, .gnu) },
.cpu = .{ .arch = .x86_64, .model = .generic(.x86_64), .features = .empty },
},
};