Skip to content

Commit

Permalink
Add /:mingw-includes CLI option
Browse files Browse the repository at this point in the history
Can be used to avoid extracting/using the bundled MinGW includes
  • Loading branch information
squeek502 committed Mar 2, 2024
1 parent 0946d56 commit e29c0ff
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 18 deletions.
50 changes: 37 additions & 13 deletions src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ pub const usage_string_after_command_name =
\\ /:auto-includes <value> 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 <path> Output a file containing a list of all the files that the
\\ .rc includes or otherwise depends on.
\\ /:depfile <path> Output a file containing a list of all the files that
\\ the .rc includes or otherwise depends on.
\\ /:depfile-fmt <value> Output format of the depfile, if /:depfile is set.
\\ json (default) A top-level JSON array of paths
\\ /:mingw-includes <path> 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 :
\\
Expand Down Expand Up @@ -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 };
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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")) {
Expand All @@ -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() };
Expand Down
15 changes: 10 additions & 5 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit e29c0ff

Please sign in to comment.