feature. See also
. The project being documented here (as the example) is the Zig library itself.
cvtres.supported_targets
pub const supported_targets = struct
File
Code
pub const supported_targets = struct {
pub const Arch = enum {
x64,
x86,
arm,
arm64,
arm64ec,
arm64x,
ia64,
ebc,
amd64,
i386,
armnt,
x86_64,
aarch64,
pub fn toCoffMachineType(arch: Arch) std.coff.IMAGE.FILE.MACHINE {
return switch (arch) {
.x64, .amd64, .x86_64 => .AMD64,
.x86, .i386 => .I386,
.arm, .armnt => .ARMNT,
.arm64, .aarch64 => .ARM64,
.arm64ec => .ARM64EC,
.arm64x => .ARM64X,
.ia64 => .IA64,
.ebc => .EBC,
};
}
pub fn description(arch: Arch) []const u8 {
return switch (arch) {
.x64, .amd64, .x86_64 => "64-bit X86",
.x86, .i386 => "32-bit X86",
.arm, .armnt => "ARM Thumb-2 little endian",
.arm64, .aarch64 => "ARM64/AArch64 little endian",
.arm64ec => "ARM64 \"Emulation Compatible\"",
.arm64x => "ARM64 and ARM64EC together",
.ia64 => "64-bit Intel Itanium",
.ebc => "EFI Byte Code",
};
}
pub const ordered_for_display: []const Arch = &.{
.x64,
.x86_64,
.amd64,
.x86,
.i386,
.arm64,
.aarch64,
.arm,
.armnt,
.arm64ec,
.arm64x,
.ia64,
.ebc,
};
comptime {
const info = @typeInfo(Arch).@"enum";
for (info.field_names, info.field_values) |field_name, field_value| {
_ = std.mem.indexOfScalar(Arch, ordered_for_display, @fromBackingInt(@intCast(field_value))) orelse {
@compileError(std.fmt.comptimePrint("'{s}' missing from ordered_for_display", .{field_name}));
};
}
}
pub const longest_name = blk: {
var len = 0;
for (@typeInfo(Arch).@"enum".field_names) |field_name| {
if (field_name.len > len) len = field_name.len;
}
break :blk len;
};
pub fn fromStringIgnoreCase(str: []const u8) ?Arch {
if (str.len > longest_name) return null;
var lower_buf: [longest_name]u8 = undefined;
const lower = std.ascii.lowerString(&lower_buf, str);
return std.meta.stringToEnum(Arch, lower);
}
test fromStringIgnoreCase {
try std.testing.expectEqual(.x64, Arch.fromStringIgnoreCase("x64").?);
try std.testing.expectEqual(.x64, Arch.fromStringIgnoreCase("X64").?);
try std.testing.expectEqual(.aarch64, Arch.fromStringIgnoreCase("Aarch64").?);
try std.testing.expectEqual(null, Arch.fromStringIgnoreCase("armzzz"));
try std.testing.expectEqual(null, Arch.fromStringIgnoreCase("long string that is longer than any field"));
}
};
pub fn rvaRelocationTypeIndicator(target: std.coff.IMAGE.FILE.MACHINE) ?u16 {
return switch (target) {
.AMD64 => @backingInt(std.coff.IMAGE.REL.AMD64.ADDR32NB),
.I386 => @backingInt(std.coff.IMAGE.REL.I386.DIR32NB),
.ARMNT => @backingInt(std.coff.IMAGE.REL.ARM.ADDR32NB),
.ARM64, .ARM64EC, .ARM64X => @backingInt(std.coff.IMAGE.REL.ARM64.ADDR32NB),
.IA64 => @backingInt(std.coff.IMAGE.REL.IA64.DIR32NB),
.EBC => 0x1,
else => null,
};
}
pub fn isSupported(target: std.coff.IMAGE.FILE.MACHINE) bool {
return rvaRelocationTypeIndicator(target) != null;
}
comptime {
// 1. Arch enum field names are all lowercase (necessary for how fromStringIgnoreCase is implemented)
// 2. All enum fields in Arch have an associated RVA relocation type when converted to a coff.IMAGE.FILE.MACHINE
for (@typeInfo(Arch).@"enum".field_names) |field_name| {
const all_lower = all_lower: for (field_name) |c| {
if (std.ascii.isUpper(c)) break :all_lower false;
} else break :all_lower true;
if (!all_lower) @compileError(std.fmt.comptimePrint("Arch field is not all lowercase: {s}", .{field_name}));
const coff_machine = @field(Arch, field_name).toCoffMachineType();
_ = rvaRelocationTypeIndicator(coff_machine) orelse {
@compileError(std.fmt.comptimePrint("No RVA relocation for Arch: {s}", .{field_name}));
};
}
}
}