commit ea3be3d4fe2c4f0aae29c2889c2079fb18133726 (tree)
parent 645a38aeb69846b7b692fabdd63f62d6e5a17464
Author: Andrew Kelley <andrew@ziglang.org>
Date: Thu, 4 Jun 2026 21:44:04 +0200
Merge pull request 'CLI: update sub-command to use StaticStringMap' (#35612) from static-string-map into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35612
Diffstat:
2 files changed, 271 insertions(+), 143 deletions(-)
diff --git a/lib/std/static_string_map.zig b/lib/std/static_string_map.zig
@@ -100,6 +100,52 @@ pub fn StaticStringMapWithEql(
}
}
+ /// Returns a map backed by static, comptime allocated memory.
+ ///
+ /// `V` must be an enum. The enum's tag names will be used as the keys.
+ pub inline fn initEnum() Self {
+ comptime {
+ var self: Self = .{};
+
+ const field_names = @typeInfo(V).@"enum".field_names;
+ if (field_names.len == 0) return self;
+
+ // Since the KVs are sorted, a linearly-growing bound will never
+ // be sufficient for extreme cases. So we grow proportional to
+ // N*log2(N).
+ @setEvalBranchQuota(10 * field_names.len * std.math.log2_int_ceil(usize, field_names.len));
+
+ var sorted_keys: [field_names.len][]const u8 = field_names[0..field_names.len].*;
+ var sorted_vals: [field_names.len]V = undefined;
+ for (&sorted_vals, @typeInfo(V).@"enum".field_values) |*x, i| x.* = @enumFromInt(i);
+
+ for (field_names) |field_name| {
+ self.min_len = @min(self.min_len, field_name.len);
+ self.max_len = @max(self.max_len, field_name.len);
+ }
+
+ mem.sortUnstableContext(0, sorted_keys.len, SortContext{
+ .keys = &sorted_keys,
+ .vals = &sorted_vals,
+ });
+
+ const final_keys = sorted_keys;
+ const final_vals = sorted_vals;
+ self.kvs = &.{
+ .keys = &final_keys,
+ .values = &final_vals,
+ .len = @intCast(field_names.len),
+ };
+
+ var len_indexes: [self.max_len + 1]u32 = undefined;
+ self.initLenIndexes(&len_indexes);
+ const final_len_indexes = len_indexes;
+ self.len_indexes = &final_len_indexes;
+ self.len_indexes_len = @intCast(len_indexes.len);
+ return self;
+ }
+ }
+
/// Returns a map backed by memory allocated with `allocator`.
///
/// Handles `kvs_list` the same way as `initComptime()`.
@@ -195,7 +241,7 @@ pub fn StaticStringMapWithEql(
return self.kvs.values[self.getIndex(str) orelse return null];
}
- pub fn getIndex(self: Self, str: []const u8) ?usize {
+ fn getIndex(self: Self, str: []const u8) ?usize {
const kvs = self.kvs.*;
if (kvs.len == 0)
return null;
@@ -536,3 +582,15 @@ test "sorting kvs doesn't exceed eval branch quota" {
});
try testing.expectEqual(1, TypeToByteSizeLUT.get("t1"));
}
+
+test "initEnum" {
+ const UnsortedEnum = enum { BB, A, CCC, DDD };
+ const map = StaticStringMap(UnsortedEnum).initEnum();
+ try testing.expect(map.has("A"));
+ try testing.expect(!map.has("a"));
+ try testing.expectEqual(.BB, map.get("BB"));
+ try testing.expectEqual(.A, map.get("A"));
+ try testing.expectEqual(.CCC, map.get("CCC"));
+ try testing.expectEqual(.DDD, map.get("DDD"));
+ try testing.expectEqual(null, map.getIndex("F"));
+}
diff --git a/src/main.zig b/src/main.zig
@@ -229,6 +229,57 @@ pub fn main(init: std.process.Init.Minimal) anyerror!void {
return mainArgs(gpa, arena, io, args, &environ_map);
}
+const cmd_map = std.StaticStringMap(Cmd).initEnum();
+
+const Cmd = enum {
+ @"build-exe",
+ @"build-lib",
+ @"build-obj",
+ @"test",
+ @"test-obj",
+ run,
+
+ dlltool,
+ ranlib,
+ lib,
+ ar,
+
+ build,
+
+ clang,
+ @"-cc1",
+ @"-cc1as",
+
+ @"ld.lld",
+ @"lld-link",
+ @"wasm-ld",
+
+ cc,
+ @"c++",
+ @"translate-c",
+ rc,
+ fmt,
+ objcopy,
+ objdump,
+ fetch,
+ libc,
+ std,
+ init,
+ targets,
+ version,
+ env,
+ reduce,
+ zen,
+ @"ast-check",
+
+ help,
+ @"-h",
+ @"--help",
+
+ changelist,
+ @"dump-zir",
+};
+
fn mainArgs(
gpa: Allocator,
arena: Allocator,
@@ -271,144 +322,169 @@ fn mainArgs(
const cmd = args[1];
const cmd_args = args[2..];
- if (mem.eql(u8, cmd, "build-exe")) {
- dev.check(.build_exe_command);
- return buildOutputType(gpa, arena, io, args, .{ .build = .Exe }, environ_map);
- } else if (mem.eql(u8, cmd, "build-lib")) {
- dev.check(.build_lib_command);
- return buildOutputType(gpa, arena, io, args, .{ .build = .Lib }, environ_map);
- } else if (mem.eql(u8, cmd, "build-obj")) {
- dev.check(.build_obj_command);
- return buildOutputType(gpa, arena, io, args, .{ .build = .Obj }, environ_map);
- } else if (mem.eql(u8, cmd, "test")) {
- dev.check(.test_command);
- return buildOutputType(gpa, arena, io, args, .zig_test, environ_map);
- } else if (mem.eql(u8, cmd, "test-obj")) {
- dev.check(.test_command);
- return buildOutputType(gpa, arena, io, args, .zig_test_obj, environ_map);
- } else if (mem.eql(u8, cmd, "run")) {
- dev.check(.run_command);
- return buildOutputType(gpa, arena, io, args, .run, environ_map);
- } else if (mem.eql(u8, cmd, "dlltool") or
- mem.eql(u8, cmd, "ranlib") or
- mem.eql(u8, cmd, "lib") or
- mem.eql(u8, cmd, "ar"))
- {
- dev.check(.ar_command);
- return process.exit(try llvmArMain(arena, args));
- } else if (mem.eql(u8, cmd, "build")) {
- dev.check(.build_command);
- return cmdBuild(gpa, arena, io, cmd_args, environ_map);
- } else if (mem.eql(u8, cmd, "clang") or
- mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as"))
- {
- dev.check(.clang_command);
- return process.exit(try clangMain(arena, args));
- } else if (mem.eql(u8, cmd, "ld.lld") or
- mem.eql(u8, cmd, "lld-link") or
- mem.eql(u8, cmd, "wasm-ld"))
- {
- dev.check(.lld_linker);
- return process.exit(try lldMain(arena, args, true));
- } else if (mem.eql(u8, cmd, "cc")) {
- dev.check(.cc_command);
- return buildOutputType(gpa, arena, io, args, .cc, environ_map);
- } else if (mem.eql(u8, cmd, "c++")) {
- dev.check(.cc_command);
- return buildOutputType(gpa, arena, io, args, .cpp, environ_map);
- } else if (mem.eql(u8, cmd, "translate-c")) {
- dev.check(.translate_c_command);
- return buildOutputType(gpa, arena, io, args, .translate_c, environ_map);
- } else if (mem.eql(u8, cmd, "rc")) {
- const use_server = cmd_args.len > 0 and std.mem.eql(u8, cmd_args[0], "--zig-integration");
- return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
- .cmd_name = "resinator",
- .root_src_path = "resinator/main.zig",
- .depend_on_aro = true,
- .prepend_zig_lib_dir_path = true,
- .server = use_server,
- .color = Color.settingFromEnvironment(environ_map),
- });
- } else if (mem.eql(u8, cmd, "fmt")) {
- dev.check(.fmt_command);
- return @import("fmt.zig").run(gpa, arena, io, cmd_args);
- } else if (mem.eql(u8, cmd, "objcopy")) {
- return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
- .cmd_name = "objcopy",
- .root_src_path = "objcopy.zig",
- .color = Color.settingFromEnvironment(environ_map),
- });
- } else if (mem.eql(u8, cmd, "objdump")) {
- return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
- .cmd_name = "objdump",
- .root_src_path = "objdump.zig",
- .color = Color.settingFromEnvironment(environ_map),
- });
- } else if (mem.eql(u8, cmd, "fetch")) {
- return cmdFetch(gpa, arena, io, cmd_args, environ_map);
- } else if (mem.eql(u8, cmd, "libc")) {
- return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
- .cmd_name = "libc",
- .root_src_path = "libc.zig",
- .prepend_zig_lib_dir_path = true,
- .color = Color.settingFromEnvironment(environ_map),
- });
- } else if (mem.eql(u8, cmd, "std")) {
- return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
- .cmd_name = "std",
- .root_src_path = "std-docs.zig",
- .prepend_zig_lib_dir_path = true,
- .prepend_zig_exe_path = true,
- .prepend_global_cache_path = true,
- .color = Color.settingFromEnvironment(environ_map),
- });
- } else if (mem.eql(u8, cmd, "init")) {
- return cmdInit(gpa, arena, io, cmd_args);
- } else if (mem.eql(u8, cmd, "targets")) {
- dev.check(.targets_command);
- const host = std.zig.resolveTargetQueryOrFatal(io, .{});
- var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
- try @import("print_targets.zig").cmdTargets(arena, io, cmd_args, &stdout_writer.interface, &host);
- return stdout_writer.interface.flush();
- } else if (mem.eql(u8, cmd, "version")) {
- dev.check(.version_command);
- try Io.File.stdout().writeStreamingAll(io, build_options.version ++ "\n");
- return;
- } else if (mem.eql(u8, cmd, "env")) {
- dev.check(.env_command);
- const host = std.zig.resolveTargetQueryOrFatal(io, .{});
- var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
- try @import("print_env.zig").cmdEnv(
- arena,
- io,
- &stdout_writer.interface,
- args,
- preopens,
- &host,
- environ_map,
- );
- return stdout_writer.interface.flush();
- } else if (mem.eql(u8, cmd, "reduce")) {
- return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
- .cmd_name = "reduce",
- .root_src_path = "reduce.zig",
- .color = Color.settingFromEnvironment(environ_map),
- });
- } else if (mem.eql(u8, cmd, "zen")) {
- dev.check(.zen_command);
- return Io.File.stdout().writeStreamingAll(io, info_zen);
- } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) {
- dev.check(.help_command);
- return Io.File.stdout().writeStreamingAll(io, usage);
- } else if (mem.eql(u8, cmd, "ast-check")) {
- return cmdAstCheck(arena, io, cmd_args, environ_map);
- } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "changelist")) {
- return cmdChangelist(arena, io, cmd_args, environ_map);
- } else if (build_options.enable_debug_extensions and mem.eql(u8, cmd, "dump-zir")) {
- return cmdDumpZir(arena, io, cmd_args);
- } else {
+ switch (cmd_map.get(cmd) orelse {
std.log.info("{s}", .{usage});
fatal("unknown command: {s}", .{args[1]});
+ }) {
+ .@"build-exe" => {
+ dev.check(.build_exe_command);
+ return buildOutputType(gpa, arena, io, args, .{ .build = .Exe }, environ_map);
+ },
+ .@"build-lib" => {
+ dev.check(.build_lib_command);
+ return buildOutputType(gpa, arena, io, args, .{ .build = .Lib }, environ_map);
+ },
+ .@"build-obj" => {
+ dev.check(.build_obj_command);
+ return buildOutputType(gpa, arena, io, args, .{ .build = .Obj }, environ_map);
+ },
+ .@"test" => {
+ dev.check(.test_command);
+ return buildOutputType(gpa, arena, io, args, .zig_test, environ_map);
+ },
+ .@"test-obj" => {
+ dev.check(.test_command);
+ return buildOutputType(gpa, arena, io, args, .zig_test_obj, environ_map);
+ },
+ .run => {
+ dev.check(.run_command);
+ return buildOutputType(gpa, arena, io, args, .run, environ_map);
+ },
+ .dlltool, .ranlib, .lib, .ar => {
+ dev.check(.ar_command);
+ return process.exit(try llvmArMain(arena, args));
+ },
+ .build => {
+ dev.check(.build_command);
+ return cmdBuild(gpa, arena, io, cmd_args, environ_map);
+ },
+ .clang, .@"-cc1", .@"-cc1as" => {
+ dev.check(.clang_command);
+ return process.exit(try clangMain(arena, args));
+ },
+ .@"ld.lld", .@"lld-link", .@"wasm-ld" => {
+ dev.check(.lld_linker);
+ return process.exit(try lldMain(arena, args, true));
+ },
+ .cc => {
+ dev.check(.cc_command);
+ return buildOutputType(gpa, arena, io, args, .cc, environ_map);
+ },
+ .@"c++" => {
+ dev.check(.cc_command);
+ return buildOutputType(gpa, arena, io, args, .cpp, environ_map);
+ },
+ .@"translate-c" => {
+ dev.check(.translate_c_command);
+ return buildOutputType(gpa, arena, io, args, .translate_c, environ_map);
+ },
+ .rc => {
+ const use_server = cmd_args.len > 0 and std.mem.eql(u8, cmd_args[0], "--zig-integration");
+ return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
+ .cmd_name = "resinator",
+ .root_src_path = "resinator/main.zig",
+ .depend_on_aro = true,
+ .prepend_zig_lib_dir_path = true,
+ .server = use_server,
+ .color = Color.settingFromEnvironment(environ_map),
+ });
+ },
+ .fmt => {
+ dev.check(.fmt_command);
+ return @import("fmt.zig").run(gpa, arena, io, cmd_args);
+ },
+ .objcopy => {
+ return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
+ .cmd_name = "objcopy",
+ .root_src_path = "objcopy.zig",
+ .color = Color.settingFromEnvironment(environ_map),
+ });
+ },
+ .objdump => {
+ return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
+ .cmd_name = "objdump",
+ .root_src_path = "objdump.zig",
+ .color = Color.settingFromEnvironment(environ_map),
+ });
+ },
+ .fetch => {
+ return cmdFetch(gpa, arena, io, cmd_args, environ_map);
+ },
+ .libc => {
+ return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
+ .cmd_name = "libc",
+ .root_src_path = "libc.zig",
+ .prepend_zig_lib_dir_path = true,
+ .color = Color.settingFromEnvironment(environ_map),
+ });
+ },
+ .std => {
+ return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
+ .cmd_name = "std",
+ .root_src_path = "std-docs.zig",
+ .prepend_zig_lib_dir_path = true,
+ .prepend_zig_exe_path = true,
+ .prepend_global_cache_path = true,
+ .color = Color.settingFromEnvironment(environ_map),
+ });
+ },
+ .init => {
+ return cmdInit(gpa, arena, io, cmd_args);
+ },
+ .targets => {
+ dev.check(.targets_command);
+ const host = std.zig.resolveTargetQueryOrFatal(io, .{});
+ var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
+ try @import("print_targets.zig").cmdTargets(arena, io, cmd_args, &stdout_writer.interface, &host);
+ return stdout_writer.interface.flush();
+ },
+ .version => {
+ dev.check(.version_command);
+ try Io.File.stdout().writeStreamingAll(io, build_options.version ++ "\n");
+ return;
+ },
+ .env => {
+ dev.check(.env_command);
+ const host = std.zig.resolveTargetQueryOrFatal(io, .{});
+ var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
+ try @import("print_env.zig").cmdEnv(
+ arena,
+ io,
+ &stdout_writer.interface,
+ args,
+ preopens,
+ &host,
+ environ_map,
+ );
+ return stdout_writer.interface.flush();
+ },
+ .reduce => {
+ return jitCmd(gpa, arena, io, cmd_args, environ_map, .{
+ .cmd_name = "reduce",
+ .root_src_path = "reduce.zig",
+ .color = Color.settingFromEnvironment(environ_map),
+ });
+ },
+ .zen => {
+ dev.check(.zen_command);
+ return Io.File.stdout().writeStreamingAll(io, info_zen);
+ },
+ .help, .@"-h", .@"--help" => {
+ dev.check(.help_command);
+ return Io.File.stdout().writeStreamingAll(io, usage);
+ },
+ .@"ast-check" => {
+ dev.check(.ast_check_command);
+ return cmdAstCheck(arena, io, cmd_args, environ_map);
+ },
+ .changelist => {
+ dev.check(.changelist_command);
+ return cmdChangelist(arena, io, cmd_args, environ_map);
+ },
+ .@"dump-zir" => {
+ dev.check(.dump_zir_command);
+ return cmdDumpZir(arena, io, cmd_args);
+ },
}
}
@@ -6537,8 +6613,6 @@ const usage_ast_check =
;
fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map: *const std.process.Environ.Map) !void {
- dev.check(.ast_check_command);
-
const Zir = std.zig.Zir;
var color: Color = Color.settingFromEnvironment(environ_map);
@@ -6705,8 +6779,6 @@ fn cmdAstCheck(arena: Allocator, io: Io, args: []const []const u8, environ_map:
/// This is only enabled for debug builds.
fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void {
- dev.check(.dump_zir_command);
-
const Zir = std.zig.Zir;
const cache_file = args[0];
@@ -6749,8 +6821,6 @@ fn cmdDumpZir(arena: Allocator, io: Io, args: []const []const u8) !void {
/// This is only enabled for debug builds.
fn cmdChangelist(arena: Allocator, io: Io, args: []const []const u8, environ_map: *const std.process.Environ.Map) !void {
- dev.check(.changelist_command);
-
const color: Color = Color.settingFromEnvironment(environ_map);
const Zir = std.zig.Zir;