aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Build/Step/ConfigHeader.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-06-27 20:05:22 -0700
committerAndrew Kelley <andrew@ziglang.org>2025-07-07 22:43:51 -0700
commit0e37ff0d591dd75ceec9208196bec29efaec607a (patch)
treec126fa823a1f3864e9c363aac70e3a3db0219957 /lib/std/Build/Step/ConfigHeader.zig
parent0b3f0124dc33403d329fb8ee63a93215d9af1f1e (diff)
downloadzig-0e37ff0d591dd75ceec9208196bec29efaec607a.tar.gz
zig-0e37ff0d591dd75ceec9208196bec29efaec607a.zip
std.fmt: breaking API changes
added adapter to AnyWriter and GenericWriter to help bridge the gap between old and new API make std.testing.expectFmt work at compile-time std.fmt no longer has a dependency on std.unicode. Formatted printing was never properly unicode-aware. Now it no longer pretends to be. Breakage/deprecations: * std.fs.File.reader -> std.fs.File.deprecatedReader * std.fs.File.writer -> std.fs.File.deprecatedWriter * std.io.GenericReader -> std.io.Reader * std.io.GenericWriter -> std.io.Writer * std.io.AnyReader -> std.io.Reader * std.io.AnyWriter -> std.io.Writer * std.fmt.format -> std.fmt.deprecatedFormat * std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape * std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape * std.fmt.fmtSliceHexLower -> {x} * std.fmt.fmtSliceHexUpper -> {X} * std.fmt.fmtIntSizeDec -> {B} * std.fmt.fmtIntSizeBin -> {Bi} * std.fmt.fmtDuration -> {D} * std.fmt.fmtDurationSigned -> {D} * {} -> {f} when there is a format method * format method signature - anytype -> *std.io.Writer - inferred error set -> error{WriteFailed} - options -> (deleted) * std.fmt.Formatted - now takes context type explicitly - no fmt string
Diffstat (limited to 'lib/std/Build/Step/ConfigHeader.zig')
-rw-r--r--lib/std/Build/Step/ConfigHeader.zig230
1 files changed, 91 insertions, 139 deletions
diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig
index 967e1edd05..d8a7a08b33 100644
--- a/lib/std/Build/Step/ConfigHeader.zig
+++ b/lib/std/Build/Step/ConfigHeader.zig
@@ -2,6 +2,7 @@ const std = @import("std");
const ConfigHeader = @This();
const Step = std.Build.Step;
const Allocator = std.mem.Allocator;
+const Writer = std.io.Writer;
pub const Style = union(enum) {
/// A configure format supported by autotools that uses `#undef foo` to
@@ -87,7 +88,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
config_header.* = .{
- .step = Step.init(.{
+ .step = .init(.{
.id = base_id,
.name = name,
.owner = owner,
@@ -95,7 +96,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
.first_ret_addr = options.first_ret_addr orelse @returnAddress(),
}),
.style = options.style,
- .values = std.StringArrayHashMap(Value).init(owner.allocator),
+ .values = .init(owner.allocator),
.max_bytes = options.max_bytes,
.include_path = include_path,
@@ -195,8 +196,9 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
man.hash.addBytes(config_header.include_path);
man.hash.addOptionalBytes(config_header.include_guard_override);
- var output = std.ArrayList(u8).init(gpa);
- defer output.deinit();
+ var aw: std.io.Writer.Allocating = .init(gpa);
+ defer aw.deinit();
+ const bw = &aw.interface;
const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
const c_generated_line = "/* " ++ header_text ++ " */\n";
@@ -204,7 +206,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
switch (config_header.style) {
.autoconf_undef, .autoconf, .autoconf_at => |file_source| {
- try output.appendSlice(c_generated_line);
+ try bw.writeAll(c_generated_line);
const src_path = file_source.getPath2(b, step);
const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
return step.fail("unable to read autoconf input file '{s}': {s}", .{
@@ -212,32 +214,33 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
});
};
switch (config_header.style) {
- .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, &output, config_header.values, src_path),
- .autoconf_at => try render_autoconf_at(step, contents, &output, config_header.values, src_path),
+ .autoconf_undef, .autoconf => try render_autoconf_undef(step, contents, bw, config_header.values, src_path),
+ .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path),
else => unreachable,
}
},
.cmake => |file_source| {
- try output.appendSlice(c_generated_line);
+ try bw.writeAll(c_generated_line);
const src_path = file_source.getPath2(b, step);
const contents = std.fs.cwd().readFileAlloc(arena, src_path, config_header.max_bytes) catch |err| {
return step.fail("unable to read cmake input file '{s}': {s}", .{
src_path, @errorName(err),
});
};
- try render_cmake(step, contents, &output, config_header.values, src_path);
+ try render_cmake(step, contents, bw, config_header.values, src_path);
},
.blank => {
- try output.appendSlice(c_generated_line);
- try render_blank(&output, config_header.values, config_header.include_path, config_header.include_guard_override);
+ try bw.writeAll(c_generated_line);
+ try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override);
},
.nasm => {
- try output.appendSlice(asm_generated_line);
- try render_nasm(&output, config_header.values);
+ try bw.writeAll(asm_generated_line);
+ try render_nasm(bw, config_header.values);
},
}
- man.hash.addBytes(output.items);
+ const output = aw.getWritten();
+ man.hash.addBytes(output);
if (try step.cacheHit(&man)) {
const digest = man.final();
@@ -256,13 +259,13 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
const sub_path_dirname = std.fs.path.dirname(sub_path).?;
b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
- return step.fail("unable to make path '{}{s}': {s}", .{
+ return step.fail("unable to make path '{f}{s}': {s}", .{
b.cache_root, sub_path_dirname, @errorName(err),
});
};
- b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output.items }) catch |err| {
- return step.fail("unable to write file '{}{s}': {s}", .{
+ b.cache_root.handle.writeFile(.{ .sub_path = sub_path, .data = output }) catch |err| {
+ return step.fail("unable to write file '{f}{s}': {s}", .{
b.cache_root, sub_path, @errorName(err),
});
};
@@ -274,7 +277,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
fn render_autoconf_undef(
step: *Step,
contents: []const u8,
- output: *std.ArrayList(u8),
+ bw: *Writer,
values: std.StringArrayHashMap(Value),
src_path: []const u8,
) !void {
@@ -289,15 +292,15 @@ fn render_autoconf_undef(
var line_it = std.mem.splitScalar(u8, contents, '\n');
while (line_it.next()) |line| : (line_index += 1) {
if (!std.mem.startsWith(u8, line, "#")) {
- try output.appendSlice(line);
- try output.appendSlice("\n");
+ try bw.writeAll(line);
+ try bw.writeByte('\n');
continue;
}
var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
const undef = it.next().?;
if (!std.mem.eql(u8, undef, "undef")) {
- try output.appendSlice(line);
- try output.appendSlice("\n");
+ try bw.writeAll(line);
+ try bw.writeByte('\n');
continue;
}
const name = it.next().?;
@@ -309,7 +312,7 @@ fn render_autoconf_undef(
continue;
};
is_used.set(index);
- try renderValueC(output, name, values.values()[index]);
+ try renderValueC(bw, name, values.values()[index]);
}
var unused_value_it = is_used.iterator(.{ .kind = .unset });
@@ -326,12 +329,13 @@ fn render_autoconf_undef(
fn render_autoconf_at(
step: *Step,
contents: []const u8,
- output: *std.ArrayList(u8),
+ aw: *std.io.Writer.Allocating,
values: std.StringArrayHashMap(Value),
src_path: []const u8,
) !void {
const build = step.owner;
const allocator = build.allocator;
+ const bw = &aw.interface;
const used = allocator.alloc(bool, values.count()) catch @panic("OOM");
for (used) |*u| u.* = false;
@@ -343,11 +347,11 @@ fn render_autoconf_at(
while (line_it.next()) |line| : (line_index += 1) {
const last_line = line_it.index == line_it.buffer.len;
- const old_len = output.items.len;
- expand_variables_autoconf_at(output, line, values, used) catch |err| switch (err) {
+ const old_len = aw.getWritten().len;
+ expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) {
error.MissingValue => {
- const name = output.items[old_len..];
- defer output.shrinkRetainingCapacity(old_len);
+ const name = aw.getWritten()[old_len..];
+ defer aw.shrinkRetainingCapacity(old_len);
try step.addError("{s}:{d}: error: unspecified config header value: '{s}'", .{
src_path, line_index + 1, name,
});
@@ -362,9 +366,7 @@ fn render_autoconf_at(
continue;
},
};
- if (!last_line) {
- try output.append('\n');
- }
+ if (!last_line) try bw.writeByte('\n');
}
for (values.unmanaged.entries.slice().items(.key), used) |name, u| {
@@ -374,15 +376,13 @@ fn render_autoconf_at(
}
}
- if (any_errors) {
- return error.MakeFailed;
- }
+ if (any_errors) return error.MakeFailed;
}
fn render_cmake(
step: *Step,
contents: []const u8,
- output: *std.ArrayList(u8),
+ bw: *Writer,
values: std.StringArrayHashMap(Value),
src_path: []const u8,
) !void {
@@ -417,10 +417,8 @@ fn render_cmake(
defer allocator.free(line);
if (!std.mem.startsWith(u8, line, "#")) {
- try output.appendSlice(line);
- if (!last_line) {
- try output.appendSlice("\n");
- }
+ try bw.writeAll(line);
+ if (!last_line) try bw.writeByte('\n');
continue;
}
var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
@@ -428,10 +426,8 @@ fn render_cmake(
if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and
!std.mem.eql(u8, cmakedefine, "cmakedefine01"))
{
- try output.appendSlice(line);
- if (!last_line) {
- try output.appendSlice("\n");
- }
+ try bw.writeAll(line);
+ if (!last_line) try bw.writeByte('\n');
continue;
}
@@ -502,7 +498,7 @@ fn render_cmake(
value = Value{ .ident = it.rest() };
}
- try renderValueC(output, name, value);
+ try renderValueC(bw, name, value);
}
if (any_errors) {
@@ -511,13 +507,14 @@ fn render_cmake(
}
fn render_blank(
- output: *std.ArrayList(u8),
+ gpa: std.mem.Allocator,
+ bw: *Writer,
defines: std.StringArrayHashMap(Value),
include_path: []const u8,
include_guard_override: ?[]const u8,
) !void {
const include_guard_name = include_guard_override orelse blk: {
- const name = try output.allocator.dupe(u8, include_path);
+ const name = try gpa.dupe(u8, include_path);
for (name) |*byte| {
switch (byte.*) {
'a'...'z' => byte.* = byte.* - 'a' + 'A',
@@ -527,92 +524,53 @@ fn render_blank(
}
break :blk name;
};
+ defer if (include_guard_override == null) gpa.free(include_guard_name);
- try output.appendSlice("#ifndef ");
- try output.appendSlice(include_guard_name);
- try output.appendSlice("\n#define ");
- try output.appendSlice(include_guard_name);
- try output.appendSlice("\n");
+ try bw.print(
+ \\#ifndef {[0]s}
+ \\#define {[0]s}
+ \\
+ , .{include_guard_name});
const values = defines.values();
- for (defines.keys(), 0..) |name, i| {
- try renderValueC(output, name, values[i]);
- }
+ for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]);
- try output.appendSlice("#endif /* ");
- try output.appendSlice(include_guard_name);
- try output.appendSlice(" */\n");
+ try bw.print(
+ \\#endif /* {s} */
+ \\
+ , .{include_guard_name});
}
-fn render_nasm(output: *std.ArrayList(u8), defines: std.StringArrayHashMap(Value)) !void {
- const values = defines.values();
- for (defines.keys(), 0..) |name, i| {
- try renderValueNasm(output, name, values[i]);
- }
+fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void {
+ for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value);
}
-fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {
+fn renderValueC(bw: *Writer, name: []const u8, value: Value) !void {
switch (value) {
- .undef => {
- try output.appendSlice("/* #undef ");
- try output.appendSlice(name);
- try output.appendSlice(" */\n");
- },
- .defined => {
- try output.appendSlice("#define ");
- try output.appendSlice(name);
- try output.appendSlice("\n");
- },
- .boolean => |b| {
- try output.appendSlice("#define ");
- try output.appendSlice(name);
- try output.appendSlice(if (b) " 1\n" else " 0\n");
- },
- .int => |i| {
- try output.writer().print("#define {s} {d}\n", .{ name, i });
- },
- .ident => |ident| {
- try output.writer().print("#define {s} {s}\n", .{ name, ident });
- },
- .string => |string| {
- // TODO: use C-specific escaping instead of zig string literals
- try output.writer().print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
- },
+ .undef => try bw.print("/* #undef {s} */\n", .{name}),
+ .defined => try bw.print("#define {s}\n", .{name}),
+ .boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
+ .int => |i| try bw.print("#define {s} {d}\n", .{ name, i }),
+ .ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }),
+ // TODO: use C-specific escaping instead of zig string literals
+ .string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
}
}
-fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !void {
+fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void {
switch (value) {
- .undef => {
- try output.appendSlice("; %undef ");
- try output.appendSlice(name);
- try output.appendSlice("\n");
- },
- .defined => {
- try output.appendSlice("%define ");
- try output.appendSlice(name);
- try output.appendSlice("\n");
- },
- .boolean => |b| {
- try output.appendSlice("%define ");
- try output.appendSlice(name);
- try output.appendSlice(if (b) " 1\n" else " 0\n");
- },
- .int => |i| {
- try output.writer().print("%define {s} {d}\n", .{ name, i });
- },
- .ident => |ident| {
- try output.writer().print("%define {s} {s}\n", .{ name, ident });
- },
- .string => |string| {
- // TODO: use nasm-specific escaping instead of zig string literals
- try output.writer().print("%define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
- },
+ .undef => try bw.print("; %undef {s}\n", .{name}),
+ .defined => try bw.print("%define {s}\n", .{name}),
+ .boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
+ .int => |i| try bw.print("%define {s} {d}\n", .{ name, i }),
+ .ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }),
+ // TODO: use nasm-specific escaping instead of zig string literals
+ .string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
}
}
fn expand_variables_autoconf_at(
- output: *std.ArrayList(u8),
+ bw: *Writer,
contents: []const u8,
values: std.StringArrayHashMap(Value),
used: []bool,
@@ -637,23 +595,17 @@ fn expand_variables_autoconf_at(
const key = contents[curr + 1 .. close_pos];
const index = values.getIndex(key) orelse {
// Report the missing key to the caller.
- try output.appendSlice(key);
+ try bw.writeAll(key);
return error.MissingValue;
};
const value = values.unmanaged.entries.slice().items(.value)[index];
used[index] = true;
- try output.appendSlice(contents[source_offset..curr]);
+ try bw.writeAll(contents[source_offset..curr]);
switch (value) {
.undef, .defined => {},
- .boolean => |b| {
- try output.append(if (b) '1' else '0');
- },
- .int => |i| {
- try output.writer().print("{d}", .{i});
- },
- .ident, .string => |s| {
- try output.appendSlice(s);
- },
+ .boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)),
+ .int => |i| try bw.print("{d}", .{i}),
+ .ident, .string => |s| try bw.writeAll(s),
}
curr = close_pos;
@@ -661,7 +613,7 @@ fn expand_variables_autoconf_at(
}
}
- try output.appendSlice(contents[source_offset..]);
+ try bw.writeAll(contents[source_offset..]);
}
fn expand_variables_cmake(
@@ -669,7 +621,7 @@ fn expand_variables_cmake(
contents: []const u8,
values: std.StringArrayHashMap(Value),
) ![]const u8 {
- var result = std.ArrayList(u8).init(allocator);
+ var result: std.ArrayList(u8) = .init(allocator);
errdefer result.deinit();
const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/_.+-";
@@ -681,7 +633,7 @@ fn expand_variables_cmake(
source: usize,
target: usize,
};
- var var_stack = std.ArrayList(Position).init(allocator);
+ var var_stack: std.ArrayList(Position) = .init(allocator);
defer var_stack.deinit();
loop: while (curr < contents.len) : (curr += 1) {
switch (contents[curr]) {
@@ -707,7 +659,7 @@ fn expand_variables_cmake(
try result.append(if (b) '1' else '0');
},
.int => |i| {
- try result.writer().print("{d}", .{i});
+ try result.print("{d}", .{i});
},
.ident, .string => |s| {
try result.appendSlice(s);
@@ -764,7 +716,7 @@ fn expand_variables_cmake(
try result.append(if (b) '1' else '0');
},
.int => |i| {
- try result.writer().print("{d}", .{i});
+ try result.print("{d}", .{i});
},
.ident, .string => |s| {
try result.appendSlice(s);
@@ -801,17 +753,17 @@ fn testReplaceVariablesAutoconfAt(
expected: []const u8,
values: std.StringArrayHashMap(Value),
) !void {
- var output = std.ArrayList(u8).init(allocator);
+ var output: std.io.Writer.Allocating = .init(allocator);
defer output.deinit();
const used = try allocator.alloc(bool, values.count());
for (used) |*u| u.* = false;
defer allocator.free(used);
- try expand_variables_autoconf_at(&output, contents, values, used);
+ try expand_variables_autoconf_at(&output.interface, contents, values, used);
for (used) |u| if (!u) return error.UnusedValue;
- try std.testing.expectEqualStrings(expected, output.items);
+ try std.testing.expectEqualStrings(expected, output.getWritten());
}
fn testReplaceVariablesCMake(
@@ -828,7 +780,7 @@ fn testReplaceVariablesCMake(
test "expand_variables_autoconf_at simple cases" {
const allocator = std.testing.allocator;
- var values = std.StringArrayHashMap(Value).init(allocator);
+ var values: std.StringArrayHashMap(Value) = .init(allocator);
defer values.deinit();
// empty strings are preserved
@@ -924,7 +876,7 @@ test "expand_variables_autoconf_at simple cases" {
test "expand_variables_autoconf_at edge cases" {
const allocator = std.testing.allocator;
- var values = std.StringArrayHashMap(Value).init(allocator);
+ var values: std.StringArrayHashMap(Value) = .init(allocator);
defer values.deinit();
// @-vars resolved only when they wrap valid characters, otherwise considered literals
@@ -940,7 +892,7 @@ test "expand_variables_autoconf_at edge cases" {
test "expand_variables_cmake simple cases" {
const allocator = std.testing.allocator;
- var values = std.StringArrayHashMap(Value).init(allocator);
+ var values: std.StringArrayHashMap(Value) = .init(allocator);
defer values.deinit();
try values.putNoClobber("undef", .undef);
@@ -1028,7 +980,7 @@ test "expand_variables_cmake simple cases" {
test "expand_variables_cmake edge cases" {
const allocator = std.testing.allocator;
- var values = std.StringArrayHashMap(Value).init(allocator);
+ var values: std.StringArrayHashMap(Value) = .init(allocator);
defer values.deinit();
// special symbols
@@ -1089,7 +1041,7 @@ test "expand_variables_cmake edge cases" {
test "expand_variables_cmake escaped characters" {
const allocator = std.testing.allocator;
- var values = std.StringArrayHashMap(Value).init(allocator);
+ var values: std.StringArrayHashMap(Value) = .init(allocator);
defer values.deinit();
try values.putNoClobber("string", Value{ .string = "text" });