From e29c0ff665c883b12ae214170044322dd6925f3f Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Fri, 1 Mar 2024 22:44:13 -0800 Subject: [PATCH] Add /:mingw-includes CLI option Can be used to avoid extracting/using the bundled MinGW includes --- src/cli.zig | 50 +++++++++++++++++++++++++++++++++++++------------- src/main.zig | 15 ++++++++++----- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/cli.zig b/src/cli.zig index 8cc55af..bbec090 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -50,12 +50,14 @@ pub const usage_string_after_command_name = \\ /:auto-includes Set the automatic include path detection behavior. \\ any (default) Use MSVC if available, fall back to MinGW \\ msvc Use MSVC include paths (must be present on the system) - \\ gnu Use MinGW include paths (requires Zig as the preprocessor) + \\ gnu Use MinGW include paths \\ none Do not use any autodetected include paths - \\ /:depfile Output a file containing a list of all the files that the - \\ .rc includes or otherwise depends on. + \\ /:depfile Output a file containing a list of all the files that + \\ the .rc includes or otherwise depends on. \\ /:depfile-fmt Output format of the depfile, if /:depfile is set. \\ json (default) A top-level JSON array of paths + \\ /:mingw-includes Path to a directory containing MinGW include files. If + \\ not specified, bundled MinGW include files will be used. \\ \\Note: For compatibility reasons, all custom options start with : \\ @@ -146,6 +148,7 @@ pub const Options = struct { auto_includes: AutoIncludes = .any, depfile_path: ?[]const u8 = null, depfile_fmt: DepfileFormat = .json, + mingw_includes_dir: ?[]const u8 = null, pub const AutoIncludes = enum { any, msvc, gnu, none }; pub const DepfileFormat = enum { json }; @@ -240,6 +243,9 @@ pub const Options = struct { if (self.depfile_path) |depfile_path| { self.allocator.free(depfile_path); } + if (self.mingw_includes_dir) |mingw_includes_dir| { + self.allocator.free(mingw_includes_dir); + } } pub fn dumpVerbose(self: *const Options, writer: anytype) !void { @@ -434,22 +440,22 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn if (std.ascii.startsWithIgnoreCase(arg_name, ":no-preprocess")) { options.preprocess = .no; arg.name_offset += ":no-preprocess".len; - } else if (std.ascii.startsWithIgnoreCase(arg_name, ":depfile-fmt")) { - const value = arg.value(":depfile-fmt".len, arg_i, args) catch { + } else if (std.ascii.startsWithIgnoreCase(arg_name, ":mingw-includes")) { + const value = arg.value(":mingw-includes".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile-fmt".len) }); + try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":mingw-includes".len) }); try diagnostics.append(err_details); arg_i += 1; break :next_arg; }; - options.depfile_fmt = std.meta.stringToEnum(Options.DepfileFormat, value.slice) orelse blk: { - var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; - var msg_writer = err_details.msg.writer(allocator); - try msg_writer.print("invalid depfile format setting: {s} ", .{value.slice}); - try diagnostics.append(err_details); - break :blk options.depfile_fmt; - }; + if (options.mingw_includes_dir) |overwritten_path| { + allocator.free(overwritten_path); + options.mingw_includes_dir = null; + } + const path = try allocator.dupe(u8, value.slice); + errdefer allocator.free(path); + options.mingw_includes_dir = path; arg_i += value.index_increment; continue :next_arg; } else if (std.ascii.startsWithIgnoreCase(arg_name, ":auto-includes")) { @@ -470,6 +476,24 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn }; arg_i += value.index_increment; continue :next_arg; + } else if (std.ascii.startsWithIgnoreCase(arg_name, ":depfile-fmt")) { + const value = arg.value(":depfile-fmt".len, arg_i, args) catch { + var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; + var msg_writer = err_details.msg.writer(allocator); + try msg_writer.print("missing value after {s}{s} option", .{ arg.prefixSlice(), arg.optionWithoutPrefix(":depfile-fmt".len) }); + try diagnostics.append(err_details); + arg_i += 1; + break :next_arg; + }; + options.depfile_fmt = std.meta.stringToEnum(Options.DepfileFormat, value.slice) orelse blk: { + var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = value.argSpan(arg) }; + var msg_writer = err_details.msg.writer(allocator); + try msg_writer.print("invalid depfile format setting: {s} ", .{value.slice}); + try diagnostics.append(err_details); + break :blk options.depfile_fmt; + }; + arg_i += value.index_increment; + continue :next_arg; } else if (std.ascii.startsWithIgnoreCase(arg_name, ":depfile")) { const value = arg.value(":depfile".len, arg_i, args) catch { var err_details = Diagnostics.ErrorDetails{ .arg_index = arg_i, .arg_span = arg.missingSpan() }; diff --git a/src/main.zig b/src/main.zig index 4c4727a..00e1ee4 100644 --- a/src/main.zig +++ b/src/main.zig @@ -83,7 +83,7 @@ pub fn main() !void { defer aro_arena_state.deinit(); const aro_arena = aro_arena_state.allocator(); - const include_paths = getIncludePaths(aro_arena, options.auto_includes) catch |err| switch (err) { + const include_paths = getIncludePaths(aro_arena, options.auto_includes, options.mingw_includes_dir) catch |err| switch (err) { error.OutOfMemory => |e| return e, else => { switch (err) { @@ -278,7 +278,7 @@ pub fn main() !void { } } -fn getIncludePaths(allocator: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes) ![]const []const u8 { +fn getIncludePaths(allocator: std.mem.Allocator, auto_includes_option: cli.Options.AutoIncludes, maybe_mingw_includes_dir: ?[]const u8) ![]const []const u8 { var includes = auto_includes_option; if (builtin.target.os.tag != .windows) { switch (includes) { @@ -311,9 +311,14 @@ fn getIncludePaths(allocator: std.mem.Allocator, auto_includes_option: cli.Optio }; }, .gnu => { - var progress = std.Progress{}; - - const include_path = try auto_includes.extractMingwIncludes(allocator, &progress); + const include_path = include_path: { + if (maybe_mingw_includes_dir) |mingw_includes_dir| { + break :include_path try allocator.dupe(u8, mingw_includes_dir); + } else { + var progress = std.Progress{}; + break :include_path try auto_includes.extractMingwIncludes(allocator, &progress); + } + }; errdefer allocator.free(include_path); var include_paths = try allocator.alloc([]const u8, 1);