From 491b460e0a5637d42cc60e9d69a666cac2591ae3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 7 Jan 2024 18:41:26 -0700 Subject: [PATCH] add tool for updating mingw crt files --- build.zig | 18 +++++ src/mingw.zig | 1 - tools/update_mingw.zig | 146 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 tools/update_mingw.zig diff --git a/build.zig b/build.zig index d24b51741a..504eb9a386 100644 --- a/build.zig +++ b/build.zig @@ -537,6 +537,24 @@ pub fn build(b: *std.Build) !void { b.step("fmt", "Modify source files in place to have conforming formatting") .dependOn(&do_fmt.step); + + const update_mingw_step = b.step("update-mingw", "Update zig's bundled mingw"); + const opt_mingw_src_path = b.option([]const u8, "mingw-src", "path to mingw-w64 source directory"); + const update_mingw_exe = b.addExecutable(.{ + .name = "update_mingw", + .target = b.host, + .root_source_file = .{ .path = "tools/update_mingw.zig" }, + }); + const update_mingw_run = b.addRunArtifact(update_mingw_exe); + update_mingw_run.addDirectoryArg(.{ .path = "lib" }); + if (opt_mingw_src_path) |mingw_src_path| { + update_mingw_run.addDirectoryArg(.{ .cwd_relative = mingw_src_path }); + } else { + // Intentionally cause an error if this build step is requested. + update_mingw_run.addArg("--missing-mingw-source-directory"); + } + + update_mingw_step.dependOn(&update_mingw_run.step); } fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { diff --git a/src/mingw.zig b/src/mingw.zig index d8f3447783..bf2c878d6f 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -782,7 +782,6 @@ const mingwex_generic_src = [_][]const u8{ "math" ++ path.sep_str ++ "tgammal.c", "math" ++ path.sep_str ++ "truncl.c", "misc" ++ path.sep_str ++ "alarm.c", - "misc" ++ path.sep_str ++ "basename.c", "misc" ++ path.sep_str ++ "btowc.c", "misc" ++ path.sep_str ++ "delay-f.c", "misc" ++ path.sep_str ++ "delay-n.c", diff --git a/tools/update_mingw.zig b/tools/update_mingw.zig new file mode 100644 index 0000000000..c3aa509728 --- /dev/null +++ b/tools/update_mingw.zig @@ -0,0 +1,146 @@ +const std = @import("std"); + +pub fn main() !void { + var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena_instance.deinit(); + const arena = arena_instance.allocator(); + + const args = try std.process.argsAlloc(arena); + const zig_src_lib_path = args[1]; + const mingw_src_path = args[2]; + + if (std.mem.eql(u8, mingw_src_path, "--missing-mingw-source-directory")) { + std.log.err("this build step requires passing -Dmingw-src=[path]", .{}); + std.process.exit(1); + } + + const dest_mingw_crt_path = try std.fs.path.join(arena, &.{ + zig_src_lib_path, "libc", "mingw", + }); + const src_mingw_crt_path = try std.fs.path.join(arena, &.{ + mingw_src_path, "mingw-w64-crt", + }); + + // Update only the set of existing files we have already chosen to include + // in zig's installation. + + var dest_crt_dir = std.fs.cwd().openDir(dest_mingw_crt_path, .{ .iterate = true }) catch |err| { + std.log.err("unable to open directory '{s}': {s}", .{ dest_mingw_crt_path, @errorName(err) }); + std.process.exit(1); + }; + defer dest_crt_dir.close(); + + var src_crt_dir = std.fs.cwd().openDir(src_mingw_crt_path, .{ .iterate = true }) catch |err| { + std.log.err("unable to open directory '{s}': {s}", .{ src_mingw_crt_path, @errorName(err) }); + std.process.exit(1); + }; + defer src_crt_dir.close(); + + { + var walker = try dest_crt_dir.walk(arena); + defer walker.deinit(); + + var fail = false; + + while (try walker.next()) |entry| { + if (entry.kind != .file) continue; + + // Special exception to keep the copyright file. + if (std.mem.eql(u8, entry.path, "COPYING")) continue; + + src_crt_dir.copyFile(entry.path, dest_crt_dir, entry.path, .{}) catch |err| switch (err) { + error.FileNotFound => { + std.log.warn("deleting {s}", .{entry.path}); + try dest_crt_dir.deleteFile(entry.path); + }, + else => { + std.log.err("unable to copy {s}: {s}", .{ entry.path, @errorName(err) }); + fail = true; + }, + }; + } + + if (fail) std.process.exit(1); + } + + { + // Also add all new def and def.in files. + var walker = try src_crt_dir.walk(arena); + defer walker.deinit(); + + var fail = false; + + while (try walker.next()) |entry| { + if (entry.kind != .file) continue; + + const ok_ext = for (ok_exts) |ext| { + if (std.mem.endsWith(u8, entry.path, ext)) break true; + } else false; + + if (!ok_ext) continue; + + const ok_prefix = for (ok_prefixes) |p| { + if (std.mem.startsWith(u8, entry.path, p)) break true; + } else false; + + if (!ok_prefix) continue; + + const blacklisted = for (blacklist) |item| { + if (std.mem.eql(u8, entry.basename, item)) break true; + } else false; + + if (blacklisted) continue; + + if (std.mem.startsWith(u8, entry.basename, "api-ms-win-")) + continue; + + src_crt_dir.copyFile(entry.path, dest_crt_dir, entry.path, .{}) catch |err| { + std.log.err("unable to copy {s}: {s}", .{ entry.path, @errorName(err) }); + fail = true; + }; + } + if (fail) std.process.exit(1); + } + + return std.process.cleanExit(); +} + +const ok_exts = [_][]const u8{ + ".def", + ".def.in", +}; + +const ok_prefixes = [_][]const u8{ + "lib32" ++ std.fs.path.sep_str, + "lib64" ++ std.fs.path.sep_str, + "libarm32" ++ std.fs.path.sep_str, + "libarm64" ++ std.fs.path.sep_str, + "lib-common" ++ std.fs.path.sep_str, + "def-include" ++ std.fs.path.sep_str, +}; + +const blacklist = [_][]const u8{ + "msvcp60.def", + "msvcp120_app.def.in", + "msvcp60.def", + "msvcp120_clr0400.def", + "msvcp110.def", + "msvcp60.def", + "msvcp120_app.def.in", + + "msvcr100.def.in", + "msvcr110.def", + "msvcr110.def.in", + "msvcr120.def.in", + "msvcr120_app.def.in", + "msvcr120_clr0400.def", + "msvcr120d.def.in", + "msvcr70.def.in", + "msvcr71.def.in", + "msvcr80.def.in", + "msvcr90.def.in", + "msvcr90d.def.in", + "msvcrt10.def.in", + "msvcrt20.def.in", + "msvcrt40.def.in", +};