pub const TargetQuery = struct {
flags: Flags,
cpu_features_add: Storage.FlagOptional(.flags, .cpu_features_add, std.Target.Cpu.Feature.Set),
cpu_features_sub: Storage.FlagOptional(.flags, .cpu_features_sub, std.Target.Cpu.Feature.Set),
cpu_name: Storage.EnumOptional(.flags, .cpu_model, .explicit, String),
os_version_min: Storage.FlagUnion(.flags, .os_version_min, OsVersion),
os_version_max: Storage.FlagUnion(.flags, .os_version_max, OsVersion),
glibc_version: Storage.FlagOptional(.flags, .glibc_version, String),
android_api_level: Storage.FlagOptional(.flags, .android_api_level, u32),
dynamic_linker: Storage.FlagOptional(.flags, .dynamic_linker, String),
pub const Index = enum(u32) {
_,
pub fn extraSlice(i: Index, extra: []const u32) []const u32 {
return extra[@backingInt(i)..][0..length(i, extra)];
}
pub fn length(i: Index, extra: []const u32) usize {
return Storage.dataLength(extra, @backingInt(i), TargetQuery);
}
pub fn get(this: @This(), c: *const Configuration) TargetQuery {
return extraData(c, TargetQuery, @backingInt(this));
}
};
pub const OptionalIndex = enum(u32) {
none = max_u32,
_,
pub fn init(i: Index) OptionalIndex {
const result: OptionalIndex = @fromBackingInt(@intCast(@backingInt(i)));
assert(result != .none);
return result;
}
pub fn unwrap(this: @This()) ?Index {
return switch (this) {
.none => null,
_ => @fromBackingInt(@intCast(@backingInt(this))),
};
}
pub fn get(this: @This(), c: *const Configuration) ?TargetQuery {
return (this.unwrap() orelse return null).get(c);
}
};
pub const CpuModel = enum(u2) {
native,
baseline,
determined_by_arch_os,
explicit,
pub fn init(x: std.Target.Query.CpuModel) @This() {
return switch (x) {
inline else => |_, tag| @field(@This(), @tagName(tag)),
};
}
};
pub const OsVersion = union(@This().Tag) {
pub const Tag = enum(u2) { none, semver, windows, default };
none: void,
semver: String,
windows: std.Target.Os.WindowsVersion,
default: void,
pub fn unwrap(this: @This(), c: *const Configuration) ?std.Target.Query.OsVersion {
return switch (this) {
.none => .none,
.semver => |sv| .{ .semver = std.SemanticVersion.parse(sv.slice(c)) catch unreachable },
.windows => |wv| .{ .windows = wv },
.default => null,
};
}
};
pub const Abi = enum(u5) {
none,
gnu,
gnuabin32,
gnuabi64,
gnueabi,
gnueabihf,
gnuf32,
gnusf,
gnux32,
eabi,
eabihf,
abin32,
x32,
ilp32,
android,
androideabi,
musl,
muslabin32,
muslabi64,
musleabi,
musleabihf,
muslf32,
muslsf,
muslx32,
msvc,
itanium,
simulator,
ohos,
ohoseabi,
call0,
default,
pub fn init(x: ?std.Target.Abi) @This() {
return switch (x orelse return .default) {
inline else => |tag| @field(@This(), @tagName(tag)),
};
}
pub fn unwrap(this: @This()) ?std.Target.Abi {
return switch (this) {
inline else => |tag| @field(std.Target.Abi, @tagName(tag)),
.default => null,
};
}
};
pub const CpuArch = enum(u6) {
aarch64,
aarch64_be,
alpha,
amdgcn,
arc,
arceb,
arm,
armeb,
avr,
bpfeb,
bpfel,
csky,
ez80,
hexagon,
hppa,
hppa64,
kalimba,
kvx,
lanai,
loongarch32,
loongarch64,
m68k,
m88k,
microblaze,
microblazeel,
mips,
mipsel,
mips64,
mips64el,
msp430,
nvptx,
nvptx64,
or1k,
powerpc,
powerpcle,
powerpc64,
powerpc64le,
propeller,
riscv32,
riscv32be,
riscv64,
riscv64be,
s390x,
sh,
sheb,
sparc,
sparc64,
spork8,
spirv32,
spirv64,
thumb,
thumbeb,
ve,
wasm32,
wasm64,
x86_16,
x86,
x86_64,
xcore,
xtensa,
xtensaeb,
default,
pub fn init(x: ?std.Target.Cpu.Arch) @This() {
return switch (x orelse return .default) {
inline else => |tag| @field(@This(), @tagName(tag)),
};
}
pub fn unwrap(this: @This()) ?std.Target.Cpu.Arch {
return switch (this) {
inline else => |tag| @field(std.Target.Cpu.Arch, @tagName(tag)),
.default => null,
};
}
};
pub const OsTag = enum(u6) {
freestanding,
other,
contiki,
fuchsia,
hermit,
managarm,
haiku,
hurd,
illumos,
linux,
plan9,
rtems,
serenity,
dragonfly,
freebsd,
netbsd,
openbsd,
driverkit,
ios,
maccatalyst,
macos,
tvos,
visionos,
watchos,
windows,
uefi,
@"3ds",
wiiu,
@"switch",
gba,
psx,
ps3,
ps4,
ps5,
psp,
vita,
emscripten,
wasi,
amdhsa,
amdpal,
cuda,
mesa3d,
nvcl,
opencl,
opengl,
vulkan,
tios,
ashetos,
default,
pub fn init(x: ?std.Target.Os.Tag) @This() {
return switch (x orelse return .default) {
inline else => |tag| @field(@This(), @tagName(tag)),
};
}
pub fn unwrap(this: @This()) ?std.Target.Os.Tag {
return switch (this) {
inline else => |tag| @field(std.Target.Os.Tag, @tagName(tag)),
.default => null,
};
}
};
pub const ObjectFormat = enum(u4) {
c,
coff,
elf,
hex,
macho,
plan9,
raw,
spirv,
wasm,
default,
pub fn init(x: ?std.Target.ObjectFormat) @This() {
return switch (x orelse return .default) {
inline else => |tag| @field(@This(), @tagName(tag)),
};
}
pub fn unwrap(this: @This()) ?std.Target.ObjectFormat {
return switch (this) {
inline else => |tag| @field(std.Target.ObjectFormat, @tagName(tag)),
.default => null,
};
}
};
pub const Flags = packed struct(u32) {
cpu_arch: CpuArch,
cpu_model: CpuModel,
cpu_features_add: bool,
cpu_features_sub: bool,
os_tag: OsTag,
abi: Abi,
object_format: ObjectFormat,
os_version_min: OsVersion.Tag,
os_version_max: OsVersion.Tag,
glibc_version: bool,
android_api_level: bool,
dynamic_linker: bool,
};
pub fn unwrapTarget(tq: *const TargetQuery, c: *const Configuration) std.Target {
const cpu_arch = tq.flags.cpu_arch.unwrap().?;
const os_tag = tq.flags.os_tag.unwrap().?;
return .{
.cpu = .{
.arch = cpu_arch,
.model = cpu_arch.parseCpuModel(tq.cpu_name.value.?.slice(c)).?,
.features = tq.cpu_features_add.value.?,
},
.os = .{
.tag = os_tag,
.version_range = switch (os_tag) {
.linux => .{ .linux = .{
.range = .{
.min = tq.os_version_min.u.unwrap(c).?.semver,
.max = tq.os_version_max.u.unwrap(c).?.semver,
},
.glibc = std.SemanticVersion.parse(tq.glibc_version.value.?.slice(c)) catch unreachable,
.android = tq.android_api_level.value.?,
} },
.hurd => .{ .hurd = .{
.range = .{
.min = tq.os_version_min.u.unwrap(c).?.semver,
.max = tq.os_version_max.u.unwrap(c).?.semver,
},
.glibc = std.SemanticVersion.parse(tq.glibc_version.value.?.slice(c)) catch unreachable,
} },
.windows => .{ .windows = .{
.min = tq.os_version_min.u.unwrap(c).?.windows,
.max = tq.os_version_max.u.unwrap(c).?.windows,
} },
else => switch (tq.os_version_min.u.unwrap(c).?) {
.none => .{ .none = {} },
.semver => |min| .{ .semver = .{
.min = min,
.max = tq.os_version_max.u.unwrap(c).?.semver,
} },
.windows => unreachable,
},
},
},
.abi = tq.flags.abi.unwrap().?,
.ofmt = tq.flags.object_format.unwrap().?,
.dynamic_linker = .init(if (tq.dynamic_linker.value) |s| s.slice(c) else null),
};
}
}