Commit 7116b02210

Krzysztof Wolicki <der.teufel.mail@gmail.com>
2024-01-14 21:21:10
Allow multiple options using the same enum type
1 parent 88ee323
Changed files (1)
lib
std
Build
lib/std/Build/Step/Options.zig
@@ -14,6 +14,7 @@ generated_file: GeneratedFile,
 
 contents: std.ArrayList(u8),
 args: std.ArrayList(Arg),
+encountered_types: std.StringHashMap(void),
 
 pub fn create(owner: *std.Build) *Options {
     const self = owner.allocator.create(Options) catch @panic("OOM");
@@ -27,6 +28,7 @@ pub fn create(owner: *std.Build) *Options {
         .generated_file = undefined,
         .contents = std.ArrayList(u8).init(owner.allocator),
         .args = std.ArrayList(Arg).init(owner.allocator),
+        .encountered_types = std.StringHashMap(void).init(owner.allocator),
     };
     self.generated_file = .{ .step = &self.step };
 
@@ -101,11 +103,14 @@ fn addOptionFallible(self: *Options, comptime T: type, name: []const u8, value:
     }
     switch (@typeInfo(T)) {
         .Enum => |enum_info| {
-            try out.print("pub const {} = enum {{\n", .{std.zig.fmtId(@typeName(T))});
-            inline for (enum_info.fields) |field| {
-                try out.print("    {},\n", .{std.zig.fmtId(field.name)});
+            const gop = try self.encountered_types.getOrPut(@typeName(T));
+            if (!gop.found_existing) {
+                try out.print("pub const {} = enum {{\n", .{std.zig.fmtId(@typeName(T))});
+                inline for (enum_info.fields) |field| {
+                    try out.print("    {},\n", .{std.zig.fmtId(field.name)});
+                }
+                try out.writeAll("};\n");
             }
-            try out.writeAll("};\n");
             try out.print("pub const {}: {s} = .{s};\n", .{
                 std.zig.fmtId(name),
                 std.zig.fmtId(@typeName(T)),
@@ -322,6 +327,11 @@ test Options {
         @"0.8.1",
     };
 
+    const NormalEnum = enum {
+        foo,
+        bar,
+    };
+
     const nested_array = [2][2]u16{
         [2]u16{ 300, 200 },
         [2]u16{ 300, 200 },
@@ -338,6 +348,8 @@ test Options {
     options.addOption([]const []const u16, "nested_slice", nested_slice);
     options.addOption(KeywordEnum, "keyword_enum", .@"0.8.1");
     options.addOption(std.SemanticVersion, "semantic_version", try std.SemanticVersion.parse("0.1.2-foo+bar"));
+    options.addOption(NormalEnum, "normal1", NormalEnum.foo);
+    options.addOption(NormalEnum, "normal2", NormalEnum.bar);
 
     try std.testing.expectEqualStrings(
         \\pub const option1: usize = 1;
@@ -377,6 +389,12 @@ test Options {
         \\    .pre = "foo",
         \\    .build = "bar",
         \\};
+        \\pub const @"Build.Step.Options.decltest.Options.NormalEnum" = enum {
+        \\    foo,
+        \\    bar,
+        \\};
+        \\pub const normal1: @"Build.Step.Options.decltest.Options.NormalEnum" = .foo;
+        \\pub const normal2: @"Build.Step.Options.decltest.Options.NormalEnum" = .bar;
         \\
     , options.contents.items);