zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 3179f58c414b5e4845b9bf3acdf276fe8e2b88a0 (tree)
parent 67d48b94d601521e15dd44c8789b1f528d09f10c
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Mon,  4 Dec 2023 12:35:04 -0700

rename std.zig.CrossTarget to std.Target.Query

Diffstat:
MCMakeLists.txt | 2+-
Mlib/std/Build.zig | 38+++++++++++++++++++-------------------
Mlib/std/Build/Step/Compile.zig | 1-
Mlib/std/Target.zig | 4+++-
Alib/std/Target/Query.zig | 855+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/std/zig.zig | 3++-
Dlib/std/zig/CrossTarget.zig | 854-------------------------------------------------------------------------------
Mlib/std/zig/system/NativeTargetInfo.zig | 106++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mlib/std/zig/system/darwin/macos.zig | 2+-
Mlib/std/zig/system/linux.zig | 3---
Mlib/std/zig/system/x86.zig | 5++---
Msrc/libc_installation.zig | 2+-
Msrc/main.zig | 74+++++++++++++++++++++++++++++++++++++-------------------------------------
Mtest/cbe.zig | 2+-
Mtest/link/elf.zig | 1-
Mtest/link/glibc_compat/build.zig | 2+-
Mtest/link/link.zig | 1-
Mtest/link/macho.zig | 2--
Mtest/llvm_targets.zig | 2+-
Mtest/src/Cases.zig | 12++++++------
Mtest/src/translate_c.zig | 5++---
Mtest/standalone.zig | 2+-
Mtest/standalone/windows_resources/build.zig | 6+++---
Mtest/tests.zig | 12++++++------
Mtest/translate_c.zig | 5++---
25 files changed, 997 insertions(+), 1004 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -481,6 +481,7 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/start.zig" "${CMAKE_SOURCE_DIR}/lib/std/std.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Target/Query.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target/aarch64.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target/amdgpu.zig" "${CMAKE_SOURCE_DIR}/lib/std/Target/arm.zig" @@ -508,7 +509,6 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/zig.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/Ast.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/AstRlAnnotate.zig" - "${CMAKE_SOURCE_DIR}/lib/std/zig/CrossTarget.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/c_builtins.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/Parse.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/render.zig" diff --git a/lib/std/Build.zig b/lib/std/Build.zig @@ -10,11 +10,11 @@ const log = std.log; const ArrayList = std.ArrayList; const StringHashMap = std.StringHashMap; const Allocator = mem.Allocator; +const Target = std.Target; const process = std.process; const EnvMap = std.process.EnvMap; const fmt_lib = std.fmt; const File = std.fs.File; -const TargetQuery = std.zig.CrossTarget; const Sha256 = std.crypto.hash.sha2.Sha256; const Build = @This(); @@ -375,7 +375,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption const v = @field(args, field.name); const T = @TypeOf(v); switch (T) { - TargetQuery => { + Target.Query => { user_input_options.put(field.name, .{ .name = field.name, .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") }, @@ -1195,9 +1195,9 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio } pub const StandardTargetOptionsArgs = struct { - whitelist: ?[]const TargetQuery = null, + whitelist: ?[]const Target.Query = null, - default_target: TargetQuery = .{}, + default_target: Target.Query = .{}, }; /// Exposes standard `zig build` options for choosing a target and additionally @@ -1208,7 +1208,7 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve } /// Exposes standard `zig build` options for choosing a target. -pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) TargetQuery { +pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) Target.Query { const maybe_triple = self.option( []const u8, "target", @@ -1222,8 +1222,8 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA const triple = maybe_triple orelse "native"; - var diags: TargetQuery.ParseOptions.Diagnostics = .{}; - const selected_target = TargetQuery.parse(.{ + var diags: Target.Query.ParseOptions.Diagnostics = .{}; + const selected_target = Target.Query.parse(.{ .arch_os_abi = triple, .cpu_features = mcpu, .diagnostics = &diags, @@ -1260,7 +1260,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA \\Available operating systems: \\ , .{diags.os_name.?}); - inline for (std.meta.fields(std.Target.Os.Tag)) |field| { + inline for (std.meta.fields(Target.Os.Tag)) |field| { log.err(" {s}", .{field.name}); } self.markInvalidUserInput(); @@ -1279,7 +1279,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA // Make sure it's a match of one of the list. var mismatch_triple = true; var mismatch_cpu_features = true; - var whitelist_item: TargetQuery = .{}; + var whitelist_item: Target.Query = .{}; for (list) |t| { mismatch_cpu_features = true; mismatch_triple = true; @@ -1316,7 +1316,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA var populated_cpu_features = whitelist_cpu.model.features; populated_cpu_features.populateDependencies(all_features); for (all_features, 0..) |feature, i_usize| { - const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize)); + const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); const in_cpu_set = populated_cpu_features.isEnabled(i); if (in_cpu_set) { log.err("{s} ", .{feature.name}); @@ -1324,7 +1324,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA } log.err(" Remove: ", .{}); for (all_features, 0..) |feature, i_usize| { - const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize)); + const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); const in_cpu_set = populated_cpu_features.isEnabled(i); const in_actual_set = selected_cpu.features.isEnabled(i); if (in_actual_set and !in_cpu_set) { @@ -1587,7 +1587,7 @@ pub fn fmt(self: *Build, comptime format: []const u8, args: anytype) []u8 { pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 { // TODO report error for ambiguous situations - const exe_extension = @as(TargetQuery, .{}).exeFileExt(); + const exe_extension = @as(Target.Query, .{}).exeFileExt(); for (self.search_prefixes.items) |search_prefix| { for (names) |name| { if (fs.path.isAbsolute(name)) { @@ -2064,7 +2064,7 @@ pub const InstalledFile = struct { } }; -pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 { +pub fn serializeCpu(allocator: Allocator, cpu: Target.Cpu) ![]const u8 { // TODO this logic can disappear if cpu model + features becomes part of the target triple const all_features = cpu.arch.allFeaturesList(); var populated_cpu_features = cpu.model.features; @@ -2078,7 +2078,7 @@ pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 { try mcpu_buffer.appendSlice(cpu.model.name); for (all_features, 0..) |feature, i_usize| { - const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize)); + const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize)); const in_cpu_set = populated_cpu_features.isEnabled(i); const in_actual_set = cpu.features.isEnabled(i); if (in_cpu_set and !in_actual_set) { @@ -2127,9 +2127,9 @@ pub fn hex64(x: u64) [16]u8 { /// target. The query is kept because the Zig toolchain needs to know which parts /// of the target are "native". This can apply to the CPU, the OS, or even the ABI. pub const ResolvedTarget = struct { - query: TargetQuery, - target: std.Target, - dynamic_linker: std.Target.DynamicLinker, + query: Target.Query, + target: Target, + dynamic_linker: Target.DynamicLinker, pub fn toNativeTargetInfo(self: ResolvedTarget) std.zig.system.NativeTargetInfo { return .{ @@ -2141,7 +2141,7 @@ pub const ResolvedTarget = struct { /// Converts a target query into a fully resolved target that can be passed to /// various parts of the API. -pub fn resolveTargetQuery(b: *Build, query: TargetQuery) ResolvedTarget { +pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { // This context will likely be required in the future when the target is // resolved via a WASI API or via the build protocol. _ = b; @@ -2156,7 +2156,7 @@ pub fn resolveTargetQuery(b: *Build, query: TargetQuery) ResolvedTarget { }; } -pub fn wantSharedLibSymLinks(target: std.Target) bool { +pub fn wantSharedLibSymLinks(target: Target) bool { return target.os.tag != .windows; } diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig @@ -9,7 +9,6 @@ const StringHashMap = std.StringHashMap; const Sha256 = std.crypto.hash.sha2.Sha256; const Allocator = mem.Allocator; const Step = std.Build.Step; -const CrossTarget = std.zig.CrossTarget; const NativeTargetInfo = std.zig.system.NativeTargetInfo; const LazyPath = std.Build.LazyPath; const PkgConfigPkg = std.Build.PkgConfigPkg; diff --git a/lib/std/Target.zig b/lib/std/Target.zig @@ -3,6 +3,8 @@ os: Os, abi: Abi, ofmt: ObjectFormat, +pub const Query = @import("Target/Query.zig"); + pub const Os = struct { tag: Tag, version_range: VersionRange, @@ -1387,7 +1389,7 @@ pub const Cpu = struct { }; pub fn zigTriple(self: Target, allocator: Allocator) ![]u8 { - return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator); + return Query.fromTarget(self).zigTriple(allocator); } pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 { diff --git a/lib/std/Target/Query.zig b/lib/std/Target/Query.zig @@ -0,0 +1,855 @@ +//! 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. This struct does reference +//! any resources and it is copyable. + +/// `null` means native. +cpu_arch: ?Target.Cpu.Arch = null, + +cpu_model: CpuModel = CpuModel.determined_by_cpu_arch, + +/// Sparse set of CPU features to add to the set from `cpu_model`. +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`. +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 default when cross compiling, or native when os_tag is native. +/// If `isGnuLibC()` is `false`, this must be `null` and is ignored. +glibc_version: ?SemanticVersion = null, + +/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI. +abi: ?Target.Abi = null, + +/// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path +/// based on the `os_tag`. +dynamic_linker: DynamicLinker = DynamicLinker{}, + +/// `null` means default for the cpu/arch/os combo. +ofmt: ?Target.ObjectFormat = null, + +pub const CpuModel = union(enum) { + /// Always native + native, + + /// Always baseline + baseline, + + /// If CPU Architecture is native, then the CPU model will be native. Otherwise, + /// it will be baseline. + determined_by_cpu_arch, + + explicit: *const Target.Cpu.Model, +}; + +pub const OsVersion = union(enum) { + none: void, + semver: SemanticVersion, + windows: Target.Os.WindowsVersion, +}; + +pub const SemanticVersion = std.SemanticVersion; + +pub const DynamicLinker = Target.DynamicLinker; + +pub fn fromTarget(target: Target) Query { + var result: Query = .{ + .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: *Query, os: Target.Os) void { + switch (os.tag) { + .freestanding, + .ananas, + .cloudabi, + .fuchsia, + .kfreebsd, + .lv2, + .solaris, + .illumos, + .zos, + .haiku, + .minix, + .rtems, + .nacl, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .ps5, + .elfiamcu, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .hurd, + .wasi, + .emscripten, + .driverkit, + .shadermodel, + .liteos, + .uefi, + .opencl, + .glsl450, + .vulkan, + .plan9, + .other, + => { + self.os_version_min = .{ .none = {} }; + self.os_version_max = .{ .none = {} }; + }, + + .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 }; + }, + } +} + +/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +pub fn toTarget(self: Query) Target { + return .{ + .cpu = self.getCpu(), + .os = self.getOs(), + .abi = self.getAbi(), + .ofmt = self.getObjectFormat(), + }; +} + +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, + + /// Absolute path to dynamic linker, to override the default, which is either a natively + /// detected path, or a standard path. + dynamic_linker: ?[]const u8 = null, + + object_format: ?[]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 name was determined, this will be populated. + os_name: ?[]const u8 = 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) !Query { + var dummy_diags: ParseOptions.Diagnostics = undefined; + const diags = args.diagnostics orelse &dummy_diags; + + var result: Query = .{ + .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; +} + +/// Similar to `parse` except instead of fully parsing, it only determines the CPU +/// architecture and returns it if it can be determined, and returns `null` otherwise. +/// This is intended to be used if the API user of Query needs to learn the +/// target CPU architecture in order to fully populate `ParseOptions`. +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); + } +} + +/// Similar to `SemanticVersion.parse`, but with following changes: +/// * Leading zeroes are allowed. +/// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0. +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 { + 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")); +} + +/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +pub fn getCpu(self: Query) 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; + }, + } +} + +pub fn getCpuArch(self: Query) Target.Cpu.Arch { + return self.cpu_arch orelse builtin.cpu.arch; +} + +pub fn getCpuModel(self: Query) *const Target.Cpu.Model { + return switch (self.cpu_model) { + .explicit => |cpu_model| cpu_model, + else => self.getCpu().model, + }; +} + +pub fn getCpuFeatures(self: Query) Target.Cpu.Feature.Set { + return self.getCpu().features; +} + +/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +pub fn getOs(self: Query) 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; +} + +pub fn getOsTag(self: Query) Target.Os.Tag { + return self.os_tag orelse builtin.os.tag; +} + +/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +pub fn getOsVersionMin(self: Query) OsVersion { + if (self.os_version_min) |version_min| return version_min; + var tmp: Query = undefined; + tmp.updateOsVersionRange(self.getOs()); + return tmp.os_version_min.?; +} + +/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +pub fn getOsVersionMax(self: Query) OsVersion { + if (self.os_version_max) |version_max| return version_max; + var tmp: Query = undefined; + tmp.updateOsVersionRange(self.getOs()); + return tmp.os_version_max.?; +} + +/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. +pub fn getAbi(self: Query) 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()); +} + +pub fn isFreeBSD(self: Query) bool { + return self.getOsTag() == .freebsd; +} + +pub fn isDarwin(self: Query) bool { + return self.getOsTag().isDarwin(); +} + +pub fn isNetBSD(self: Query) bool { + return self.getOsTag() == .netbsd; +} + +pub fn isOpenBSD(self: Query) bool { + return self.getOsTag() == .openbsd; +} + +pub fn isUefi(self: Query) bool { + return self.getOsTag() == .uefi; +} + +pub fn isDragonFlyBSD(self: Query) bool { + return self.getOsTag() == .dragonfly; +} + +pub fn isLinux(self: Query) bool { + return self.getOsTag() == .linux; +} + +pub fn isWindows(self: Query) bool { + return self.getOsTag() == .windows; +} + +pub fn exeFileExt(self: Query) [:0]const u8 { + return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag()); +} + +pub fn staticLibSuffix(self: Query) [:0]const u8 { + return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi()); +} + +pub fn dynamicLibSuffix(self: Query) [:0]const u8 { + return self.getOsTag().dynamicLibSuffix(); +} + +pub fn libPrefix(self: Query) [:0]const u8 { + return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi()); +} + +pub fn isNativeCpu(self: Query) 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(); +} + +pub fn isNativeOs(self: Query) 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; +} + +pub fn isNativeAbi(self: Query) bool { + return self.os_tag == null and self.abi == null; +} + +pub fn isNative(self: Query) bool { + return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi(); +} + +/// Formats a version with the patch component omitted if it is zero, +/// unlike SemanticVersion.format which formats all its version components regardless. +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 }); + } +} + +pub fn zigTriple(self: Query, 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(); +} + +pub fn allocDescription(self: Query, 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: Query, allocator: mem.Allocator) ![]u8 { + return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); +} + +pub fn isGnuLibC(self: Query) bool { + return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi()); +} + +pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void { + assert(self.isGnuLibC()); + self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; +} + +pub fn getObjectFormat(self: Query) Target.ObjectFormat { + return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch()); +} + +pub fn updateCpuFeatures(self: Query, 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: *Query, 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 }; + }, + } +} + +const Query = @This(); +const std = @import("../std.zig"); +const builtin = @import("builtin"); +const assert = std.debug.assert; +const Target = std.Target; +const mem = std.mem; + +test parse { + if (builtin.target.isGnuLibC()) { + var query = try Query.parse(.{}); + query.setGnuLibCVersion(2, 1, 1); + + const text = try query.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 query = try Query.parse(.{ + .arch_os_abi = "aarch64-linux", + .cpu_features = "native", + }); + + try std.testing.expect(query.cpu_arch.? == .aarch64); + try std.testing.expect(query.cpu_model == .native); + } + { + const query = try Query.parse(.{ .arch_os_abi = "native" }); + + try std.testing.expect(query.cpu_arch == null); + try std.testing.expect(query.isNative()); + + const text = try query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + try std.testing.expectEqualSlices(u8, "native", text); + } + { + const query = try Query.parse(.{ + .arch_os_abi = "x86_64-linux-gnu", + .cpu_features = "x86_64-sse-sse2-avx-cx8", + }); + const target = query.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 query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + try std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text); + } + { + const query = try Query.parse(.{ + .arch_os_abi = "arm-linux-musleabihf", + .cpu_features = "generic+v8a", + }); + const target = query.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 query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + try std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text); + } + { + const query = try Query.parse(.{ + .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", + .cpu_features = "generic+v8a", + }); + const target = query.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 query.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); + } +} diff --git a/lib/std/zig.zig b/lib/std/zig.zig @@ -16,7 +16,8 @@ pub const number_literal = @import("zig/number_literal.zig"); pub const primitives = @import("zig/primitives.zig"); pub const Ast = @import("zig/Ast.zig"); pub const system = @import("zig/system.zig"); -pub const CrossTarget = @import("zig/CrossTarget.zig"); +/// Deprecated: use `std.Target.Query`. +pub const CrossTarget = std.Target.Query; pub const BuiltinFn = @import("zig/BuiltinFn.zig"); pub const AstRlAnnotate = @import("zig/AstRlAnnotate.zig"); diff --git a/lib/std/zig/CrossTarget.zig b/lib/std/zig/CrossTarget.zig @@ -1,854 +0,0 @@ -//! 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. -//! This struct does reference any resources and it is copyable. - -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; - -/// `null` means native. -cpu_arch: ?Target.Cpu.Arch = null, - -cpu_model: CpuModel = CpuModel.determined_by_cpu_arch, - -/// Sparse set of CPU features to add to the set from `cpu_model`. -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`. -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 default when cross compiling, or native when os_tag is native. -/// If `isGnuLibC()` is `false`, this must be `null` and is ignored. -glibc_version: ?SemanticVersion = null, - -/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI. -abi: ?Target.Abi = null, - -/// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path -/// based on the `os_tag`. -dynamic_linker: DynamicLinker = DynamicLinker{}, - -/// `null` means default for the cpu/arch/os combo. -ofmt: ?Target.ObjectFormat = null, - -pub const CpuModel = union(enum) { - /// Always native - native, - - /// Always baseline - baseline, - - /// If CPU Architecture is native, then the CPU model will be native. Otherwise, - /// it will be baseline. - determined_by_cpu_arch, - - explicit: *const Target.Cpu.Model, -}; - -pub const OsVersion = union(enum) { - none: void, - semver: SemanticVersion, - windows: Target.Os.WindowsVersion, -}; - -pub const SemanticVersion = std.SemanticVersion; - -pub const DynamicLinker = Target.DynamicLinker; - -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 }; - }, - } -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -pub fn toTarget(self: CrossTarget) Target { - return .{ - .cpu = self.getCpu(), - .os = self.getOs(), - .abi = self.getAbi(), - .ofmt = self.getObjectFormat(), - }; -} - -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, - - /// Absolute path to dynamic linker, to override the default, which is either a natively - /// detected path, or a standard path. - dynamic_linker: ?[]const u8 = null, - - object_format: ?[]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 name was determined, this will be populated. - os_name: ?[]const u8 = 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; - - 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; -} - -/// Similar to `parse` except instead of fully parsing, it only determines the CPU -/// architecture and returns it if it can be determined, and returns `null` otherwise. -/// This is intended to be used if the API user of CrossTarget needs to learn the -/// target CPU architecture in order to fully populate `ParseOptions`. -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); - } -} - -/// Similar to `SemanticVersion.parse`, but with following changes: -/// * Leading zeroes are allowed. -/// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0. -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 { - 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")); -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -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; - }, - } -} - -pub fn getCpuArch(self: CrossTarget) Target.Cpu.Arch { - return self.cpu_arch orelse builtin.cpu.arch; -} - -pub fn getCpuModel(self: CrossTarget) *const Target.Cpu.Model { - return switch (self.cpu_model) { - .explicit => |cpu_model| cpu_model, - else => self.getCpu().model, - }; -} - -pub fn getCpuFeatures(self: CrossTarget) Target.Cpu.Feature.Set { - return self.getCpu().features; -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -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; -} - -pub fn getOsTag(self: CrossTarget) Target.Os.Tag { - return self.os_tag orelse builtin.os.tag; -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -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.?; -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -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.?; -} - -/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`. -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()); -} - -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 isOpenBSD(self: CrossTarget) bool { - return self.getOsTag() == .openbsd; -} - -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 exeFileExt(self: CrossTarget) [:0]const u8 { - return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag()); -} - -pub fn staticLibSuffix(self: CrossTarget) [:0]const u8 { - return Target.staticLibSuffix_os_abi(self.getOsTag(), 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_os_abi(self.getOsTag(), self.getAbi()); -} - -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(); -} - -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; -} - -pub fn isNativeAbi(self: CrossTarget) bool { - return self.os_tag == null and self.abi == null; -} - -pub fn isNative(self: CrossTarget) bool { - return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi(); -} - -/// Formats a version with the patch component omitted if it is zero, -/// unlike SemanticVersion.format which formats all its version components regardless. -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 }); - } -} - -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(); -} - -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); -} - -pub fn linuxTriple(self: CrossTarget, allocator: mem.Allocator) ![]u8 { - return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); -} - -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 = SemanticVersion{ .major = major, .minor = minor, .patch = patch }; -} - -pub fn getObjectFormat(self: CrossTarget) Target.ObjectFormat { - return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch()); -} - -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" { - 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); - } -} diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig @@ -9,7 +9,6 @@ const native_endian = builtin.cpu.arch.endian(); const NativeTargetInfo = @This(); const Target = std.Target; const Allocator = std.mem.Allocator; -const CrossTarget = std.zig.CrossTarget; const windows = std.zig.system.windows; const darwin = std.zig.system.darwin; const linux = std.zig.system.linux; @@ -30,13 +29,14 @@ pub const DetectError = error{ Unexpected, }; -/// Given a `CrossTarget`, which specifies in detail which parts of the target should be detected -/// natively, which should be standard or default, and which are provided explicitly, this function -/// resolves the native components by detecting the native system, and then resolves standard/default parts -/// relative to that. -pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { - var os = cross_target.getOsTag().defaultVersionRange(cross_target.getCpuArch()); - if (cross_target.os_tag == null) { +/// Given a `Target.Query`, which specifies in detail which parts of the +/// target should be detected natively, which should be standard or default, +/// and which are provided explicitly, this function resolves the native +/// components by detecting the native system, and then resolves +/// standard/default parts relative to that. +pub fn detect(query: Target.Query) DetectError!NativeTargetInfo { + var os = query.getOsTag().defaultVersionRange(query.getCpuArch()); + if (query.os_tag == null) { switch (builtin.target.os.tag) { .linux => { const uts = std.os.uname(); @@ -162,45 +162,45 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { } } - if (cross_target.os_version_min) |min| switch (min) { + if (query.os_version_min) |min| switch (min) { .none => {}, - .semver => |semver| switch (cross_target.getOsTag()) { + .semver => |semver| switch (query.getOsTag()) { .linux => os.version_range.linux.range.min = semver, else => os.version_range.semver.min = semver, }, .windows => |win_ver| os.version_range.windows.min = win_ver, }; - if (cross_target.os_version_max) |max| switch (max) { + if (query.os_version_max) |max| switch (max) { .none => {}, - .semver => |semver| switch (cross_target.getOsTag()) { + .semver => |semver| switch (query.getOsTag()) { .linux => os.version_range.linux.range.max = semver, else => os.version_range.semver.max = semver, }, .windows => |win_ver| os.version_range.windows.max = win_ver, }; - if (cross_target.glibc_version) |glibc| { - assert(cross_target.isGnuLibC()); + if (query.glibc_version) |glibc| { + assert(query.isGnuLibC()); os.version_range.linux.glibc = glibc; } // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the // native CPU architecture as being different than the current target), we use this: - const cpu_arch = cross_target.getCpuArch(); + const cpu_arch = query.getCpuArch(); - const cpu = switch (cross_target.cpu_model) { - .native => detectNativeCpuAndFeatures(cpu_arch, os, cross_target), + const cpu = switch (query.cpu_model) { + .native => detectNativeCpuAndFeatures(cpu_arch, os, query), .baseline => Target.Cpu.baseline(cpu_arch), - .determined_by_cpu_arch => if (cross_target.cpu_arch == null) - detectNativeCpuAndFeatures(cpu_arch, os, cross_target) + .determined_by_cpu_arch => if (query.cpu_arch == null) + detectNativeCpuAndFeatures(cpu_arch, os, query) else Target.Cpu.baseline(cpu_arch), .explicit => |model| model.toCpu(cpu_arch), } orelse backup_cpu_detection: { break :backup_cpu_detection Target.Cpu.baseline(cpu_arch); }; - var result = try detectAbiAndDynamicLinker(cpu, os, cross_target); + var result = try detectAbiAndDynamicLinker(cpu, os, query); // For x86, we need to populate some CPU feature flags depending on architecture // and mode: // * 16bit_mode => if the abi is code16 @@ -209,15 +209,15 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { // sets one of them, that takes precedence. switch (cpu_arch) { .x86 => { - if (!std.Target.x86.featureSetHasAny(cross_target.cpu_features_add, .{ + if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{ .@"16bit_mode", .@"32bit_mode", })) { switch (result.target.abi) { .code16 => result.target.cpu.features.addFeature( - @intFromEnum(std.Target.x86.Feature.@"16bit_mode"), + @intFromEnum(Target.x86.Feature.@"16bit_mode"), ), else => result.target.cpu.features.addFeature( - @intFromEnum(std.Target.x86.Feature.@"32bit_mode"), + @intFromEnum(Target.x86.Feature.@"32bit_mode"), ), } } @@ -228,12 +228,12 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { }, .thumb, .thumbeb => { result.target.cpu.features.addFeature( - @intFromEnum(std.Target.arm.Feature.thumb_mode), + @intFromEnum(Target.arm.Feature.thumb_mode), ); }, else => {}, } - cross_target.updateCpuFeatures(&result.target.cpu.features); + query.updateCpuFeatures(&result.target.cpu.features); return result; } @@ -253,22 +253,22 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo { fn detectAbiAndDynamicLinker( cpu: Target.Cpu, os: Target.Os, - cross_target: CrossTarget, + query: Target.Query, ) DetectError!NativeTargetInfo { const native_target_has_ld = comptime builtin.target.hasDynamicLinker(); const is_linux = builtin.target.os.tag == .linux; const is_solarish = builtin.target.os.tag.isSolarish(); - const have_all_info = cross_target.dynamic_linker.get() != null and - cross_target.abi != null and (!is_linux or cross_target.abi.?.isGnu()); - const os_is_non_native = cross_target.os_tag != null; + const have_all_info = query.dynamic_linker.get() != null and + query.abi != null and (!is_linux or query.abi.?.isGnu()); + const os_is_non_native = query.os_tag != null; // The Solaris/illumos environment is always the same. if (!native_target_has_ld or have_all_info or os_is_non_native or is_solarish) { - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); } - if (cross_target.abi) |abi| { + if (query.abi) |abi| { if (abi.isMusl()) { // musl implies static linking. - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); } } // The current target's ABI cannot be relied on for this. For example, we may build the zig @@ -287,7 +287,7 @@ fn detectAbiAndDynamicLinker( }; var ld_info_list_buffer: [all_abis.len]LdInfo = undefined; var ld_info_list_len: usize = 0; - const ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch); + const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch); for (all_abis) |abi| { // This may be a nonsensical parameter. We detect this with @@ -345,7 +345,7 @@ fn detectAbiAndDynamicLinker( error.Unexpected, => |e| { std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); }, else => |e| return e, @@ -363,7 +363,7 @@ fn detectAbiAndDynamicLinker( const line = buffer[0..newline]; if (!mem.startsWith(u8, line, "#!")) break :blk file; var it = mem.tokenizeScalar(u8, line[2..], ' '); - file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, cross_target); + file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, query); file.close(); } }; @@ -373,7 +373,7 @@ fn detectAbiAndDynamicLinker( // trick (block self_exe) won't work. The next thing we fall back to is the same thing, but for elf_file. // TODO: inline this function and combine the buffer we already read above to find // the possible shebang line with the buffer we use for the ELF header. - return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, cross_target) catch |err| switch (err) { + return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, query) catch |err| switch (err) { error.FileSystem, error.SystemResources, error.SymLinkLoop, @@ -393,7 +393,7 @@ fn detectAbiAndDynamicLinker( // Finally, we fall back on the standard path. => |e| { std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)}); - return defaultAbiAndDynamicLinker(cpu, os, cross_target); + return defaultAbiAndDynamicLinker(cpu, os, query); }, }; } @@ -565,7 +565,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion { while (it.next()) |s| { if (mem.startsWith(u8, s, "GLIBC_2.")) { const chopped = s["GLIBC_".len..]; - const ver = CrossTarget.parseVersion(chopped) catch |err| switch (err) { + const ver = Target.Query.parseVersion(chopped) catch |err| switch (err) { error.Overflow => return error.InvalidGnuLibCVersion, error.InvalidVersion => return error.InvalidGnuLibCVersion, }; @@ -588,7 +588,7 @@ fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) error{ Unreco } // chop off "libc-" and ".so" const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len]; - return CrossTarget.parseVersion(link_name_chopped) catch |err| switch (err) { + return Target.Query.parseVersion(link_name_chopped) catch |err| switch (err) { error.Overflow => return error.InvalidGnuLibCVersion, error.InvalidVersion => return error.InvalidGnuLibCVersion, }; @@ -627,7 +627,7 @@ pub fn abiAndDynamicLinkerFromFile( cpu: Target.Cpu, os: Target.Os, ld_info_list: []const LdInfo, - cross_target: CrossTarget, + query: Target.Query, ) AbiAndDynamicLinkerFromFileError!NativeTargetInfo { var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); @@ -655,13 +655,13 @@ pub fn abiAndDynamicLinkerFromFile( .target = .{ .cpu = cpu, .os = os, - .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os), - .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), + .abi = query.abi orelse Target.Abi.default(cpu.arch, os), + .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), }, - .dynamic_linker = cross_target.dynamic_linker, + .dynamic_linker = query.dynamic_linker, }; var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC - const look_for_ld = cross_target.dynamic_linker.get() == null; + const look_for_ld = query.dynamic_linker.get() == null; var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined; if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile; @@ -706,7 +706,7 @@ pub fn abiAndDynamicLinkerFromFile( }, // We only need this for detecting glibc version. elf.PT_DYNAMIC => if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and - cross_target.glibc_version == null) + query.glibc_version == null) { var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset); const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz); @@ -747,7 +747,7 @@ pub fn abiAndDynamicLinkerFromFile( } if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and - cross_target.glibc_version == null) + query.glibc_version == null) { const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx); @@ -927,19 +927,19 @@ fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize { return i; } -fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, cross_target: CrossTarget) !NativeTargetInfo { +fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) !NativeTargetInfo { const target: Target = .{ .cpu = cpu, .os = os, - .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os), - .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), + .abi = query.abi orelse Target.Abi.default(cpu.arch, os), + .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), }; return NativeTargetInfo{ .target = target, - .dynamic_linker = if (cross_target.dynamic_linker.get() == null) + .dynamic_linker = if (query.dynamic_linker.get() == null) target.standardDynamicLinkerPath() else - cross_target.dynamic_linker, + query.dynamic_linker, }; } @@ -964,13 +964,13 @@ pub fn elfInt(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @ } } -fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) ?Target.Cpu { +fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu { // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`, // although it is a runtime value, is guaranteed to be one of the architectures in the set // of the respective switch prong. switch (builtin.cpu.arch) { .x86_64, .x86 => { - return @import("x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, cross_target); + return @import("x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, query); }, else => {}, } diff --git a/lib/std/zig/system/darwin/macos.zig b/lib/std/zig/system/darwin/macos.zig @@ -87,7 +87,7 @@ fn parseSystemVersion(buf: []const u8) !std.SemanticVersion { const ver = try svt.expectContent(); try svt.skipUntilTag(.end, "string"); - return try std.zig.CrossTarget.parseVersion(ver); + return try std.Target.Query.parseVersion(ver); } const SystemVersionTokenizer = struct { diff --git a/lib/std/zig/system/linux.zig b/lib/std/zig/system/linux.zig @@ -5,10 +5,7 @@ const io = std.io; const fs = std.fs; const fmt = std.fmt; const testing = std.testing; - const Target = std.Target; -const CrossTarget = std.zig.CrossTarget; - const assert = std.debug.assert; const SparcCpuinfoImpl = struct { diff --git a/lib/std/zig/system/x86.zig b/lib/std/zig/system/x86.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const Target = std.Target; -const CrossTarget = std.zig.CrossTarget; const XCR0_XMM = 0x02; const XCR0_YMM = 0x04; @@ -23,8 +22,8 @@ inline fn hasMask(input: u32, mask: u32) bool { return (input & mask) == mask; } -pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) Target.Cpu { - _ = cross_target; +pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) Target.Cpu { + _ = query; var cpu = Target.Cpu{ .arch = arch, .model = Target.Cpu.Model.generic(arch), diff --git a/src/libc_installation.zig b/src/libc_installation.zig @@ -41,7 +41,7 @@ pub const LibCInstallation = struct { pub fn parse( allocator: Allocator, libc_file: []const u8, - target: std.zig.CrossTarget, + target: std.Target.Query, ) !LibCInstallation { var self: LibCInstallation = .{}; diff --git a/src/main.zig b/src/main.zig @@ -2551,7 +2551,7 @@ fn buildOutputType( } }; - var target_parse_options: std.zig.CrossTarget.ParseOptions = .{ + var target_parse_options: std.Target.Query.ParseOptions = .{ .arch_os_abi = target_arch_os_abi, .cpu_features = target_mcpu, .dynamic_linker = target_dynamic_linker, @@ -2563,7 +2563,7 @@ fn buildOutputType( if (llvm_m_args.items.len != 0) { // If this returns null, we let it fall through to the case below which will // run the full parse function and do proper error handling. - if (std.zig.CrossTarget.parseCpuArch(target_parse_options)) |cpu_arch| { + if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| { var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa); defer llvm_to_zig_name.deinit(); @@ -2607,8 +2607,8 @@ fn buildOutputType( } } - const cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options); - const target_info = try detectNativeTargetInfo(cross_target); + const target_query = try parseTargetQueryOrReportFatalError(arena, target_parse_options); + const target_info = try detectNativeTargetInfo(target_query); if (target_info.target.os.tag != .freestanding) { if (ensure_libc_on_non_freestanding) @@ -2695,13 +2695,13 @@ fn buildOutputType( } if (use_lld) |opt| { - if (opt and cross_target.isDarwin()) { + if (opt and target_query.isDarwin()) { fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{}); } } if (want_lto) |opt| { - if (opt and cross_target.isDarwin()) { + if (opt and target_query.isDarwin()) { fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{}); } } @@ -2771,7 +2771,7 @@ fn buildOutputType( var libc_installation: ?LibCInstallation = null; if (libc_paths_file) |paths_file| { - libc_installation = LibCInstallation.parse(arena, paths_file, cross_target) catch |err| { + libc_installation = LibCInstallation.parse(arena, paths_file, target_query) catch |err| { fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) }); }; } @@ -2835,7 +2835,7 @@ fn buildOutputType( // After this point, external_system_libs is used instead of system_libs. // Trigger native system library path detection if necessary. - if (sysroot == null and cross_target.isNativeOs() and cross_target.isNativeAbi() and + if (sysroot == null and target_query.isNativeOs() and target_query.isNativeAbi() and (external_system_libs.len != 0 or want_native_include_dirs)) { const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| { @@ -2864,7 +2864,7 @@ fn buildOutputType( libc_installation = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true, - .target = cross_target.toTarget(), + .target = target_query.toTarget(), }); try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? }); @@ -3455,8 +3455,8 @@ fn buildOutputType( .global_cache_directory = global_cache_directory, .root_name = root_name, .target = target_info.target, - .is_native_os = cross_target.isNativeOs(), - .is_native_abi = cross_target.isNativeAbi(), + .is_native_os = target_query.isNativeOs(), + .is_native_abi = target_query.isNativeAbi(), .dynamic_linker = target_info.dynamic_linker.get(), .sysroot = sysroot, .output_mode = output_mode, @@ -4013,16 +4013,16 @@ const ModuleDepIterator = struct { } }; -fn parseCrossTargetOrReportFatalError( +fn parseTargetQueryOrReportFatalError( allocator: Allocator, - opts: std.zig.CrossTarget.ParseOptions, -) !std.zig.CrossTarget { + opts: std.Target.Query.ParseOptions, +) !std.Target.Query { var opts_with_diags = opts; - var diags: std.zig.CrossTarget.ParseOptions.Diagnostics = .{}; + var diags: std.Target.Query.ParseOptions.Diagnostics = .{}; if (opts_with_diags.diagnostics == null) { opts_with_diags.diagnostics = &diags; } - return std.zig.CrossTarget.parse(opts_with_diags) catch |err| switch (err) { + return std.Target.Query.parse(opts_with_diags) catch |err| switch (err) { error.UnknownCpuModel => { help: { var help_text = std.ArrayList(u8).init(allocator); @@ -4666,9 +4666,9 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: while (true) { switch (cur_includes) { .any, .msvc => { - const cross_target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "native-windows-msvc" }) catch unreachable; - const target = cross_target.toTarget(); - const is_native_abi = cross_target.isNativeAbi(); + const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-msvc" }) catch unreachable; + const target = target_query.toTarget(); + const is_native_abi = target_query.isNativeAbi(); const detected_libc = Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null) catch |err| { if (cur_includes == .any) { // fall back to mingw @@ -4691,9 +4691,9 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes: }; }, .gnu => { - const cross_target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "native-windows-gnu" }) catch unreachable; - const target = cross_target.toTarget(); - const is_native_abi = cross_target.isNativeAbi(); + const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-gnu" }) catch unreachable; + const target = target_query.toTarget(); + const is_native_abi = target_query.isNativeAbi(); const detected_libc = try Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null); return .{ .include_paths = detected_libc.libc_include_dir_list, @@ -4754,7 +4754,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { } } - const cross_target = try parseCrossTargetOrReportFatalError(gpa, .{ + const target_query = try parseTargetQueryOrReportFatalError(gpa, .{ .arch_os_abi = target_arch_os_abi, }); @@ -4766,7 +4766,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { const libc_installation: ?*LibCInstallation = libc: { if (input_file) |libc_file| { const libc = try arena.create(LibCInstallation); - libc.* = LibCInstallation.parse(arena, libc_file, cross_target) catch |err| { + libc.* = LibCInstallation.parse(arena, libc_file, target_query) catch |err| { fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); }; break :libc libc; @@ -4781,8 +4781,8 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { }; defer zig_lib_directory.handle.close(); - const target = cross_target.toTarget(); - const is_native_abi = cross_target.isNativeAbi(); + const target = target_query.toTarget(); + const is_native_abi = target_query.isNativeAbi(); const libc_dirs = Compilation.detectLibCIncludeDirs( arena, @@ -4812,15 +4812,15 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void { } if (input_file) |libc_file| { - var libc = LibCInstallation.parse(gpa, libc_file, cross_target) catch |err| { + var libc = LibCInstallation.parse(gpa, libc_file, target_query) catch |err| { fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) }); }; defer libc.deinit(gpa); } else { - if (!cross_target.isNative()) { + if (!target_query.isNative()) { fatal("unable to detect libc for non-native target", .{}); } - const target_info = try detectNativeTargetInfo(cross_target); + const target_info = try detectNativeTargetInfo(target_query); var libc = LibCInstallation.findNative(.{ .allocator = gpa, @@ -5113,8 +5113,8 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi gimmeMoreOfThoseSweetSweetFileDescriptors(); - const cross_target: std.zig.CrossTarget = .{}; - const target_info = try detectNativeTargetInfo(cross_target); + const target_query: std.Target.Query = .{}; + const target_info = try detectNativeTargetInfo(target_query); const exe_basename = try std.zig.binNameAlloc(arena, .{ .root_name = "build", @@ -5283,8 +5283,8 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .global_cache_directory = global_cache_directory, .root_name = "build", .target = target_info.target, - .is_native_os = cross_target.isNativeOs(), - .is_native_abi = cross_target.isNativeAbi(), + .is_native_os = target_query.isNativeOs(), + .is_native_abi = target_query.isNativeAbi(), .dynamic_linker = target_info.dynamic_linker.get(), .output_mode = .Exe, .main_mod = &main_mod, @@ -6269,8 +6269,8 @@ test "fds" { gimmeMoreOfThoseSweetSweetFileDescriptors(); } -fn detectNativeTargetInfo(cross_target: std.zig.CrossTarget) !std.zig.system.NativeTargetInfo { - return std.zig.system.NativeTargetInfo.detect(cross_target); +fn detectNativeTargetInfo(target_query: std.Target.Query) !std.zig.system.NativeTargetInfo { + return std.zig.system.NativeTargetInfo.detect(target_query); } const usage_ast_check = @@ -6672,8 +6672,8 @@ fn warnAboutForeignBinaries( target_info: *const std.zig.system.NativeTargetInfo, link_libc: bool, ) !void { - const host_cross_target: std.zig.CrossTarget = .{}; - const host_target_info = try detectNativeTargetInfo(host_cross_target); + const host_query: std.Target.Query = .{}; + const host_target_info = try detectNativeTargetInfo(host_query); switch (host_target_info.getExternalExecutor(target_info, .{ .link_libc = link_libc })) { .native => return, diff --git a/test/cbe.zig b/test/cbe.zig @@ -5,7 +5,7 @@ const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; pub fn addCases(ctx: *Cases, b: *std.Build) !void { // These tests should work with all platforms, but we're using linux_x64 for // now for consistency. Will be expanded eventually. - const linux_x64: std.zig.CrossTarget = .{ + const linux_x64: std.Target.Query = .{ .cpu_arch = .x86_64, .os_tag = .linux, }; diff --git a/test/link/elf.zig b/test/link/elf.zig @@ -3833,7 +3833,6 @@ const link = @import("link.zig"); const std = @import("std"); const Build = std.Build; -const CrossTarget = std.zig.CrossTarget; const Options = link.Options; const Step = Build.Step; const WriteFile = Step.WriteFile; diff --git a/test/link/glibc_compat/build.zig b/test/link/glibc_compat/build.zig @@ -8,7 +8,7 @@ pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = t, .root_source_file = .{ .path = "main.c" }, - .target = b.resolveTargetQuery(std.zig.CrossTarget.parse( + .target = b.resolveTargetQuery(std.Target.Query.parse( .{ .arch_os_abi = t }, ) catch unreachable), }); diff --git a/test/link/link.zig b/test/link/link.zig @@ -199,7 +199,6 @@ const std = @import("std"); const Build = std.Build; const Compile = Step.Compile; -const CrossTarget = std.zig.CrossTarget; const Run = Step.Run; const Step = Build.Step; const WriteFile = Step.WriteFile; diff --git a/test/link/macho.zig b/test/link/macho.zig @@ -95,7 +95,5 @@ const addExecutable = link.addExecutable; const expectLinkErrors = link.expectLinkErrors; const link = @import("link.zig"); const std = @import("std"); - -const CrossTarget = std.zig.CrossTarget; const Options = link.Options; const Step = std.Build.Step; diff --git a/test/llvm_targets.zig b/test/llvm_targets.zig @@ -1,7 +1,7 @@ const std = @import("std"); const Cases = @import("src/Cases.zig"); -const targets = [_]std.zig.CrossTarget{ +const targets = [_]std.Target.Query{ .{ .cpu_arch = .aarch64, .os_tag = .freestanding, .abi = .none }, .{ .cpu_arch = .aarch64, .os_tag = .ios, .abi = .none }, .{ .cpu_arch = .aarch64, .os_tag = .ios, .abi = .simulator }, diff --git a/test/src/Cases.zig b/test/src/Cases.zig @@ -188,7 +188,7 @@ pub fn exe(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Cas return ctx.addExe(name, target); } -pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target_query: std.zig.CrossTarget, b: *std.Build) *Case { +pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target_query: std.Target.Query, b: *std.Build) *Case { var adjusted_query = target_query; adjusted_query.ofmt = .c; ctx.cases.append(Case{ @@ -423,7 +423,7 @@ fn addFromDirInner( var manifest = try TestManifest.parse(ctx.arena, src); const backends = try manifest.getConfigForKeyAlloc(ctx.arena, "backend", Backend); - const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.zig.CrossTarget); + const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.Target.Query); const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); @@ -1160,9 +1160,9 @@ const TestManifest = struct { } fn getDefaultParser(comptime T: type) ParseFn(T) { - if (T == std.zig.CrossTarget) return struct { + if (T == std.Target.Query) return struct { fn parse(str: []const u8) anyerror!T { - return std.zig.CrossTarget.parse(.{ .arch_os_abi = str }); + return std.Target.Query.parse(.{ .arch_os_abi = str }); } }.parse; @@ -1287,7 +1287,7 @@ pub fn main() !void { if (cases.items.len == 0) { const backends = try manifest.getConfigForKeyAlloc(arena, "backend", Backend); - const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.zig.CrossTarget); + const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.Target.Query); const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend); const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool); const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool); @@ -1385,7 +1385,7 @@ pub fn main() !void { return runCases(&ctx, zig_exe_path); } -fn resolveTargetQuery(query: std.zig.CrossTarget) std.Build.ResolvedTarget { +fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget { const result = std.zig.system.NativeTargetInfo.detect(query) catch @panic("unable to resolve target query"); diff --git a/test/src/translate_c.zig b/test/src/translate_c.zig @@ -5,7 +5,6 @@ const ArrayList = std.ArrayList; const fmt = std.fmt; const mem = std.mem; const fs = std.fs; -const CrossTarget = std.zig.CrossTarget; pub const TranslateCContext = struct { b: *std.Build, @@ -18,7 +17,7 @@ pub const TranslateCContext = struct { sources: ArrayList(SourceFile), expected_lines: ArrayList([]const u8), allow_warnings: bool, - target: CrossTarget = .{}, + target: std.Target.Query = .{}, const SourceFile = struct { filename: []const u8, @@ -74,7 +73,7 @@ pub const TranslateCContext = struct { pub fn addWithTarget( self: *TranslateCContext, name: []const u8, - target: CrossTarget, + target: std.Target.Query, source: []const u8, expected_lines: []const []const u8, ) void { diff --git a/test/standalone.zig b/test/standalone.zig @@ -2,7 +2,7 @@ pub const SimpleCase = struct { src_path: []const u8, link_libc: bool = false, all_modes: bool = false, - target: std.zig.CrossTarget = .{}, + target: std.Target.Query = .{}, is_test: bool = false, is_exe: bool = true, /// Run only on this OS. diff --git a/test/standalone/windows_resources/build.zig b/test/standalone/windows_resources/build.zig @@ -4,17 +4,17 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test it"); b.default_step = test_step; - const cross_target = b.resolveTargetQuery(.{ + const target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu, }); add(b, b.host, .any, test_step); - add(b, cross_target, .any, test_step); + add(b, target, .any, test_step); add(b, b.host, .gnu, test_step); - add(b, cross_target, .gnu, test_step); + add(b, target, .gnu, test_step); } fn add( diff --git a/test/tests.zig b/test/tests.zig @@ -21,7 +21,7 @@ pub const CompareOutputContext = @import("src/CompareOutput.zig"); pub const StackTracesContext = @import("src/StackTrace.zig"); const TestTarget = struct { - target: std.zig.CrossTarget = .{}, + target: std.Target.Query = .{}, optimize_mode: std.builtin.OptimizeMode = .Debug, link_libc: ?bool = null, single_threaded: ?bool = null, @@ -145,7 +145,7 @@ const test_targets = blk: { //}, // https://github.com/ziglang/zig/issues/13623 //.{ - // .target = std.zig.CrossTarget.parse(.{ + // .target = std.Target.Query.parse(.{ // .arch_os_abi = "arm-linux-none", // .cpu_features = "generic+v8a", // }) catch unreachable, @@ -286,13 +286,13 @@ const test_targets = blk: { }, .{ - .target = std.zig.CrossTarget.parse(.{ + .target = std.Target.Query.parse(.{ .arch_os_abi = "arm-linux-none", .cpu_features = "generic+v8a", }) catch unreachable, }, .{ - .target = std.zig.CrossTarget.parse(.{ + .target = std.Target.Query.parse(.{ .arch_os_abi = "arm-linux-musleabihf", .cpu_features = "generic+v8a", }) catch unreachable, @@ -300,7 +300,7 @@ const test_targets = blk: { }, // https://github.com/ziglang/zig/issues/3287 //.{ - // .target = std.zig.CrossTarget.parse(.{ + // .target = std.Target.Query.parse(.{ // .arch_os_abi = "arm-linux-gnueabihf", // .cpu_features = "generic+v8a", // }) catch unreachable, @@ -494,7 +494,7 @@ const test_targets = blk: { }; const CAbiTarget = struct { - target: std.zig.CrossTarget = .{}, + target: std.Target.Query = .{}, use_llvm: ?bool = null, use_lld: ?bool = null, pic: ?bool = null, diff --git a/test/translate_c.zig b/test/translate_c.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const tests = @import("tests.zig"); -const CrossTarget = std.zig.CrossTarget; // ******************************************************** // * * @@ -1846,7 +1845,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn foo5(a: [*c]f32) callconv(.Thiscall) void; }); - cases.addWithTarget("Calling convention", CrossTarget.parse(.{ + cases.addWithTarget("Calling convention", std.Target.Query.parse(.{ .arch_os_abi = "arm-linux-none", .cpu_features = "generic+v8_5a", }) catch unreachable, @@ -1857,7 +1856,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void; }); - cases.addWithTarget("Calling convention", CrossTarget.parse(.{ + cases.addWithTarget("Calling convention", std.Target.Query.parse(.{ .arch_os_abi = "aarch64-linux-none", .cpu_features = "generic+v8_5a", }) catch unreachable,