|
const CrossTarget = @This(); const std = @import("../std.zig"); const builtin = @import("builtin"); const assert = std.debug.assert; const Target = std.Target; const mem = std.mem; cpu_arch: ?Target.Cpu.Arch = null, cpu_model: CpuModel = CpuModel.determined_by_cpu_arch, cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty, cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty, os_tag: ?Target.Os.Tag = null, os_version_min: ?OsVersion = null, os_version_max: ?OsVersion = null, glibc_version: ?SemanticVersion = null, abi: ?Target.Abi = null, dynamic_linker: DynamicLinker = DynamicLinker{}, ofmt: ?Target.ObjectFormat = null, |
CpuModel |
pub const CpuModel = union(enum) { native, baseline, determined_by_cpu_arch, explicit: *const Target.Cpu.Model, }; |
OsVersionAlways native Always baseline If CPU Architecture is native, then the CPU model will be native. Otherwise, it will be baseline. |
pub const OsVersion = union(enum) { none: void, semver: SemanticVersion, windows: Target.Os.WindowsVersion, }; |
SemanticVersion |
pub const SemanticVersion = std.SemanticVersion; |
DynamicLinker |
pub const DynamicLinker = Target.DynamicLinker; |
fromTarget() |
pub fn fromTarget(target: Target) CrossTarget { var result: CrossTarget = .{ .cpu_arch = target.cpu.arch, .cpu_model = .{ .explicit = target.cpu.model }, .os_tag = target.os.tag, .os_version_min = undefined, .os_version_max = undefined, .abi = target.abi, .glibc_version = if (target.isGnuLibC()) target.os.version_range.linux.glibc else null, }; result.updateOsVersionRange(target.os); const all_features = target.cpu.arch.allFeaturesList(); var cpu_model_set = target.cpu.model.features; cpu_model_set.populateDependencies(all_features); { // The "add" set is the full set with the CPU Model set removed. const add_set = &result.cpu_features_add; add_set.* = target.cpu.features; add_set.removeFeatureSet(cpu_model_set); } { // The "sub" set is the features that are on in CPU Model set and off in the full set. const sub_set = &result.cpu_features_sub; sub_set.* = cpu_model_set; sub_set.removeFeatureSet(target.cpu.features); } return result; } fn updateOsVersionRange(self: *CrossTarget, 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 = {} }; }, .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 }; }, .windows => { self.os_version_min = .{ .windows = os.version_range.windows.min }; self.os_version_max = .{ .windows = os.version_range.windows.max }; }, } } |
toTarget() TODO deprecated, use |
pub fn toTarget(self: CrossTarget) Target { return .{ .cpu = self.getCpu(), .os = self.getOs(), .abi = self.getAbi(), .ofmt = self.getObjectFormat(), }; } |
ParseOptions |
pub const ParseOptions = struct { arch_os_abi: []const u8 = "native", cpu_features: ?[]const u8 = null, dynamic_linker: ?[]const u8 = null, object_format: ?[]const u8 = null, diagnostics: ?*Diagnostics = null, pub const Diagnostics = struct { arch: ?Target.Cpu.Arch = null, os_name: ?[]const u8 = null, os_tag: ?Target.Os.Tag = null, abi: ?Target.Abi = null, cpu_name: ?[]const u8 = null, unknown_feature_name: ?[]const u8 = null, }; }; |
parse() This is sometimes called a "triple". It looks roughly like this: riscv64-linux-musl The fields are, respectively: * CPU Architecture * Operating System (and optional version range) * C ABI (optional, with optional glibc version) The string "native" can be used for CPU architecture as well as Operating System. If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted. Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features to remove from the set. The following special strings are recognized for CPU Model name: * "baseline" - The "default" set of CPU features for cross-compiling. A conservative set of features that is expected to be supported on most available hardware. * "native" - The native CPU model is to be detected when compiling. If this field is not provided ( |
pub fn parse(args: ParseOptions) !CrossTarget { var dummy_diags: ParseOptions.Diagnostics = undefined; const diags = args.diagnostics orelse &dummy_diags; var result: CrossTarget = .{ .dynamic_linker = DynamicLinker.init(args.dynamic_linker), }; var it = mem.splitScalar(u8, args.arch_os_abi, '-'); const arch_name = it.first(); const arch_is_native = mem.eql(u8, arch_name, "native"); if (!arch_is_native) { result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse return error.UnknownArchitecture; } const arch = result.getCpuArch(); diags.arch = arch; if (it.next()) |os_text| { try parseOs(&result, diags, os_text); } else if (!arch_is_native) { return error.MissingOperatingSystem; } const opt_abi_text = it.next(); if (opt_abi_text) |abi_text| { var abi_it = mem.splitScalar(u8, abi_text, '.'); const abi = std.meta.stringToEnum(Target.Abi, abi_it.first()) orelse return error.UnknownApplicationBinaryInterface; result.abi = abi; diags.abi = abi; const abi_ver_text = abi_it.rest(); if (abi_it.next() != null) { if (result.isGnuLibC()) { result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) { error.Overflow => return error.InvalidAbiVersion, error.InvalidVersion => return error.InvalidAbiVersion, }; } else { return error.InvalidAbiVersion; } } } if (it.next() != null) return error.UnexpectedExtraField; if (args.cpu_features) |cpu_features| { const all_features = arch.allFeaturesList(); var index: usize = 0; while (index < cpu_features.len and cpu_features[index] != '+' and cpu_features[index] != '-') { index += 1; } const cpu_name = cpu_features[0..index]; diags.cpu_name = cpu_name; const add_set = &result.cpu_features_add; const sub_set = &result.cpu_features_sub; if (mem.eql(u8, cpu_name, "native")) { result.cpu_model = .native; } else if (mem.eql(u8, cpu_name, "baseline")) { result.cpu_model = .baseline; } else { result.cpu_model = .{ .explicit = try arch.parseCpuModel(cpu_name) }; } while (index < cpu_features.len) { const op = cpu_features[index]; const set = switch (op) { '+' => add_set, '-' => sub_set, else => unreachable, }; index += 1; const start = index; while (index < cpu_features.len and cpu_features[index] != '+' and cpu_features[index] != '-') { index += 1; } const feature_name = cpu_features[start..index]; for (all_features, 0..) |feature, feat_index_usize| { const feat_index = @as(Target.Cpu.Feature.Set.Index, @intCast(feat_index_usize)); if (mem.eql(u8, feature_name, feature.name)) { set.addFeature(feat_index); break; } } else { diags.unknown_feature_name = feature_name; return error.UnknownCpuFeature; } } } if (args.object_format) |ofmt_name| { result.ofmt = std.meta.stringToEnum(Target.ObjectFormat, ofmt_name) orelse return error.UnknownObjectFormat; } return result; } |
parseCpuArch() Similar to |
pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch { var it = mem.splitScalar(u8, args.arch_os_abi, '-'); const arch_name = it.first(); const arch_is_native = mem.eql(u8, arch_name, "native"); if (arch_is_native) { return builtin.cpu.arch; } else { return std.meta.stringToEnum(Target.Cpu.Arch, arch_name); } } |
parseVersion() Similar to |
pub fn parseVersion(ver: []const u8) error{ InvalidVersion, Overflow }!SemanticVersion { const parseVersionComponentFn = (struct { fn parseVersionComponentInner(component: []const u8) error{ InvalidVersion, Overflow }!usize { return std.fmt.parseUnsigned(usize, component, 10) catch |err| switch (err) { error.InvalidCharacter => return error.InvalidVersion, error.Overflow => return error.Overflow, }; } }).parseVersionComponentInner; var version_components = mem.splitScalar(u8, ver, '.'); const major = version_components.first(); const minor = version_components.next() orelse return error.InvalidVersion; const patch = version_components.next() orelse "0"; if (version_components.next() != null) return error.InvalidVersion; return .{ .major = try parseVersionComponentFn(major), .minor = try parseVersionComponentFn(minor), .patch = try parseVersionComponentFn(patch), }; } |
Test: parseVersion |
test parseVersion { try std.testing.expectError(error.InvalidVersion, parseVersion("1")); try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 0 }, try parseVersion("1.2")); try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 3 }, try parseVersion("1.2.3")); try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4")); } |
getCpu() TODO deprecated, use |
pub fn getCpu(self: CrossTarget) Target.Cpu { switch (self.cpu_model) { .native => { // This works when doing `zig build` because Zig generates a build executable using // native CPU model & features. However this will not be accurate otherwise, and // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. return builtin.cpu; }, .baseline => { var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch()); self.updateCpuFeatures(&adjusted_baseline.features); return adjusted_baseline; }, .determined_by_cpu_arch => if (self.cpu_arch == null) { // This works when doing `zig build` because Zig generates a build executable using // native CPU model & features. However this will not be accurate otherwise, and // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. return builtin.cpu; } else { var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch()); self.updateCpuFeatures(&adjusted_baseline.features); return adjusted_baseline; }, .explicit => |model| { var adjusted_model = model.toCpu(self.getCpuArch()); self.updateCpuFeatures(&adjusted_model.features); return adjusted_model; }, } } |
getCpuArch() |
pub fn getCpuArch(self: CrossTarget) Target.Cpu.Arch { return self.cpu_arch orelse builtin.cpu.arch; } |
getCpuModel() |
pub fn getCpuModel(self: CrossTarget) *const Target.Cpu.Model { return switch (self.cpu_model) { .explicit => |cpu_model| cpu_model, else => self.getCpu().model, }; } |
getCpuFeatures() |
pub fn getCpuFeatures(self: CrossTarget) Target.Cpu.Feature.Set { return self.getCpu().features; } |
getOs() TODO deprecated, use |
pub fn getOs(self: CrossTarget) Target.Os { // `builtin.os` works when doing `zig build` because Zig generates a build executable using // native OS version range. However this will not be accurate otherwise, and // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. var adjusted_os = if (self.os_tag) |os_tag| os_tag.defaultVersionRange(self.getCpuArch()) else builtin.os; if (self.os_version_min) |min| switch (min) { .none => {}, .semver => |semver| switch (self.getOsTag()) { .linux => adjusted_os.version_range.linux.range.min = semver, else => adjusted_os.version_range.semver.min = semver, }, .windows => |win_ver| adjusted_os.version_range.windows.min = win_ver, }; if (self.os_version_max) |max| switch (max) { .none => {}, .semver => |semver| switch (self.getOsTag()) { .linux => adjusted_os.version_range.linux.range.max = semver, else => adjusted_os.version_range.semver.max = semver, }, .windows => |win_ver| adjusted_os.version_range.windows.max = win_ver, }; if (self.glibc_version) |glibc| { assert(self.isGnuLibC()); adjusted_os.version_range.linux.glibc = glibc; } return adjusted_os; } |
getOsTag() |
pub fn getOsTag(self: CrossTarget) Target.Os.Tag { return self.os_tag orelse builtin.os.tag; } |
getOsVersionMin() TODO deprecated, use |
pub fn getOsVersionMin(self: CrossTarget) OsVersion { if (self.os_version_min) |version_min| return version_min; var tmp: CrossTarget = undefined; tmp.updateOsVersionRange(self.getOs()); return tmp.os_version_min.?; } |
getOsVersionMax() TODO deprecated, use |
pub fn getOsVersionMax(self: CrossTarget) OsVersion { if (self.os_version_max) |version_max| return version_max; var tmp: CrossTarget = undefined; tmp.updateOsVersionRange(self.getOs()); return tmp.os_version_max.?; } |
getAbi() TODO deprecated, use |
pub fn getAbi(self: CrossTarget) Target.Abi { if (self.abi) |abi| return abi; if (self.os_tag == null) { // This works when doing `zig build` because Zig generates a build executable using // native CPU model & features. However this will not be accurate otherwise, and // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. return builtin.abi; } return Target.Abi.default(self.getCpuArch(), self.getOs()); } |
isFreeBSD() |
pub fn isFreeBSD(self: CrossTarget) bool { return self.getOsTag() == .freebsd; } |
isDarwin() |
pub fn isDarwin(self: CrossTarget) bool { return self.getOsTag().isDarwin(); } |
isNetBSD() |
pub fn isNetBSD(self: CrossTarget) bool { return self.getOsTag() == .netbsd; } |
isOpenBSD() |
pub fn isOpenBSD(self: CrossTarget) bool { return self.getOsTag() == .openbsd; } |
isUefi() |
pub fn isUefi(self: CrossTarget) bool { return self.getOsTag() == .uefi; } |
isDragonFlyBSD() |
pub fn isDragonFlyBSD(self: CrossTarget) bool { return self.getOsTag() == .dragonfly; } |
isLinux() |
pub fn isLinux(self: CrossTarget) bool { return self.getOsTag() == .linux; } |
isWindows() |
pub fn isWindows(self: CrossTarget) bool { return self.getOsTag() == .windows; } |
exeFileExt() |
pub fn exeFileExt(self: CrossTarget) [:0]const u8 { return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag()); } |
staticLibSuffix() |
pub fn staticLibSuffix(self: CrossTarget) [:0]const u8 { return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi()); } |
dynamicLibSuffix() |
pub fn dynamicLibSuffix(self: CrossTarget) [:0]const u8 { return self.getOsTag().dynamicLibSuffix(); } |
libPrefix() |
pub fn libPrefix(self: CrossTarget) [:0]const u8 { return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi()); } |
isNativeCpu() |
pub fn isNativeCpu(self: CrossTarget) bool { return self.cpu_arch == null and (self.cpu_model == .native or self.cpu_model == .determined_by_cpu_arch) and self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty(); } |
isNativeOs() |
pub fn isNativeOs(self: CrossTarget) bool { return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and self.dynamic_linker.get() == null and self.glibc_version == null; } |
isNativeAbi() |
pub fn isNativeAbi(self: CrossTarget) bool { return self.os_tag == null and self.abi == null; } |
isNative() |
pub fn isNative(self: CrossTarget) bool { return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi(); } fn formatVersion(version: SemanticVersion, writer: anytype) !void { if (version.patch == 0) { try writer.print("{d}.{d}", .{ version.major, version.minor }); } else { try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch }); } } |
zigTriple()Formats a version with the patch component omitted if it is zero, unlike SemanticVersion.format which formats all its version components regardless. |
pub fn zigTriple(self: CrossTarget, allocator: mem.Allocator) error{OutOfMemory}![]u8 { if (self.isNative()) { return allocator.dupe(u8, "native"); } const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native"; const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native"; var result = std.ArrayList(u8).init(allocator); defer result.deinit(); try result.writer().print("{s}-{s}", .{ arch_name, os_name }); // The zig target syntax does not allow specifying a max os version with no min, so // if either are present, we need the min. if (self.os_version_min != null or self.os_version_max != null) { switch (self.getOsVersionMin()) { .none => {}, .semver => |v| { try result.writer().writeAll("."); try formatVersion(v, result.writer()); }, .windows => |v| try result.writer().print("{s}", .{v}), } } if (self.os_version_max) |max| { switch (max) { .none => {}, .semver => |v| { try result.writer().writeAll("..."); try formatVersion(v, result.writer()); }, .windows => |v| try result.writer().print("..{s}", .{v}), } } if (self.glibc_version) |v| { try result.writer().print("-{s}.", .{@tagName(self.getAbi())}); try formatVersion(v, result.writer()); } else if (self.abi) |abi| { try result.writer().print("-{s}", .{@tagName(abi)}); } return result.toOwnedSlice(); } |
allocDescription() |
pub fn allocDescription(self: CrossTarget, allocator: mem.Allocator) ![]u8 { // TODO is there anything else worthy of the description that is not // already captured in the triple? return self.zigTriple(allocator); } |
linuxTriple() |
pub fn linuxTriple(self: CrossTarget, allocator: mem.Allocator) ![]u8 { return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); } |
wantSharedLibSymLinks() |
pub fn wantSharedLibSymLinks(self: CrossTarget) bool { return self.getOsTag() != .windows; } |
VcpkgLinkage |
pub const VcpkgLinkage = std.builtin.LinkMode; |
vcpkgTriplet()Returned slice must be freed by the caller. |
pub fn vcpkgTriplet(self: CrossTarget, allocator: mem.Allocator, linkage: VcpkgLinkage) ![]u8 { const arch = switch (self.getCpuArch()) { .x86 => "x86", .x86_64 => "x64", .arm, .armeb, .thumb, .thumbeb, .aarch64_32, => "arm", .aarch64, .aarch64_be, => "arm64", else => return error.UnsupportedVcpkgArchitecture, }; const os = switch (self.getOsTag()) { .windows => "windows", .linux => "linux", .macos => "macos", else => return error.UnsupportedVcpkgOperatingSystem, }; const static_suffix = switch (linkage) { .Static => "-static", .Dynamic => "", }; return std.fmt.allocPrint(allocator, "{s}-{s}{s}", .{ arch, os, static_suffix }); } |
isGnuLibC() |
pub fn isGnuLibC(self: CrossTarget) bool { return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi()); } |
setGnuLibCVersion() |
pub fn setGnuLibCVersion(self: *CrossTarget, major: u32, minor: u32, patch: u32) void { assert(self.isGnuLibC()); self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; } |
getObjectFormat() |
pub fn getObjectFormat(self: CrossTarget) Target.ObjectFormat { return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch()); } |
updateCpuFeatures() |
pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void { set.removeFeatureSet(self.cpu_features_sub); set.addFeatureSet(self.cpu_features_add); set.populateDependencies(self.getCpuArch().allFeaturesList()); set.removeFeatureSet(self.cpu_features_sub); } fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const u8) !void { var it = mem.splitScalar(u8, text, '.'); const os_name = it.first(); diags.os_name = os_name; const os_is_native = mem.eql(u8, os_name, "native"); if (!os_is_native) { result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse return error.UnknownOperatingSystem; } const tag = result.getOsTag(); 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, => { 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 = 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 = max_ver }; }, .windows => { 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 }; }, } } |
Test:CrossTarget.parse |
test "CrossTarget.parse" { if (builtin.target.isGnuLibC()) { var cross_target = try CrossTarget.parse(.{}); cross_target.setGnuLibCVersion(2, 1, 1); const text = try cross_target.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); var buf: [256]u8 = undefined; const triple = std.fmt.bufPrint( buf[0..], "native-native-{s}.2.1.1", .{@tagName(builtin.abi)}, ) catch unreachable; try std.testing.expectEqualSlices(u8, triple, text); } { const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "aarch64-linux", .cpu_features = "native", }); try std.testing.expect(cross_target.cpu_arch.? == .aarch64); try std.testing.expect(cross_target.cpu_model == .native); } { const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "native" }); try std.testing.expect(cross_target.cpu_arch == null); try std.testing.expect(cross_target.isNative()); const text = try cross_target.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "native", text); } { const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu", .cpu_features = "x86_64-sse-sse2-avx-cx8", }); const target = cross_target.toTarget(); try std.testing.expect(target.os.tag == .linux); try std.testing.expect(target.abi == .gnu); try std.testing.expect(target.cpu.arch == .x86_64); try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse)); try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx)); try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8)); try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov)); try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); try std.testing.expect(Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx, .cmov })); try std.testing.expect(!Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx })); try std.testing.expect(Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87 })); try std.testing.expect(!Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87, .sse })); const text = try cross_target.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text); } { const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "arm-linux-musleabihf", .cpu_features = "generic+v8a", }); const target = cross_target.toTarget(); try std.testing.expect(target.os.tag == .linux); try std.testing.expect(target.abi == .musleabihf); try std.testing.expect(target.cpu.arch == .arm); try std.testing.expect(target.cpu.model == &Target.arm.cpu.generic); try std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a)); const text = try cross_target.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text); } { const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", .cpu_features = "generic+v8a", }); const target = cross_target.toTarget(); try std.testing.expect(target.cpu.arch == .aarch64); try std.testing.expect(target.os.tag == .linux); try std.testing.expect(target.os.version_range.linux.range.min.major == 3); try std.testing.expect(target.os.version_range.linux.range.min.minor == 10); try std.testing.expect(target.os.version_range.linux.range.min.patch == 0); try std.testing.expect(target.os.version_range.linux.range.max.major == 4); try std.testing.expect(target.os.version_range.linux.range.max.minor == 4); try std.testing.expect(target.os.version_range.linux.range.max.patch == 1); try std.testing.expect(target.os.version_range.linux.glibc.major == 2); try std.testing.expect(target.os.version_range.linux.glibc.minor == 27); try std.testing.expect(target.os.version_range.linux.glibc.patch == 0); try std.testing.expect(target.abi == .gnu); const text = try cross_target.zigTriple(std.testing.allocator); defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text); } } |
Generated by zstd-browse2 on 2023-11-04 14:12:17 -0400. |