update some of the build system to new API

This commit is contained in:
Andrew Kelley 2025-02-16 03:46:12 -08:00
parent 1d0495678d
commit ff3581ca2d
8 changed files with 506 additions and 474 deletions

View File

@ -435,7 +435,7 @@ pub const Token = union(enum) {
.incomplete_quoted_prerequisite,
.incomplete_target,
=> |index_and_bytes| {
try list.print("{s} '", .{self.errStr()});
try list.print(gpa, "{s} '", .{self.errStr()});
if (self == .incomplete_target) {
const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };
try tmp.resolve(gpa, list);
@ -451,7 +451,7 @@ pub const Token = union(enum) {
.incomplete_escape,
.expected_colon,
=> |index_and_char| {
try list.appendSlice("illegal char ");
try list.appendSlice(gpa, "illegal char ");
try printUnderstandableChar(gpa, list, index_and_char.char);
try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() });
},
@ -1076,17 +1076,15 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
try testing.expectEqualStrings(expect, buffer.items);
}
fn printCharValues(out: anytype, bytes: []const u8) !void {
for (bytes) |b| {
try out.writeAll(&[_]u8{printable_char_tab[b]});
}
fn printCharValues(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), bytes: []const u8) !void {
for (bytes) |b| try list.append(gpa, printable_char_tab[b]);
}
fn printUnderstandableChar(out: anytype, char: u8) !void {
fn printUnderstandableChar(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), char: u8) !void {
if (std.ascii.isPrint(char)) {
try out.print("'{c}'", .{char});
try list.print(gpa, "'{c}'", .{char});
} else {
try out.print("\\x{X:0>2}", .{char});
try list.print(gpa, "\\x{X:0>2}", .{char});
}
}

View File

@ -287,26 +287,26 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
/// For debugging purposes, prints identifying information about this Step.
pub fn dump(step: *Step, file: std.fs.File) void {
const w = file.writer();
var bw = file.unbufferedWriter();
const tty_config = std.io.tty.detectConfig(file);
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
bw.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
@errorName(err),
}) catch {};
return;
};
if (step.getStackTrace()) |stack_trace| {
w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
std.debug.writeStackTrace(stack_trace, w, debug_info, tty_config) catch |err| {
w.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
bw.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
std.debug.writeStackTrace(stack_trace, &bw, debug_info, tty_config) catch |err| {
bw.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
return;
};
} else {
const field = "debug_stack_frames_count";
comptime assert(@hasField(Build, field));
tty_config.setColor(w, .yellow) catch {};
w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};
tty_config.setColor(w, .reset) catch {};
tty_config.setColor(&bw, .yellow) catch {};
bw.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};
tty_config.setColor(&bw, .reset) catch {};
}
}
@ -738,7 +738,7 @@ pub fn allocPrintCmd2(
argv: []const []const u8,
) Allocator.Error![]u8 {
const shell = struct {
fn escape(writer: anytype, string: []const u8, is_argv0: bool) !void {
fn escape(writer: *std.io.Writer, string: []const u8, is_argv0: bool) !void {
for (string) |c| {
if (switch (c) {
else => true,
@ -772,9 +772,9 @@ pub fn allocPrintCmd2(
}
};
var buf: std.ArrayListUnmanaged(u8) = .empty;
const writer = buf.writer(arena);
if (opt_cwd) |cwd| try writer.print("cd {s} && ", .{cwd});
var aw: std.io.Writer.Allocating = .init(arena);
const w = &aw.interface;
if (opt_cwd) |cwd| try w.print(arena, "cd {s} && ", .{cwd});
if (opt_env) |env| {
const process_env_map = std.process.getEnvMap(arena) catch std.process.EnvMap.init(arena);
var it = env.iterator();
@ -784,17 +784,17 @@ pub fn allocPrintCmd2(
if (process_env_map.get(key)) |process_value| {
if (std.mem.eql(u8, value, process_value)) continue;
}
try writer.print("{s}=", .{key});
try shell.escape(writer, value, false);
try writer.writeByte(' ');
try w.print(arena, "{s}=", .{key});
try shell.escape(w, value, false);
try w.writeByte(arena, ' ');
}
}
try shell.escape(writer, argv[0], true);
try shell.escape(w, argv[0], true);
for (argv[1..]) |arg| {
try writer.writeByte(' ');
try shell.escape(writer, arg, false);
try w.writeByte(arena, ' ');
try shell.escape(w, arg, false);
}
return buf.toOwnedSlice(arena);
return aw.getWritten();
}
/// Prefer `cacheHitAndWatch` unless you already added watch inputs

File diff suppressed because it is too large Load Diff

View File

@ -1769,12 +1769,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
for (arg, 0..) |c, arg_idx| {
if (c == '\\' or c == '"') {
// Slow path for arguments that need to be escaped. We'll need to allocate and copy
var escaped = try ArrayList(u8).initCapacity(arena, arg.len + 1);
const writer = escaped.writer();
try writer.writeAll(arg[0..arg_idx]);
var escaped: std.ArrayListUnmanaged(u8) = .empty;
try escaped.ensureTotalCapacityPrecise(arena, arg.len + 1);
try escaped.appendSlice(arena, arg[0..arg_idx]);
for (arg[arg_idx..]) |to_escape| {
if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\');
try writer.writeByte(to_escape);
if (to_escape == '\\' or to_escape == '"') try escaped.append(arena, '\\');
try escaped.append(arena, to_escape);
}
escaped_args.appendAssumeCapacity(escaped.items);
continue :arg_blk;

View File

@ -569,14 +569,14 @@ fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !voi
try output.appendSlice(if (b) " 1\n" else " 0\n");
},
.int => |i| {
try output.writer().print("#define {s} {d}\n", .{ name, i });
try output.print("#define {s} {d}\n", .{ name, i });
},
.ident => |ident| {
try output.writer().print("#define {s} {s}\n", .{ name, ident });
try output.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) });
try output.print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
},
}
}

View File

@ -12,9 +12,9 @@ pub const base_id: Step.Id = .options;
step: Step,
generated_file: GeneratedFile,
contents: std.ArrayList(u8),
args: std.ArrayList(Arg),
encountered_types: std.StringHashMap(void),
contents: std.ArrayListUnmanaged(u8),
args: std.ArrayListUnmanaged(Arg),
encountered_types: std.StringHashMapUnmanaged(void),
pub fn create(owner: *std.Build) *Options {
const options = owner.allocator.create(Options) catch @panic("OOM");
@ -26,9 +26,9 @@ pub fn create(owner: *std.Build) *Options {
.makeFn = make,
}),
.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),
.contents = .empty,
.args = .empty,
.encountered_types = .empty,
};
options.generated_file = .{ .step = &options.step };
@ -40,110 +40,117 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T
}
fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {
const out = options.contents.writer();
try printType(options, out, T, value, 0, name);
try printType(options, &options.contents, T, value, 0, name);
}
fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent: u8, name: ?[]const u8) !void {
fn printType(
options: *Options,
out: *std.ArrayListUnmanaged(u8),
comptime T: type,
value: T,
indent: u8,
name: ?[]const u8,
) !void {
const gpa = options.step.owner.allocator;
switch (T) {
[]const []const u8 => {
if (name) |payload| {
try out.print("pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});
try out.print(gpa, "pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});
}
try out.writeAll("&[_][]const u8{\n");
try out.appendSlice(gpa, "&[_][]const u8{\n");
for (value) |slice| {
try out.writeByteNTimes(' ', indent);
try out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)});
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " \"{}\",\n", .{std.zig.fmtEscapes(slice)});
}
if (name != null) {
try out.writeAll("};\n");
try out.appendSlice(gpa, "};\n");
} else {
try out.writeAll("},\n");
try out.appendSlice(gpa, "},\n");
}
return;
},
[]const u8 => {
if (name) |some| {
try out.print("pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
try out.print(gpa, "pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
} else {
try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});
try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
}
return out.writeAll("\n");
return out.appendSlice(gpa, "\n");
},
[:0]const u8 => {
if (name) |some| {
try out.print("pub const {}: [:0]const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
try out.print(gpa, "pub const {}: [:0]const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
} else {
try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});
try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
}
return out.writeAll("\n");
return out.appendSlice(gpa, "\n");
},
?[]const u8 => {
if (name) |some| {
try out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(some)});
try out.print(gpa, "pub const {}: ?[]const u8 = ", .{std.zig.fmtId(some)});
}
if (value) |payload| {
try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});
try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});
} else {
try out.writeAll("null");
try out.appendSlice(gpa, "null");
}
if (name != null) {
try out.writeAll(";\n");
try out.appendSlice(gpa, ";\n");
} else {
try out.writeAll(",\n");
try out.appendSlice(gpa, ",\n");
}
return;
},
?[:0]const u8 => {
if (name) |some| {
try out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});
try out.print(gpa, "pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});
}
if (value) |payload| {
try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});
try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});
} else {
try out.writeAll("null");
try out.appendSlice(gpa, "null");
}
if (name != null) {
try out.writeAll(";\n");
try out.appendSlice(gpa, ";\n");
} else {
try out.writeAll(",\n");
try out.appendSlice(gpa, ",\n");
}
return;
},
std.SemanticVersion => {
if (name) |some| {
try out.print("pub const {}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
try out.print(gpa, "pub const {}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
}
try out.writeAll(".{\n");
try out.writeByteNTimes(' ', indent);
try out.print(" .major = {d},\n", .{value.major});
try out.writeByteNTimes(' ', indent);
try out.print(" .minor = {d},\n", .{value.minor});
try out.writeByteNTimes(' ', indent);
try out.print(" .patch = {d},\n", .{value.patch});
try out.appendSlice(gpa, ".{\n");
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " .major = {d},\n", .{value.major});
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " .minor = {d},\n", .{value.minor});
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " .patch = {d},\n", .{value.patch});
if (value.pre) |some| {
try out.writeByteNTimes(' ', indent);
try out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});
}
if (value.build) |some| {
try out.writeByteNTimes(' ', indent);
try out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});
}
if (name != null) {
try out.writeAll("};\n");
try out.appendSlice(gpa, "};\n");
} else {
try out.writeAll("},\n");
try out.appendSlice(gpa, "},\n");
}
return;
},
@ -153,21 +160,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
switch (@typeInfo(T)) {
.array => {
if (name) |some| {
try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
try out.print(gpa, "pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
}
try out.print("{s} {{\n", .{@typeName(T)});
try out.print(gpa, "{s} {{\n", .{@typeName(T)});
for (value) |item| {
try out.writeByteNTimes(' ', indent + 4);
try out.appendNTimes(gpa, ' ', indent + 4);
try printType(options, out, @TypeOf(item), item, indent + 4, null);
}
try out.writeByteNTimes(' ', indent);
try out.writeAll("}");
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, "}");
if (name != null) {
try out.writeAll(";\n");
try out.appendSlice(gpa, ";\n");
} else {
try out.writeAll(",\n");
try out.appendSlice(gpa, ",\n");
}
return;
},
@ -177,27 +184,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
}
if (name) |some| {
try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
try out.print(gpa, "pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
}
try out.print("&[_]{s} {{\n", .{@typeName(p.child)});
try out.print(gpa, "&[_]{s} {{\n", .{@typeName(p.child)});
for (value) |item| {
try out.writeByteNTimes(' ', indent + 4);
try out.appendNTimes(gpa, ' ', indent + 4);
try printType(options, out, @TypeOf(item), item, indent + 4, null);
}
try out.writeByteNTimes(' ', indent);
try out.writeAll("}");
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, "}");
if (name != null) {
try out.writeAll(";\n");
try out.appendSlice(gpa, ";\n");
} else {
try out.writeAll(",\n");
try out.appendSlice(gpa, ",\n");
}
return;
},
.optional => {
if (name) |some| {
try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
try out.print(gpa, "pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
}
if (value) |inner| {
@ -206,13 +213,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
_ = options.contents.pop();
_ = options.contents.pop();
} else {
try out.writeAll("null");
try out.appendSlice(gpa, "null");
}
if (name != null) {
try out.writeAll(";\n");
try out.appendSlice(gpa, ";\n");
} else {
try out.writeAll(",\n");
try out.appendSlice(gpa, ",\n");
}
return;
},
@ -224,9 +231,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
.null,
=> {
if (name) |some| {
try out.print("pub const {}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
try out.print(gpa, "pub const {}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
} else {
try out.print("{any},\n", .{value});
try out.print(gpa, "{any},\n", .{value});
}
return;
},
@ -234,7 +241,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
try printEnum(options, out, T, info, indent);
if (name) |some| {
try out.print("pub const {}: {} = .{p_};\n", .{
try out.print(gpa, "pub const {}: {} = .{p_};\n", .{
std.zig.fmtId(some),
std.zig.fmtId(@typeName(T)),
std.zig.fmtId(@tagName(value)),
@ -246,7 +253,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
try printStruct(options, out, T, info, indent);
if (name) |some| {
try out.print("pub const {}: {} = ", .{
try out.print(gpa, "pub const {}: {} = ", .{
std.zig.fmtId(some),
std.zig.fmtId(@typeName(T)),
});
@ -258,7 +265,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
}
}
fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, indent: u8) !void {
fn printUserDefinedType(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, indent: u8) !void {
switch (@typeInfo(T)) {
.@"enum" => |info| {
return try printEnum(options, out, T, info, indent);
@ -270,94 +277,109 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden
}
}
fn printEnum(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Enum, indent: u8) !void {
const gop = try options.encountered_types.getOrPut(@typeName(T));
fn printEnum(
options: *Options,
out: *std.ArrayListUnmanaged(u8),
comptime T: type,
comptime val: std.builtin.Type.Enum,
indent: u8,
) !void {
const gpa = options.step.owner.allocator;
const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
if (gop.found_existing) return;
try out.writeByteNTimes(' ', indent);
try out.print("pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, "pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
inline for (val.fields) |field| {
try out.writeByteNTimes(' ', indent);
try out.print(" {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
}
if (!val.is_exhaustive) {
try out.writeByteNTimes(' ', indent);
try out.writeAll(" _,\n");
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, " _,\n");
}
try out.writeByteNTimes(' ', indent);
try out.writeAll("};\n");
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, "};\n");
}
fn printStruct(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
const gop = try options.encountered_types.getOrPut(@typeName(T));
fn printStruct(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
const gpa = options.step.owner.allocator;
const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
if (gop.found_existing) return;
try out.writeByteNTimes(' ', indent);
try out.print("pub const {} = ", .{std.zig.fmtId(@typeName(T))});
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, "pub const {} = ", .{std.zig.fmtId(@typeName(T))});
switch (val.layout) {
.@"extern" => try out.writeAll("extern struct"),
.@"packed" => try out.writeAll("packed struct"),
else => try out.writeAll("struct"),
.@"extern" => try out.appendSlice(gpa, "extern struct"),
.@"packed" => try out.appendSlice(gpa, "packed struct"),
else => try out.appendSlice(gpa, "struct"),
}
try out.writeAll(" {\n");
try out.appendSlice(gpa, " {\n");
inline for (val.fields) |field| {
try out.writeByteNTimes(' ', indent);
try out.appendNTimes(gpa, ' ', indent);
const type_name = @typeName(field.type);
// If the type name doesn't contains a '.' the type is from zig builtins.
if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {
try out.print(" {p_}: {}", .{ std.zig.fmtId(field.name), std.zig.fmtId(type_name) });
try out.print(gpa, " {p_}: {}", .{ std.zig.fmtId(field.name), std.zig.fmtId(type_name) });
} else {
try out.print(" {p_}: {s}", .{ std.zig.fmtId(field.name), type_name });
try out.print(gpa, " {p_}: {s}", .{ std.zig.fmtId(field.name), type_name });
}
if (field.defaultValue()) |default_value| {
try out.writeAll(" = ");
try out.appendSlice(gpa, " = ");
switch (@typeInfo(@TypeOf(default_value))) {
.@"enum" => try out.print(".{s},\n", .{@tagName(default_value)}),
.@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(default_value)}),
.@"struct" => |info| {
try printStructValue(options, out, info, default_value, indent + 4);
},
else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),
}
} else {
try out.writeAll(",\n");
try out.appendSlice(gpa, ",\n");
}
}
// TODO: write declarations
try out.writeByteNTimes(' ', indent);
try out.writeAll("};\n");
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, "};\n");
inline for (val.fields) |field| {
try printUserDefinedType(options, out, field.type, 0);
}
}
fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.builtin.Type.Struct, val: anytype, indent: u8) !void {
try out.writeAll(".{\n");
fn printStructValue(
options: *Options,
out: *std.ArrayListUnmanaged(u8),
comptime struct_val: std.builtin.Type.Struct,
val: anytype,
indent: u8,
) !void {
const gpa = options.step.owner.allocator;
try out.appendSlice(gpa, ".{\n");
if (struct_val.is_tuple) {
inline for (struct_val.fields) |field| {
try out.writeByteNTimes(' ', indent);
try out.appendNTimes(gpa, ' ', indent);
try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);
}
} else {
inline for (struct_val.fields) |field| {
try out.writeByteNTimes(' ', indent);
try out.print(" .{p_} = ", .{std.zig.fmtId(field.name)});
try out.appendNTimes(gpa, ' ', indent);
try out.print(gpa, " .{p_} = ", .{std.zig.fmtId(field.name)});
const field_name = @field(val, field.name);
switch (@typeInfo(@TypeOf(field_name))) {
.@"enum" => try out.print(".{s},\n", .{@tagName(field_name)}),
.@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(field_name)}),
.@"struct" => |struct_info| {
try printStructValue(options, out, struct_info, field_name, indent + 4);
},
@ -367,10 +389,10 @@ fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.bu
}
if (indent == 0) {
try out.writeAll("};\n");
try out.appendSlice(gpa, "};\n");
} else {
try out.writeByteNTimes(' ', indent);
try out.writeAll("},\n");
try out.appendNTimes(gpa, ' ', indent);
try out.appendSlice(gpa, "},\n");
}
}

View File

@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool {
/// Formats a version with the patch component omitted if it is zero,
/// unlike SemanticVersion.format which formats all its version components regardless.
fn formatVersion(version: SemanticVersion, writer: anytype) !void {
fn formatVersion(version: SemanticVersion, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) !void {
if (version.patch == 0) {
try writer.print("{d}.{d}", .{ version.major, version.minor });
try list.print(gpa, "{d}.{d}", .{ version.major, version.minor });
} else {
try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
try list.print(gpa, "{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
}
}
pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
if (self.isNativeTriple())
return allocator.dupe(u8, "native");
pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
if (self.isNativeTriple()) return gpa.dupe(u8, "native");
const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
var result = std.ArrayList(u8).init(allocator);
defer result.deinit();
var result: std.ArrayListUnmanaged(u8) = .empty;
defer result.deinit(gpa);
try result.writer().print("{s}-{s}", .{ arch_name, os_name });
try result.print(gpa, "{s}-{s}", .{ arch_name, os_name });
// The zig target syntax does not allow specifying a max os version with no min, so
// if either are present, we need the min.
@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
switch (min) {
.none => {},
.semver => |v| {
try result.writer().writeAll(".");
try formatVersion(v, result.writer());
try result.appendSlice(gpa, ".");
try formatVersion(v, gpa, &result);
},
.windows => |v| {
try result.writer().print("{s}", .{v});
try result.print(gpa, "{s}", .{v});
},
}
}
@ -432,39 +431,39 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
switch (max) {
.none => {},
.semver => |v| {
try result.writer().writeAll("...");
try formatVersion(v, result.writer());
try result.appendSlice(gpa, "...");
try formatVersion(v, gpa, &result);
},
.windows => |v| {
// This is counting on a custom format() function defined on `WindowsVersion`
// to add a prefix '.' and make there be a total of three dots.
try result.writer().print("..{s}", .{v});
try result.print(gpa, "..{s}", .{v});
},
}
}
if (self.glibc_version) |v| {
const name = if (self.abi) |abi| @tagName(abi) else "gnu";
try result.ensureUnusedCapacity(name.len + 2);
try result.ensureUnusedCapacity(gpa, name.len + 2);
result.appendAssumeCapacity('-');
result.appendSliceAssumeCapacity(name);
result.appendAssumeCapacity('.');
try formatVersion(v, result.writer());
try formatVersion(v, gpa, &result);
} else if (self.android_api_level) |lvl| {
const name = if (self.abi) |abi| @tagName(abi) else "android";
try result.ensureUnusedCapacity(name.len + 2);
try result.ensureUnusedCapacity(gpa, name.len + 2);
result.appendAssumeCapacity('-');
result.appendSliceAssumeCapacity(name);
result.appendAssumeCapacity('.');
try result.writer().print("{d}", .{lvl});
try result.print(gpa, "{d}", .{lvl});
} else if (self.abi) |abi| {
const name = @tagName(abi);
try result.ensureUnusedCapacity(name.len + 1);
try result.ensureUnusedCapacity(gpa, name.len + 1);
result.appendAssumeCapacity('-');
result.appendSliceAssumeCapacity(name);
}
return result.toOwnedSlice();
return result.toOwnedSlice(gpa);
}
/// Renders the query into a textual representation that can be parsed via the

View File

@ -77,6 +77,12 @@ pub fn toArrayList(aw: *AllocatingWriter) std.ArrayListUnmanaged(u8) {
return result;
}
pub fn toOwnedSlice(aw: *AllocatingWriter) error{OutOfMemory}![]u8 {
const gpa = aw.allocator;
var list = toArrayList(aw);
return list.toOwnedSlice(gpa);
}
fn setArrayList(aw: *AllocatingWriter, list: std.ArrayListUnmanaged(u8)) void {
aw.written = list.items;
aw.buffered_writer.buffer = list.unusedCapacitySlice();