Output zig targets as ZON instead of JSON (#22939)

* Adds startTupleField/startStructField, makes pattern in print targets less verbose

* Makes some enums into strings

* Start/finish renamed to begin/end

I feel bad changing this, but I don't know why I named them this way in the first place.
Begin/end is consistent with the json API, and with other APIs in the wild that follow this pattern.
Better to change now than later.
This commit is contained in:
Mason Remaley 2025-02-21 18:40:57 -08:00 committed by GitHub
parent 65e7ede499
commit 339b628d4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 283 additions and 195 deletions

View File

@ -438,17 +438,17 @@ pub const SerializeContainerOptions = struct {
/// * `multilineString`
///
/// For manual serialization of containers, see:
/// * `startStruct`
/// * `startTuple`
/// * `beginStruct`
/// * `beginTuple`
///
/// # Example
/// ```zig
/// var sz = serializer(writer, .{});
/// var vec2 = try sz.startStruct(.{});
/// var vec2 = try sz.beginStruct(.{});
/// try vec2.field("x", 1.5, .{});
/// try vec2.fieldPrefix();
/// try sz.value(2.5);
/// try vec2.finish();
/// try vec2.end();
/// ```
pub fn Serializer(Writer: type) type {
return struct {
@ -525,22 +525,22 @@ pub fn Serializer(Writer: type) type {
}
},
.array => {
var container = try self.startTuple(
var container = try self.beginTuple(
.{ .whitespace_style = .{ .fields = val.len } },
);
for (val) |item_val| {
try container.fieldArbitraryDepth(item_val, options);
}
try container.finish();
try container.end();
},
.@"struct" => |@"struct"| if (@"struct".is_tuple) {
var container = try self.startTuple(
var container = try self.beginTuple(
.{ .whitespace_style = .{ .fields = @"struct".fields.len } },
);
inline for (val) |field_value| {
try container.fieldArbitraryDepth(field_value, options);
}
try container.finish();
try container.end();
} else {
// Decide which fields to emit
const fields, const skipped: [@"struct".fields.len]bool = if (options.emit_default_optional_fields) b: {
@ -562,7 +562,7 @@ pub fn Serializer(Writer: type) type {
};
// Emit those fields
var container = try self.startStruct(
var container = try self.beginStruct(
.{ .whitespace_style = .{ .fields = fields } },
);
inline for (@"struct".fields, skipped) |field_info, skip| {
@ -574,7 +574,7 @@ pub fn Serializer(Writer: type) type {
);
}
}
try container.finish();
try container.end();
},
.@"union" => |@"union"| {
comptime assert(@"union".tag_type != null);
@ -582,7 +582,7 @@ pub fn Serializer(Writer: type) type {
inline else => |pl, tag| if (@TypeOf(pl) == void)
try self.writer.print(".{s}", .{@tagName(tag)})
else {
var container = try self.startStruct(.{ .whitespace_style = .{ .fields = 1 } });
var container = try self.beginStruct(.{ .whitespace_style = .{ .fields = 1 } });
try container.fieldArbitraryDepth(
@tagName(tag),
@ -590,7 +590,7 @@ pub fn Serializer(Writer: type) type {
options,
);
try container.finish();
try container.end();
},
}
},
@ -600,13 +600,13 @@ pub fn Serializer(Writer: type) type {
try self.writer.writeAll("null");
},
.vector => |vector| {
var container = try self.startTuple(
var container = try self.beginTuple(
.{ .whitespace_style = .{ .fields = vector.len } },
);
for (0..vector.len) |i| {
try container.fieldArbitraryDepth(val[i], options);
}
try container.finish();
try container.end();
},
else => comptime unreachable,
@ -691,18 +691,18 @@ pub fn Serializer(Writer: type) type {
comptime assert(canSerializeType(@TypeOf(val)));
switch (@typeInfo(@TypeOf(val))) {
.@"struct" => {
var container = try self.startTuple(.{ .whitespace_style = .{ .fields = val.len } });
var container = try self.beginTuple(.{ .whitespace_style = .{ .fields = val.len } });
inline for (val) |item_val| {
try container.fieldArbitraryDepth(item_val, options);
}
try container.finish();
try container.end();
},
.pointer, .array => {
var container = try self.startTuple(.{ .whitespace_style = .{ .fields = val.len } });
var container = try self.beginTuple(.{ .whitespace_style = .{ .fields = val.len } });
for (val) |item_val| {
try container.fieldArbitraryDepth(item_val, options);
}
try container.finish();
try container.end();
},
else => comptime unreachable,
}
@ -767,19 +767,19 @@ pub fn Serializer(Writer: type) type {
}
/// Create a `Struct` for writing ZON structs field by field.
pub fn startStruct(
pub fn beginStruct(
self: *Self,
options: SerializeContainerOptions,
) Writer.Error!Struct {
return Struct.start(self, options);
return Struct.begin(self, options);
}
/// Creates a `Tuple` for writing ZON tuples field by field.
pub fn startTuple(
pub fn beginTuple(
self: *Self,
options: SerializeContainerOptions,
) Writer.Error!Tuple {
return Tuple.start(self, options);
return Tuple.begin(self, options);
}
fn indent(self: *Self) Writer.Error!void {
@ -812,17 +812,17 @@ pub fn Serializer(Writer: type) type {
pub const Tuple = struct {
container: Container,
fn start(parent: *Self, options: SerializeContainerOptions) Writer.Error!Tuple {
fn begin(parent: *Self, options: SerializeContainerOptions) Writer.Error!Tuple {
return .{
.container = try Container.start(parent, .anon, options),
.container = try Container.begin(parent, .anon, options),
};
}
/// Finishes serializing the tuple.
///
/// Prints a trailing comma as configured when appropriate, and the closing bracket.
pub fn finish(self: *Tuple) Writer.Error!void {
try self.container.finish();
pub fn end(self: *Tuple) Writer.Error!void {
try self.container.end();
self.* = undefined;
}
@ -855,6 +855,24 @@ pub fn Serializer(Writer: type) type {
try self.container.fieldArbitraryDepth(null, val, options);
}
/// Starts a field with a struct as a value. Returns the struct.
pub fn beginStructField(
self: *Tuple,
options: SerializeContainerOptions,
) Writer.Error!Struct {
try self.fieldPrefix();
return self.container.serializer.beginStruct(options);
}
/// Starts a field with a tuple as a value. Returns the tuple.
pub fn beginTupleField(
self: *Tuple,
options: SerializeContainerOptions,
) Writer.Error!Tuple {
try self.fieldPrefix();
return self.container.serializer.beginTuple(options);
}
/// Print a field prefix. This prints any necessary commas, and whitespace as
/// configured. Useful if you want to serialize the field value yourself.
pub fn fieldPrefix(self: *Tuple) Writer.Error!void {
@ -866,17 +884,17 @@ pub fn Serializer(Writer: type) type {
pub const Struct = struct {
container: Container,
fn start(parent: *Self, options: SerializeContainerOptions) Writer.Error!Struct {
fn begin(parent: *Self, options: SerializeContainerOptions) Writer.Error!Struct {
return .{
.container = try Container.start(parent, .named, options),
.container = try Container.begin(parent, .named, options),
};
}
/// Finishes serializing the struct.
///
/// Prints a trailing comma as configured when appropriate, and the closing bracket.
pub fn finish(self: *Struct) Writer.Error!void {
try self.container.finish();
pub fn end(self: *Struct) Writer.Error!void {
try self.container.end();
self.* = undefined;
}
@ -912,6 +930,26 @@ pub fn Serializer(Writer: type) type {
try self.container.fieldArbitraryDepth(name, val, options);
}
/// Starts a field with a struct as a value. Returns the struct.
pub fn beginStructField(
self: *Struct,
name: []const u8,
options: SerializeContainerOptions,
) Writer.Error!Struct {
try self.fieldPrefix(name);
return self.container.serializer.beginStruct(options);
}
/// Starts a field with a tuple as a value. Returns the tuple.
pub fn beginTupleField(
self: *Struct,
name: []const u8,
options: SerializeContainerOptions,
) Writer.Error!Tuple {
try self.fieldPrefix(name);
return self.container.serializer.beginTuple(options);
}
/// Print a field prefix. This prints any necessary commas, the field name (escaped if
/// necessary) and whitespace as configured. Useful if you want to serialize the field
/// value yourself.
@ -928,7 +966,7 @@ pub fn Serializer(Writer: type) type {
options: SerializeContainerOptions,
empty: bool,
fn start(
fn begin(
sz: *Self,
field_style: FieldStyle,
options: SerializeContainerOptions,
@ -943,7 +981,7 @@ pub fn Serializer(Writer: type) type {
};
}
fn finish(self: *Container) Writer.Error!void {
fn end(self: *Container) Writer.Error!void {
if (self.options.shouldWrap()) self.serializer.indent_level -|= 1;
if (!self.empty) {
if (self.options.shouldWrap()) {
@ -1139,52 +1177,52 @@ test "std.zon stringify whitespace, low level API" {
// Empty containers
{
var container = try sz.startStruct(.{});
try container.finish();
var container = try sz.beginStruct(.{});
try container.end();
try std.testing.expectEqualStrings(".{}", buf.items);
buf.clearRetainingCapacity();
}
{
var container = try sz.startTuple(.{});
try container.finish();
var container = try sz.beginTuple(.{});
try container.end();
try std.testing.expectEqualStrings(".{}", buf.items);
buf.clearRetainingCapacity();
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });
try container.finish();
var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
try container.end();
try std.testing.expectEqualStrings(".{}", buf.items);
buf.clearRetainingCapacity();
}
{
var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });
try container.finish();
var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
try container.end();
try std.testing.expectEqualStrings(".{}", buf.items);
buf.clearRetainingCapacity();
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 0 } });
try container.finish();
var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 0 } });
try container.end();
try std.testing.expectEqualStrings(".{}", buf.items);
buf.clearRetainingCapacity();
}
{
var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 0 } });
try container.finish();
var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 0 } });
try container.end();
try std.testing.expectEqualStrings(".{}", buf.items);
buf.clearRetainingCapacity();
}
// Size 1
{
var container = try sz.startStruct(.{});
var container = try sz.beginStruct(.{});
try container.field("a", 1, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1198,9 +1236,9 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{});
var container = try sz.beginTuple(.{});
try container.field(1, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1214,9 +1252,9 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });
var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
try container.field("a", 1, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ .a = 1 }", buf.items);
} else {
@ -1228,9 +1266,9 @@ test "std.zon stringify whitespace, low level API" {
{
// We get extra spaces here, since we didn't know up front that there would only be one
// field.
var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });
var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
try container.field(1, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ 1 }", buf.items);
} else {
@ -1240,9 +1278,9 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 1 } });
var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 1 } });
try container.field("a", 1, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ .a = 1 }", buf.items);
} else {
@ -1252,19 +1290,19 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 1 } });
var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 1 } });
try container.field(1, .{});
try container.finish();
try container.end();
try std.testing.expectEqualStrings(".{1}", buf.items);
buf.clearRetainingCapacity();
}
// Size 2
{
var container = try sz.startStruct(.{});
var container = try sz.beginStruct(.{});
try container.field("a", 1, .{});
try container.field("b", 2, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1279,10 +1317,10 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{});
var container = try sz.beginTuple(.{});
try container.field(1, .{});
try container.field(2, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1297,10 +1335,10 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });
var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
try container.field("a", 1, .{});
try container.field("b", 2, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ .a = 1, .b = 2 }", buf.items);
} else {
@ -1310,10 +1348,10 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });
var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
try container.field(1, .{});
try container.field(2, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ 1, 2 }", buf.items);
} else {
@ -1323,10 +1361,10 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 2 } });
var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 2 } });
try container.field("a", 1, .{});
try container.field("b", 2, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ .a = 1, .b = 2 }", buf.items);
} else {
@ -1336,10 +1374,10 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 2 } });
var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 2 } });
try container.field(1, .{});
try container.field(2, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ 1, 2 }", buf.items);
} else {
@ -1350,11 +1388,11 @@ test "std.zon stringify whitespace, low level API" {
// Size 3
{
var container = try sz.startStruct(.{});
var container = try sz.beginStruct(.{});
try container.field("a", 1, .{});
try container.field("b", 2, .{});
try container.field("c", 3, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1370,11 +1408,11 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{});
var container = try sz.beginTuple(.{});
try container.field(1, .{});
try container.field(2, .{});
try container.field(3, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1390,11 +1428,11 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });
var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
try container.field("a", 1, .{});
try container.field("b", 2, .{});
try container.field("c", 3, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ .a = 1, .b = 2, .c = 3 }", buf.items);
} else {
@ -1404,11 +1442,11 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });
var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
try container.field(1, .{});
try container.field(2, .{});
try container.field(3, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(".{ 1, 2, 3 }", buf.items);
} else {
@ -1418,11 +1456,11 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 3 } });
var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 3 } });
try container.field("a", 1, .{});
try container.field("b", 2, .{});
try container.field("c", 3, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1438,11 +1476,11 @@ test "std.zon stringify whitespace, low level API" {
}
{
var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 3 } });
var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 3 } });
try container.field(1, .{});
try container.field(2, .{});
try container.field(3, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{
@ -1459,10 +1497,10 @@ test "std.zon stringify whitespace, low level API" {
// Nested objects where the outer container doesn't wrap but the inner containers do
{
var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });
var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
try container.field("first", .{ 1, 2, 3 }, .{});
try container.field("second", .{ 4, 5, 6 }, .{});
try container.finish();
try container.end();
if (whitespace) {
try std.testing.expectEqualStrings(
\\.{ .first = .{
@ -2016,26 +2054,26 @@ test "std.zon depth limits" {
try sz.value(3, .{});
try sz.valueArbitraryDepth(maybe_recurse, .{});
var s = try sz.startStruct(.{});
var s = try sz.beginStruct(.{});
try std.testing.expectError(error.ExceededMaxDepth, s.fieldMaxDepth("a", 1, .{}, 0));
try s.fieldMaxDepth("b", 4, .{}, 1);
try s.field("c", 5, .{});
try s.fieldArbitraryDepth("d", maybe_recurse, .{});
try s.finish();
try s.end();
var t = try sz.startTuple(.{});
var t = try sz.beginTuple(.{});
try std.testing.expectError(error.ExceededMaxDepth, t.fieldMaxDepth(1, .{}, 0));
try t.fieldMaxDepth(6, .{}, 1);
try t.field(7, .{});
try t.fieldArbitraryDepth(maybe_recurse, .{});
try t.finish();
try t.end();
var a = try sz.startTuple(.{});
var a = try sz.beginTuple(.{});
try std.testing.expectError(error.ExceededMaxDepth, a.fieldMaxDepth(1, .{}, 0));
try a.fieldMaxDepth(8, .{}, 1);
try a.field(9, .{});
try a.fieldArbitraryDepth(maybe_recurse, .{});
try a.finish();
try a.end();
try std.testing.expectEqualStrings(
\\23.{}.{
@ -2315,3 +2353,73 @@ test "std.zon pointers" {
, val, .{});
}
}
test "std.zon tuple/struct field" {
var buf = std.ArrayList(u8).init(std.testing.allocator);
defer buf.deinit();
var sz = serializer(buf.writer(), .{});
// Test on structs
{
var root = try sz.beginStruct(.{});
{
var tuple = try root.beginTupleField("foo", .{});
try tuple.field(0, .{});
try tuple.field(1, .{});
try tuple.end();
}
{
var strct = try root.beginStructField("bar", .{});
try strct.field("a", 0, .{});
try strct.field("b", 1, .{});
try strct.end();
}
try root.end();
try std.testing.expectEqualStrings(
\\.{
\\ .foo = .{
\\ 0,
\\ 1,
\\ },
\\ .bar = .{
\\ .a = 0,
\\ .b = 1,
\\ },
\\}
, buf.items);
buf.clearRetainingCapacity();
}
// Test on tuples
{
var root = try sz.beginTuple(.{});
{
var tuple = try root.beginTupleField(.{});
try tuple.field(0, .{});
try tuple.field(1, .{});
try tuple.end();
}
{
var strct = try root.beginStructField(.{});
try strct.field("a", 0, .{});
try strct.field("b", 1, .{});
try strct.end();
}
try root.end();
try std.testing.expectEqualStrings(
\\.{
\\ .{
\\ 0,
\\ 1,
\\ },
\\ .{
\\ .a = 0,
\\ .b = 1,
\\ },
\\}
, buf.items);
buf.clearRetainingCapacity();
}
}

View File

@ -40,121 +40,101 @@ pub fn cmdTargets(
var bw = io.bufferedWriter(stdout);
const w = bw.writer();
var jws = std.json.writeStream(w, .{ .whitespace = .indent_1 });
var sz = std.zon.stringify.serializer(w, .{});
try jws.beginObject();
try jws.objectField("arch");
try jws.beginArray();
for (meta.fieldNames(Target.Cpu.Arch)) |field| {
try jws.write(field);
}
try jws.endArray();
try jws.objectField("os");
try jws.beginArray();
for (meta.fieldNames(Target.Os.Tag)) |field| {
try jws.write(field);
}
try jws.endArray();
try jws.objectField("abi");
try jws.beginArray();
for (meta.fieldNames(Target.Abi)) |field| {
try jws.write(field);
}
try jws.endArray();
try jws.objectField("libc");
try jws.beginArray();
for (std.zig.target.available_libcs) |libc| {
const tmp = try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{
@tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi),
});
defer allocator.free(tmp);
try jws.write(tmp);
}
try jws.endArray();
try jws.objectField("glibc");
try jws.beginArray();
for (glibc_abi.all_versions) |ver| {
const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});
defer allocator.free(tmp);
try jws.write(tmp);
}
try jws.endArray();
try jws.objectField("cpus");
try jws.beginObject();
for (meta.tags(Target.Cpu.Arch)) |arch| {
try jws.objectField(@tagName(arch));
try jws.beginObject();
for (arch.allCpuModels()) |model| {
try jws.objectField(model.name);
try jws.beginArray();
for (arch.allFeaturesList(), 0..) |feature, i_usize| {
const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
if (model.features.isEnabled(index)) {
try jws.write(feature.name);
}
}
try jws.endArray();
}
try jws.endObject();
}
try jws.endObject();
try jws.objectField("cpuFeatures");
try jws.beginObject();
for (meta.tags(Target.Cpu.Arch)) |arch| {
try jws.objectField(@tagName(arch));
try jws.beginArray();
for (arch.allFeaturesList()) |feature| {
try jws.write(feature.name);
}
try jws.endArray();
}
try jws.endObject();
try jws.objectField("native");
try jws.beginObject();
{
const triple = try native_target.zigTriple(allocator);
defer allocator.free(triple);
try jws.objectField("triple");
try jws.write(triple);
}
{
try jws.objectField("cpu");
try jws.beginObject();
try jws.objectField("arch");
try jws.write(@tagName(native_target.cpu.arch));
var root_obj = try sz.beginStruct(.{});
try jws.objectField("name");
const cpu = native_target.cpu;
try jws.write(cpu.model.name);
try root_obj.field("arch", meta.fieldNames(Target.Cpu.Arch), .{});
try root_obj.field("os", meta.fieldNames(Target.Os.Tag), .{});
try root_obj.field("abi", meta.fieldNames(Target.Abi), .{});
{
try jws.objectField("features");
try jws.beginArray();
for (native_target.cpu.arch.allFeaturesList(), 0..) |feature, i_usize| {
const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
if (cpu.features.isEnabled(index)) {
try jws.write(feature.name);
}
var libc_obj = try root_obj.beginTupleField("libc", .{});
for (std.zig.target.available_libcs) |libc| {
const tmp = try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{
@tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi),
});
defer allocator.free(tmp);
try libc_obj.field(tmp, .{});
}
try jws.endArray();
try libc_obj.end();
}
try jws.endObject();
}
try jws.objectField("os");
try jws.write(@tagName(native_target.os.tag));
try jws.objectField("abi");
try jws.write(@tagName(native_target.abi));
try jws.endObject();
try jws.endObject();
{
var glibc_obj = try root_obj.beginTupleField("glibc", .{});
for (glibc_abi.all_versions) |ver| {
const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});
defer allocator.free(tmp);
try glibc_obj.field(tmp, .{});
}
try glibc_obj.end();
}
{
var cpus_obj = try root_obj.beginStructField("cpus", .{});
for (meta.tags(Target.Cpu.Arch)) |arch| {
var arch_obj = try cpus_obj.beginStructField(@tagName(arch), .{});
for (arch.allCpuModels()) |model| {
var features = try arch_obj.beginTupleField(model.name, .{});
for (arch.allFeaturesList(), 0..) |feature, i_usize| {
const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
if (model.features.isEnabled(index)) {
try features.field(feature.name, .{});
}
}
try features.end();
}
try arch_obj.end();
}
try cpus_obj.end();
}
{
var cpu_features_obj = try root_obj.beginStructField("cpu_features", .{});
for (meta.tags(Target.Cpu.Arch)) |arch| {
var arch_features = try cpu_features_obj.beginTupleField(@tagName(arch), .{});
for (arch.allFeaturesList()) |feature| {
try arch_features.field(feature.name, .{});
}
try arch_features.end();
}
try cpu_features_obj.end();
}
{
var native_obj = try root_obj.beginStructField("native", .{});
{
const triple = try native_target.zigTriple(allocator);
defer allocator.free(triple);
try native_obj.field("triple", triple, .{});
}
{
var cpu_obj = try native_obj.beginStructField("cpu", .{});
try cpu_obj.field("arch", @tagName(native_target.cpu.arch), .{});
try cpu_obj.field("name", native_target.cpu.model.name, .{});
{
var features = try native_obj.beginTupleField("features", .{});
for (native_target.cpu.arch.allFeaturesList(), 0..) |feature, i_usize| {
const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
if (native_target.cpu.features.isEnabled(index)) {
try features.field(feature.name, .{});
}
}
try features.end();
}
try cpu_obj.end();
}
try native_obj.field("os", @tagName(native_target.os.tag), .{});
try native_obj.field("abi", @tagName(native_target.abi), .{});
try native_obj.end();
}
try root_obj.end();
}
try w.writeByte('\n');
return bw.flush();