Commit 533f54c68e
Changed files (4)
lib
std
src
lib/std/Target/Query.zig
@@ -124,71 +124,21 @@ pub fn fromTarget(target: Target) Query {
}
fn updateOsVersionRange(self: *Query, os: Target.Os) void {
- switch (os.tag) {
- .freestanding,
- .ananas,
- .cloudabi,
- .fuchsia,
- .kfreebsd,
- .lv2,
- .solaris,
- .illumos,
- .zos,
- .haiku,
- .minix,
- .rtems,
- .nacl,
- .aix,
- .cuda,
- .nvcl,
- .amdhsa,
- .ps4,
- .ps5,
- .elfiamcu,
- .mesa3d,
- .contiki,
- .amdpal,
- .hermit,
- .hurd,
- .wasi,
- .emscripten,
- .driverkit,
- .shadermodel,
- .liteos,
- .uefi,
- .opencl,
- .glsl450,
- .vulkan,
- .plan9,
- .other,
- => {
- self.os_version_min = .{ .none = {} };
- self.os_version_max = .{ .none = {} };
+ self.os_version_min, self.os_version_max = switch (os.tag.getVersionRangeTag()) {
+ .none => .{ .{ .none = {} }, .{ .none = {} } },
+ .semver => .{
+ .{ .semver = os.version_range.semver.min },
+ .{ .semver = os.version_range.semver.max },
},
-
- .freebsd,
- .macos,
- .ios,
- .tvos,
- .watchos,
- .netbsd,
- .openbsd,
- .dragonfly,
- => {
- self.os_version_min = .{ .semver = os.version_range.semver.min };
- self.os_version_max = .{ .semver = os.version_range.semver.max };
- },
-
- .linux => {
- self.os_version_min = .{ .semver = os.version_range.linux.range.min };
- self.os_version_max = .{ .semver = os.version_range.linux.range.max };
+ .linux => .{
+ .{ .semver = os.version_range.linux.range.min },
+ .{ .semver = os.version_range.linux.range.max },
},
-
- .windows => {
- self.os_version_min = .{ .windows = os.version_range.windows.min };
- self.os_version_max = .{ .windows = os.version_range.windows.max };
+ .windows => .{
+ .{ .windows = os.version_range.windows.min },
+ .{ .windows = os.version_range.windows.max },
},
- }
+ };
}
pub const ParseOptions = struct {
@@ -278,7 +228,8 @@ pub fn parse(args: ParseOptions) !Query {
const abi_ver_text = abi_it.rest();
if (abi_it.next() != null) {
- if (Target.isGnuLibC_os_tag_abi(result.os_tag orelse builtin.os.tag, abi)) {
+ const tag = result.os_tag orelse builtin.os.tag;
+ if (tag.isGnuLibC(abi)) {
result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
error.Overflow => return error.InvalidAbiVersion,
error.InvalidVersion => return error.InvalidAbiVersion,
@@ -567,88 +518,33 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
diags.os_tag = tag;
const version_text = it.rest();
- if (it.next() == null) return;
-
- switch (tag) {
- .freestanding,
- .ananas,
- .cloudabi,
- .fuchsia,
- .kfreebsd,
- .lv2,
- .solaris,
- .illumos,
- .zos,
- .haiku,
- .minix,
- .rtems,
- .nacl,
- .aix,
- .cuda,
- .nvcl,
- .amdhsa,
- .ps4,
- .ps5,
- .elfiamcu,
- .mesa3d,
- .contiki,
- .amdpal,
- .hermit,
- .hurd,
- .wasi,
- .emscripten,
- .uefi,
- .opencl,
- .glsl450,
- .vulkan,
- .plan9,
- .driverkit,
- .shadermodel,
- .liteos,
- .other,
- => return error.InvalidOperatingSystemVersion,
-
- .freebsd,
- .macos,
- .ios,
- .tvos,
- .watchos,
- .netbsd,
- .openbsd,
- .linux,
- .dragonfly,
- => {
+ if (version_text.len > 0) switch (tag.getVersionRangeTag()) {
+ .none => return error.InvalidOperatingSystemVersion,
+ .semver, .linux => range: {
var range_it = mem.splitSequence(u8, version_text, "...");
-
- const min_text = range_it.next().?;
- const min_ver = parseVersion(min_text) catch |err| switch (err) {
- error.Overflow => return error.InvalidOperatingSystemVersion,
- error.InvalidVersion => return error.InvalidOperatingSystemVersion,
+ result.os_version_min = .{
+ .semver = parseVersion(range_it.first()) catch |err| switch (err) {
+ error.Overflow => return error.InvalidOperatingSystemVersion,
+ error.InvalidVersion => return error.InvalidOperatingSystemVersion,
+ },
};
- result.os_version_min = .{ .semver = min_ver };
-
- const max_text = range_it.next() orelse return;
- const max_ver = parseVersion(max_text) catch |err| switch (err) {
- error.Overflow => return error.InvalidOperatingSystemVersion,
- error.InvalidVersion => return error.InvalidOperatingSystemVersion,
+ result.os_version_max = .{
+ .semver = parseVersion(range_it.next() orelse break :range) catch |err| switch (err) {
+ error.Overflow => return error.InvalidOperatingSystemVersion,
+ error.InvalidVersion => return error.InvalidOperatingSystemVersion,
+ },
};
- result.os_version_max = .{ .semver = max_ver };
},
-
- .windows => {
+ .windows => range: {
var range_it = mem.splitSequence(u8, version_text, "...");
-
- const min_text = range_it.first();
- const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse
- return error.InvalidOperatingSystemVersion;
- result.os_version_min = .{ .windows = min_ver };
-
- const max_text = range_it.next() orelse return;
- const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse
- return error.InvalidOperatingSystemVersion;
- result.os_version_max = .{ .windows = max_ver };
+ result.os_version_min = .{
+ .windows = try Target.Os.WindowsVersion.parse(range_it.first()),
+ };
+ result.os_version_max = .{
+ .windows = try Target.Os.WindowsVersion.parse(range_it.next() orelse break :range),
+ };
},
- }
+ };
}
pub fn eql(a: Query, b: Query) bool {
lib/std/zig/system.zig
@@ -430,9 +430,9 @@ pub fn abiAndDynamicLinkerFromFile(
query: Target.Query,
) AbiAndDynamicLinkerFromFileError!Target {
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
- _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
- const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));
- const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));
+ _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
+ const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
+ const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
elf.ELFDATA2LSB => .little,
@@ -469,7 +469,7 @@ pub fn abiAndDynamicLinkerFromFile(
// Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits.
const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
- const ph_read_byte_len = try preadMin(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
+ const ph_read_byte_len = try preadAtLeast(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
var ph_buf_i: usize = 0;
while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
ph_i += 1;
@@ -484,13 +484,13 @@ pub fn abiAndDynamicLinkerFromFile(
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
- const filesz = @as(usize, @intCast(p_filesz));
- _ = try preadMin(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
+ const filesz: usize = @intCast(p_filesz);
+ _ = try preadAtLeast(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
// PT_INTERP includes a null byte in filesz.
const len = filesz - 1;
// dynamic_linker.max_byte is "max", not "len".
// We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
- result.dynamic_linker.max_byte = @as(u8, @intCast(len - 1));
+ result.dynamic_linker.len = @intCast(len);
// Use it to determine ABI.
const full_ld_path = result.dynamic_linker.buffer[0..len];
@@ -516,7 +516,7 @@ pub fn abiAndDynamicLinkerFromFile(
// Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits.
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
- const dyn_read_byte_len = try preadMin(
+ const dyn_read_byte_len = try preadAtLeast(
file,
dyn_buf[0 .. dyn_buf.len - dyn_reserve],
dyn_off,
@@ -556,14 +556,14 @@ pub fn abiAndDynamicLinkerFromFile(
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
if (sh_buf.len < shentsize) return error.InvalidElfFile;
- _ = try preadMin(file, &sh_buf, str_section_off, shentsize);
+ _ = try preadAtLeast(file, &sh_buf, str_section_off, shentsize);
const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
var strtab_buf: [4096:0]u8 = undefined;
const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
- const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
+ const shstrtab_read_len = try preadAtLeast(file, &strtab_buf, shstrtab_off, shstrtab_len);
const shstrtab = strtab_buf[0..shstrtab_read_len];
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
@@ -572,7 +572,7 @@ pub fn abiAndDynamicLinkerFromFile(
// Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits.
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
- const sh_read_byte_len = try preadMin(
+ const sh_read_byte_len = try preadAtLeast(
file,
sh_buf[0 .. sh_buf.len - sh_reserve],
shoff,
@@ -604,7 +604,7 @@ pub fn abiAndDynamicLinkerFromFile(
const rp_max_size = ds.size - rpoff;
const strtab_len = @min(rp_max_size, strtab_buf.len);
- const strtab_read_len = try preadMin(file, &strtab_buf, rpoff_file, strtab_len);
+ const strtab_read_len = try preadAtLeast(file, &strtab_buf, rpoff_file, strtab_len);
const strtab = strtab_buf[0..strtab_read_len];
const rpath_list = mem.sliceTo(strtab, 0);
@@ -814,9 +814,9 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion {
fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
- _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
- const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));
- const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));
+ _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
+ const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
+ const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
elf.ELFDATA2LSB => .little,
@@ -838,14 +838,14 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
if (sh_buf.len < shentsize) return error.InvalidElfFile;
- _ = try preadMin(file, &sh_buf, str_section_off, shentsize);
+ _ = try preadAtLeast(file, &sh_buf, str_section_off, shentsize);
const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
var strtab_buf: [4096:0]u8 = undefined;
const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
- const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
+ const shstrtab_read_len = try preadAtLeast(file, &strtab_buf, shstrtab_off, shstrtab_len);
const shstrtab = strtab_buf[0..shstrtab_read_len];
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
var sh_i: u16 = 0;
@@ -853,7 +853,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
// Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits.
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
- const sh_read_byte_len = try preadMin(
+ const sh_read_byte_len = try preadAtLeast(
file,
sh_buf[0 .. sh_buf.len - sh_reserve],
shoff,
@@ -890,7 +890,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
const dynstr_size: usize = @intCast(dynstr.size);
const dynstr_bytes = buf[0..dynstr_size];
- _ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
+ _ = try preadAtLeast(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
var it = mem.splitScalar(u8, dynstr_bytes, 0);
var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };
while (it.next()) |s| {
@@ -1029,7 +1029,7 @@ fn detectAbiAndDynamicLinker(
};
errdefer file.close();
- const len = preadMin(file, &buffer, 0, buffer.len) catch |err| switch (err) {
+ const len = preadAtLeast(file, &buffer, 0, buffer.len) catch |err| switch (err) {
error.UnexpectedEndOfFile,
error.UnableToReadElfFile,
=> break :blk file,
@@ -1083,7 +1083,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer
.abi = abi,
.ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
.dynamic_linker = if (query.dynamic_linker.get() == null)
- Target.standardDynamicLinkerPath_cpu_os_abi(cpu, os.tag, abi)
+ Target.DynamicLinker.standard(cpu, os.tag, abi)
else
query.dynamic_linker,
};
@@ -1094,7 +1094,7 @@ const LdInfo = struct {
abi: Target.Abi,
};
-fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
+fn preadAtLeast(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
var i: usize = 0;
while (i < min_read_len) {
const len = file.pread(buf[i..], offset + i) catch |err| switch (err) {
lib/std/Target.zig
@@ -81,14 +81,48 @@ pub const Os = struct {
return tag == .solaris or tag == .illumos;
}
+ pub fn exeFileExt(tag: Tag, arch: Cpu.Arch) [:0]const u8 {
+ return switch (tag) {
+ .windows => ".exe",
+ .uefi => ".efi",
+ .plan9 => arch.plan9Ext(),
+ else => switch (arch) {
+ .wasm32, .wasm64 => ".wasm",
+ else => "",
+ },
+ };
+ }
+
+ pub fn staticLibSuffix(tag: Tag, abi: Abi) [:0]const u8 {
+ return switch (abi) {
+ .msvc => ".lib",
+ else => switch (tag) {
+ .windows, .uefi => ".lib",
+ else => ".a",
+ },
+ };
+ }
+
pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 {
- if (tag.isDarwin()) {
- return ".dylib";
- }
- switch (tag) {
- .windows => return ".dll",
- else => return ".so",
- }
+ return switch (tag) {
+ .windows, .uefi => ".dll",
+ .ios, .macos, .watchos, .tvos => ".dylib",
+ else => ".so",
+ };
+ }
+
+ pub fn libPrefix(tag: Os.Tag, abi: Abi) [:0]const u8 {
+ return switch (abi) {
+ .msvc => "",
+ else => switch (tag) {
+ .windows, .uefi => "",
+ else => "lib",
+ },
+ };
+ }
+
+ pub inline fn isGnuLibC(tag: Os.Tag, abi: Abi) bool {
+ return tag == .linux and abi.isGnu();
}
pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch) Os {
@@ -97,6 +131,78 @@ pub const Os = struct {
.version_range = VersionRange.default(tag, arch),
};
}
+
+ pub inline fn getVersionRangeTag(tag: Tag) @typeInfo(TaggedVersionRange).Union.tag_type.? {
+ return switch (tag) {
+ .freestanding,
+ .ananas,
+ .cloudabi,
+ .fuchsia,
+ .kfreebsd,
+ .lv2,
+ .zos,
+ .haiku,
+ .minix,
+ .rtems,
+ .nacl,
+ .aix,
+ .cuda,
+ .nvcl,
+ .amdhsa,
+ .ps4,
+ .ps5,
+ .elfiamcu,
+ .mesa3d,
+ .contiki,
+ .amdpal,
+ .hermit,
+ .hurd,
+ .wasi,
+ .emscripten,
+ .driverkit,
+ .shadermodel,
+ .liteos,
+ .uefi,
+ .opencl, // TODO: OpenCL versions
+ .glsl450, // TODO: GLSL versions
+ .vulkan,
+ .plan9,
+ .illumos,
+ .other,
+ => .none,
+
+ .freebsd,
+ .macos,
+ .ios,
+ .tvos,
+ .watchos,
+ .netbsd,
+ .openbsd,
+ .dragonfly,
+ .solaris,
+ => .semver,
+
+ .linux => .linux,
+
+ .windows => .windows,
+ };
+ }
+
+ pub fn archName(tag: Tag, arch: Cpu.Arch) [:0]const u8 {
+ return switch (tag) {
+ .linux => switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => "arm",
+ .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
+ .mips, .mipsel, .mips64, .mips64el => "mips",
+ .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc",
+ .riscv32, .riscv64 => "riscv",
+ .sparc, .sparcel, .sparc64 => "sparc",
+ .x86, .x86_64 => "x86",
+ else => @tagName(arch),
+ },
+ else => @tagName(arch),
+ };
+ }
};
/// Based on NTDDI version constants from
@@ -142,52 +248,60 @@ pub const Os = struct {
19042, //win10_fe aka win10_20h2
};
- /// Returns whether the first version `self` is newer (greater) than or equal to the second version `ver`.
- pub inline fn isAtLeast(self: WindowsVersion, ver: WindowsVersion) bool {
- return @intFromEnum(self) >= @intFromEnum(ver);
+ /// Returns whether the first version `ver` is newer (greater) than or equal to the second version `ver`.
+ pub inline fn isAtLeast(ver: WindowsVersion, min_ver: WindowsVersion) bool {
+ return @intFromEnum(ver) >= @intFromEnum(min_ver);
}
pub const Range = struct {
min: WindowsVersion,
max: WindowsVersion,
- pub inline fn includesVersion(self: Range, ver: WindowsVersion) bool {
- return @intFromEnum(ver) >= @intFromEnum(self.min) and @intFromEnum(ver) <= @intFromEnum(self.max);
+ pub inline fn includesVersion(range: Range, ver: WindowsVersion) bool {
+ return @intFromEnum(ver) >= @intFromEnum(range.min) and
+ @intFromEnum(ver) <= @intFromEnum(range.max);
}
/// Checks if system is guaranteed to be at least `version` or older than `version`.
/// Returns `null` if a runtime check is required.
- pub inline fn isAtLeast(self: Range, ver: WindowsVersion) ?bool {
- if (@intFromEnum(self.min) >= @intFromEnum(ver)) return true;
- if (@intFromEnum(self.max) < @intFromEnum(ver)) return false;
+ pub inline fn isAtLeast(range: Range, min_ver: WindowsVersion) ?bool {
+ if (@intFromEnum(range.min) >= @intFromEnum(min_ver)) return true;
+ if (@intFromEnum(range.max) < @intFromEnum(min_ver)) return false;
return null;
}
};
+ pub fn parse(str: []const u8) !WindowsVersion {
+ return std.meta.stringToEnum(WindowsVersion, str) orelse
+ @enumFromInt(std.fmt.parseInt(u32, str, 0) catch
+ return error.InvalidOperatingSystemVersion);
+ }
+
/// This function is defined to serialize a Zig source code representation of this
/// type, that, when parsed, will deserialize into the same data.
pub fn format(
- self: WindowsVersion,
- comptime fmt: []const u8,
+ ver: WindowsVersion,
+ comptime fmt_str: []const u8,
_: std.fmt.FormatOptions,
- out_stream: anytype,
- ) !void {
- if (comptime std.mem.eql(u8, fmt, "s")) {
- if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {
- try std.fmt.format(out_stream, ".{s}", .{@tagName(self)});
- } else {
- // TODO this code path breaks zig triples, but it is used in `builtin`
- try std.fmt.format(out_stream, "@enumFromInt(Target.Os.WindowsVersion, 0x{X:0>8})", .{@intFromEnum(self)});
- }
- } else if (fmt.len == 0) {
- if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {
- try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)});
- } else {
- try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@intFromEnum(self)});
- }
- } else {
- std.fmt.invalidFmtError(fmt, self);
- }
+ writer: anytype,
+ ) @TypeOf(writer).Error!void {
+ const maybe_name = std.enums.tagName(WindowsVersion, ver);
+ if (comptime std.mem.eql(u8, fmt_str, "s")) {
+ if (maybe_name) |name|
+ try writer.print(".{s}", .{name})
+ else
+ try writer.print(".{d}", .{@intFromEnum(ver)});
+ } else if (comptime std.mem.eql(u8, fmt_str, "c")) {
+ if (maybe_name) |name|
+ try writer.print(".{s}", .{name})
+ else
+ try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
+ } else if (fmt_str.len == 0) {
+ if (maybe_name) |name|
+ try writer.print("WindowsVersion.{s}", .{name})
+ else
+ try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
+ } else std.fmt.invalidFmtError(fmt_str, ver);
}
};
@@ -195,14 +309,14 @@ pub const Os = struct {
range: std.SemanticVersion.Range,
glibc: std.SemanticVersion,
- pub inline fn includesVersion(self: LinuxVersionRange, ver: std.SemanticVersion) bool {
- return self.range.includesVersion(ver);
+ pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
+ return range.range.includesVersion(ver);
}
/// Checks if system is guaranteed to be at least `version` or older than `version`.
/// Returns `null` if a runtime check is required.
- pub inline fn isAtLeast(self: LinuxVersionRange, ver: std.SemanticVersion) ?bool {
- return self.range.isAtLeast(ver);
+ pub inline fn isAtLeast(range: LinuxVersionRange, ver: std.SemanticVersion) ?bool {
+ return range.range.isAtLeast(ver);
}
};
@@ -239,7 +353,7 @@ pub const Os = struct {
/// The default `VersionRange` represents the range that the Zig Standard Library
/// bases its abstractions on.
pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange {
- switch (tag) {
+ return switch (tag) {
.freestanding,
.ananas,
.cloudabi,
@@ -275,15 +389,15 @@ pub const Os = struct {
.plan9,
.illumos,
.other,
- => return .{ .none = {} },
+ => .{ .none = {} },
- .freebsd => return .{
+ .freebsd => .{
.semver = std.SemanticVersion.Range{
.min = .{ .major = 12, .minor = 0, .patch = 0 },
.max = .{ .major = 14, .minor = 0, .patch = 0 },
},
},
- .macos => return switch (arch) {
+ .macos => switch (arch) {
.aarch64 => VersionRange{
.semver = .{
.min = .{ .major = 11, .minor = 7, .patch = 1 },
@@ -298,50 +412,50 @@ pub const Os = struct {
},
else => unreachable,
},
- .ios => return .{
+ .ios => .{
.semver = .{
.min = .{ .major = 12, .minor = 0, .patch = 0 },
.max = .{ .major = 17, .minor = 1, .patch = 0 },
},
},
- .watchos => return .{
+ .watchos => .{
.semver = .{
.min = .{ .major = 6, .minor = 0, .patch = 0 },
.max = .{ .major = 10, .minor = 1, .patch = 0 },
},
},
- .tvos => return .{
+ .tvos => .{
.semver = .{
.min = .{ .major = 13, .minor = 0, .patch = 0 },
.max = .{ .major = 17, .minor = 1, .patch = 0 },
},
},
- .netbsd => return .{
+ .netbsd => .{
.semver = .{
.min = .{ .major = 8, .minor = 0, .patch = 0 },
.max = .{ .major = 10, .minor = 0, .patch = 0 },
},
},
- .openbsd => return .{
+ .openbsd => .{
.semver = .{
.min = .{ .major = 6, .minor = 8, .patch = 0 },
.max = .{ .major = 7, .minor = 4, .patch = 0 },
},
},
- .dragonfly => return .{
+ .dragonfly => .{
.semver = .{
.min = .{ .major = 5, .minor = 8, .patch = 0 },
.max = .{ .major = 6, .minor = 4, .patch = 0 },
},
},
- .solaris => return .{
+ .solaris => .{
.semver = .{
.min = .{ .major = 5, .minor = 11, .patch = 0 },
.max = .{ .major = 5, .minor = 11, .patch = 0 },
},
},
- .linux => return .{
+ .linux => .{
.linux = .{
.range = .{
.min = .{ .major = 4, .minor = 19, .patch = 0 },
@@ -351,13 +465,13 @@ pub const Os = struct {
},
},
- .windows => return .{
+ .windows => .{
.windows = .{
.min = .win8_1,
.max = WindowsVersion.latest,
},
},
- }
+ };
}
};
@@ -370,38 +484,28 @@ pub const Os = struct {
/// Provides a tagged union. `Target` does not store the tag because it is
/// redundant with the OS tag; this function abstracts that part away.
- pub inline fn getVersionRange(self: Os) TaggedVersionRange {
- switch (self.tag) {
- .linux => return TaggedVersionRange{ .linux = self.version_range.linux },
- .windows => return TaggedVersionRange{ .windows = self.version_range.windows },
-
- .freebsd,
- .macos,
- .ios,
- .tvos,
- .watchos,
- .netbsd,
- .openbsd,
- .dragonfly,
- .solaris,
- => return TaggedVersionRange{ .semver = self.version_range.semver },
-
- else => return .none,
- }
+ pub inline fn getVersionRange(os: Os) TaggedVersionRange {
+ return switch (os.tag.getVersionRangeTag()) {
+ .none => .{ .none = {} },
+ .semver => .{ .semver = os.version_range.semver },
+ .linux => .{ .linux = os.version_range.linux },
+ .windows => .{ .windows = os.version_range.windows },
+ };
}
/// Checks if system is guaranteed to be at least `version` or older than `version`.
/// Returns `null` if a runtime check is required.
- pub inline fn isAtLeast(self: Os, comptime tag: Tag, version: switch (tag) {
- else => std.SemanticVersion,
+ pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.getVersionRangeTag()) {
+ .none => void,
+ .semver, .linux => std.SemanticVersion,
.windows => WindowsVersion,
}) ?bool {
- if (self.tag != tag) return false;
-
- return switch (tag) {
- .linux => self.version_range.linux.isAtLeast(version),
- .windows => self.version_range.windows.isAtLeast(version),
- else => self.version_range.semver.isAtLeast(version),
+ return if (os.tag != tag) false else switch (tag.getVersionRangeTag()) {
+ .none => true,
+ inline .semver,
+ .linux,
+ .windows,
+ => |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
};
}
@@ -528,11 +632,8 @@ pub const Abi = enum {
mesh,
amplification,
- pub fn default(arch: Cpu.Arch, target_os: Os) Abi {
- if (arch.isWasm()) {
- return .musl;
- }
- switch (target_os.tag) {
+ pub fn default(arch: Cpu.Arch, os: Os) Abi {
+ return if (arch.isWasm()) .musl else switch (os.tag) {
.freestanding,
.ananas,
.cloudabi,
@@ -554,7 +655,7 @@ pub const Abi = enum {
.amdpal,
.hermit,
.other,
- => return .eabi,
+ => .eabi,
.openbsd,
.freebsd,
.fuchsia,
@@ -563,12 +664,12 @@ pub const Abi = enum {
.hurd,
.haiku,
.windows,
- => return .gnu,
- .uefi => return .msvc,
+ => .gnu,
+ .uefi => .msvc,
.linux,
.wasi,
.emscripten,
- => return .musl,
+ => .musl,
.opencl, // TODO: SPIR-V ABIs with Linkage capability
.glsl450,
.vulkan,
@@ -582,8 +683,8 @@ pub const Abi = enum {
.liteos, // TODO: audit this
.solaris,
.illumos,
- => return .none,
- }
+ => .none,
+ };
}
pub inline fn isGnu(abi: Abi) bool {
@@ -635,7 +736,7 @@ pub const ObjectFormat = enum {
/// Nvidia PTX format
nvptx,
- pub fn fileExt(of: ObjectFormat, cpu_arch: Cpu.Arch) [:0]const u8 {
+ pub fn fileExt(of: ObjectFormat, arch: Cpu.Arch) [:0]const u8 {
return switch (of) {
.coff => ".obj",
.elf, .macho, .wasm => ".o",
@@ -643,18 +744,18 @@ pub const ObjectFormat = enum {
.spirv => ".spv",
.hex => ".ihex",
.raw => ".bin",
- .plan9 => plan9Ext(cpu_arch),
+ .plan9 => arch.plan9Ext(),
.nvptx => ".ptx",
.dxcontainer => ".dxil",
};
}
- pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat {
+ pub fn default(os_tag: Os.Tag, arch: Cpu.Arch) ObjectFormat {
return switch (os_tag) {
.windows, .uefi => .coff,
.ios, .macos, .watchos, .tvos => .macho,
.plan9 => .plan9,
- else => return switch (cpu_arch) {
+ else => switch (arch) {
.wasm32, .wasm64 => .wasm,
.spirv32, .spirv64 => .spirv,
.nvptx, .nvptx64 => .nvptx,
@@ -725,14 +826,14 @@ pub const Cpu = struct {
pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
const usize_index = arch_feature_index / @bitSizeOf(usize);
- const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
+ const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;
}
/// Adds the specified feature but not its dependencies.
pub fn addFeature(set: *Set, arch_feature_index: Index) void {
const usize_index = arch_feature_index / @bitSizeOf(usize);
- const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
+ const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
set.ints[usize_index] |= @as(usize, 1) << bit_index;
}
@@ -751,7 +852,7 @@ pub const Cpu = struct {
/// Removes the specified feature but not its dependents.
pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
const usize_index = arch_feature_index / @bitSizeOf(usize);
- const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
+ const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
}
@@ -773,7 +874,7 @@ pub const Cpu = struct {
var old = set.ints;
while (true) {
for (all_features_list, 0..) |feature, index_usize| {
- const index = @as(Index, @intCast(index_usize));
+ const index: Index = @intCast(index_usize);
if (set.isEnabled(index)) {
set.addFeatureSet(feature.dependencies);
}
@@ -785,7 +886,7 @@ pub const Cpu = struct {
}
pub fn asBytes(set: *const Set) *const [byte_count]u8 {
- return @as(*const [byte_count]u8, @ptrCast(&set.ints));
+ return std.mem.sliceAsBytes(&set.ints)[0..byte_count];
}
pub fn eql(set: Set, other_set: Set) bool {
@@ -1231,7 +1332,7 @@ pub const Cpu = struct {
}
/// Returns a name that matches the lib/std/target/* source file name.
- pub fn genericName(arch: Arch) []const u8 {
+ pub fn genericName(arch: Arch) [:0]const u8 {
return switch (arch) {
.arm, .armeb, .thumb, .thumbeb => "arm",
.aarch64, .aarch64_be, .aarch64_32 => "aarch64",
@@ -1320,6 +1421,30 @@ pub const Cpu = struct {
const finalized = array;
return &finalized;
}
+
+ /// 0c spim little-endian MIPS 3000 family
+ /// 1c 68000 Motorola MC68000
+ /// 2c 68020 Motorola MC68020
+ /// 5c arm little-endian ARM
+ /// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
+ /// 7c arm64 ARM64 (ARMv8)
+ /// 8c 386 Intel x86, i486, Pentium, etc.
+ /// kc sparc Sun SPARC
+ /// qc power Power PC
+ /// vc mips big-endian MIPS 3000 family
+ pub fn plan9Ext(arch: Cpu.Arch) [:0]const u8 {
+ return switch (arch) {
+ .arm => ".5",
+ .x86_64 => ".6",
+ .aarch64 => ".7",
+ .x86 => ".8",
+ .sparc => ".k",
+ .powerpc, .powerpcle => ".q",
+ .mips, .mipsel => ".v",
+ // ISAs without designated characters get 'X' for lack of a better option.
+ else => ".X",
+ };
+ }
};
pub const Model = struct {
@@ -1399,112 +1524,76 @@ pub const Cpu = struct {
}
};
-pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 {
- return Query.fromTarget(self).zigTriple(allocator);
-}
-
-pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
- return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
-}
-
-pub fn linuxTriple(self: Target, allocator: Allocator) ![]u8 {
- return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi);
+pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
+ return Query.fromTarget(target).zigTriple(allocator);
}
-pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 {
- return switch (os_tag) {
- .windows => ".exe",
- .uefi => ".efi",
- .plan9 => plan9Ext(cpu_arch),
- else => switch (cpu_arch) {
- .wasm32, .wasm64 => ".wasm",
- else => "",
- },
- };
-}
-
-pub fn exeFileExt(self: Target) [:0]const u8 {
- return exeFileExtSimple(self.cpu.arch, self.os.tag);
-}
-
-pub fn staticLibSuffix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {
- if (abi == .msvc) {
- return ".lib";
- }
- switch (os_tag) {
- .windows, .uefi => return ".lib",
- else => return ".a",
- }
+pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
+ return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
}
-pub fn staticLibSuffix(self: Target) [:0]const u8 {
- return staticLibSuffix_os_abi(self.os.tag, self.abi);
+pub fn linuxTriple(target: Target, allocator: Allocator) ![]u8 {
+ return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
}
-pub fn dynamicLibSuffix(self: Target) [:0]const u8 {
- return self.os.tag.dynamicLibSuffix();
+pub fn exeFileExt(target: Target) [:0]const u8 {
+ return target.os.tag.exeFileExt(target.cpu.arch);
}
-pub fn libPrefix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {
- if (abi == .msvc) {
- return "";
- }
- switch (os_tag) {
- .windows, .uefi => return "",
- else => return "lib",
- }
+pub fn staticLibSuffix(target: Target) [:0]const u8 {
+ return target.os.tag.staticLibSuffix(target.abi);
}
-pub fn libPrefix(self: Target) [:0]const u8 {
- return libPrefix_os_abi(self.os.tag, self.abi);
+pub fn dynamicLibSuffix(target: Target) [:0]const u8 {
+ return target.os.tag.dynamicLibSuffix();
}
-pub inline fn isMinGW(self: Target) bool {
- return self.os.tag == .windows and self.isGnu();
+pub fn libPrefix(target: Target) [:0]const u8 {
+ return target.os.tag.libPrefix(target.abi);
}
-pub inline fn isGnu(self: Target) bool {
- return self.abi.isGnu();
+pub inline fn isMinGW(target: Target) bool {
+ return target.os.tag == .windows and target.isGnu();
}
-pub inline fn isMusl(self: Target) bool {
- return self.abi.isMusl();
+pub inline fn isGnu(target: Target) bool {
+ return target.abi.isGnu();
}
-pub inline fn isAndroid(self: Target) bool {
- return self.abi == .android;
+pub inline fn isMusl(target: Target) bool {
+ return target.abi.isMusl();
}
-pub inline fn isWasm(self: Target) bool {
- return self.cpu.arch.isWasm();
+pub inline fn isAndroid(target: Target) bool {
+ return target.abi == .android;
}
-pub inline fn isDarwin(self: Target) bool {
- return self.os.tag.isDarwin();
+pub inline fn isWasm(target: Target) bool {
+ return target.cpu.arch.isWasm();
}
-pub inline fn isBSD(self: Target) bool {
- return self.os.tag.isBSD();
+pub inline fn isDarwin(target: Target) bool {
+ return target.os.tag.isDarwin();
}
-pub inline fn isBpfFreestanding(self: Target) bool {
- return self.cpu.arch.isBpf() and self.os.tag == .freestanding;
+pub inline fn isBSD(target: Target) bool {
+ return target.os.tag.isBSD();
}
-pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool {
- return os_tag == .linux and abi.isGnu();
+pub inline fn isBpfFreestanding(target: Target) bool {
+ return target.cpu.arch.isBpf() and target.os.tag == .freestanding;
}
-pub inline fn isGnuLibC(self: Target) bool {
- return isGnuLibC_os_tag_abi(self.os.tag, self.abi);
+pub inline fn isGnuLibC(target: Target) bool {
+ return target.os.tag.isGnuLibC(target.abi);
}
-pub inline fn supportsNewStackCall(self: Target) bool {
- return !self.cpu.arch.isWasm();
+pub inline fn supportsNewStackCall(target: Target) bool {
+ return !target.cpu.arch.isWasm();
}
-pub inline fn isSpirV(self: Target) bool {
- return self.cpu.arch.isSpirV();
+pub inline fn isSpirV(target: Target) bool {
+ return target.cpu.arch.isSpirV();
}
pub const FloatAbi = enum {
@@ -1512,15 +1601,15 @@ pub const FloatAbi = enum {
soft,
};
-pub inline fn getFloatAbi(self: Target) FloatAbi {
- return self.abi.floatAbi();
+pub inline fn getFloatAbi(target: Target) FloatAbi {
+ return target.abi.floatAbi();
}
-pub inline fn hasDynamicLinker(self: Target) bool {
- if (self.cpu.arch.isWasm()) {
+pub inline fn hasDynamicLinker(target: Target) bool {
+ if (target.cpu.arch.isWasm()) {
return false;
}
- switch (self.os.tag) {
+ switch (target.os.tag) {
.freestanding,
.ios,
.tvos,
@@ -1547,259 +1636,210 @@ pub const DynamicLinker = struct {
/// Used to construct the dynamic linker path. This field should not be used
/// directly. See `get` and `set`.
- max_byte: ?u8,
+ len: u8,
- pub const none: DynamicLinker = .{
- .buffer = undefined,
- .max_byte = null,
- };
+ pub const none: DynamicLinker = .{ .buffer = undefined, .len = 0 };
/// Asserts that the length is less than or equal to 255 bytes.
- pub fn init(dl_or_null: ?[]const u8) DynamicLinker {
- var result: DynamicLinker = undefined;
- result.set(dl_or_null);
- return result;
+ pub fn init(maybe_path: ?[]const u8) DynamicLinker {
+ var dl: DynamicLinker = undefined;
+ dl.set(maybe_path);
+ return dl;
+ }
+
+ pub fn initFmt(comptime fmt_str: []const u8, args: anytype) !DynamicLinker {
+ var dl: DynamicLinker = undefined;
+ try dl.setFmt(fmt_str, args);
+ return dl;
}
/// The returned memory has the same lifetime as the `DynamicLinker`.
- pub fn get(self: *const DynamicLinker) ?[]const u8 {
- const m: usize = self.max_byte orelse return null;
- return self.buffer[0 .. m + 1];
+ pub fn get(dl: *const DynamicLinker) ?[]const u8 {
+ return if (dl.len > 0) dl.buffer[0..dl.len] else null;
}
/// Asserts that the length is less than or equal to 255 bytes.
- pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {
- if (dl_or_null) |dl| {
- @memcpy(self.buffer[0..dl.len], dl);
- self.max_byte = @intCast(dl.len - 1);
- } else {
- self.max_byte = null;
- }
+ pub fn set(dl: *DynamicLinker, maybe_path: ?[]const u8) void {
+ const path = maybe_path orelse "";
+ @memcpy(dl.buffer[0..path.len], path);
+ dl.len = @intCast(path.len);
}
- pub fn eql(a: DynamicLinker, b: DynamicLinker) bool {
- const a_m = a.max_byte orelse return b.max_byte == null;
- const b_m = b.max_byte orelse return false;
- if (a_m != b_m) return false;
- const a_s = a.buffer[0 .. a_m + 1];
- const b_s = b.buffer[0 .. a_m + 1];
- return std.mem.eql(u8, a_s, b_s);
+ /// Asserts that the length is less than or equal to 255 bytes.
+ pub fn setFmt(dl: *DynamicLinker, comptime fmt_str: []const u8, args: anytype) !void {
+ dl.len = @intCast((try std.fmt.bufPrint(&dl.buffer, fmt_str, args)).len);
}
-};
-
-pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
- return standardDynamicLinkerPath_cpu_os_abi(target.cpu, target.os.tag, target.abi);
-}
-pub fn standardDynamicLinkerPath_cpu_os_abi(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
- var result = DynamicLinker.none;
- const S = struct {
- fn print(r: *DynamicLinker, comptime fmt: []const u8, args: anytype) DynamicLinker {
- r.max_byte = @as(u8, @intCast((std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1));
- return r.*;
- }
- fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
- @memcpy(r.buffer[0..s.len], s);
- r.max_byte = @as(u8, @intCast(s.len - 1));
- return r.*;
- }
- };
- const print = S.print;
- const copy = S.copy;
-
- if (abi == .android) {
- const suffix = if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "";
- return print(&result, "/system/bin/linker{s}", .{suffix});
+ pub fn eql(lhs: DynamicLinker, rhs: DynamicLinker) bool {
+ return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
}
- if (abi.isMusl()) {
- const is_arm = switch (cpu.arch) {
- .arm, .armeb, .thumb, .thumbeb => true,
- else => false,
- };
- const arch_part = switch (cpu.arch) {
- .arm, .thumb => "arm",
- .armeb, .thumbeb => "armeb",
- else => |arch| @tagName(arch),
- };
- const arch_suffix = if (is_arm and abi.floatAbi() == .hard) "hf" else "";
- return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix });
- }
+ pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
+ return if (abi == .android) initFmt("/system/bin/linker{s}", .{
+ if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
+ }) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{
+ @tagName(switch (cpu.arch) {
+ .thumb => .arm,
+ .thumbeb => .armeb,
+ else => cpu.arch,
+ }),
+ if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "",
+ }) catch unreachable else switch (os_tag) {
+ .freebsd => init("/libexec/ld-elf.so.1"),
+ .netbsd => init("/libexec/ld.elf_so"),
+ .openbsd => init("/usr/libexec/ld.so"),
+ .dragonfly => init("/libexec/ld-elf.so.2"),
+ .solaris, .illumos => init("/lib/64/ld.so.1"),
+ .linux => switch (cpu.arch) {
+ .x86,
+ .sparc,
+ .sparcel,
+ => init("/lib/ld-linux.so.2"),
- switch (os_tag) {
- .freebsd => return copy(&result, "/libexec/ld-elf.so.1"),
- .netbsd => return copy(&result, "/libexec/ld.elf_so"),
- .openbsd => return copy(&result, "/usr/libexec/ld.so"),
- .dragonfly => return copy(&result, "/libexec/ld-elf.so.2"),
- .solaris, .illumos => return copy(&result, "/lib/64/ld.so.1"),
- .linux => switch (cpu.arch) {
- .x86,
- .sparc,
- .sparcel,
- => return copy(&result, "/lib/ld-linux.so.2"),
+ .aarch64 => init("/lib/ld-linux-aarch64.so.1"),
+ .aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
+ .aarch64_32 => init("/lib/ld-linux-aarch64_32.so.1"),
- .aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"),
- .aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"),
- .aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"),
+ .arm,
+ .armeb,
+ .thumb,
+ .thumbeb,
+ => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi.floatAbi()) {
+ .hard => "-armhf",
+ else => "",
+ }}) catch unreachable,
- .arm,
- .armeb,
- .thumb,
- .thumbeb,
- => return copy(&result, switch (abi.floatAbi()) {
- .hard => "/lib/ld-linux-armhf.so.3",
- else => "/lib/ld-linux.so.3",
- }),
+ .mips,
+ .mipsel,
+ .mips64,
+ .mips64el,
+ => initFmt("/lib{s}/{s}", .{
+ switch (abi) {
+ .gnuabin32, .gnux32 => "32",
+ .gnuabi64 => "64",
+ else => "",
+ },
+ if (mips.featureSetHas(cpu.features, .nan2008))
+ "ld-linux-mipsn8.so.1"
+ else
+ "ld.so.1",
+ }) catch unreachable,
+
+ .powerpc, .powerpcle => init("/lib/ld.so.1"),
+ .powerpc64, .powerpc64le => init("/lib64/ld64.so.2"),
+ .s390x => init("/lib64/ld64.so.1"),
+ .sparc64 => init("/lib64/ld-linux.so.2"),
+ .x86_64 => init(switch (abi) {
+ .gnux32 => "/libx32/ld-linux-x32.so.2",
+ else => "/lib64/ld-linux-x86-64.so.2",
+ }),
+
+ .riscv32 => init("/lib/ld-linux-riscv32-ilp32.so.1"),
+ .riscv64 => init("/lib/ld-linux-riscv64-lp64.so.1"),
+
+ // Architectures in this list have been verified as not having a standard
+ // dynamic linker path.
+ .wasm32,
+ .wasm64,
+ .bpfel,
+ .bpfeb,
+ .nvptx,
+ .nvptx64,
+ .spu_2,
+ .avr,
+ .spirv32,
+ .spirv64,
+ => none,
- .mips,
- .mipsel,
- .mips64,
- .mips64el,
- => {
- const lib_suffix = switch (abi) {
- .gnuabin32, .gnux32 => "32",
- .gnuabi64 => "64",
- else => "",
- };
- const is_nan_2008 = mips.featureSetHas(cpu.features, .nan2008);
- const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";
- return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader });
+ // TODO go over each item in this list and either move it to the above list, or
+ // implement the standard dynamic linker path code for it.
+ .arc,
+ .csky,
+ .hexagon,
+ .m68k,
+ .msp430,
+ .r600,
+ .amdgcn,
+ .tce,
+ .tcele,
+ .xcore,
+ .le32,
+ .le64,
+ .amdil,
+ .amdil64,
+ .hsail,
+ .hsail64,
+ .spir,
+ .spir64,
+ .kalimba,
+ .shave,
+ .lanai,
+ .renderscript32,
+ .renderscript64,
+ .ve,
+ .dxil,
+ .loongarch32,
+ .loongarch64,
+ .xtensa,
+ => none,
},
- .powerpc, .powerpcle => return copy(&result, "/lib/ld.so.1"),
- .powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"),
- .s390x => return copy(&result, "/lib64/ld64.so.1"),
- .sparc64 => return copy(&result, "/lib64/ld-linux.so.2"),
- .x86_64 => return copy(&result, switch (abi) {
- .gnux32 => "/libx32/ld-linux-x32.so.2",
- else => "/lib64/ld-linux-x86-64.so.2",
- }),
-
- .riscv32 => return copy(&result, "/lib/ld-linux-riscv32-ilp32.so.1"),
- .riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"),
+ .ios,
+ .tvos,
+ .watchos,
+ .macos,
+ => init("/usr/lib/dyld"),
- // Architectures in this list have been verified as not having a standard
+ // Operating systems in this list have been verified as not having a standard
// dynamic linker path.
- .wasm32,
- .wasm64,
- .bpfel,
- .bpfeb,
- .nvptx,
- .nvptx64,
- .spu_2,
- .avr,
- .spirv32,
- .spirv64,
- => return result,
+ .freestanding,
+ .uefi,
+ .windows,
+ .emscripten,
+ .wasi,
+ .opencl,
+ .glsl450,
+ .vulkan,
+ .other,
+ .plan9,
+ => none,
+
+ // TODO revisit when multi-arch for Haiku is available
+ .haiku => init("/system/runtime_loader"),
// TODO go over each item in this list and either move it to the above list, or
// implement the standard dynamic linker path code for it.
- .arc,
- .csky,
- .hexagon,
- .m68k,
- .msp430,
- .r600,
- .amdgcn,
- .tce,
- .tcele,
- .xcore,
- .le32,
- .le64,
- .amdil,
- .amdil64,
- .hsail,
- .hsail64,
- .spir,
- .spir64,
- .kalimba,
- .shave,
- .lanai,
- .renderscript32,
- .renderscript64,
- .ve,
- .dxil,
- .loongarch32,
- .loongarch64,
- .xtensa,
- => return result,
- },
-
- .ios,
- .tvos,
- .watchos,
- .macos,
- => return copy(&result, "/usr/lib/dyld"),
-
- // Operating systems in this list have been verified as not having a standard
- // dynamic linker path.
- .freestanding,
- .uefi,
- .windows,
- .emscripten,
- .wasi,
- .opencl,
- .glsl450,
- .vulkan,
- .other,
- .plan9,
- => return result,
-
- // TODO revisit when multi-arch for Haiku is available
- .haiku => return copy(&result, "/system/runtime_loader"),
-
- // TODO go over each item in this list and either move it to the above list, or
- // implement the standard dynamic linker path code for it.
- .ananas,
- .cloudabi,
- .fuchsia,
- .kfreebsd,
- .lv2,
- .zos,
- .minix,
- .rtems,
- .nacl,
- .aix,
- .cuda,
- .nvcl,
- .amdhsa,
- .ps4,
- .ps5,
- .elfiamcu,
- .mesa3d,
- .contiki,
- .amdpal,
- .hermit,
- .hurd,
- .driverkit,
- .shadermodel,
- .liteos,
- => return result,
+ .ananas,
+ .cloudabi,
+ .fuchsia,
+ .kfreebsd,
+ .lv2,
+ .zos,
+ .minix,
+ .rtems,
+ .nacl,
+ .aix,
+ .cuda,
+ .nvcl,
+ .amdhsa,
+ .ps4,
+ .ps5,
+ .elfiamcu,
+ .mesa3d,
+ .contiki,
+ .amdpal,
+ .hermit,
+ .hurd,
+ .driverkit,
+ .shadermodel,
+ .liteos,
+ => none,
+ };
}
-}
+};
-/// 0c spim little-endian MIPS 3000 family
-/// 1c 68000 Motorola MC68000
-/// 2c 68020 Motorola MC68020
-/// 5c arm little-endian ARM
-/// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
-/// 7c arm64 ARM64 (ARMv8)
-/// 8c 386 Intel x86, i486, Pentium, etc.
-/// kc sparc Sun SPARC
-/// qc power Power PC
-/// vc mips big-endian MIPS 3000 family
-pub fn plan9Ext(cpu_arch: Cpu.Arch) [:0]const u8 {
- return switch (cpu_arch) {
- .arm => ".5",
- .x86_64 => ".6",
- .aarch64 => ".7",
- .x86 => ".8",
- .sparc => ".k",
- .powerpc, .powerpcle => ".q",
- .mips, .mipsel => ".v",
- // ISAs without designated characters get 'X' for lack of a better option.
- else => ".X",
- };
+pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
+ return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
}
pub fn maxIntAlignment(target: Target) u16 {
@@ -2076,7 +2116,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
16 => 2,
32 => 4,
64 => 8,
- 80 => @as(u16, @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble)))),
+ 80 => @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble))),
128 => 16,
else => unreachable,
},
@@ -2419,7 +2459,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
// Next-power-of-two-aligned, up to a maximum.
return @min(
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
- switch (target.cpu.arch) {
+ @as(u16, switch (target.cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
.netbsd => switch (target.abi) {
.gnueabi,
@@ -2431,7 +2471,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
.musleabihf,
=> 8,
- else => @as(u16, 4),
+ else => 4,
},
.ios, .tvos, .watchos => 4,
else => 8,
@@ -2501,7 +2541,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
.wasm32,
.wasm64,
=> 16,
- },
+ }),
);
}
@@ -2559,8 +2599,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
// Next-power-of-two-aligned, up to a maximum.
return @min(
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
- switch (target.cpu.arch) {
- .msp430 => @as(u16, 2),
+ @as(u16, switch (target.cpu.arch) {
+ .msp430 => 2,
.csky,
.xcore,
@@ -2627,7 +2667,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
.wasm32,
.wasm64,
=> 16,
- },
+ }),
);
}
@@ -2767,19 +2807,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
}
pub fn osArchName(target: std.Target) [:0]const u8 {
- return switch (target.os.tag) {
- .linux => switch (target.cpu.arch) {
- .arm, .armeb, .thumb, .thumbeb => "arm",
- .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
- .mips, .mipsel, .mips64, .mips64el => "mips",
- .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc",
- .riscv32, .riscv64 => "riscv",
- .sparc, .sparcel, .sparc64 => "sparc",
- .x86, .x86_64 => "x86",
- else => @tagName(target.cpu.arch),
- },
- else => @tagName(target.cpu.arch),
- };
+ return target.os.tag.archName(target.cpu.arch);
}
const Target = @This();
src/Builtin.zig
@@ -140,13 +140,11 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
}),
.windows => |windows| try buffer.writer().print(
\\ .windows = .{{
- \\ .min = {s},
- \\ .max = {s},
+ \\ .min = {c},
+ \\ .max = {c},
\\ }}}},
\\
- ,
- .{ windows.min, windows.max },
- ),
+ , .{ windows.min, windows.max }),
}
try buffer.appendSlice(
\\};