Commit dbe4d72bcf
Changed files (14)
doc
src-self-hosted
doc/docgen.zig
@@ -10,8 +10,8 @@ const testing = std.testing;
const max_doc_file_size = 10 * 1024 * 1024;
-const exe_ext = @as(std.build.Target, std.build.Target.Native).exeFileExt();
-const obj_ext = @as(std.build.Target, std.build.Target.Native).oFileExt();
+const exe_ext = @as(std.zig.CrossTarget, .{}).exeFileExt();
+const obj_ext = @as(std.zig.CrossTarget, .{}).oFileExt();
const tmp_dir_name = "docgen_tmp";
const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext;
lib/std/build/translate_c.zig
@@ -7,6 +7,7 @@ const LibExeObjStep = build.LibExeObjStep;
const CheckFileStep = build.CheckFileStep;
const fs = std.fs;
const mem = std.mem;
+const CrossTarget = std.zig.CrossTarget;
pub const TranslateCStep = struct {
step: Step,
@@ -14,7 +15,7 @@ pub const TranslateCStep = struct {
source: build.FileSource,
output_dir: ?[]const u8,
out_basename: []const u8,
- target: build.Target = .Native,
+ target: CrossTarget = CrossTarget{},
pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep {
const self = builder.allocator.create(TranslateCStep) catch unreachable;
@@ -39,7 +40,7 @@ pub const TranslateCStep = struct {
) catch unreachable;
}
- pub fn setTarget(self: *TranslateCStep, target: build.Target) void {
+ pub fn setTarget(self: *TranslateCStep, target: CrossTarget) void {
self.target = target;
}
@@ -63,12 +64,9 @@ pub const TranslateCStep = struct {
try argv_list.append("--cache");
try argv_list.append("on");
- switch (self.target) {
- .Native => {},
- .Cross => {
- try argv_list.append("-target");
- try argv_list.append(try self.target.zigTriple(self.builder.allocator));
- },
+ if (!self.target.isNative()) {
+ try argv_list.append("-target");
+ try argv_list.append(try self.target.zigTriple(self.builder.allocator));
}
try argv_list.append(self.source.getPath(self.builder));
lib/std/zig/cross_target.zig
@@ -0,0 +1,766 @@
+const std = @import("../std.zig");
+const assert = std.debug.assert;
+const Target = std.Target;
+const mem = std.mem;
+
+/// Contains all the same data as `Target`, additionally introducing the concept of "the native target".
+/// The purpose of this abstraction is to provide meaningful and unsurprising defaults.
+pub const CrossTarget = struct {
+ /// `null` means native.
+ cpu_arch: ?Target.Cpu.Arch = null,
+
+ /// If `cpu_arch` is native, `null` means native. Otherwise it means baseline.
+ /// If this is non-null, `cpu_arch` must be specified.
+ cpu_model: ?*const Target.Cpu.Model = null,
+
+ /// Sparse set of CPU features to add to the set from `cpu_model`.
+ /// If this is non-empty, `cpu_arch` must be specified.
+ cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
+
+ /// Sparse set of CPU features to remove from the set from `cpu_model`.
+ /// If this is non-empty, `cpu_arch` must be specified.
+ cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
+
+ /// `null` means native.
+ os_tag: ?Target.Os.Tag = null,
+
+ /// `null` means the default version range for `os_tag`. If `os_tag` is `null` (native)
+ /// then `null` for this field means native.
+ os_version_min: ?OsVersion = null,
+
+ /// When cross compiling, `null` means default (latest known OS version).
+ /// When `os_tag` is native, `null` means equal to the native OS version.
+ os_version_max: ?OsVersion = null,
+
+ /// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
+ abi: ?Target.Abi = null,
+
+ /// `null` means default when cross compiling, or native when os_tag is native.
+ /// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
+ glibc_version: ?SemVer = null,
+
+ pub const OsVersion = union(enum) {
+ none: void,
+ semver: SemVer,
+ windows: Target.Os.WindowsVersion,
+ };
+
+ pub const SemVer = std.builtin.Version;
+
+ pub fn fromTarget(target: Target) CrossTarget {
+ var result: CrossTarget = .{
+ .cpu_arch = target.cpu.arch,
+ .cpu_model = 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,
+ .dragonfly,
+ .fuchsia,
+ .ios,
+ .kfreebsd,
+ .lv2,
+ .solaris,
+ .haiku,
+ .minix,
+ .rtems,
+ .nacl,
+ .cnk,
+ .aix,
+ .cuda,
+ .nvcl,
+ .amdhsa,
+ .ps4,
+ .elfiamcu,
+ .tvos,
+ .watchos,
+ .mesa3d,
+ .contiki,
+ .amdpal,
+ .hermit,
+ .hurd,
+ .wasi,
+ .emscripten,
+ .uefi,
+ .other,
+ => {
+ self.os_version_min = .{ .none = {} };
+ self.os_version_max = .{ .none = {} };
+ },
+
+ .freebsd,
+ .macosx,
+ .netbsd,
+ .openbsd,
+ => {
+ 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 };
+ },
+ }
+ }
+
+ pub fn toTarget(self: CrossTarget) Target {
+ return .{
+ .cpu = self.getCpu(),
+ .os = self.getOs(),
+ .abi = self.getAbi(),
+ };
+ }
+
+ pub const ParseOptions = struct {
+ /// 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.
+ arch_os_abi: []const u8 = "native",
+
+ /// 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 (`null`), then the value will depend on the
+ /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline".
+ cpu_features: ?[]const u8 = null,
+
+ /// If this is provided, the function will populate some information about parsing failures,
+ /// so that user-friendly error messages can be delivered.
+ diagnostics: ?*Diagnostics = null,
+
+ pub const Diagnostics = struct {
+ /// If the architecture was determined, this will be populated.
+ arch: ?Target.Cpu.Arch = null,
+
+ /// If the OS tag was determined, this will be populated.
+ os_tag: ?Target.Os.Tag = null,
+
+ /// If the ABI was determined, this will be populated.
+ abi: ?Target.Abi = null,
+
+ /// If the CPU name was determined, this will be populated.
+ cpu_name: ?[]const u8 = null,
+
+ /// If error.UnknownCpuFeature is returned, this will be populated.
+ unknown_feature_name: ?[]const u8 = null,
+ };
+ };
+
+ pub fn parse(args: ParseOptions) !CrossTarget {
+ var dummy_diags: ParseOptions.Diagnostics = undefined;
+ const diags = args.diagnostics orelse &dummy_diags;
+
+ // Start with everything initialized to default values.
+ var result: CrossTarget = .{};
+
+ var it = mem.separate(args.arch_os_abi, "-");
+ const arch_name = it.next().?;
+ 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.separate(abi_text, ".");
+ const abi = std.meta.stringToEnum(Target.Abi, abi_it.next().?) orelse
+ return error.UnknownApplicationBinaryInterface;
+ diags.abi = abi;
+
+ const abi_ver_text = abi_it.rest();
+ if (abi_it.next() != null) {
+ if (result.isGnuLibC()) {
+ result.glibc_version = SemVer.parse(abi_ver_text) catch |err| switch (err) {
+ error.Overflow => return error.InvalidAbiVersion,
+ error.InvalidCharacter => 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 = null;
+ } else if (mem.eql(u8, cpu_name, "baseline")) {
+ result.cpu_model = Target.Cpu.Model.baseline(arch);
+ } else {
+ result.cpu_model = 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) |feature, feat_index_usize| {
+ const feat_index = @intCast(Target.Cpu.Feature.Set.Index, 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;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ pub fn getCpu(self: CrossTarget) Target.Cpu {
+ if (self.cpu_arch) |arch| {
+ if (self.cpu_model) |model| {
+ var adjusted_model = model.toCpu(arch);
+ self.updateCpuFeatures(&adjusted_model.features);
+ return adjusted_model;
+ } else {
+ var adjusted_baseline = Target.Cpu.baseline(arch);
+ self.updateCpuFeatures(&adjusted_baseline.features);
+ return adjusted_baseline;
+ }
+ } else {
+ assert(self.cpu_model == null);
+ assert(self.cpu_features_sub.isEmpty());
+ assert(self.cpu_features_add.isEmpty());
+ // 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 Target.current.cpu;
+ }
+ }
+
+ pub fn getCpuArch(self: CrossTarget) Target.Cpu.Arch {
+ return self.cpu_arch orelse Target.current.cpu.arch;
+ }
+
+ pub fn getCpuModel(self: CrossTarget) *const Target.Cpu.Model {
+ if (self.cpu_model) |cpu_model| return cpu_model;
+ return self.getCpu().model;
+ }
+
+ pub fn getCpuFeatures(self: CrossTarget) Target.Cpu.Feature.Set {
+ return self.getCpu().features;
+ }
+
+ pub fn getOs(self: CrossTarget) Target.Os {
+ // `Target.current.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| Target.Os.defaultVersionRange(os_tag) else Target.current.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;
+ }
+
+ pub fn getOsTag(self: CrossTarget) Target.Os.Tag {
+ return self.os_tag orelse Target.current.os.tag;
+ }
+
+ 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.?;
+ }
+
+ 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.?;
+ }
+
+ pub fn getAbi(self: CrossTarget) Target.Abi {
+ if (self.abi) |abi| return abi;
+
+ if (self.isNativeOs()) {
+ // 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 Target.current.abi;
+ }
+
+ return Target.Abi.default(self.getCpuArch(), self.getOs());
+ }
+
+ pub fn isFreeBSD(self: CrossTarget) bool {
+ return self.getOsTag() == .freebsd;
+ }
+
+ pub fn isDarwin(self: CrossTarget) bool {
+ return self.getOsTag().isDarwin();
+ }
+
+ pub fn isNetBSD(self: CrossTarget) bool {
+ return self.getOsTag() == .netbsd;
+ }
+
+ pub fn isUefi(self: CrossTarget) bool {
+ return self.getOsTag() == .uefi;
+ }
+
+ pub fn isDragonFlyBSD(self: CrossTarget) bool {
+ return self.getOsTag() == .dragonfly;
+ }
+
+ pub fn isLinux(self: CrossTarget) bool {
+ return self.getOsTag() == .linux;
+ }
+
+ pub fn isWindows(self: CrossTarget) bool {
+ return self.getOsTag() == .windows;
+ }
+
+ pub fn oFileExt(self: CrossTarget) [:0]const u8 {
+ return self.getAbi().oFileExt();
+ }
+
+ pub fn exeFileExt(self: CrossTarget) [:0]const u8 {
+ return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag());
+ }
+
+ pub fn staticLibSuffix(self: CrossTarget) [:0]const u8 {
+ return Target.staticLibSuffix_cpu_arch_abi(self.getCpuArch(), self.getAbi());
+ }
+
+ pub fn dynamicLibSuffix(self: CrossTarget) [:0]const u8 {
+ return self.getOsTag().dynamicLibSuffix();
+ }
+
+ pub fn libPrefix(self: CrossTarget) [:0]const u8 {
+ return Target.libPrefix_cpu_arch_abi(self.getCpuArch(), self.getAbi());
+ }
+
+ pub fn isNativeCpu(self: CrossTarget) bool {
+ return self.cpu_arch == null and self.cpu_model == null and
+ self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty();
+ }
+
+ pub fn isNativeOs(self: CrossTarget) bool {
+ return self.os_tag == null and self.os_version_min == null and self.os_version_max == null;
+ }
+
+ pub fn isNativeAbi(self: CrossTarget) bool {
+ return self.abi == null and self.glibc_version == null;
+ }
+
+ pub fn isNative(self: CrossTarget) bool {
+ return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi();
+ }
+
+ pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![:0]u8 {
+ if (self.isNative()) {
+ return mem.dupeZ(allocator, u8, "native");
+ }
+
+ const arch_name = if (self.isNativeCpu()) "native" else @tagName(self.getCpuArch());
+ const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
+
+ var result = try std.Buffer.allocPrint(allocator, "{}-{}", .{ arch_name, os_name });
+ defer result.deinit();
+
+ // 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.print(".{}", .{v}),
+ .windows => |v| try result.print(".{}", .{@tagName(v)}),
+ }
+ }
+ if (self.os_version_max) |max| {
+ switch (max) {
+ .none => {},
+ .semver => |v| try result.print("...{}", .{v}),
+ .windows => |v| try result.print("...{}", .{@tagName(v)}),
+ }
+ }
+
+ if (self.abi) |abi| {
+ try result.print("-{}", .{@tagName(abi)});
+ if (self.glibc_version) |v| {
+ try result.print(".{}", .{v});
+ }
+ } else {
+ assert(self.glibc_version == null);
+ }
+
+ return result.toOwnedSlice();
+ }
+
+ pub fn allocDescription(self: CrossTarget, allocator: *mem.Allocator) ![:0]u8 {
+ // TODO is there anything else worthy of the description that is not
+ // already captured in the triple?
+ return self.zigTriple(allocator);
+ }
+
+ pub fn linuxTriple(self: CrossTarget, allocator: *mem.Allocator) ![:0]u8 {
+ return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi());
+ }
+
+ pub fn wantSharedLibSymLinks(self: CrossTarget) bool {
+ return self.getOsTag() != .windows;
+ }
+
+ pub const VcpkgLinkage = std.builtin.LinkMode;
+
+ /// Returned slice must be freed by the caller.
+ pub fn vcpkgTriplet(self: CrossTarget, allocator: *mem.Allocator, linkage: VcpkgLinkage) ![:0]u8 {
+ const arch = switch (self.getCpuArch()) {
+ .i386 => "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",
+ .macosx => "macos",
+ else => return error.UnsupportedVcpkgOperatingSystem,
+ };
+
+ const static_suffix = switch (linkage) {
+ .Static => "-static",
+ .Dynamic => "",
+ };
+
+ return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
+ }
+
+ pub const Executor = union(enum) {
+ native,
+ qemu: []const u8,
+ wine: []const u8,
+ wasmtime: []const u8,
+ unavailable,
+ };
+
+ pub fn getExternalExecutor(self: CrossTarget) Executor {
+ const os_tag = self.getOsTag();
+ const cpu_arch = self.getCpuArch();
+
+ // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture.
+ if (os_tag == Target.current.os.tag) {
+ return switch (cpu_arch) {
+ .aarch64 => Executor{ .qemu = "qemu-aarch64" },
+ .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" },
+ .arm => Executor{ .qemu = "qemu-arm" },
+ .armeb => Executor{ .qemu = "qemu-armeb" },
+ .i386 => Executor{ .qemu = "qemu-i386" },
+ .mips => Executor{ .qemu = "qemu-mips" },
+ .mipsel => Executor{ .qemu = "qemu-mipsel" },
+ .mips64 => Executor{ .qemu = "qemu-mips64" },
+ .mips64el => Executor{ .qemu = "qemu-mips64el" },
+ .powerpc => Executor{ .qemu = "qemu-ppc" },
+ .powerpc64 => Executor{ .qemu = "qemu-ppc64" },
+ .powerpc64le => Executor{ .qemu = "qemu-ppc64le" },
+ .riscv32 => Executor{ .qemu = "qemu-riscv32" },
+ .riscv64 => Executor{ .qemu = "qemu-riscv64" },
+ .s390x => Executor{ .qemu = "qemu-s390x" },
+ .sparc => Executor{ .qemu = "qemu-sparc" },
+ .x86_64 => Executor{ .qemu = "qemu-x86_64" },
+ else => return .unavailable,
+ };
+ }
+
+ switch (os_tag) {
+ .windows => switch (cpu_arch.ptrBitWidth()) {
+ 32 => return Executor{ .wine = "wine" },
+ 64 => return Executor{ .wine = "wine64" },
+ else => return .unavailable,
+ },
+ .wasi => switch (cpu_arch.ptrBitWidth()) {
+ 32 => return Executor{ .wasmtime = "wasmtime" },
+ else => return .unavailable,
+ },
+ else => return .unavailable,
+ }
+ }
+
+ pub fn isGnuLibC(self: CrossTarget) bool {
+ return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi());
+ }
+
+ pub fn setGnuLibCVersion(self: CrossTarget, major: u32, minor: u32, patch: u32) void {
+ assert(self.isGnuLibC());
+ self.glibc_version = SemVer{ .major = major, .minor = minor, .patch = patch };
+ }
+
+ 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.separate(text, ".");
+ const os_name = it.next().?;
+ 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,
+ .dragonfly,
+ .fuchsia,
+ .ios,
+ .kfreebsd,
+ .lv2,
+ .solaris,
+ .haiku,
+ .minix,
+ .rtems,
+ .nacl,
+ .cnk,
+ .aix,
+ .cuda,
+ .nvcl,
+ .amdhsa,
+ .ps4,
+ .elfiamcu,
+ .tvos,
+ .watchos,
+ .mesa3d,
+ .contiki,
+ .amdpal,
+ .hermit,
+ .hurd,
+ .wasi,
+ .emscripten,
+ .uefi,
+ .other,
+ => return error.InvalidOperatingSystemVersion,
+
+ .freebsd,
+ .macosx,
+ .netbsd,
+ .openbsd,
+ .linux,
+ => {
+ var range_it = mem.separate(version_text, "...");
+
+ const min_text = range_it.next().?;
+ const min_ver = SemVer.parse(min_text) catch |err| switch (err) {
+ error.Overflow => return error.InvalidOperatingSystemVersion,
+ error.InvalidCharacter => 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 = SemVer.parse(max_text) catch |err| switch (err) {
+ error.Overflow => return error.InvalidOperatingSystemVersion,
+ error.InvalidCharacter => return error.InvalidOperatingSystemVersion,
+ error.InvalidVersion => return error.InvalidOperatingSystemVersion,
+ };
+ result.os_version_max = .{ .semver = max_ver };
+ },
+
+ .windows => {
+ var range_it = mem.separate(version_text, "...");
+
+ const min_text = range_it.next().?;
+ 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" {
+ {
+ 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();
+
+ std.testing.expect(target.os.tag == .linux);
+ std.testing.expect(target.abi == .gnu);
+ std.testing.expect(target.cpu.arch == .x86_64);
+ std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse));
+ std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx));
+ std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8));
+ std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov));
+ std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr));
+
+ const text = try cross_target.zigTriple(std.testing.allocator);
+ defer std.testing.allocator.free(text);
+ 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();
+
+ std.testing.expect(target.os.tag == .linux);
+ std.testing.expect(target.abi == .musleabihf);
+ std.testing.expect(target.cpu.arch == .arm);
+ std.testing.expect(target.cpu.model == &Target.arm.cpu.generic);
+ 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);
+ 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();
+
+ std.testing.expect(target.cpu.arch == .aarch64);
+ std.testing.expect(target.os.tag == .linux);
+ std.testing.expect(target.os.version_range.linux.range.min.major == 3);
+ std.testing.expect(target.os.version_range.linux.range.min.minor == 10);
+ std.testing.expect(target.os.version_range.linux.range.min.patch == 0);
+ std.testing.expect(target.os.version_range.linux.range.max.major == 4);
+ std.testing.expect(target.os.version_range.linux.range.max.minor == 4);
+ std.testing.expect(target.os.version_range.linux.range.max.patch == 1);
+ std.testing.expect(target.os.version_range.linux.glibc.major == 2);
+ std.testing.expect(target.os.version_range.linux.glibc.minor == 27);
+ std.testing.expect(target.os.version_range.linux.glibc.patch == 0);
+ std.testing.expect(target.abi == .gnu);
+
+ const text = try cross_target.zigTriple(std.testing.allocator);
+ defer std.testing.allocator.free(text);
+ std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text);
+ }
+}
lib/std/build.zig
@@ -1,5 +1,5 @@
const std = @import("std.zig");
-const builtin = @import("builtin");
+const builtin = std.builtin;
const io = std.io;
const fs = std.fs;
const mem = std.mem;
@@ -15,6 +15,7 @@ const BufSet = std.BufSet;
const BufMap = std.BufMap;
const fmt_lib = std.fmt;
const File = std.fs.File;
+const CrossTarget = std.zig.CrossTarget;
pub const FmtStep = @import("build/fmt.zig").FmtStep;
pub const TranslateCStep = @import("build/translate_c.zig").TranslateCStep;
@@ -521,24 +522,77 @@ pub const Builder = struct {
return mode;
}
- /// Exposes standard `zig build` options for choosing a target. Pass `null` to support all targets.
- pub fn standardTargetOptions(self: *Builder, supported_targets: ?[]const Target) Target {
- if (supported_targets) |target_list| {
- // TODO detect multiple args and emit an error message
- // there's probably a better way to collect the target
- for (target_list) |targ| {
- const targ_str = targ.zigTriple(self.allocator) catch unreachable;
- const targ_desc = targ.allocDescription(self.allocator) catch unreachable;
- const this_targ_opt = self.option(bool, targ_str, targ_desc) orelse false;
- if (this_targ_opt) {
- return targ;
+ pub const StandardTargetOptionsArgs = struct {
+ whitelist: ?[]const CrossTarget = null,
+
+ default_target: CrossTarget = .{},
+ };
+
+ /// Exposes standard `zig build` options for choosing a target.
+ pub fn standardTargetOptions(self: *Builder, args: StandardTargetOptionsArgs) CrossTarget {
+ const triple = self.option(
+ []const u8,
+ "target",
+ "The Arch, OS, and ABI to build for.",
+ ) orelse return args.default_target;
+
+ // TODO add cpu and features as part of the target triple
+
+ var diags: std.Target.ParseOptions.Diagnostics = .{};
+ const selected_target = CrossTarget.parse(.{
+ .arch_os_abi = triple,
+ .diagnostics = &diags,
+ }) catch |err| switch (err) {
+ error.UnknownCpuModel => {
+ std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
+ diags.cpu_name.?,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allCpuModels()) |cpu| {
+ std.debug.warn(" {}\n", .{cpu.name});
+ }
+ process.exit(1);
+ },
+ error.UnknownCpuFeature => {
+ std.debug.warn(
+ \\Unknown CPU feature: '{}'
+ \\Available CPU features for architecture '{}':
+ \\
+ , .{
+ diags.unknown_feature_name,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allFeaturesList()) |feature| {
+ std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
+ }
+ process.exit(1);
+ },
+ else => |e| return e,
+ };
+
+ const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch unreachable;
+
+ if (args.whitelist) |list| whitelist_check: {
+ // Make sure it's a match of one of the list.
+ for (list) |t| {
+ const t_triple = t.zigTriple(self.allocator) catch unreachable;
+ if (mem.eql(u8, t_triple, selected_canonicalized_triple)) {
+ break :whitelist_check;
}
}
- return Target.Native;
- } else {
- const target_str = self.option([]const u8, "target", "the target to build for") orelse return Target.Native;
- return Target.parse(.{ .arch_os_abi = target_str }) catch unreachable; // TODO better error message for bad target
+ std.debug.warn("Chosen target '{}' does not match one of the supported targets:\n", .{
+ selected_canonicalized_triple,
+ });
+ for (list) |t| {
+ const t_triple = t.zigTriple(self.allocator) catch unreachable;
+ std.debug.warn(" {}\n", t_triple);
+ }
+ // TODO instead of process exit, return error and have a zig build flag implemented by
+ // the build runner that turns process exits into error return traces
+ process.exit(1);
}
+
+ return selected_target;
}
pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool {
@@ -796,7 +850,7 @@ pub const Builder = struct {
pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
// TODO report error for ambiguous situations
- const exe_extension = (Target{ .Native = {} }).exeFileExt();
+ const exe_extension = @as(CrossTarget, .{}).exeFileExt();
for (self.search_prefixes.toSliceConst()) |search_prefix| {
for (names) |name| {
if (fs.path.isAbsolute(name)) {
@@ -978,111 +1032,11 @@ test "builder.findProgram compiles" {
_ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;
}
-/// Deprecated. Use `builtin.Version`.
+/// Deprecated. Use `std.builtin.Version`.
pub const Version = builtin.Version;
-/// Deprecated. Use `std.Target`.
-pub const CrossTarget = std.Target;
-
-/// Wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target.
-pub const Target = union(enum) {
- Native,
- Cross: std.Target,
-
- pub fn getTarget(self: Target) std.Target {
- return switch (self) {
- .Native => std.Target.current,
- .Cross => |t| t,
- };
- }
-
- pub fn getOs(self: Target) std.Target.Os.Tag {
- return self.getTarget().os.tag;
- }
-
- pub fn getCpu(self: Target) std.Target.Cpu {
- return self.getTarget().cpu;
- }
-
- pub fn getAbi(self: Target) std.Target.Abi {
- return self.getTarget().abi;
- }
-
- pub fn getArch(self: Target) std.Target.Cpu.Arch {
- return self.getCpu().arch;
- }
-
- pub fn isFreeBSD(self: Target) bool {
- return self.getTarget().os.tag == .freebsd;
- }
-
- pub fn isDarwin(self: Target) bool {
- return self.getTarget().os.tag.isDarwin();
- }
-
- pub fn isNetBSD(self: Target) bool {
- return self.getTarget().os.tag == .netbsd;
- }
-
- pub fn isUefi(self: Target) bool {
- return self.getTarget().os.tag == .uefi;
- }
-
- pub fn isDragonFlyBSD(self: Target) bool {
- return self.getTarget().os.tag == .dragonfly;
- }
-
- pub fn isLinux(self: Target) bool {
- return self.getTarget().os.tag == .linux;
- }
-
- pub fn isWindows(self: Target) bool {
- return self.getTarget().os.tag == .windows;
- }
-
- pub fn oFileExt(self: Target) []const u8 {
- return self.getTarget().oFileExt();
- }
-
- pub fn exeFileExt(self: Target) []const u8 {
- return self.getTarget().exeFileExt();
- }
-
- pub fn staticLibSuffix(self: Target) []const u8 {
- return self.getTarget().staticLibSuffix();
- }
-
- pub fn libPrefix(self: Target) []const u8 {
- return self.getTarget().libPrefix();
- }
-
- pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
- return self.getTarget().zigTriple(allocator);
- }
-
- pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
- return self.getTarget().linuxTriple(allocator);
- }
-
- pub fn wantSharedLibSymLinks(self: Target) bool {
- return self.getTarget().wantSharedLibSymLinks();
- }
-
- pub fn vcpkgTriplet(self: Target, allocator: *mem.Allocator, linkage: std.build.VcpkgLinkage) ![]const u8 {
- return self.getTarget().vcpkgTriplet(allocator, linkage);
- }
-
- pub fn getExternalExecutor(self: Target) std.Target.Executor {
- switch (self) {
- .Native => return .native,
- .Cross => |t| return t.getExternalExecutor(),
- }
- }
-
- pub fn isGnuLibC(self: Target) bool {
- return self.getTarget().isGnuLibC();
- }
-};
+/// Deprecated. Use `std.zig.CrossTarget`.
+pub const Target = std.zig.CrossTarget;
pub const Pkg = struct {
name: []const u8,
@@ -1135,7 +1089,7 @@ pub const LibExeObjStep = struct {
step: Step,
builder: *Builder,
name: []const u8,
- target: Target,
+ target: CrossTarget = CrossTarget{},
linker_script: ?[]const u8 = null,
version_script: ?[]const u8 = null,
out_filename: []const u8,
@@ -1188,7 +1142,6 @@ pub const LibExeObjStep = struct {
install_step: ?*InstallArtifactStep,
libc_file: ?[]const u8 = null,
- target_glibc: ?Version = null,
valgrind_support: ?bool = null,
@@ -1288,7 +1241,6 @@ pub const LibExeObjStep = struct {
.kind = kind,
.root_src = root_src,
.name = name,
- .target = Target.Native,
.frameworks = BufSet.init(builder.allocator),
.step = Step.init(name, builder.allocator, make),
.version = ver,
@@ -1379,36 +1331,11 @@ pub const LibExeObjStep = struct {
}
}
- /// Deprecated. Use `setTheTarget`.
- pub fn setTarget(
- self: *LibExeObjStep,
- target_arch: builtin.Arch,
- target_os: builtin.Os,
- target_abi: builtin.Abi,
- ) void {
- return self.setTheTarget(Target{
- .Cross = CrossTarget{
- .arch = target_arch,
- .os = target_os,
- .abi = target_abi,
- .cpu_features = target_arch.getBaselineCpuFeatures(),
- },
- });
- }
-
- pub fn setTheTarget(self: *LibExeObjStep, target: Target) void {
+ pub fn setTarget(self: *LibExeObjStep, target: CrossTarget) void {
self.target = target;
self.computeOutFileNames();
}
- pub fn setTargetGLibC(self: *LibExeObjStep, major: u32, minor: u32, patch: u32) void {
- self.target_glibc = Version{
- .major = major,
- .minor = minor,
- .patch = patch,
- };
- }
-
pub fn setOutputDir(self: *LibExeObjStep, dir: []const u8) void {
self.output_dir = self.builder.dupePath(dir);
}
@@ -2002,47 +1929,41 @@ pub const LibExeObjStep = struct {
try zig_args.append(@tagName(self.code_model));
}
- switch (self.target) {
- .Native => {},
- .Cross => |cross| {
- try zig_args.append("-target");
- try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
+ if (!self.target.isNative()) {
+ try zig_args.append("-target");
+ try zig_args.append(try self.target.zigTriple(builder.allocator));
- const all_features = self.target.getArch().allFeaturesList();
- var populated_cpu_features = cross.cpu.model.features;
- populated_cpu_features.populateDependencies(all_features);
+ // TODO this logic can disappear if cpu model + features becomes part of the target triple
+ const cross = self.target.toTarget();
+ const all_features = cross.cpu.arch.allFeaturesList();
+ var populated_cpu_features = cross.cpu.model.features;
+ populated_cpu_features.populateDependencies(all_features);
- if (populated_cpu_features.eql(cross.cpu.features)) {
- // The CPU name alone is sufficient.
- // If it is the baseline CPU, no command line args are required.
- if (cross.cpu.model != std.Target.Cpu.baseline(self.target.getArch()).model) {
- try zig_args.append("-mcpu");
- try zig_args.append(cross.cpu.model.name);
- }
- } else {
- var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu=");
- try mcpu_buffer.append(cross.cpu.model.name);
-
- for (all_features) |feature, i_usize| {
- const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
- const in_cpu_set = populated_cpu_features.isEnabled(i);
- const in_actual_set = cross.cpu.features.isEnabled(i);
- if (in_cpu_set and !in_actual_set) {
- try mcpu_buffer.appendByte('-');
- try mcpu_buffer.append(feature.name);
- } else if (!in_cpu_set and in_actual_set) {
- try mcpu_buffer.appendByte('+');
- try mcpu_buffer.append(feature.name);
- }
+ if (populated_cpu_features.eql(cross.cpu.features)) {
+ // The CPU name alone is sufficient.
+ // If it is the baseline CPU, no command line args are required.
+ if (cross.cpu.model != std.Target.Cpu.baseline(cross.cpu.arch).model) {
+ try zig_args.append("-mcpu");
+ try zig_args.append(cross.cpu.model.name);
+ }
+ } else {
+ var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu=");
+ try mcpu_buffer.append(cross.cpu.model.name);
+
+ for (all_features) |feature, i_usize| {
+ const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
+ const in_cpu_set = populated_cpu_features.isEnabled(i);
+ const in_actual_set = cross.cpu.features.isEnabled(i);
+ if (in_cpu_set and !in_actual_set) {
+ try mcpu_buffer.appendByte('-');
+ try mcpu_buffer.append(feature.name);
+ } else if (!in_cpu_set and in_actual_set) {
+ try mcpu_buffer.appendByte('+');
+ try mcpu_buffer.append(feature.name);
}
- try zig_args.append(mcpu_buffer.toSliceConst());
}
- },
- }
-
- if (self.target_glibc) |ver| {
- try zig_args.append("-target-glibc");
- try zig_args.append(builder.fmt("{}.{}.{}", .{ ver.major, ver.minor, ver.patch }));
+ try zig_args.append(mcpu_buffer.toSliceConst());
+ }
}
if (self.linker_script) |linker_script| {
@@ -2517,10 +2438,7 @@ const VcpkgRootStatus = enum {
Found,
};
-pub const VcpkgLinkage = enum {
- Static,
- Dynamic,
-};
+pub const VcpkgLinkage = std.builtin.LinkMode;
pub const InstallDir = enum {
Prefix,
lib/std/builtin.zig
@@ -429,6 +429,29 @@ pub const Version = struct {
.patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
};
}
+
+ pub fn format(
+ self: Version,
+ comptime fmt: []const u8,
+ options: std.fmt.FormatOptions,
+ context: var,
+ comptime Error: type,
+ comptime output: fn (@TypeOf(context), []const u8) Error!void,
+ ) Error!void {
+ if (fmt.len == 0) {
+ if (self.patch == 0) {
+ if (self.minor == 0) {
+ return std.fmt.format(context, Error, output, "{}", .{self.major});
+ } else {
+ return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor });
+ }
+ } else {
+ return std.fmt.format(context, Error, output, "{}.{}.{}", .{ self.major, self.minor, self.patch });
+ }
+ } else {
+ @compileError("Unknown format string: '" ++ fmt ++ "'");
+ }
+ }
};
/// This data structure is used by the Zig language code generation and
lib/std/target.zig
@@ -60,6 +60,16 @@ pub const Target = struct {
else => false,
};
}
+
+ pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 {
+ if (tag.isDarwin()) {
+ return ".dylib";
+ }
+ switch (tag) {
+ .windows => return ".dll",
+ else => return ".so",
+ }
+ }
};
/// Based on NTDDI version constants from
@@ -210,64 +220,31 @@ pub const Target = struct {
}
};
- pub fn parse(text: []const u8) !Os {
- var it = mem.separate(text, ".");
- const os_name = it.next().?;
- const tag = std.meta.stringToEnum(Tag, os_name) orelse return error.UnknownOperatingSystem;
- const version_text = it.rest();
- const S = struct {
- fn parseNone(s: []const u8) !void {
- if (s.len != 0) return error.InvalidOperatingSystemVersion;
- }
- fn parseSemVer(s: []const u8, d_range: Version.Range) !Version.Range {
- if (s.len == 0) return d_range;
- var range_it = mem.separate(s, "...");
-
- const min_text = range_it.next().?;
- const min_ver = Version.parse(min_text) catch |err| switch (err) {
- error.Overflow => return error.InvalidOperatingSystemVersion,
- error.InvalidCharacter => return error.InvalidOperatingSystemVersion,
- error.InvalidVersion => return error.InvalidOperatingSystemVersion,
- };
-
- const max_text = range_it.next() orelse return Version.Range{
- .min = min_ver,
- .max = d_range.max,
- };
- const max_ver = Version.parse(max_text) catch |err| switch (err) {
- error.Overflow => return error.InvalidOperatingSystemVersion,
- error.InvalidCharacter => return error.InvalidOperatingSystemVersion,
- error.InvalidVersion => return error.InvalidOperatingSystemVersion,
- };
-
- return Version.Range{ .min = min_ver, .max = max_ver };
- }
- fn parseWindows(s: []const u8, d_range: WindowsVersion.Range) !WindowsVersion.Range {
- if (s.len == 0) return d_range;
- var range_it = mem.separate(s, "...");
-
- const min_text = range_it.next().?;
- const min_ver = std.meta.stringToEnum(WindowsVersion, min_text) orelse
- return error.InvalidOperatingSystemVersion;
+ pub fn defaultVersionRange(tag: Tag) Os {
+ return .{
+ .tag = tag,
+ .version_range = VersionRange.default(tag),
+ };
+ }
- const max_text = range_it.next() orelse return WindowsVersion.Range{
- .min = min_ver,
- .max = d_range.max,
- };
- const max_ver = std.meta.stringToEnum(WindowsVersion, max_text) orelse
- return error.InvalidOperatingSystemVersion;
+ pub fn requiresLibC(os: Os) bool {
+ return switch (os.tag) {
+ .freebsd,
+ .netbsd,
+ .macosx,
+ .ios,
+ .tvos,
+ .watchos,
+ .dragonfly,
+ .openbsd,
+ => true,
- return WindowsVersion.Range{ .min = min_ver, .max = max_ver };
- }
- };
- const d_range = VersionRange.default(tag);
- switch (tag) {
+ .linux,
+ .windows,
.freestanding,
.ananas,
.cloudabi,
- .dragonfly,
.fuchsia,
- .ios,
.kfreebsd,
.lv2,
.solaris,
@@ -282,8 +259,6 @@ pub const Target = struct {
.amdhsa,
.ps4,
.elfiamcu,
- .tvos,
- .watchos,
.mesa3d,
.contiki,
.amdpal,
@@ -293,41 +268,7 @@ pub const Target = struct {
.emscripten,
.uefi,
.other,
- => return Os{
- .tag = tag,
- .version_range = .{ .none = try S.parseNone(version_text) },
- },
-
- .freebsd,
- .macosx,
- .netbsd,
- .openbsd,
- => return Os{
- .tag = tag,
- .version_range = .{ .semver = try S.parseSemVer(version_text, d_range.semver) },
- },
-
- .linux => return Os{
- .tag = tag,
- .version_range = .{
- .linux = .{
- .range = try S.parseSemVer(version_text, d_range.linux.range),
- .glibc = d_range.linux.glibc,
- },
- },
- },
-
- .windows => return Os{
- .tag = tag,
- .version_range = .{ .windows = try S.parseWindows(version_text, d_range.windows) },
- },
- }
- }
-
- pub fn defaultVersionRange(tag: Tag) Os {
- return .{
- .tag = tag,
- .version_range = VersionRange.default(tag),
+ => false,
};
}
};
@@ -434,6 +375,13 @@ pub const Target = struct {
else => false,
};
}
+
+ pub fn oFileExt(abi: Abi) [:0]const u8 {
+ return switch (abi) {
+ .msvc => ".obj",
+ else => ".o",
+ };
+ }
};
pub const ObjectFormat = enum {
@@ -500,6 +448,12 @@ pub const Target = struct {
return Set{ .ints = [1]usize{0} ** usize_count };
}
+ pub fn isEmpty(set: Set) bool {
+ return for (set.ints) |x| {
+ if (x != 0) break false;
+ } else true;
+ }
+
pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
const usize_index = arch_feature_index / @bitSizeOf(usize);
const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize));
@@ -526,6 +480,15 @@ pub const Target = struct {
set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
}
+ /// Removes the specified feature but not its dependents.
+ pub fn removeFeatureSet(set: *Set, other_set: Set) void {
+ // TODO should be able to use binary not on @Vector type.
+ // https://github.com/ziglang/zig/issues/903
+ for (set.ints) |*int, i| {
+ int.* &= ~other_set.ints[i];
+ }
+ }
+
pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void {
@setEvalBranchQuota(1000000);
@@ -663,7 +626,7 @@ pub const Target = struct {
return cpu;
}
}
- return error.UnknownCpu;
+ return error.UnknownCpuModel;
}
pub fn toElfMachine(arch: Arch) std.elf.EM {
@@ -779,6 +742,66 @@ pub const Target = struct {
};
}
+ pub fn ptrBitWidth(arch: Arch) u32 {
+ switch (arch) {
+ .avr,
+ .msp430,
+ => return 16,
+
+ .arc,
+ .arm,
+ .armeb,
+ .hexagon,
+ .le32,
+ .mips,
+ .mipsel,
+ .powerpc,
+ .r600,
+ .riscv32,
+ .sparc,
+ .sparcel,
+ .tce,
+ .tcele,
+ .thumb,
+ .thumbeb,
+ .i386,
+ .xcore,
+ .nvptx,
+ .amdil,
+ .hsail,
+ .spir,
+ .kalimba,
+ .shave,
+ .lanai,
+ .wasm32,
+ .renderscript32,
+ .aarch64_32,
+ => return 32,
+
+ .aarch64,
+ .aarch64_be,
+ .mips64,
+ .mips64el,
+ .powerpc64,
+ .powerpc64le,
+ .riscv64,
+ .x86_64,
+ .nvptx64,
+ .le64,
+ .amdil64,
+ .hsail64,
+ .spir64,
+ .wasm64,
+ .renderscript64,
+ .amdgcn,
+ .bpfel,
+ .bpfeb,
+ .sparcv9,
+ .s390x,
+ => return 64,
+ }
+ }
+
/// Returns a name that matches the lib/std/target/* directory name.
pub fn genericName(arch: Arch) []const u8 {
return switch (arch) {
@@ -846,16 +869,6 @@ pub const Target = struct {
else => &[0]*const Model{},
};
}
-
- pub fn parse(text: []const u8) !Arch {
- const info = @typeInfo(Arch);
- inline for (info.Enum.fields) |field| {
- if (mem.eql(u8, text, field.name)) {
- return @as(Arch, @field(Arch, field.name));
- }
- }
- return error.UnknownArchitecture;
- }
};
pub const Model = struct {
@@ -872,41 +885,44 @@ pub const Target = struct {
.features = features,
};
}
+
+ pub fn baseline(arch: Arch) *const Model {
+ const S = struct {
+ const generic_model = Model{
+ .name = "generic",
+ .llvm_name = null,
+ .features = Cpu.Feature.Set.empty,
+ };
+ };
+ return switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline,
+ .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic,
+ .avr => &avr.cpu.avr1,
+ .bpfel, .bpfeb => &bpf.cpu.generic,
+ .hexagon => &hexagon.cpu.generic,
+ .mips, .mipsel => &mips.cpu.mips32,
+ .mips64, .mips64el => &mips.cpu.mips64,
+ .msp430 => &msp430.cpu.generic,
+ .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic,
+ .amdgcn => &amdgpu.cpu.generic,
+ .riscv32 => &riscv.cpu.baseline_rv32,
+ .riscv64 => &riscv.cpu.baseline_rv64,
+ .sparc, .sparcv9, .sparcel => &sparc.cpu.generic,
+ .s390x => &systemz.cpu.generic,
+ .i386 => &x86.cpu.pentium4,
+ .x86_64 => &x86.cpu.x86_64,
+ .nvptx, .nvptx64 => &nvptx.cpu.sm_20,
+ .wasm32, .wasm64 => &wasm.cpu.generic,
+
+ else => &S.generic_model,
+ };
+ }
};
/// The "default" set of CPU features for cross-compiling. A conservative set
/// of features that is expected to be supported on most available hardware.
pub fn baseline(arch: Arch) Cpu {
- const S = struct {
- const generic_model = Model{
- .name = "generic",
- .llvm_name = null,
- .features = Cpu.Feature.Set.empty,
- };
- };
- const model = switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline,
- .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic,
- .avr => &avr.cpu.avr1,
- .bpfel, .bpfeb => &bpf.cpu.generic,
- .hexagon => &hexagon.cpu.generic,
- .mips, .mipsel => &mips.cpu.mips32,
- .mips64, .mips64el => &mips.cpu.mips64,
- .msp430 => &msp430.cpu.generic,
- .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic,
- .amdgcn => &amdgpu.cpu.generic,
- .riscv32 => &riscv.cpu.baseline_rv32,
- .riscv64 => &riscv.cpu.baseline_rv64,
- .sparc, .sparcv9, .sparcel => &sparc.cpu.generic,
- .s390x => &systemz.cpu.generic,
- .i386 => &x86.cpu.pentium4,
- .x86_64 => &x86.cpu.x86_64,
- .nvptx, .nvptx64 => &nvptx.cpu.sm_20,
- .wasm32, .wasm64 => &wasm.cpu.generic,
-
- else => &S.generic_model,
- };
- return model.toCpu(arch);
+ return Model.baseline(arch).toCpu(arch);
}
};
@@ -918,239 +934,70 @@ pub const Target = struct {
pub const stack_align = 16;
- /// TODO add OS version ranges and glibc version
- pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
- return std.fmt.allocPrint(allocator, "{}-{}-{}", .{
- @tagName(self.cpu.arch),
- @tagName(self.os.tag),
- @tagName(self.abi),
- });
+ pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 {
+ return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator);
}
- /// Returned slice must be freed by the caller.
- pub fn vcpkgTriplet(target: Target, allocator: *mem.Allocator, linkage: std.build.VcpkgLinkage) ![]const u8 {
- const arch = switch (target.cpu.arch) {
- .i386 => "x86",
- .x86_64 => "x64",
-
- .arm,
- .armeb,
- .thumb,
- .thumbeb,
- .aarch64_32,
- => "arm",
-
- .aarch64,
- .aarch64_be,
- => "arm64",
-
- else => return error.VcpkgNoSuchArchitecture,
- };
-
- const os = switch (target.os) {
- .windows => "windows",
- .linux => "linux",
- .macosx => "macos",
- else => return error.VcpkgNoSuchOs,
- };
-
- if (linkage == .Static) {
- return try mem.join(allocator, "-", &[_][]const u8{ arch, os, "static" });
- } else {
- return try mem.join(allocator, "-", &[_][]const u8{ arch, os });
- }
+ pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 {
+ return std.fmt.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
}
- pub fn allocDescription(self: Target, 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);
+ pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 {
+ return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi);
}
- pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
- return std.fmt.allocPrint(allocator, "{}-{}-{}", .{
- @tagName(self.cpu.arch),
- @tagName(self.os.tag),
- @tagName(self.abi),
- });
+ pub fn oFileExt(self: Target) [:0]const u8 {
+ return self.abi.oFileExt();
}
- pub const ParseOptions = struct {
- /// This is sometimes called a "triple". It looks roughly like this:
- /// riscv64-linux-gnu
- /// The fields are, respectively:
- /// * CPU Architecture
- /// * Operating System
- /// * C ABI (optional)
- arch_os_abi: []const u8,
-
- /// 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.
- cpu_features: []const u8 = "baseline",
-
- /// If this is provided, the function will populate some information about parsing failures,
- /// so that user-friendly error messages can be delivered.
- diagnostics: ?*Diagnostics = null,
-
- pub const Diagnostics = struct {
- /// If the architecture was determined, this will be populated.
- arch: ?Cpu.Arch = null,
-
- /// If the OS was determined, this will be populated.
- os: ?Os = null,
-
- /// If the ABI was determined, this will be populated.
- abi: ?Abi = null,
-
- /// If the CPU name was determined, this will be populated.
- cpu_name: ?[]const u8 = null,
-
- /// If error.UnknownCpuFeature is returned, this will be populated.
- unknown_feature_name: ?[]const u8 = null,
- };
- };
-
- pub fn parse(args: ParseOptions) !Target {
- var dummy_diags: ParseOptions.Diagnostics = undefined;
- var diags = args.diagnostics orelse &dummy_diags;
-
- var it = mem.separate(args.arch_os_abi, "-");
- const arch_name = it.next() orelse return error.MissingArchitecture;
- const arch = try Cpu.Arch.parse(arch_name);
- diags.arch = arch;
-
- const os_name = it.next() orelse return error.MissingOperatingSystem;
- var os = try Os.parse(os_name);
- diags.os = os;
-
- const opt_abi_text = it.next();
- const abi = if (opt_abi_text) |abi_text| blk: {
- var abi_it = mem.separate(abi_text, ".");
- const abi = std.meta.stringToEnum(Abi, abi_it.next().?) orelse
- return error.UnknownApplicationBinaryInterface;
- const abi_ver_text = abi_it.rest();
- if (abi_ver_text.len != 0) {
- if (os.tag == .linux and abi.isGnu()) {
- os.version_range.linux.glibc = Version.parse(abi_ver_text) catch |err| switch (err) {
- error.Overflow => return error.InvalidAbiVersion,
- error.InvalidCharacter => return error.InvalidAbiVersion,
- error.InvalidVersion => return error.InvalidAbiVersion,
- };
- } else {
- return error.InvalidAbiVersion;
- }
- }
- break :blk abi;
- } else Abi.default(arch, os);
- diags.abi = abi;
-
- if (it.next() != null) return error.UnexpectedExtraField;
-
- const all_features = arch.allFeaturesList();
- var index: usize = 0;
- while (index < args.cpu_features.len and
- args.cpu_features[index] != '+' and
- args.cpu_features[index] != '-')
- {
- index += 1;
+ pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 {
+ switch (os_tag) {
+ .windows => return ".exe",
+ .uefi => return ".efi",
+ else => if (cpu_arch.isWasm()) {
+ return ".wasm";
+ } else {
+ return "";
+ },
}
- const cpu_name = args.cpu_features[0..index];
- diags.cpu_name = cpu_name;
-
- const cpu: Cpu = if (mem.eql(u8, cpu_name, "baseline")) Cpu.baseline(arch) else blk: {
- const cpu_model = try arch.parseCpuModel(cpu_name);
-
- var set = cpu_model.features;
- while (index < args.cpu_features.len) {
- const op = args.cpu_features[index];
- index += 1;
- const start = index;
- while (index < args.cpu_features.len and
- args.cpu_features[index] != '+' and
- args.cpu_features[index] != '-')
- {
- index += 1;
- }
- const feature_name = args.cpu_features[start..index];
- for (all_features) |feature, feat_index_usize| {
- const feat_index = @intCast(Cpu.Feature.Set.Index, feat_index_usize);
- if (mem.eql(u8, feature_name, feature.name)) {
- switch (op) {
- '+' => set.addFeature(feat_index),
- '-' => set.removeFeature(feat_index),
- else => unreachable,
- }
- break;
- }
- } else {
- diags.unknown_feature_name = feature_name;
- return error.UnknownCpuFeature;
- }
- }
- set.populateDependencies(all_features);
- break :blk .{
- .arch = arch,
- .model = cpu_model,
- .features = set,
- };
- };
- return Target{
- .cpu = cpu,
- .os = os,
- .abi = abi,
- };
}
- pub fn oFileExt(self: Target) []const u8 {
- return switch (self.abi) {
- .msvc => ".obj",
- else => ".o",
- };
- }
-
- pub fn exeFileExt(self: Target) []const u8 {
- if (self.os.tag == .windows) {
- return ".exe";
- } else if (self.os.tag == .uefi) {
- return ".efi";
- } else if (self.cpu.arch.isWasm()) {
- return ".wasm";
- } else {
- return "";
- }
+ pub fn exeFileExt(self: Target) [:0]const u8 {
+ return exeFileExtSimple(self.cpu.arch, self.os.tag);
}
- pub fn staticLibSuffix(self: Target) []const u8 {
- if (self.cpu.arch.isWasm()) {
+ pub fn staticLibSuffix_cpu_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) [:0]const u8 {
+ if (cpu_arch.isWasm()) {
return ".wasm";
}
- switch (self.abi) {
+ switch (abi) {
.msvc => return ".lib",
else => return ".a",
}
}
- pub fn dynamicLibSuffix(self: Target) []const u8 {
- if (self.isDarwin()) {
- return ".dylib";
- }
- switch (self.os) {
- .windows => return ".dll",
- else => return ".so",
- }
+ pub fn staticLibSuffix(self: Target) [:0]const u8 {
+ return staticLibSuffix_cpu_arch_abi(self.cpu.arch, self.abi);
}
- pub fn libPrefix(self: Target) []const u8 {
- if (self.cpu.arch.isWasm()) {
+ pub fn dynamicLibSuffix(self: Target) [:0]const u8 {
+ return self.os.tag.dynamicLibSuffix();
+ }
+
+ pub fn libPrefix_cpu_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) [:0]const u8 {
+ if (cpu_arch.isWasm()) {
return "";
}
- switch (self.abi) {
+ switch (abi) {
.msvc => return "",
else => return "lib",
}
}
+ pub fn libPrefix(self: Target) [:0]const u8 {
+ return libPrefix_cpu_arch_abi(self.cpu.arch, self.abi);
+ }
+
pub fn getObjectFormat(self: Target) ObjectFormat {
if (self.os.tag == .windows or self.os.tag == .uefi) {
return .coff;
@@ -1190,129 +1037,18 @@ pub const Target = struct {
return self.os.tag.isDarwin();
}
- pub fn isGnuLibC(self: Target) bool {
- return self.os.tag == .linux and self.abi.isGnu();
+ pub fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool {
+ return os_tag == .linux and abi.isGnu();
}
- pub fn wantSharedLibSymLinks(self: Target) bool {
- return self.os.tag != .windows;
- }
-
- pub fn osRequiresLibC(self: Target) bool {
- return self.isDarwin() or self.os.tag == .freebsd or self.os.tag == .netbsd;
- }
-
- pub fn getArchPtrBitWidth(self: Target) u32 {
- switch (self.cpu.arch) {
- .avr,
- .msp430,
- => return 16,
-
- .arc,
- .arm,
- .armeb,
- .hexagon,
- .le32,
- .mips,
- .mipsel,
- .powerpc,
- .r600,
- .riscv32,
- .sparc,
- .sparcel,
- .tce,
- .tcele,
- .thumb,
- .thumbeb,
- .i386,
- .xcore,
- .nvptx,
- .amdil,
- .hsail,
- .spir,
- .kalimba,
- .shave,
- .lanai,
- .wasm32,
- .renderscript32,
- .aarch64_32,
- => return 32,
-
- .aarch64,
- .aarch64_be,
- .mips64,
- .mips64el,
- .powerpc64,
- .powerpc64le,
- .riscv64,
- .x86_64,
- .nvptx64,
- .le64,
- .amdil64,
- .hsail64,
- .spir64,
- .wasm64,
- .renderscript64,
- .amdgcn,
- .bpfel,
- .bpfeb,
- .sparcv9,
- .s390x,
- => return 64,
- }
+ pub fn isGnuLibC(self: Target) bool {
+ return isGnuLibC_os_tag_abi(self.os.tag, self.abi);
}
pub fn supportsNewStackCall(self: Target) bool {
return !self.cpu.arch.isWasm();
}
- pub const Executor = union(enum) {
- native,
- qemu: []const u8,
- wine: []const u8,
- wasmtime: []const u8,
- unavailable,
- };
-
- pub fn getExternalExecutor(self: Target) Executor {
- // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture.
- if (self.os.tag == builtin.os.tag) {
- return switch (self.cpu.arch) {
- .aarch64 => Executor{ .qemu = "qemu-aarch64" },
- .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" },
- .arm => Executor{ .qemu = "qemu-arm" },
- .armeb => Executor{ .qemu = "qemu-armeb" },
- .i386 => Executor{ .qemu = "qemu-i386" },
- .mips => Executor{ .qemu = "qemu-mips" },
- .mipsel => Executor{ .qemu = "qemu-mipsel" },
- .mips64 => Executor{ .qemu = "qemu-mips64" },
- .mips64el => Executor{ .qemu = "qemu-mips64el" },
- .powerpc => Executor{ .qemu = "qemu-ppc" },
- .powerpc64 => Executor{ .qemu = "qemu-ppc64" },
- .powerpc64le => Executor{ .qemu = "qemu-ppc64le" },
- .riscv32 => Executor{ .qemu = "qemu-riscv32" },
- .riscv64 => Executor{ .qemu = "qemu-riscv64" },
- .s390x => Executor{ .qemu = "qemu-s390x" },
- .sparc => Executor{ .qemu = "qemu-sparc" },
- .x86_64 => Executor{ .qemu = "qemu-x86_64" },
- else => return .unavailable,
- };
- }
-
- switch (self.os.tag) {
- .windows => switch (self.getArchPtrBitWidth()) {
- 32 => return Executor{ .wine = "wine" },
- 64 => return Executor{ .wine = "wine64" },
- else => return .unavailable,
- },
- .wasi => switch (self.getArchPtrBitWidth()) {
- 32 => return Executor{ .wasmtime = "wasmtime" },
- else => return .unavailable,
- },
- else => return .unavailable,
- }
- }
-
pub const FloatAbi = enum {
hard,
soft,
@@ -1359,7 +1095,7 @@ pub const Target = struct {
}![:0]u8 {
const a = allocator;
if (self.isAndroid()) {
- return mem.dupeZ(a, u8, if (self.getArchPtrBitWidth() == 64)
+ return mem.dupeZ(a, u8, if (self.cpu.arch.ptrBitWidth() == 64)
"/system/bin/linker64"
else
"/system/bin/linker");
@@ -1477,52 +1213,3 @@ pub const Target = struct {
}
}
};
-
-test "Target.parse" {
- {
- const target = try Target.parse(.{
- .arch_os_abi = "x86_64-linux-gnu",
- .cpu_features = "x86_64-sse-sse2-avx-cx8",
- });
-
- std.testing.expect(target.os.tag == .linux);
- std.testing.expect(target.abi == .gnu);
- std.testing.expect(target.cpu.arch == .x86_64);
- std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse));
- std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx));
- std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8));
- std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov));
- std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr));
- }
- {
- const target = try Target.parse(.{
- .arch_os_abi = "arm-linux-musleabihf",
- .cpu_features = "generic+v8a",
- });
-
- std.testing.expect(target.os.tag == .linux);
- std.testing.expect(target.abi == .musleabihf);
- std.testing.expect(target.cpu.arch == .arm);
- std.testing.expect(target.cpu.model == &Target.arm.cpu.generic);
- std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a));
- }
- {
- const target = try Target.parse(.{
- .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27",
- .cpu_features = "generic+v8a",
- });
-
- std.testing.expect(target.cpu.arch == .aarch64);
- std.testing.expect(target.os.tag == .linux);
- std.testing.expect(target.os.version_range.linux.range.min.major == 3);
- std.testing.expect(target.os.version_range.linux.range.min.minor == 10);
- std.testing.expect(target.os.version_range.linux.range.min.patch == 0);
- std.testing.expect(target.os.version_range.linux.range.max.major == 4);
- std.testing.expect(target.os.version_range.linux.range.max.minor == 4);
- std.testing.expect(target.os.version_range.linux.range.max.patch == 1);
- std.testing.expect(target.os.version_range.linux.glibc.major == 2);
- std.testing.expect(target.os.version_range.linux.glibc.minor == 27);
- std.testing.expect(target.os.version_range.linux.glibc.patch == 0);
- std.testing.expect(target.abi == .gnu);
- }
-}
lib/std/testing.zig
@@ -1,5 +1,3 @@
-const builtin = @import("builtin");
-const TypeId = builtin.TypeId;
const std = @import("std.zig");
pub const LeakCountAllocator = @import("testing/leak_count_allocator.zig").LeakCountAllocator;
@@ -65,16 +63,16 @@ pub fn expectEqual(expected: var, actual: @TypeOf(expected)) void {
.Pointer => |pointer| {
switch (pointer.size) {
- builtin.TypeInfo.Pointer.Size.One,
- builtin.TypeInfo.Pointer.Size.Many,
- builtin.TypeInfo.Pointer.Size.C,
+ .One,
+ .Many,
+ .C,
=> {
if (actual != expected) {
std.debug.panic("expected {*}, found {*}", .{ expected, actual });
}
},
- builtin.TypeInfo.Pointer.Size.Slice => {
+ .Slice => {
if (actual.ptr != expected.ptr) {
std.debug.panic("expected slice ptr {}, found {}", .{ expected.ptr, actual.ptr });
}
lib/std/zig.zig
@@ -6,11 +6,8 @@ pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStri
pub const render = @import("zig/render.zig").render;
pub const ast = @import("zig/ast.zig");
pub const system = @import("zig/system.zig");
+pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget;
-test "std.zig tests" {
- _ = @import("zig/ast.zig");
- _ = @import("zig/parse.zig");
- _ = @import("zig/render.zig");
- _ = @import("zig/tokenizer.zig");
- _ = @import("zig/parse_string_literal.zig");
+test "" {
+ @import("std").meta.refAllDecls(@This());
}
src-self-hosted/stage2.zig
@@ -10,6 +10,7 @@ const Allocator = mem.Allocator;
const ArrayList = std.ArrayList;
const Buffer = std.Buffer;
const Target = std.Target;
+const CrossTarget = std.zig.CrossTarget;
const self_hosted_main = @import("main.zig");
const errmsg = @import("errmsg.zig");
const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
@@ -87,7 +88,7 @@ const Error = extern enum {
NotLazy,
IsAsync,
ImportOutsidePkgPath,
- UnknownCpu,
+ UnknownCpuModel,
UnknownCpuFeature,
InvalidCpuFeatures,
InvalidLlvmCpuFeaturesFormat,
@@ -634,13 +635,9 @@ export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
}
fn cmdTargets(zig_triple: [*:0]const u8) !void {
- var target = try Target.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) });
- target.cpu = blk: {
- const llvm = @import("llvm.zig");
- const llvm_cpu_name = llvm.GetHostCPUName();
- const llvm_cpu_features = llvm.GetNativeFeatures();
- break :blk try detectNativeCpuWithLLVM(target.cpu.arch, llvm_cpu_name, llvm_cpu_features);
- };
+ var cross_target = try CrossTarget.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) });
+ var dynamic_linker: ?[*:0]u8 = null;
+ const target = try crossTargetToTarget(cross_target, &dynamic_linker);
return @import("print_targets.zig").cmdTargets(
std.heap.c_allocator,
&[0][]u8{},
@@ -661,7 +658,6 @@ export fn stage2_target_parse(
error.UnknownOperatingSystem => return .UnknownOperatingSystem,
error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
error.MissingOperatingSystem => return .MissingOperatingSystem,
- error.MissingArchitecture => return .MissingArchitecture,
error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
error.UnexpectedExtraField => return .SemanticAnalyzeFail,
error.InvalidAbiVersion => return .InvalidAbiVersion,
@@ -681,44 +677,42 @@ fn stage2TargetParse(
zig_triple_oz: ?[*:0]const u8,
mcpu_oz: ?[*:0]const u8,
) !void {
- const target: std.build.Target = if (zig_triple_oz) |zig_triple_z| blk: {
+ const target: CrossTarget = if (zig_triple_oz) |zig_triple_z| blk: {
const zig_triple = mem.toSliceConst(u8, zig_triple_z);
const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline";
- var diags: std.Target.ParseOptions.Diagnostics = .{};
- break :blk std.build.Target{
- .Cross = Target.parse(.{
- .arch_os_abi = zig_triple,
- .cpu_features = mcpu,
- .diagnostics = &diags,
- }) catch |err| switch (err) {
- error.UnknownCpu => {
- std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
- diags.cpu_name.?,
- @tagName(diags.arch.?),
- });
- for (diags.arch.?.allCpuModels()) |cpu| {
- std.debug.warn(" {}\n", .{cpu.name});
- }
- process.exit(1);
- },
- error.UnknownCpuFeature => {
- std.debug.warn(
- \\Unknown CPU feature: '{}'
- \\Available CPU features for architecture '{}':
- \\
- , .{
- diags.unknown_feature_name,
- @tagName(diags.arch.?),
- });
- for (diags.arch.?.allFeaturesList()) |feature| {
- std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
- }
- process.exit(1);
- },
- else => |e| return e,
+ var diags: CrossTarget.ParseOptions.Diagnostics = .{};
+ break :blk CrossTarget.parse(.{
+ .arch_os_abi = zig_triple,
+ .cpu_features = mcpu,
+ .diagnostics = &diags,
+ }) catch |err| switch (err) {
+ error.UnknownCpuModel => {
+ std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
+ diags.cpu_name.?,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allCpuModels()) |cpu| {
+ std.debug.warn(" {}\n", .{cpu.name});
+ }
+ process.exit(1);
},
+ error.UnknownCpuFeature => {
+ std.debug.warn(
+ \\Unknown CPU feature: '{}'
+ \\Available CPU features for architecture '{}':
+ \\
+ , .{
+ diags.unknown_feature_name,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allFeaturesList()) |feature| {
+ std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
+ }
+ process.exit(1);
+ },
+ else => |e| return e,
};
- } else std.build.Target.Native;
+ } else .{};
try stage1_target.fromTarget(target);
}
@@ -908,8 +902,8 @@ const Stage2Target = extern struct {
dynamic_linker: ?[*:0]const u8,
- fn toTarget(in_target: Stage2Target) std.build.Target {
- if (in_target.is_native) return .Native;
+ fn toTarget(in_target: Stage2Target) CrossTarget {
+ if (in_target.is_native) return .{};
const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch
const in_os = in_target.os;
@@ -924,28 +918,11 @@ const Stage2Target = extern struct {
};
}
- fn fromTarget(self: *Stage2Target, build_target: std.build.Target) !void {
+ fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
const allocator = std.heap.c_allocator;
- var dynamic_linker: ?[*:0]u8 = null;
- const target = switch (build_target) {
- .Native => blk: {
- const info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator);
- if (info.dynamic_linker) |dl| {
- dynamic_linker = dl.ptr;
- }
- // TODO we want to just use info.target but implementing CPU model & feature detection is todo
- // so here we rely on LLVM
- const llvm = @import("llvm.zig");
- const llvm_cpu_name = llvm.GetHostCPUName();
- const llvm_cpu_features = llvm.GetNativeFeatures();
- const arch = std.Target.current.cpu.arch;
- var t = info.target;
- t.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
- break :blk t;
- },
- .Cross => |t| t,
- };
+ var dynamic_linker: ?[*:0]u8 = null;
+ const target = try crossTargetToTarget(cross_target, &dynamic_linker);
var cache_hash = try std.Buffer.allocPrint(allocator, "{}\n{}\n", .{
target.cpu.model.name,
@@ -1145,7 +1122,7 @@ const Stage2Target = extern struct {
.cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr,
.os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr,
.cache_hash = cache_hash.toOwnedSlice().ptr,
- .is_native = build_target == .Native,
+ .is_native = cross_target.isNative(),
.glibc_version = glibc_version,
.dynamic_linker = dynamic_linker,
};
@@ -1156,6 +1133,40 @@ fn enumInt(comptime Enum: type, int: c_int) Enum {
return @intToEnum(Enum, @intCast(@TagType(Enum), int));
}
+/// TODO move dynamic linker to be part of the target
+/// TODO self-host this function
+fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target {
+ var adjusted_target = cross_target.toTarget();
+ if (cross_target.isNativeCpu() or cross_target.isNativeOs()) {
+ const detected_info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator);
+ if (cross_target.isNativeCpu()) {
+ adjusted_target.cpu = detected_info.target.cpu;
+
+ // TODO We want to just use detected_info.target but implementing
+ // CPU model & feature detection is todo so here we rely on LLVM.
+ // There is another occurrence of this; search for detectNativeCpuWithLLVM.
+ const llvm = @import("llvm.zig");
+ const llvm_cpu_name = llvm.GetHostCPUName();
+ const llvm_cpu_features = llvm.GetNativeFeatures();
+ const arch = std.Target.current.cpu.arch;
+ adjusted_target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
+ }
+ if (cross_target.isNativeOs()) {
+ adjusted_target.os = detected_info.target.os;
+
+ if (detected_info.dynamic_linker) |dl| {
+ dynamic_linker_ptr.* = dl.ptr;
+ }
+ if (cross_target.abi == null) {
+ adjusted_target.abi = detected_info.target.abi;
+ }
+ } else if (cross_target.abi == null) {
+ adjusted_target.abi = Target.Abi.default(adjusted_target.cpu.arch, adjusted_target.os);
+ }
+ }
+ return adjusted_target;
+}
+
// ABI warning
const Stage2GLibCVersion = extern struct {
major: u32,
test/src/translate_c.zig
@@ -7,6 +7,7 @@ const fmt = std.fmt;
const mem = std.mem;
const fs = std.fs;
const warn = std.debug.warn;
+const CrossTarget = std.zig.CrossTarget;
pub const TranslateCContext = struct {
b: *build.Builder,
@@ -19,7 +20,7 @@ pub const TranslateCContext = struct {
sources: ArrayList(SourceFile),
expected_lines: ArrayList([]const u8),
allow_warnings: bool,
- target: build.Target = .Native,
+ target: CrossTarget = CrossTarget{},
const SourceFile = struct {
filename: []const u8,
@@ -75,7 +76,7 @@ pub const TranslateCContext = struct {
pub fn addWithTarget(
self: *TranslateCContext,
name: []const u8,
- target: build.Target,
+ target: CrossTarget,
source: []const u8,
expected_lines: []const []const u8,
) void {
test/compile_errors.zig
@@ -1,5 +1,5 @@
const tests = @import("tests.zig");
-const Target = @import("std").Target;
+const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.addTest("type mismatch with tuple concatenation",
@@ -386,12 +386,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
, &[_][]const u8{
"tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack",
});
- tc.target = tests.Target{
- .Cross = .{
- .cpu = Target.Cpu.baseline(.wasm32),
- .os = Target.Os.defaultVersionRange(.wasi),
- .abi = .none,
- },
+ tc.target = std.zig.CrossTarget{
+ .cpu_arch = .wasm32,
+ .os_tag = .wasi,
+ .abi = .none,
};
break :x tc;
});
@@ -787,12 +785,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
, &[_][]const u8{
"tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs",
});
- tc.target = tests.Target{
- .Cross = .{
- .cpu = Target.Cpu.baseline(.x86_64),
- .os = Target.Os.defaultVersionRange(.linux),
- .abi = .gnu,
- },
+ tc.target = std.zig.CrossTarget{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .gnu,
};
break :x tc;
});
@@ -1452,7 +1448,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:2:18: error: invalid operands to binary expression: 'error{A}' and 'error{B}'",
});
- if (Target.current.os.tag == .linux) {
+ if (std.Target.current.os.tag == .linux) {
cases.addTest("implicit dependency on libc",
\\extern "c" fn exit(u8) void;
\\export fn entry() void {
test/tests.zig
@@ -3,7 +3,7 @@ const builtin = std.builtin;
const debug = std.debug;
const warn = debug.warn;
const build = std.build;
-pub const Target = build.Target;
+const CrossTarget = std.zig.CrossTarget;
const Buffer = std.Buffer;
const io = std.io;
const fs = std.fs;
@@ -30,7 +30,7 @@ pub const RunTranslatedCContext = @import("src/run_translated_c.zig").RunTransla
pub const CompareOutputContext = @import("src/compare_output.zig").CompareOutputContext;
const TestTarget = struct {
- target: build.Target = .Native,
+ target: CrossTarget = @as(CrossTarget, .{}),
mode: builtin.Mode = .Debug,
link_libc: bool = false,
single_threaded: bool = false,
@@ -52,105 +52,85 @@ const test_targets = blk: {
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.x86_64),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .none,
- },
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .none,
},
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.x86_64),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .gnu,
- },
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .gnu,
},
.link_libc = true,
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.x86_64),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .musl,
- },
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .linux,
+ .abi = .musl,
},
.link_libc = true,
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.i386),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .none,
- },
+ .target = .{
+ .cpu_arch = .i386,
+ .os_tag = .linux,
+ .abi = .none,
},
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.i386),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .musl,
- },
+ .target = .{
+ .cpu_arch = .i386,
+ .os_tag = .linux,
+ .abi = .musl,
},
.link_libc = true,
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.aarch64),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .none,
- },
+ .target = .{
+ .cpu_arch = .aarch64,
+ .os_tag = .linux,
+ .abi = .none,
},
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.aarch64),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .musl,
- },
+ .target = .{
+ .cpu_arch = .aarch64,
+ .os_tag = .linux,
+ .abi = .musl,
},
.link_libc = true,
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.aarch64),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .gnu,
- },
+ .target = .{
+ .cpu_arch = .aarch64,
+ .os_tag = .linux,
+ .abi = .gnu,
},
.link_libc = true,
},
TestTarget{
- .target = .{
- .Cross = std.Target.parse(.{
- .arch_os_abi = "arm-linux-none",
- .cpu_features = "generic+v8a",
- }) catch unreachable,
- },
+ .target = CrossTarget.parse(.{
+ .arch_os_abi = "arm-linux-none",
+ .cpu_features = "generic+v8a",
+ }) catch unreachable,
},
TestTarget{
- .target = .{
- .Cross = std.Target.parse(.{
- .arch_os_abi = "arm-linux-musleabihf",
- .cpu_features = "generic+v8a",
- }) catch unreachable,
- },
+ .target = CrossTarget.parse(.{
+ .arch_os_abi = "arm-linux-musleabihf",
+ .cpu_features = "generic+v8a",
+ }) catch unreachable,
.link_libc = true,
},
// TODO https://github.com/ziglang/zig/issues/3287
//TestTarget{
- // .target = std.Target.parse(.{
+ // .target = CrossTarget.parse(.{
// .arch_os_abi = "arm-linux-gnueabihf",
// .cpu_features = "generic+v8a",
// }) catch unreachable,
@@ -158,75 +138,61 @@ const test_targets = blk: {
//},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.mipsel),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .none,
- },
+ .target = .{
+ .cpu_arch = .mipsel,
+ .os_tag = .linux,
+ .abi = .none,
},
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.mipsel),
- .os = std.Target.Os.defaultVersionRange(.linux),
- .abi = .musl,
- },
+ .target = .{
+ .cpu_arch = .mipsel,
+ .os_tag = .linux,
+ .abi = .musl,
},
.link_libc = true,
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.x86_64),
- .os = std.Target.Os.defaultVersionRange(.macosx),
- .abi = .gnu,
- },
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .macosx,
+ .abi = .gnu,
},
// TODO https://github.com/ziglang/zig/issues/3295
.disable_native = true,
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.i386),
- .os = std.Target.Os.defaultVersionRange(.windows),
- .abi = .msvc,
- },
+ .target = .{
+ .cpu_arch = .i386,
+ .os_tag = .windows,
+ .abi = .msvc,
},
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.x86_64),
- .os = std.Target.Os.defaultVersionRange(.windows),
- .abi = .msvc,
- },
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .msvc,
},
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.i386),
- .os = std.Target.Os.defaultVersionRange(.windows),
- .abi = .gnu,
- },
+ .target = .{
+ .cpu_arch = .i386,
+ .os_tag = .windows,
+ .abi = .gnu,
},
.link_libc = true,
},
TestTarget{
- .target = Target{
- .Cross = .{
- .cpu = std.Target.Cpu.baseline(.x86_64),
- .os = std.Target.Os.defaultVersionRange(.windows),
- .abi = .gnu,
- },
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
},
.link_libc = true,
},
@@ -435,13 +401,13 @@ pub fn addPkgTests(
const step = b.step(b.fmt("test-{}", .{name}), desc);
for (test_targets) |test_target| {
- if (skip_non_native and test_target.target != .Native)
+ if (skip_non_native and !test_target.target.isNative())
continue;
if (skip_libc and test_target.link_libc)
continue;
- if (test_target.link_libc and test_target.target.getTarget().osRequiresLibC()) {
+ if (test_target.link_libc and test_target.target.getOs().requiresLibC()) {
// This would be a redundant test.
continue;
}
@@ -451,8 +417,8 @@ pub fn addPkgTests(
const ArchTag = @TagType(builtin.Arch);
if (test_target.disable_native and
- test_target.target.getOs() == std.Target.current.os.tag and
- test_target.target.getArch() == std.Target.current.cpu.arch)
+ test_target.target.getOsTag() == std.Target.current.os.tag and
+ test_target.target.getCpuArch() == std.Target.current.cpu.arch)
{
continue;
}
@@ -462,17 +428,14 @@ pub fn addPkgTests(
} else false;
if (!want_this_mode) continue;
- const libc_prefix = if (test_target.target.getTarget().osRequiresLibC())
+ const libc_prefix = if (test_target.target.getOs().requiresLibC())
""
else if (test_target.link_libc)
"c"
else
"bare";
- const triple_prefix = if (test_target.target == .Native)
- @as([]const u8, "native")
- else
- test_target.target.zigTriple(b.allocator) catch unreachable;
+ const triple_prefix = test_target.target.zigTriple(b.allocator) catch unreachable;
const these_tests = b.addTest(root_src);
const single_threaded_txt = if (test_target.single_threaded) "single" else "multi";
@@ -486,7 +449,7 @@ pub fn addPkgTests(
these_tests.single_threaded = test_target.single_threaded;
these_tests.setFilter(test_filter);
these_tests.setBuildMode(test_target.mode);
- these_tests.setTheTarget(test_target.target);
+ these_tests.setTarget(test_target.target);
if (test_target.link_libc) {
these_tests.linkSystemLibrary("c");
}
@@ -716,7 +679,7 @@ pub const CompileErrorContext = struct {
link_libc: bool,
is_exe: bool,
is_test: bool,
- target: Target = .Native,
+ target: CrossTarget = CrossTarget{},
const SourceFile = struct {
filename: []const u8,
@@ -808,12 +771,9 @@ pub const CompileErrorContext = struct {
zig_args.append("--output-dir") catch unreachable;
zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable;
- switch (self.case.target) {
- .Native => {},
- .Cross => {
- try zig_args.append("-target");
- try zig_args.append(try self.case.target.zigTriple(b.allocator));
- },
+ if (!self.case.target.isNative()) {
+ try zig_args.append("-target");
+ try zig_args.append(try self.case.target.zigTriple(b.allocator));
}
switch (self.build_mode) {
test/translate_c.zig
@@ -1,6 +1,6 @@
const tests = @import("tests.zig");
const std = @import("std");
-const Target = std.Target;
+const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("macro line continuation",
@@ -665,7 +665,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
- if (Target.current.os.tag != .windows) {
+ if (std.Target.current.os.tag != .windows) {
// Windows treats this as an enum with type c_int
cases.add("big negative enum init values when C ABI supports long long enums",
\\enum EnumWithInits {
@@ -1064,7 +1064,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
- if (Target.current.os.tag != .windows) {
+ if (std.Target.current.os.tag != .windows) {
// sysv_abi not currently supported on windows
cases.add("Macro qualified functions",
\\void __attribute__((sysv_abi)) foo(void);
@@ -1094,11 +1094,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
});
cases.addWithTarget("Calling convention", .{
- .Cross = .{
- .cpu = Target.Cpu.baseline(.i386),
- .os = Target.Os.defaultVersionRange(.linux),
- .abi = .none,
- },
+ .cpu_arch = .i386,
+ .os_tag = .linux,
+ .abi = .none,
},
\\void __attribute__((fastcall)) foo1(float *a);
\\void __attribute__((stdcall)) foo2(float *a);
@@ -1113,12 +1111,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void;
});
- cases.addWithTarget("Calling convention", .{
- .Cross = Target.parse(.{
- .arch_os_abi = "arm-linux-none",
- .cpu_features = "generic+v8_5a",
- }) catch unreachable,
- },
+ cases.addWithTarget("Calling convention", CrossTarget.parse(.{
+ .arch_os_abi = "arm-linux-none",
+ .cpu_features = "generic+v8_5a",
+ }) catch unreachable,
\\void __attribute__((pcs("aapcs"))) foo1(float *a);
\\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
, &[_][]const u8{
@@ -1126,12 +1122,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void;
});
- cases.addWithTarget("Calling convention", .{
- .Cross = Target.parse(.{
- .arch_os_abi = "aarch64-linux-none",
- .cpu_features = "generic+v8_5a",
- }) catch unreachable,
- },
+ cases.addWithTarget("Calling convention", CrossTarget.parse(.{
+ .arch_os_abi = "aarch64-linux-none",
+ .cpu_features = "generic+v8_5a",
+ }) catch unreachable,
\\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
, &[_][]const u8{
\\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void;
@@ -1600,7 +1594,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
- if (Target.current.os.tag != .windows) {
+ if (std.Target.current.os.tag != .windows) {
// When clang uses the <arch>-windows-none triple it behaves as MSVC and
// interprets the inner `struct Bar` as an anonymous structure
cases.add("type referenced struct",
build.zig
@@ -298,7 +298,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
}
dependOnLib(b, exe, ctx.llvm);
- if (exe.target.getOs() == .linux) {
+ if (exe.target.getOsTag() == .linux) {
try addCxxKnownPath(b, ctx, exe, "libstdc++.a",
\\Unable to determine path to libstdc++.a
\\On Fedora, install libstdc++-static and try again.