zig/src/print_targets.zig
Mason Remaley 339b628d4c
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.
2025-02-21 21:40:57 -05:00

142 lines
5.1 KiB
Zig

const std = @import("std");
const fs = std.fs;
const io = std.io;
const mem = std.mem;
const meta = std.meta;
const Allocator = std.mem.Allocator;
const Target = std.Target;
const target = @import("target.zig");
const assert = std.debug.assert;
const glibc = @import("glibc.zig");
const introspect = @import("introspect.zig");
const fatal = @import("main.zig").fatal;
pub fn cmdTargets(
allocator: Allocator,
args: []const []const u8,
/// Output stream
stdout: anytype,
native_target: Target,
) !void {
_ = args;
var zig_lib_directory = introspect.findZigLibDir(allocator) catch |err| {
fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)});
};
defer zig_lib_directory.handle.close();
defer allocator.free(zig_lib_directory.path.?);
const abilists_contents = zig_lib_directory.handle.readFileAlloc(
allocator,
glibc.abilists_path,
glibc.abilists_max_size,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}),
};
defer allocator.free(abilists_contents);
const glibc_abi = try glibc.loadMetaData(allocator, abilists_contents);
defer glibc_abi.destroy(allocator);
var bw = io.bufferedWriter(stdout);
const w = bw.writer();
var sz = std.zon.stringify.serializer(w, .{});
{
var root_obj = try sz.beginStruct(.{});
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), .{});
{
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 libc_obj.end();
}
{
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();
}