1const std = @import("std");
2const Io = std.Io;
3const fs = std.fs;
4const mem = std.mem;
5const meta = std.meta;
6const fatal = std.process.fatal;
7const Allocator = std.mem.Allocator;
8const Target = std.Target;
9const assert = std.debug.assert;
10
11const glibc = @import("libs/glibc.zig");
12const target = @import("target.zig");
13
14pub fn cmdTargets(
15 allocator: Allocator,
16 io: Io,
17 directories: *const std.zig.Directories,
18 args: []const []const u8,
19 out: *std.Io.Writer,
20 native_target: *const Target,
21) !void {
22 _ = args;
23 const zig_lib_directory = directories.zig_lib;
24 const abilists_contents = zig_lib_directory.handle.readFileAlloc(
25 io,
26 glibc.abilists_path,
27 allocator,
28 .limited(glibc.abilists_max_size),
29 ) catch |err| switch (err) {
30 error.OutOfMemory => |e| return e,
31 else => fatal("unable to read " ++ glibc.abilists_path ++ ": {t}", .{err}),
32 };
33 defer allocator.free(abilists_contents);
34
35 const glibc_abi = try glibc.loadMetaData(allocator, abilists_contents);
36 defer glibc_abi.destroy(allocator);
37
38 var serializer: std.zon.Serializer = .{ .writer = out };
39
40 {
41 var root_obj = try serializer.beginStruct(.{});
42
43 try root_obj.field("arch", @typeInfo(Target.Cpu.Arch).@"enum".field_names, .{});
44 try root_obj.field("os", @typeInfo(Target.Os.Tag).@"enum".field_names, .{});
45 try root_obj.field("abi", @typeInfo(Target.Abi).@"enum".field_names, .{});
46
47 {
48 var libc_obj = try root_obj.beginTupleField("libc", .{});
49 for (std.zig.target.available_libcs) |libc| {
50 const tmp = try std.fmt.allocPrint(allocator, "{t}-{t}-{t}", .{ libc.arch, libc.os, libc.abi });
51 defer allocator.free(tmp);
52 try libc_obj.field(tmp, .{});
53 }
54 try libc_obj.end();
55 }
56
57 {
58 var glibc_obj = try root_obj.beginTupleField("glibc", .{});
59 for (glibc_abi.all_versions) |ver| {
60 const tmp = try std.fmt.allocPrint(allocator, "{f}", .{ver});
61 defer allocator.free(tmp);
62 try glibc_obj.field(tmp, .{});
63 }
64 try glibc_obj.end();
65 }
66
67 {
68 var cpus_obj = try root_obj.beginStructField("cpus", .{});
69 for (meta.tags(Target.Cpu.Arch)) |arch| {
70 var arch_obj = try cpus_obj.beginStructField(@tagName(arch), .{});
71 for (arch.allCpuModels()) |model| {
72 var features = try arch_obj.beginTupleField(model.name, .{});
73 for (arch.allFeaturesList(), 0..) |feature, i_usize| {
74 const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
75 if (model.features.isEnabled(index)) {
76 try features.field(feature.name, .{});
77 }
78 }
79 try features.end();
80 }
81 try arch_obj.end();
82 }
83 try cpus_obj.end();
84 }
85
86 {
87 var cpu_features_obj = try root_obj.beginStructField("cpu_features", .{});
88 for (meta.tags(Target.Cpu.Arch)) |arch| {
89 var arch_features = try cpu_features_obj.beginTupleField(@tagName(arch), .{});
90 for (arch.allFeaturesList()) |feature| {
91 try arch_features.field(feature.name, .{});
92 }
93 try arch_features.end();
94 }
95 try cpu_features_obj.end();
96 }
97
98 {
99 var native_obj = try root_obj.beginStructField("native", .{});
100 {
101 const triple = try native_target.zigTriple(allocator);
102 defer allocator.free(triple);
103 try native_obj.field("triple", triple, .{});
104 }
105 {
106 var cpu_obj = try native_obj.beginStructField("cpu", .{});
107 try cpu_obj.field("arch", @tagName(native_target.cpu.arch), .{});
108
109 try cpu_obj.field("name", native_target.cpu.model.name, .{});
110
111 {
112 var features = try native_obj.beginTupleField("features", .{});
113 for (native_target.cpu.arch.allFeaturesList(), 0..) |feature, i_usize| {
114 const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
115 if (native_target.cpu.features.isEnabled(index)) {
116 try features.field(feature.name, .{});
117 }
118 }
119 try features.end();
120 }
121 try cpu_obj.end();
122 }
123
124 try native_obj.field("os", @tagName(native_target.os.tag), .{});
125 try native_obj.field("abi", @tagName(native_target.abi), .{});
126 try native_obj.end();
127 }
128
129 try root_obj.end();
130 }
131
132 try out.writeByte('\n');
133}