authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-22 00:25:09-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-02-22 00:25:09-05:00
loga7467b9bb2aa667a8d34bc8b678ce35fcb19ebd4
treeddfd13e95e409cb787aba1fb875596912312d59a
parent300cb4881f675140d89a8bbd889d51490701fbac
parentc1c6f082961a2735ff3c91167f0e1bcfcfcc2010
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22941 from Techatrix/config-header

std.Build.Step.ConfigHeader: improve handling of autoconf style headers

5 files changed, 88 insertions(+), 8 deletions(-)

lib/std/Build/Step/ConfigHeader.zig+13-8
...@@ -131,7 +131,7 @@ fn putValue(config_header: *ConfigHeader, field_name: []const u8, comptime T: ty...@@ -131,7 +131,7 @@ fn putValue(config_header: *ConfigHeader, field_name: []const u8, comptime T: ty
131 .comptime_int => {131 .comptime_int => {
132 try config_header.values.put(field_name, .{ .int = v });132 try config_header.values.put(field_name, .{ .int = v });
133 },133 },
134 .enum_literal => {134 .@"enum", .enum_literal => {
135 try config_header.values.put(field_name, .{ .ident = @tagName(v) });135 try config_header.values.put(field_name, .{ .ident = @tagName(v) });
136 },136 },
137 .optional => {137 .optional => {
...@@ -264,8 +264,11 @@ fn render_autoconf(...@@ -264,8 +264,11 @@ fn render_autoconf(
264 values: std.StringArrayHashMap(Value),264 values: std.StringArrayHashMap(Value),
265 src_path: []const u8,265 src_path: []const u8,
266) !void {266) !void {
267 var values_copy = try values.clone();267 const build = step.owner;
268 defer values_copy.deinit();268 const allocator = build.allocator;
269
270 var is_used: std.DynamicBitSetUnmanaged = try .initEmpty(allocator, values.count());
271 defer is_used.deinit(allocator);
269272
270 var any_errors = false;273 var any_errors = false;
271 var line_index: u32 = 0;274 var line_index: u32 = 0;
...@@ -283,19 +286,21 @@ fn render_autoconf(...@@ -283,19 +286,21 @@ fn render_autoconf(
283 try output.appendSlice("\n");286 try output.appendSlice("\n");
284 continue;287 continue;
285 }288 }
286 const name = it.rest();289 const name = it.next().?;
287 const kv = values_copy.fetchSwapRemove(name) orelse {290 const index = values.getIndex(name) orelse {
288 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{291 try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
289 src_path, line_index + 1, name,292 src_path, line_index + 1, name,
290 });293 });
291 any_errors = true;294 any_errors = true;
292 continue;295 continue;
293 };296 };
294 try renderValueC(output, name, kv.value);297 is_used.set(index);
298 try renderValueC(output, name, values.values()[index]);
295 }299 }
296300
297 for (values_copy.keys()) |name| {301 var unused_value_it = is_used.iterator(.{ .kind = .unset });
298 try step.addError("{s}: error: config header value unused: '{s}'", .{ src_path, name });302 while (unused_value_it.next()) |index| {
303 try step.addError("{s}: error: config header value unused: '{s}'", .{ src_path, values.keys()[index] });
299 any_errors = true;304 any_errors = true;
300 }305 }
301306
test/standalone/build.zig.zon+3
...@@ -186,6 +186,9 @@...@@ -186,6 +186,9 @@
186 .omit_cfi = .{186 .omit_cfi = .{
187 .path = "omit_cfi",187 .path = "omit_cfi",
188 },188 },
189 .config_header = .{
190 .path = "config_header",
191 },
189 },192 },
190 .paths = .{193 .paths = .{
191 "build.zig",194 "build.zig",
test/standalone/config_header/build.zig created+28
...@@ -0,0 +1,28 @@
1const std = @import("std");
2
3pub fn build(b: *std.Build) void {
4 const config_header = b.addConfigHeader(
5 .{ .style = .{ .autoconf = b.path("config.h.in") } },
6 .{
7 .SOME_NO = null,
8 .SOME_TRUE = true,
9 .SOME_FALSE = false,
10 .SOME_ZERO = 0,
11 .SOME_ONE = 1,
12 .SOME_TEN = 10,
13 .SOME_ENUM = @as(enum { foo, bar }, .foo),
14 .SOME_ENUM_LITERAL = .@"test",
15 .SOME_STRING = "test",
16
17 .PREFIX_SPACE = null,
18 .PREFIX_TAB = null,
19 .POSTFIX_SPACE = null,
20 .POSTFIX_TAB = null,
21 },
22 );
23
24 const check_config_header = b.addCheckFile(config_header.getOutput(), .{ .expected_exact = @embedFile("config.h") });
25
26 const test_step = b.step("test", "Test it");
27 test_step.dependOn(&check_config_header.step);
28}
test/standalone/config_header/config.h created+23
...@@ -0,0 +1,23 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2/* Some Comment */
3
4int foo();
5
6/* #undef SOME_NO */
7#define SOME_TRUE 1
8#define SOME_FALSE 0
9#define SOME_ZERO 0
10#define SOME_ONE 1
11#define SOME_TEN 10
12#define SOME_ENUM foo
13#define SOME_ENUM_LITERAL test
14#define SOME_STRING "test"
15
16// Used twice
17#define SOME_TRUE 1
18
19/* #undef PREFIX_SPACE */
20/* #undef PREFIX_TAB */
21/* #undef POSTFIX_SPACE */
22/* #undef POSTFIX_TAB */
23
test/standalone/config_header/config.h.in created+21
...@@ -0,0 +1,21 @@
1/* Some Comment */
2
3int foo();
4
5#undef SOME_NO
6#undef SOME_TRUE
7#undef SOME_FALSE
8#undef SOME_ZERO
9#undef SOME_ONE
10#undef SOME_TEN
11#undef SOME_ENUM
12#undef SOME_ENUM_LITERAL
13#undef SOME_STRING
14
15// Used twice
16#undef SOME_TRUE
17
18#undef PREFIX_SPACE
19#undef PREFIX_TAB
20#undef POSTFIX_SPACE
21#undef POSTFIX_TAB