authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-04 12:35:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:18-07:00
log3179f58c414b5e4845b9bf3acdf276fe8e2b88a0
tree23d8f051385f7948aa8c97ece358fdbe35b86803
parent67d48b94d601521e15dd44c8789b1f528d09f10c

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


25 files changed, 997 insertions(+), 1004 deletions(-)

CMakeLists.txt+1-1
......@@ -481,6 +481,7 @@ set(ZIG_STAGE2_SOURCES
481481 "${CMAKE_SOURCE_DIR}/lib/std/start.zig"
482482 "${CMAKE_SOURCE_DIR}/lib/std/std.zig"
483483 "${CMAKE_SOURCE_DIR}/lib/std/Target.zig"
484 "${CMAKE_SOURCE_DIR}/lib/std/Target/Query.zig"
484485 "${CMAKE_SOURCE_DIR}/lib/std/Target/aarch64.zig"
485486 "${CMAKE_SOURCE_DIR}/lib/std/Target/amdgpu.zig"
486487 "${CMAKE_SOURCE_DIR}/lib/std/Target/arm.zig"
......@@ -508,7 +509,6 @@ set(ZIG_STAGE2_SOURCES
508509 "${CMAKE_SOURCE_DIR}/lib/std/zig.zig"
509510 "${CMAKE_SOURCE_DIR}/lib/std/zig/Ast.zig"
510511 "${CMAKE_SOURCE_DIR}/lib/std/zig/AstRlAnnotate.zig"
511 "${CMAKE_SOURCE_DIR}/lib/std/zig/CrossTarget.zig"
512512 "${CMAKE_SOURCE_DIR}/lib/std/zig/c_builtins.zig"
513513 "${CMAKE_SOURCE_DIR}/lib/std/zig/Parse.zig"
514514 "${CMAKE_SOURCE_DIR}/lib/std/zig/render.zig"
lib/std/Build.zig+19-19
......@@ -10,11 +10,11 @@ const log = std.log;
1010const ArrayList = std.ArrayList;
1111const StringHashMap = std.StringHashMap;
1212const Allocator = mem.Allocator;
13const Target = std.Target;
1314const process = std.process;
1415const EnvMap = std.process.EnvMap;
1516const fmt_lib = std.fmt;
1617const File = std.fs.File;
17const TargetQuery = std.zig.CrossTarget;
1818const Sha256 = std.crypto.hash.sha2.Sha256;
1919const Build = @This();
2020
......@@ -375,7 +375,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption
375375 const v = @field(args, field.name);
376376 const T = @TypeOf(v);
377377 switch (T) {
378 TargetQuery => {
378 Target.Query => {
379379 user_input_options.put(field.name, .{
380380 .name = field.name,
381381 .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") },
......@@ -1195,9 +1195,9 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio
11951195}
11961196
11971197pub const StandardTargetOptionsArgs = struct {
1198 whitelist: ?[]const TargetQuery = null,
1198 whitelist: ?[]const Target.Query = null,
11991199
1200 default_target: TargetQuery = .{},
1200 default_target: Target.Query = .{},
12011201};
12021202
12031203/// Exposes standard `zig build` options for choosing a target and additionally
......@@ -1208,7 +1208,7 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve
12081208}
12091209
12101210/// Exposes standard `zig build` options for choosing a target.
1211pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) TargetQuery {
1211pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) Target.Query {
12121212 const maybe_triple = self.option(
12131213 []const u8,
12141214 "target",
......@@ -1222,8 +1222,8 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
12221222
12231223 const triple = maybe_triple orelse "native";
12241224
1225 var diags: TargetQuery.ParseOptions.Diagnostics = .{};
1226 const selected_target = TargetQuery.parse(.{
1225 var diags: Target.Query.ParseOptions.Diagnostics = .{};
1226 const selected_target = Target.Query.parse(.{
12271227 .arch_os_abi = triple,
12281228 .cpu_features = mcpu,
12291229 .diagnostics = &diags,
......@@ -1260,7 +1260,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
12601260 \\Available operating systems:
12611261 \\
12621262 , .{diags.os_name.?});
1263 inline for (std.meta.fields(std.Target.Os.Tag)) |field| {
1263 inline for (std.meta.fields(Target.Os.Tag)) |field| {
12641264 log.err(" {s}", .{field.name});
12651265 }
12661266 self.markInvalidUserInput();
......@@ -1279,7 +1279,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
12791279 // Make sure it's a match of one of the list.
12801280 var mismatch_triple = true;
12811281 var mismatch_cpu_features = true;
1282 var whitelist_item: TargetQuery = .{};
1282 var whitelist_item: Target.Query = .{};
12831283 for (list) |t| {
12841284 mismatch_cpu_features = true;
12851285 mismatch_triple = true;
......@@ -1316,7 +1316,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
13161316 var populated_cpu_features = whitelist_cpu.model.features;
13171317 populated_cpu_features.populateDependencies(all_features);
13181318 for (all_features, 0..) |feature, i_usize| {
1319 const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize));
1319 const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
13201320 const in_cpu_set = populated_cpu_features.isEnabled(i);
13211321 if (in_cpu_set) {
13221322 log.err("{s} ", .{feature.name});
......@@ -1324,7 +1324,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
13241324 }
13251325 log.err(" Remove: ", .{});
13261326 for (all_features, 0..) |feature, i_usize| {
1327 const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize));
1327 const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
13281328 const in_cpu_set = populated_cpu_features.isEnabled(i);
13291329 const in_actual_set = selected_cpu.features.isEnabled(i);
13301330 if (in_actual_set and !in_cpu_set) {
......@@ -1587,7 +1587,7 @@ pub fn fmt(self: *Build, comptime format: []const u8, args: anytype) []u8 {
15871587
15881588pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 {
15891589 // TODO report error for ambiguous situations
1590 const exe_extension = @as(TargetQuery, .{}).exeFileExt();
1590 const exe_extension = @as(Target.Query, .{}).exeFileExt();
15911591 for (self.search_prefixes.items) |search_prefix| {
15921592 for (names) |name| {
15931593 if (fs.path.isAbsolute(name)) {
......@@ -2064,7 +2064,7 @@ pub const InstalledFile = struct {
20642064 }
20652065};
20662066
2067pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 {
2067pub fn serializeCpu(allocator: Allocator, cpu: Target.Cpu) ![]const u8 {
20682068 // TODO this logic can disappear if cpu model + features becomes part of the target triple
20692069 const all_features = cpu.arch.allFeaturesList();
20702070 var populated_cpu_features = cpu.model.features;
......@@ -2078,7 +2078,7 @@ pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 {
20782078 try mcpu_buffer.appendSlice(cpu.model.name);
20792079
20802080 for (all_features, 0..) |feature, i_usize| {
2081 const i = @as(std.Target.Cpu.Feature.Set.Index, @intCast(i_usize));
2081 const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
20822082 const in_cpu_set = populated_cpu_features.isEnabled(i);
20832083 const in_actual_set = cpu.features.isEnabled(i);
20842084 if (in_cpu_set and !in_actual_set) {
......@@ -2127,9 +2127,9 @@ pub fn hex64(x: u64) [16]u8 {
21272127/// target. The query is kept because the Zig toolchain needs to know which parts
21282128/// of the target are "native". This can apply to the CPU, the OS, or even the ABI.
21292129pub const ResolvedTarget = struct {
2130 query: TargetQuery,
2131 target: std.Target,
2132 dynamic_linker: std.Target.DynamicLinker,
2130 query: Target.Query,
2131 target: Target,
2132 dynamic_linker: Target.DynamicLinker,
21332133
21342134 pub fn toNativeTargetInfo(self: ResolvedTarget) std.zig.system.NativeTargetInfo {
21352135 return .{
......@@ -2141,7 +2141,7 @@ pub const ResolvedTarget = struct {
21412141
21422142/// Converts a target query into a fully resolved target that can be passed to
21432143/// various parts of the API.
2144pub fn resolveTargetQuery(b: *Build, query: TargetQuery) ResolvedTarget {
2144pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget {
21452145 // This context will likely be required in the future when the target is
21462146 // resolved via a WASI API or via the build protocol.
21472147 _ = b;
......@@ -2156,7 +2156,7 @@ pub fn resolveTargetQuery(b: *Build, query: TargetQuery) ResolvedTarget {
21562156 };
21572157}
21582158
2159pub fn wantSharedLibSymLinks(target: std.Target) bool {
2159pub fn wantSharedLibSymLinks(target: Target) bool {
21602160 return target.os.tag != .windows;
21612161}
21622162
lib/std/Build/Step/Compile.zig-1
......@@ -9,7 +9,6 @@ const StringHashMap = std.StringHashMap;
99const Sha256 = std.crypto.hash.sha2.Sha256;
1010const Allocator = mem.Allocator;
1111const Step = std.Build.Step;
12const CrossTarget = std.zig.CrossTarget;
1312const NativeTargetInfo = std.zig.system.NativeTargetInfo;
1413const LazyPath = std.Build.LazyPath;
1514const PkgConfigPkg = std.Build.PkgConfigPkg;
lib/std/Target.zig+3-1
......@@ -3,6 +3,8 @@ os: Os,
33abi: Abi,
44ofmt: ObjectFormat,
55
6pub const Query = @import("Target/Query.zig");
7
68pub const Os = struct {
79 tag: Tag,
810 version_range: VersionRange,
......@@ -1387,7 +1389,7 @@ pub const Cpu = struct {
13871389};
13881390
13891391pub fn zigTriple(self: Target, allocator: Allocator) ![]u8 {
1390 return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator);
1392 return Query.fromTarget(self).zigTriple(allocator);
13911393}
13921394
13931395pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
lib/std/Target/Query.zig created+855
......@@ -0,0 +1,855 @@
1//! Contains all the same data as `Target`, additionally introducing the
2//! concept of "the native target". The purpose of this abstraction is to
3//! provide meaningful and unsurprising defaults. This struct does reference
4//! any resources and it is copyable.
5
6/// `null` means native.
7cpu_arch: ?Target.Cpu.Arch = null,
8
9cpu_model: CpuModel = CpuModel.determined_by_cpu_arch,
10
11/// Sparse set of CPU features to add to the set from `cpu_model`.
12cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
13
14/// Sparse set of CPU features to remove from the set from `cpu_model`.
15cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
16
17/// `null` means native.
18os_tag: ?Target.Os.Tag = null,
19
20/// `null` means the default version range for `os_tag`. If `os_tag` is `null` (native)
21/// then `null` for this field means native.
22os_version_min: ?OsVersion = null,
23
24/// When cross compiling, `null` means default (latest known OS version).
25/// When `os_tag` is native, `null` means equal to the native OS version.
26os_version_max: ?OsVersion = null,
27
28/// `null` means default when cross compiling, or native when os_tag is native.
29/// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
30glibc_version: ?SemanticVersion = null,
31
32/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
33abi: ?Target.Abi = null,
34
35/// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path
36/// based on the `os_tag`.
37dynamic_linker: DynamicLinker = DynamicLinker{},
38
39/// `null` means default for the cpu/arch/os combo.
40ofmt: ?Target.ObjectFormat = null,
41
42pub const CpuModel = union(enum) {
43 /// Always native
44 native,
45
46 /// Always baseline
47 baseline,
48
49 /// If CPU Architecture is native, then the CPU model will be native. Otherwise,
50 /// it will be baseline.
51 determined_by_cpu_arch,
52
53 explicit: *const Target.Cpu.Model,
54};
55
56pub const OsVersion = union(enum) {
57 none: void,
58 semver: SemanticVersion,
59 windows: Target.Os.WindowsVersion,
60};
61
62pub const SemanticVersion = std.SemanticVersion;
63
64pub const DynamicLinker = Target.DynamicLinker;
65
66pub fn fromTarget(target: Target) Query {
67 var result: Query = .{
68 .cpu_arch = target.cpu.arch,
69 .cpu_model = .{ .explicit = target.cpu.model },
70 .os_tag = target.os.tag,
71 .os_version_min = undefined,
72 .os_version_max = undefined,
73 .abi = target.abi,
74 .glibc_version = if (target.isGnuLibC())
75 target.os.version_range.linux.glibc
76 else
77 null,
78 };
79 result.updateOsVersionRange(target.os);
80
81 const all_features = target.cpu.arch.allFeaturesList();
82 var cpu_model_set = target.cpu.model.features;
83 cpu_model_set.populateDependencies(all_features);
84 {
85 // The "add" set is the full set with the CPU Model set removed.
86 const add_set = &result.cpu_features_add;
87 add_set.* = target.cpu.features;
88 add_set.removeFeatureSet(cpu_model_set);
89 }
90 {
91 // The "sub" set is the features that are on in CPU Model set and off in the full set.
92 const sub_set = &result.cpu_features_sub;
93 sub_set.* = cpu_model_set;
94 sub_set.removeFeatureSet(target.cpu.features);
95 }
96 return result;
97}
98
99fn updateOsVersionRange(self: *Query, os: Target.Os) void {
100 switch (os.tag) {
101 .freestanding,
102 .ananas,
103 .cloudabi,
104 .fuchsia,
105 .kfreebsd,
106 .lv2,
107 .solaris,
108 .illumos,
109 .zos,
110 .haiku,
111 .minix,
112 .rtems,
113 .nacl,
114 .aix,
115 .cuda,
116 .nvcl,
117 .amdhsa,
118 .ps4,
119 .ps5,
120 .elfiamcu,
121 .mesa3d,
122 .contiki,
123 .amdpal,
124 .hermit,
125 .hurd,
126 .wasi,
127 .emscripten,
128 .driverkit,
129 .shadermodel,
130 .liteos,
131 .uefi,
132 .opencl,
133 .glsl450,
134 .vulkan,
135 .plan9,
136 .other,
137 => {
138 self.os_version_min = .{ .none = {} };
139 self.os_version_max = .{ .none = {} };
140 },
141
142 .freebsd,
143 .macos,
144 .ios,
145 .tvos,
146 .watchos,
147 .netbsd,
148 .openbsd,
149 .dragonfly,
150 => {
151 self.os_version_min = .{ .semver = os.version_range.semver.min };
152 self.os_version_max = .{ .semver = os.version_range.semver.max };
153 },
154
155 .linux => {
156 self.os_version_min = .{ .semver = os.version_range.linux.range.min };
157 self.os_version_max = .{ .semver = os.version_range.linux.range.max };
158 },
159
160 .windows => {
161 self.os_version_min = .{ .windows = os.version_range.windows.min };
162 self.os_version_max = .{ .windows = os.version_range.windows.max };
163 },
164 }
165}
166
167/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
168pub fn toTarget(self: Query) Target {
169 return .{
170 .cpu = self.getCpu(),
171 .os = self.getOs(),
172 .abi = self.getAbi(),
173 .ofmt = self.getObjectFormat(),
174 };
175}
176
177pub const ParseOptions = struct {
178 /// This is sometimes called a "triple". It looks roughly like this:
179 /// riscv64-linux-musl
180 /// The fields are, respectively:
181 /// * CPU Architecture
182 /// * Operating System (and optional version range)
183 /// * C ABI (optional, with optional glibc version)
184 /// The string "native" can be used for CPU architecture as well as Operating System.
185 /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted.
186 arch_os_abi: []const u8 = "native",
187
188 /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e"
189 /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features
190 /// to remove from the set.
191 /// The following special strings are recognized for CPU Model name:
192 /// * "baseline" - The "default" set of CPU features for cross-compiling. A conservative set
193 /// of features that is expected to be supported on most available hardware.
194 /// * "native" - The native CPU model is to be detected when compiling.
195 /// If this field is not provided (`null`), then the value will depend on the
196 /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline".
197 cpu_features: ?[]const u8 = null,
198
199 /// Absolute path to dynamic linker, to override the default, which is either a natively
200 /// detected path, or a standard path.
201 dynamic_linker: ?[]const u8 = null,
202
203 object_format: ?[]const u8 = null,
204
205 /// If this is provided, the function will populate some information about parsing failures,
206 /// so that user-friendly error messages can be delivered.
207 diagnostics: ?*Diagnostics = null,
208
209 pub const Diagnostics = struct {
210 /// If the architecture was determined, this will be populated.
211 arch: ?Target.Cpu.Arch = null,
212
213 /// If the OS name was determined, this will be populated.
214 os_name: ?[]const u8 = null,
215
216 /// If the OS tag was determined, this will be populated.
217 os_tag: ?Target.Os.Tag = null,
218
219 /// If the ABI was determined, this will be populated.
220 abi: ?Target.Abi = null,
221
222 /// If the CPU name was determined, this will be populated.
223 cpu_name: ?[]const u8 = null,
224
225 /// If error.UnknownCpuFeature is returned, this will be populated.
226 unknown_feature_name: ?[]const u8 = null,
227 };
228};
229
230pub fn parse(args: ParseOptions) !Query {
231 var dummy_diags: ParseOptions.Diagnostics = undefined;
232 const diags = args.diagnostics orelse &dummy_diags;
233
234 var result: Query = .{
235 .dynamic_linker = DynamicLinker.init(args.dynamic_linker),
236 };
237
238 var it = mem.splitScalar(u8, args.arch_os_abi, '-');
239 const arch_name = it.first();
240 const arch_is_native = mem.eql(u8, arch_name, "native");
241 if (!arch_is_native) {
242 result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse
243 return error.UnknownArchitecture;
244 }
245 const arch = result.getCpuArch();
246 diags.arch = arch;
247
248 if (it.next()) |os_text| {
249 try parseOs(&result, diags, os_text);
250 } else if (!arch_is_native) {
251 return error.MissingOperatingSystem;
252 }
253
254 const opt_abi_text = it.next();
255 if (opt_abi_text) |abi_text| {
256 var abi_it = mem.splitScalar(u8, abi_text, '.');
257 const abi = std.meta.stringToEnum(Target.Abi, abi_it.first()) orelse
258 return error.UnknownApplicationBinaryInterface;
259 result.abi = abi;
260 diags.abi = abi;
261
262 const abi_ver_text = abi_it.rest();
263 if (abi_it.next() != null) {
264 if (result.isGnuLibC()) {
265 result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
266 error.Overflow => return error.InvalidAbiVersion,
267 error.InvalidVersion => return error.InvalidAbiVersion,
268 };
269 } else {
270 return error.InvalidAbiVersion;
271 }
272 }
273 }
274
275 if (it.next() != null) return error.UnexpectedExtraField;
276
277 if (args.cpu_features) |cpu_features| {
278 const all_features = arch.allFeaturesList();
279 var index: usize = 0;
280 while (index < cpu_features.len and
281 cpu_features[index] != '+' and
282 cpu_features[index] != '-')
283 {
284 index += 1;
285 }
286 const cpu_name = cpu_features[0..index];
287 diags.cpu_name = cpu_name;
288
289 const add_set = &result.cpu_features_add;
290 const sub_set = &result.cpu_features_sub;
291 if (mem.eql(u8, cpu_name, "native")) {
292 result.cpu_model = .native;
293 } else if (mem.eql(u8, cpu_name, "baseline")) {
294 result.cpu_model = .baseline;
295 } else {
296 result.cpu_model = .{ .explicit = try arch.parseCpuModel(cpu_name) };
297 }
298
299 while (index < cpu_features.len) {
300 const op = cpu_features[index];
301 const set = switch (op) {
302 '+' => add_set,
303 '-' => sub_set,
304 else => unreachable,
305 };
306 index += 1;
307 const start = index;
308 while (index < cpu_features.len and
309 cpu_features[index] != '+' and
310 cpu_features[index] != '-')
311 {
312 index += 1;
313 }
314 const feature_name = cpu_features[start..index];
315 for (all_features, 0..) |feature, feat_index_usize| {
316 const feat_index = @as(Target.Cpu.Feature.Set.Index, @intCast(feat_index_usize));
317 if (mem.eql(u8, feature_name, feature.name)) {
318 set.addFeature(feat_index);
319 break;
320 }
321 } else {
322 diags.unknown_feature_name = feature_name;
323 return error.UnknownCpuFeature;
324 }
325 }
326 }
327
328 if (args.object_format) |ofmt_name| {
329 result.ofmt = std.meta.stringToEnum(Target.ObjectFormat, ofmt_name) orelse
330 return error.UnknownObjectFormat;
331 }
332
333 return result;
334}
335
336/// Similar to `parse` except instead of fully parsing, it only determines the CPU
337/// architecture and returns it if it can be determined, and returns `null` otherwise.
338/// This is intended to be used if the API user of Query needs to learn the
339/// target CPU architecture in order to fully populate `ParseOptions`.
340pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch {
341 var it = mem.splitScalar(u8, args.arch_os_abi, '-');
342 const arch_name = it.first();
343 const arch_is_native = mem.eql(u8, arch_name, "native");
344 if (arch_is_native) {
345 return builtin.cpu.arch;
346 } else {
347 return std.meta.stringToEnum(Target.Cpu.Arch, arch_name);
348 }
349}
350
351/// Similar to `SemanticVersion.parse`, but with following changes:
352/// * Leading zeroes are allowed.
353/// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0.
354pub fn parseVersion(ver: []const u8) error{ InvalidVersion, Overflow }!SemanticVersion {
355 const parseVersionComponentFn = (struct {
356 fn parseVersionComponentInner(component: []const u8) error{ InvalidVersion, Overflow }!usize {
357 return std.fmt.parseUnsigned(usize, component, 10) catch |err| switch (err) {
358 error.InvalidCharacter => return error.InvalidVersion,
359 error.Overflow => return error.Overflow,
360 };
361 }
362 }).parseVersionComponentInner;
363 var version_components = mem.splitScalar(u8, ver, '.');
364 const major = version_components.first();
365 const minor = version_components.next() orelse return error.InvalidVersion;
366 const patch = version_components.next() orelse "0";
367 if (version_components.next() != null) return error.InvalidVersion;
368 return .{
369 .major = try parseVersionComponentFn(major),
370 .minor = try parseVersionComponentFn(minor),
371 .patch = try parseVersionComponentFn(patch),
372 };
373}
374
375test parseVersion {
376 try std.testing.expectError(error.InvalidVersion, parseVersion("1"));
377 try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 0 }, try parseVersion("1.2"));
378 try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 3 }, try parseVersion("1.2.3"));
379 try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4"));
380}
381
382/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
383pub fn getCpu(self: Query) Target.Cpu {
384 switch (self.cpu_model) {
385 .native => {
386 // This works when doing `zig build` because Zig generates a build executable using
387 // native CPU model & features. However this will not be accurate otherwise, and
388 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
389 return builtin.cpu;
390 },
391 .baseline => {
392 var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch());
393 self.updateCpuFeatures(&adjusted_baseline.features);
394 return adjusted_baseline;
395 },
396 .determined_by_cpu_arch => if (self.cpu_arch == null) {
397 // This works when doing `zig build` because Zig generates a build executable using
398 // native CPU model & features. However this will not be accurate otherwise, and
399 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
400 return builtin.cpu;
401 } else {
402 var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch());
403 self.updateCpuFeatures(&adjusted_baseline.features);
404 return adjusted_baseline;
405 },
406 .explicit => |model| {
407 var adjusted_model = model.toCpu(self.getCpuArch());
408 self.updateCpuFeatures(&adjusted_model.features);
409 return adjusted_model;
410 },
411 }
412}
413
414pub fn getCpuArch(self: Query) Target.Cpu.Arch {
415 return self.cpu_arch orelse builtin.cpu.arch;
416}
417
418pub fn getCpuModel(self: Query) *const Target.Cpu.Model {
419 return switch (self.cpu_model) {
420 .explicit => |cpu_model| cpu_model,
421 else => self.getCpu().model,
422 };
423}
424
425pub fn getCpuFeatures(self: Query) Target.Cpu.Feature.Set {
426 return self.getCpu().features;
427}
428
429/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
430pub fn getOs(self: Query) Target.Os {
431 // `builtin.os` works when doing `zig build` because Zig generates a build executable using
432 // native OS version range. However this will not be accurate otherwise, and
433 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
434 var adjusted_os = if (self.os_tag) |os_tag| os_tag.defaultVersionRange(self.getCpuArch()) else builtin.os;
435
436 if (self.os_version_min) |min| switch (min) {
437 .none => {},
438 .semver => |semver| switch (self.getOsTag()) {
439 .linux => adjusted_os.version_range.linux.range.min = semver,
440 else => adjusted_os.version_range.semver.min = semver,
441 },
442 .windows => |win_ver| adjusted_os.version_range.windows.min = win_ver,
443 };
444
445 if (self.os_version_max) |max| switch (max) {
446 .none => {},
447 .semver => |semver| switch (self.getOsTag()) {
448 .linux => adjusted_os.version_range.linux.range.max = semver,
449 else => adjusted_os.version_range.semver.max = semver,
450 },
451 .windows => |win_ver| adjusted_os.version_range.windows.max = win_ver,
452 };
453
454 if (self.glibc_version) |glibc| {
455 assert(self.isGnuLibC());
456 adjusted_os.version_range.linux.glibc = glibc;
457 }
458
459 return adjusted_os;
460}
461
462pub fn getOsTag(self: Query) Target.Os.Tag {
463 return self.os_tag orelse builtin.os.tag;
464}
465
466/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
467pub fn getOsVersionMin(self: Query) OsVersion {
468 if (self.os_version_min) |version_min| return version_min;
469 var tmp: Query = undefined;
470 tmp.updateOsVersionRange(self.getOs());
471 return tmp.os_version_min.?;
472}
473
474/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
475pub fn getOsVersionMax(self: Query) OsVersion {
476 if (self.os_version_max) |version_max| return version_max;
477 var tmp: Query = undefined;
478 tmp.updateOsVersionRange(self.getOs());
479 return tmp.os_version_max.?;
480}
481
482/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
483pub fn getAbi(self: Query) Target.Abi {
484 if (self.abi) |abi| return abi;
485
486 if (self.os_tag == null) {
487 // This works when doing `zig build` because Zig generates a build executable using
488 // native CPU model & features. However this will not be accurate otherwise, and
489 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
490 return builtin.abi;
491 }
492
493 return Target.Abi.default(self.getCpuArch(), self.getOs());
494}
495
496pub fn isFreeBSD(self: Query) bool {
497 return self.getOsTag() == .freebsd;
498}
499
500pub fn isDarwin(self: Query) bool {
501 return self.getOsTag().isDarwin();
502}
503
504pub fn isNetBSD(self: Query) bool {
505 return self.getOsTag() == .netbsd;
506}
507
508pub fn isOpenBSD(self: Query) bool {
509 return self.getOsTag() == .openbsd;
510}
511
512pub fn isUefi(self: Query) bool {
513 return self.getOsTag() == .uefi;
514}
515
516pub fn isDragonFlyBSD(self: Query) bool {
517 return self.getOsTag() == .dragonfly;
518}
519
520pub fn isLinux(self: Query) bool {
521 return self.getOsTag() == .linux;
522}
523
524pub fn isWindows(self: Query) bool {
525 return self.getOsTag() == .windows;
526}
527
528pub fn exeFileExt(self: Query) [:0]const u8 {
529 return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag());
530}
531
532pub fn staticLibSuffix(self: Query) [:0]const u8 {
533 return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi());
534}
535
536pub fn dynamicLibSuffix(self: Query) [:0]const u8 {
537 return self.getOsTag().dynamicLibSuffix();
538}
539
540pub fn libPrefix(self: Query) [:0]const u8 {
541 return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi());
542}
543
544pub fn isNativeCpu(self: Query) bool {
545 return self.cpu_arch == null and
546 (self.cpu_model == .native or self.cpu_model == .determined_by_cpu_arch) and
547 self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty();
548}
549
550pub fn isNativeOs(self: Query) bool {
551 return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and
552 self.dynamic_linker.get() == null and self.glibc_version == null;
553}
554
555pub fn isNativeAbi(self: Query) bool {
556 return self.os_tag == null and self.abi == null;
557}
558
559pub fn isNative(self: Query) bool {
560 return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi();
561}
562
563/// Formats a version with the patch component omitted if it is zero,
564/// unlike SemanticVersion.format which formats all its version components regardless.
565fn formatVersion(version: SemanticVersion, writer: anytype) !void {
566 if (version.patch == 0) {
567 try writer.print("{d}.{d}", .{ version.major, version.minor });
568 } else {
569 try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
570 }
571}
572
573pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8 {
574 if (self.isNative()) {
575 return allocator.dupe(u8, "native");
576 }
577
578 const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
579 const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
580
581 var result = std.ArrayList(u8).init(allocator);
582 defer result.deinit();
583
584 try result.writer().print("{s}-{s}", .{ arch_name, os_name });
585
586 // The zig target syntax does not allow specifying a max os version with no min, so
587 // if either are present, we need the min.
588 if (self.os_version_min != null or self.os_version_max != null) {
589 switch (self.getOsVersionMin()) {
590 .none => {},
591 .semver => |v| {
592 try result.writer().writeAll(".");
593 try formatVersion(v, result.writer());
594 },
595 .windows => |v| try result.writer().print("{s}", .{v}),
596 }
597 }
598 if (self.os_version_max) |max| {
599 switch (max) {
600 .none => {},
601 .semver => |v| {
602 try result.writer().writeAll("...");
603 try formatVersion(v, result.writer());
604 },
605 .windows => |v| try result.writer().print("..{s}", .{v}),
606 }
607 }
608
609 if (self.glibc_version) |v| {
610 try result.writer().print("-{s}.", .{@tagName(self.getAbi())});
611 try formatVersion(v, result.writer());
612 } else if (self.abi) |abi| {
613 try result.writer().print("-{s}", .{@tagName(abi)});
614 }
615
616 return result.toOwnedSlice();
617}
618
619pub fn allocDescription(self: Query, allocator: mem.Allocator) ![]u8 {
620 // TODO is there anything else worthy of the description that is not
621 // already captured in the triple?
622 return self.zigTriple(allocator);
623}
624
625pub fn linuxTriple(self: Query, allocator: mem.Allocator) ![]u8 {
626 return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi());
627}
628
629pub fn isGnuLibC(self: Query) bool {
630 return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi());
631}
632
633pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void {
634 assert(self.isGnuLibC());
635 self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch };
636}
637
638pub fn getObjectFormat(self: Query) Target.ObjectFormat {
639 return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch());
640}
641
642pub fn updateCpuFeatures(self: Query, set: *Target.Cpu.Feature.Set) void {
643 set.removeFeatureSet(self.cpu_features_sub);
644 set.addFeatureSet(self.cpu_features_add);
645 set.populateDependencies(self.getCpuArch().allFeaturesList());
646 set.removeFeatureSet(self.cpu_features_sub);
647}
648
649fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !void {
650 var it = mem.splitScalar(u8, text, '.');
651 const os_name = it.first();
652 diags.os_name = os_name;
653 const os_is_native = mem.eql(u8, os_name, "native");
654 if (!os_is_native) {
655 result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse
656 return error.UnknownOperatingSystem;
657 }
658 const tag = result.getOsTag();
659 diags.os_tag = tag;
660
661 const version_text = it.rest();
662 if (it.next() == null) return;
663
664 switch (tag) {
665 .freestanding,
666 .ananas,
667 .cloudabi,
668 .fuchsia,
669 .kfreebsd,
670 .lv2,
671 .solaris,
672 .illumos,
673 .zos,
674 .haiku,
675 .minix,
676 .rtems,
677 .nacl,
678 .aix,
679 .cuda,
680 .nvcl,
681 .amdhsa,
682 .ps4,
683 .ps5,
684 .elfiamcu,
685 .mesa3d,
686 .contiki,
687 .amdpal,
688 .hermit,
689 .hurd,
690 .wasi,
691 .emscripten,
692 .uefi,
693 .opencl,
694 .glsl450,
695 .vulkan,
696 .plan9,
697 .driverkit,
698 .shadermodel,
699 .liteos,
700 .other,
701 => return error.InvalidOperatingSystemVersion,
702
703 .freebsd,
704 .macos,
705 .ios,
706 .tvos,
707 .watchos,
708 .netbsd,
709 .openbsd,
710 .linux,
711 .dragonfly,
712 => {
713 var range_it = mem.splitSequence(u8, version_text, "...");
714
715 const min_text = range_it.next().?;
716 const min_ver = parseVersion(min_text) catch |err| switch (err) {
717 error.Overflow => return error.InvalidOperatingSystemVersion,
718 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
719 };
720 result.os_version_min = .{ .semver = min_ver };
721
722 const max_text = range_it.next() orelse return;
723 const max_ver = parseVersion(max_text) catch |err| switch (err) {
724 error.Overflow => return error.InvalidOperatingSystemVersion,
725 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
726 };
727 result.os_version_max = .{ .semver = max_ver };
728 },
729
730 .windows => {
731 var range_it = mem.splitSequence(u8, version_text, "...");
732
733 const min_text = range_it.first();
734 const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse
735 return error.InvalidOperatingSystemVersion;
736 result.os_version_min = .{ .windows = min_ver };
737
738 const max_text = range_it.next() orelse return;
739 const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse
740 return error.InvalidOperatingSystemVersion;
741 result.os_version_max = .{ .windows = max_ver };
742 },
743 }
744}
745
746const Query = @This();
747const std = @import("../std.zig");
748const builtin = @import("builtin");
749const assert = std.debug.assert;
750const Target = std.Target;
751const mem = std.mem;
752
753test parse {
754 if (builtin.target.isGnuLibC()) {
755 var query = try Query.parse(.{});
756 query.setGnuLibCVersion(2, 1, 1);
757
758 const text = try query.zigTriple(std.testing.allocator);
759 defer std.testing.allocator.free(text);
760
761 var buf: [256]u8 = undefined;
762 const triple = std.fmt.bufPrint(
763 buf[0..],
764 "native-native-{s}.2.1.1",
765 .{@tagName(builtin.abi)},
766 ) catch unreachable;
767
768 try std.testing.expectEqualSlices(u8, triple, text);
769 }
770 {
771 const query = try Query.parse(.{
772 .arch_os_abi = "aarch64-linux",
773 .cpu_features = "native",
774 });
775
776 try std.testing.expect(query.cpu_arch.? == .aarch64);
777 try std.testing.expect(query.cpu_model == .native);
778 }
779 {
780 const query = try Query.parse(.{ .arch_os_abi = "native" });
781
782 try std.testing.expect(query.cpu_arch == null);
783 try std.testing.expect(query.isNative());
784
785 const text = try query.zigTriple(std.testing.allocator);
786 defer std.testing.allocator.free(text);
787 try std.testing.expectEqualSlices(u8, "native", text);
788 }
789 {
790 const query = try Query.parse(.{
791 .arch_os_abi = "x86_64-linux-gnu",
792 .cpu_features = "x86_64-sse-sse2-avx-cx8",
793 });
794 const target = query.toTarget();
795
796 try std.testing.expect(target.os.tag == .linux);
797 try std.testing.expect(target.abi == .gnu);
798 try std.testing.expect(target.cpu.arch == .x86_64);
799 try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse));
800 try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx));
801 try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8));
802 try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov));
803 try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr));
804
805 try std.testing.expect(Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx, .cmov }));
806 try std.testing.expect(!Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx }));
807 try std.testing.expect(Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87 }));
808 try std.testing.expect(!Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87, .sse }));
809
810 const text = try query.zigTriple(std.testing.allocator);
811 defer std.testing.allocator.free(text);
812 try std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text);
813 }
814 {
815 const query = try Query.parse(.{
816 .arch_os_abi = "arm-linux-musleabihf",
817 .cpu_features = "generic+v8a",
818 });
819 const target = query.toTarget();
820
821 try std.testing.expect(target.os.tag == .linux);
822 try std.testing.expect(target.abi == .musleabihf);
823 try std.testing.expect(target.cpu.arch == .arm);
824 try std.testing.expect(target.cpu.model == &Target.arm.cpu.generic);
825 try std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a));
826
827 const text = try query.zigTriple(std.testing.allocator);
828 defer std.testing.allocator.free(text);
829 try std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text);
830 }
831 {
832 const query = try Query.parse(.{
833 .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27",
834 .cpu_features = "generic+v8a",
835 });
836 const target = query.toTarget();
837
838 try std.testing.expect(target.cpu.arch == .aarch64);
839 try std.testing.expect(target.os.tag == .linux);
840 try std.testing.expect(target.os.version_range.linux.range.min.major == 3);
841 try std.testing.expect(target.os.version_range.linux.range.min.minor == 10);
842 try std.testing.expect(target.os.version_range.linux.range.min.patch == 0);
843 try std.testing.expect(target.os.version_range.linux.range.max.major == 4);
844 try std.testing.expect(target.os.version_range.linux.range.max.minor == 4);
845 try std.testing.expect(target.os.version_range.linux.range.max.patch == 1);
846 try std.testing.expect(target.os.version_range.linux.glibc.major == 2);
847 try std.testing.expect(target.os.version_range.linux.glibc.minor == 27);
848 try std.testing.expect(target.os.version_range.linux.glibc.patch == 0);
849 try std.testing.expect(target.abi == .gnu);
850
851 const text = try query.zigTriple(std.testing.allocator);
852 defer std.testing.allocator.free(text);
853 try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text);
854 }
855}
lib/std/zig.zig+2-1
......@@ -16,7 +16,8 @@ pub const number_literal = @import("zig/number_literal.zig");
1616pub const primitives = @import("zig/primitives.zig");
1717pub const Ast = @import("zig/Ast.zig");
1818pub const system = @import("zig/system.zig");
19pub const CrossTarget = @import("zig/CrossTarget.zig");
19/// Deprecated: use `std.Target.Query`.
20pub const CrossTarget = std.Target.Query;
2021pub const BuiltinFn = @import("zig/BuiltinFn.zig");
2122pub const AstRlAnnotate = @import("zig/AstRlAnnotate.zig");
2223
lib/std/zig/CrossTarget.zig deleted-854
......@@ -1,854 +0,0 @@
1//! Contains all the same data as `Target`, additionally introducing the concept of "the native target".
2//! The purpose of this abstraction is to provide meaningful and unsurprising defaults.
3//! This struct does reference any resources and it is copyable.
4
5const CrossTarget = @This();
6const std = @import("../std.zig");
7const builtin = @import("builtin");
8const assert = std.debug.assert;
9const Target = std.Target;
10const mem = std.mem;
11
12/// `null` means native.
13cpu_arch: ?Target.Cpu.Arch = null,
14
15cpu_model: CpuModel = CpuModel.determined_by_cpu_arch,
16
17/// Sparse set of CPU features to add to the set from `cpu_model`.
18cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
19
20/// Sparse set of CPU features to remove from the set from `cpu_model`.
21cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
22
23/// `null` means native.
24os_tag: ?Target.Os.Tag = null,
25
26/// `null` means the default version range for `os_tag`. If `os_tag` is `null` (native)
27/// then `null` for this field means native.
28os_version_min: ?OsVersion = null,
29
30/// When cross compiling, `null` means default (latest known OS version).
31/// When `os_tag` is native, `null` means equal to the native OS version.
32os_version_max: ?OsVersion = null,
33
34/// `null` means default when cross compiling, or native when os_tag is native.
35/// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
36glibc_version: ?SemanticVersion = null,
37
38/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
39abi: ?Target.Abi = null,
40
41/// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path
42/// based on the `os_tag`.
43dynamic_linker: DynamicLinker = DynamicLinker{},
44
45/// `null` means default for the cpu/arch/os combo.
46ofmt: ?Target.ObjectFormat = null,
47
48pub const CpuModel = union(enum) {
49 /// Always native
50 native,
51
52 /// Always baseline
53 baseline,
54
55 /// If CPU Architecture is native, then the CPU model will be native. Otherwise,
56 /// it will be baseline.
57 determined_by_cpu_arch,
58
59 explicit: *const Target.Cpu.Model,
60};
61
62pub const OsVersion = union(enum) {
63 none: void,
64 semver: SemanticVersion,
65 windows: Target.Os.WindowsVersion,
66};
67
68pub const SemanticVersion = std.SemanticVersion;
69
70pub const DynamicLinker = Target.DynamicLinker;
71
72pub fn fromTarget(target: Target) CrossTarget {
73 var result: CrossTarget = .{
74 .cpu_arch = target.cpu.arch,
75 .cpu_model = .{ .explicit = target.cpu.model },
76 .os_tag = target.os.tag,
77 .os_version_min = undefined,
78 .os_version_max = undefined,
79 .abi = target.abi,
80 .glibc_version = if (target.isGnuLibC())
81 target.os.version_range.linux.glibc
82 else
83 null,
84 };
85 result.updateOsVersionRange(target.os);
86
87 const all_features = target.cpu.arch.allFeaturesList();
88 var cpu_model_set = target.cpu.model.features;
89 cpu_model_set.populateDependencies(all_features);
90 {
91 // The "add" set is the full set with the CPU Model set removed.
92 const add_set = &result.cpu_features_add;
93 add_set.* = target.cpu.features;
94 add_set.removeFeatureSet(cpu_model_set);
95 }
96 {
97 // The "sub" set is the features that are on in CPU Model set and off in the full set.
98 const sub_set = &result.cpu_features_sub;
99 sub_set.* = cpu_model_set;
100 sub_set.removeFeatureSet(target.cpu.features);
101 }
102 return result;
103}
104
105fn updateOsVersionRange(self: *CrossTarget, os: Target.Os) void {
106 switch (os.tag) {
107 .freestanding,
108 .ananas,
109 .cloudabi,
110 .fuchsia,
111 .kfreebsd,
112 .lv2,
113 .solaris,
114 .illumos,
115 .zos,
116 .haiku,
117 .minix,
118 .rtems,
119 .nacl,
120 .aix,
121 .cuda,
122 .nvcl,
123 .amdhsa,
124 .ps4,
125 .ps5,
126 .elfiamcu,
127 .mesa3d,
128 .contiki,
129 .amdpal,
130 .hermit,
131 .hurd,
132 .wasi,
133 .emscripten,
134 .driverkit,
135 .shadermodel,
136 .liteos,
137 .uefi,
138 .opencl,
139 .glsl450,
140 .vulkan,
141 .plan9,
142 .other,
143 => {
144 self.os_version_min = .{ .none = {} };
145 self.os_version_max = .{ .none = {} };
146 },
147
148 .freebsd,
149 .macos,
150 .ios,
151 .tvos,
152 .watchos,
153 .netbsd,
154 .openbsd,
155 .dragonfly,
156 => {
157 self.os_version_min = .{ .semver = os.version_range.semver.min };
158 self.os_version_max = .{ .semver = os.version_range.semver.max };
159 },
160
161 .linux => {
162 self.os_version_min = .{ .semver = os.version_range.linux.range.min };
163 self.os_version_max = .{ .semver = os.version_range.linux.range.max };
164 },
165
166 .windows => {
167 self.os_version_min = .{ .windows = os.version_range.windows.min };
168 self.os_version_max = .{ .windows = os.version_range.windows.max };
169 },
170 }
171}
172
173/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
174pub fn toTarget(self: CrossTarget) Target {
175 return .{
176 .cpu = self.getCpu(),
177 .os = self.getOs(),
178 .abi = self.getAbi(),
179 .ofmt = self.getObjectFormat(),
180 };
181}
182
183pub const ParseOptions = struct {
184 /// This is sometimes called a "triple". It looks roughly like this:
185 /// riscv64-linux-musl
186 /// The fields are, respectively:
187 /// * CPU Architecture
188 /// * Operating System (and optional version range)
189 /// * C ABI (optional, with optional glibc version)
190 /// The string "native" can be used for CPU architecture as well as Operating System.
191 /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted.
192 arch_os_abi: []const u8 = "native",
193
194 /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e"
195 /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features
196 /// to remove from the set.
197 /// The following special strings are recognized for CPU Model name:
198 /// * "baseline" - The "default" set of CPU features for cross-compiling. A conservative set
199 /// of features that is expected to be supported on most available hardware.
200 /// * "native" - The native CPU model is to be detected when compiling.
201 /// If this field is not provided (`null`), then the value will depend on the
202 /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline".
203 cpu_features: ?[]const u8 = null,
204
205 /// Absolute path to dynamic linker, to override the default, which is either a natively
206 /// detected path, or a standard path.
207 dynamic_linker: ?[]const u8 = null,
208
209 object_format: ?[]const u8 = null,
210
211 /// If this is provided, the function will populate some information about parsing failures,
212 /// so that user-friendly error messages can be delivered.
213 diagnostics: ?*Diagnostics = null,
214
215 pub const Diagnostics = struct {
216 /// If the architecture was determined, this will be populated.
217 arch: ?Target.Cpu.Arch = null,
218
219 /// If the OS name was determined, this will be populated.
220 os_name: ?[]const u8 = null,
221
222 /// If the OS tag was determined, this will be populated.
223 os_tag: ?Target.Os.Tag = null,
224
225 /// If the ABI was determined, this will be populated.
226 abi: ?Target.Abi = null,
227
228 /// If the CPU name was determined, this will be populated.
229 cpu_name: ?[]const u8 = null,
230
231 /// If error.UnknownCpuFeature is returned, this will be populated.
232 unknown_feature_name: ?[]const u8 = null,
233 };
234};
235
236pub fn parse(args: ParseOptions) !CrossTarget {
237 var dummy_diags: ParseOptions.Diagnostics = undefined;
238 const diags = args.diagnostics orelse &dummy_diags;
239
240 var result: CrossTarget = .{
241 .dynamic_linker = DynamicLinker.init(args.dynamic_linker),
242 };
243
244 var it = mem.splitScalar(u8, args.arch_os_abi, '-');
245 const arch_name = it.first();
246 const arch_is_native = mem.eql(u8, arch_name, "native");
247 if (!arch_is_native) {
248 result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse
249 return error.UnknownArchitecture;
250 }
251 const arch = result.getCpuArch();
252 diags.arch = arch;
253
254 if (it.next()) |os_text| {
255 try parseOs(&result, diags, os_text);
256 } else if (!arch_is_native) {
257 return error.MissingOperatingSystem;
258 }
259
260 const opt_abi_text = it.next();
261 if (opt_abi_text) |abi_text| {
262 var abi_it = mem.splitScalar(u8, abi_text, '.');
263 const abi = std.meta.stringToEnum(Target.Abi, abi_it.first()) orelse
264 return error.UnknownApplicationBinaryInterface;
265 result.abi = abi;
266 diags.abi = abi;
267
268 const abi_ver_text = abi_it.rest();
269 if (abi_it.next() != null) {
270 if (result.isGnuLibC()) {
271 result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
272 error.Overflow => return error.InvalidAbiVersion,
273 error.InvalidVersion => return error.InvalidAbiVersion,
274 };
275 } else {
276 return error.InvalidAbiVersion;
277 }
278 }
279 }
280
281 if (it.next() != null) return error.UnexpectedExtraField;
282
283 if (args.cpu_features) |cpu_features| {
284 const all_features = arch.allFeaturesList();
285 var index: usize = 0;
286 while (index < cpu_features.len and
287 cpu_features[index] != '+' and
288 cpu_features[index] != '-')
289 {
290 index += 1;
291 }
292 const cpu_name = cpu_features[0..index];
293 diags.cpu_name = cpu_name;
294
295 const add_set = &result.cpu_features_add;
296 const sub_set = &result.cpu_features_sub;
297 if (mem.eql(u8, cpu_name, "native")) {
298 result.cpu_model = .native;
299 } else if (mem.eql(u8, cpu_name, "baseline")) {
300 result.cpu_model = .baseline;
301 } else {
302 result.cpu_model = .{ .explicit = try arch.parseCpuModel(cpu_name) };
303 }
304
305 while (index < cpu_features.len) {
306 const op = cpu_features[index];
307 const set = switch (op) {
308 '+' => add_set,
309 '-' => sub_set,
310 else => unreachable,
311 };
312 index += 1;
313 const start = index;
314 while (index < cpu_features.len and
315 cpu_features[index] != '+' and
316 cpu_features[index] != '-')
317 {
318 index += 1;
319 }
320 const feature_name = cpu_features[start..index];
321 for (all_features, 0..) |feature, feat_index_usize| {
322 const feat_index = @as(Target.Cpu.Feature.Set.Index, @intCast(feat_index_usize));
323 if (mem.eql(u8, feature_name, feature.name)) {
324 set.addFeature(feat_index);
325 break;
326 }
327 } else {
328 diags.unknown_feature_name = feature_name;
329 return error.UnknownCpuFeature;
330 }
331 }
332 }
333
334 if (args.object_format) |ofmt_name| {
335 result.ofmt = std.meta.stringToEnum(Target.ObjectFormat, ofmt_name) orelse
336 return error.UnknownObjectFormat;
337 }
338
339 return result;
340}
341
342/// Similar to `parse` except instead of fully parsing, it only determines the CPU
343/// architecture and returns it if it can be determined, and returns `null` otherwise.
344/// This is intended to be used if the API user of CrossTarget needs to learn the
345/// target CPU architecture in order to fully populate `ParseOptions`.
346pub fn parseCpuArch(args: ParseOptions) ?Target.Cpu.Arch {
347 var it = mem.splitScalar(u8, args.arch_os_abi, '-');
348 const arch_name = it.first();
349 const arch_is_native = mem.eql(u8, arch_name, "native");
350 if (arch_is_native) {
351 return builtin.cpu.arch;
352 } else {
353 return std.meta.stringToEnum(Target.Cpu.Arch, arch_name);
354 }
355}
356
357/// Similar to `SemanticVersion.parse`, but with following changes:
358/// * Leading zeroes are allowed.
359/// * Supports only 2 or 3 version components (major, minor, [patch]). If 3-rd component is omitted, it will be 0.
360pub fn parseVersion(ver: []const u8) error{ InvalidVersion, Overflow }!SemanticVersion {
361 const parseVersionComponentFn = (struct {
362 fn parseVersionComponentInner(component: []const u8) error{ InvalidVersion, Overflow }!usize {
363 return std.fmt.parseUnsigned(usize, component, 10) catch |err| switch (err) {
364 error.InvalidCharacter => return error.InvalidVersion,
365 error.Overflow => return error.Overflow,
366 };
367 }
368 }).parseVersionComponentInner;
369 var version_components = mem.splitScalar(u8, ver, '.');
370 const major = version_components.first();
371 const minor = version_components.next() orelse return error.InvalidVersion;
372 const patch = version_components.next() orelse "0";
373 if (version_components.next() != null) return error.InvalidVersion;
374 return .{
375 .major = try parseVersionComponentFn(major),
376 .minor = try parseVersionComponentFn(minor),
377 .patch = try parseVersionComponentFn(patch),
378 };
379}
380
381test parseVersion {
382 try std.testing.expectError(error.InvalidVersion, parseVersion("1"));
383 try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 0 }, try parseVersion("1.2"));
384 try std.testing.expectEqual(SemanticVersion{ .major = 1, .minor = 2, .patch = 3 }, try parseVersion("1.2.3"));
385 try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4"));
386}
387
388/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
389pub fn getCpu(self: CrossTarget) Target.Cpu {
390 switch (self.cpu_model) {
391 .native => {
392 // This works when doing `zig build` because Zig generates a build executable using
393 // native CPU model & features. However this will not be accurate otherwise, and
394 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
395 return builtin.cpu;
396 },
397 .baseline => {
398 var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch());
399 self.updateCpuFeatures(&adjusted_baseline.features);
400 return adjusted_baseline;
401 },
402 .determined_by_cpu_arch => if (self.cpu_arch == null) {
403 // This works when doing `zig build` because Zig generates a build executable using
404 // native CPU model & features. However this will not be accurate otherwise, and
405 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
406 return builtin.cpu;
407 } else {
408 var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch());
409 self.updateCpuFeatures(&adjusted_baseline.features);
410 return adjusted_baseline;
411 },
412 .explicit => |model| {
413 var adjusted_model = model.toCpu(self.getCpuArch());
414 self.updateCpuFeatures(&adjusted_model.features);
415 return adjusted_model;
416 },
417 }
418}
419
420pub fn getCpuArch(self: CrossTarget) Target.Cpu.Arch {
421 return self.cpu_arch orelse builtin.cpu.arch;
422}
423
424pub fn getCpuModel(self: CrossTarget) *const Target.Cpu.Model {
425 return switch (self.cpu_model) {
426 .explicit => |cpu_model| cpu_model,
427 else => self.getCpu().model,
428 };
429}
430
431pub fn getCpuFeatures(self: CrossTarget) Target.Cpu.Feature.Set {
432 return self.getCpu().features;
433}
434
435/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
436pub fn getOs(self: CrossTarget) Target.Os {
437 // `builtin.os` works when doing `zig build` because Zig generates a build executable using
438 // native OS version range. However this will not be accurate otherwise, and
439 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
440 var adjusted_os = if (self.os_tag) |os_tag| os_tag.defaultVersionRange(self.getCpuArch()) else builtin.os;
441
442 if (self.os_version_min) |min| switch (min) {
443 .none => {},
444 .semver => |semver| switch (self.getOsTag()) {
445 .linux => adjusted_os.version_range.linux.range.min = semver,
446 else => adjusted_os.version_range.semver.min = semver,
447 },
448 .windows => |win_ver| adjusted_os.version_range.windows.min = win_ver,
449 };
450
451 if (self.os_version_max) |max| switch (max) {
452 .none => {},
453 .semver => |semver| switch (self.getOsTag()) {
454 .linux => adjusted_os.version_range.linux.range.max = semver,
455 else => adjusted_os.version_range.semver.max = semver,
456 },
457 .windows => |win_ver| adjusted_os.version_range.windows.max = win_ver,
458 };
459
460 if (self.glibc_version) |glibc| {
461 assert(self.isGnuLibC());
462 adjusted_os.version_range.linux.glibc = glibc;
463 }
464
465 return adjusted_os;
466}
467
468pub fn getOsTag(self: CrossTarget) Target.Os.Tag {
469 return self.os_tag orelse builtin.os.tag;
470}
471
472/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
473pub fn getOsVersionMin(self: CrossTarget) OsVersion {
474 if (self.os_version_min) |version_min| return version_min;
475 var tmp: CrossTarget = undefined;
476 tmp.updateOsVersionRange(self.getOs());
477 return tmp.os_version_min.?;
478}
479
480/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
481pub fn getOsVersionMax(self: CrossTarget) OsVersion {
482 if (self.os_version_max) |version_max| return version_max;
483 var tmp: CrossTarget = undefined;
484 tmp.updateOsVersionRange(self.getOs());
485 return tmp.os_version_max.?;
486}
487
488/// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
489pub fn getAbi(self: CrossTarget) Target.Abi {
490 if (self.abi) |abi| return abi;
491
492 if (self.os_tag == null) {
493 // This works when doing `zig build` because Zig generates a build executable using
494 // native CPU model & features. However this will not be accurate otherwise, and
495 // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`.
496 return builtin.abi;
497 }
498
499 return Target.Abi.default(self.getCpuArch(), self.getOs());
500}
501
502pub fn isFreeBSD(self: CrossTarget) bool {
503 return self.getOsTag() == .freebsd;
504}
505
506pub fn isDarwin(self: CrossTarget) bool {
507 return self.getOsTag().isDarwin();
508}
509
510pub fn isNetBSD(self: CrossTarget) bool {
511 return self.getOsTag() == .netbsd;
512}
513
514pub fn isOpenBSD(self: CrossTarget) bool {
515 return self.getOsTag() == .openbsd;
516}
517
518pub fn isUefi(self: CrossTarget) bool {
519 return self.getOsTag() == .uefi;
520}
521
522pub fn isDragonFlyBSD(self: CrossTarget) bool {
523 return self.getOsTag() == .dragonfly;
524}
525
526pub fn isLinux(self: CrossTarget) bool {
527 return self.getOsTag() == .linux;
528}
529
530pub fn isWindows(self: CrossTarget) bool {
531 return self.getOsTag() == .windows;
532}
533
534pub fn exeFileExt(self: CrossTarget) [:0]const u8 {
535 return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag());
536}
537
538pub fn staticLibSuffix(self: CrossTarget) [:0]const u8 {
539 return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi());
540}
541
542pub fn dynamicLibSuffix(self: CrossTarget) [:0]const u8 {
543 return self.getOsTag().dynamicLibSuffix();
544}
545
546pub fn libPrefix(self: CrossTarget) [:0]const u8 {
547 return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi());
548}
549
550pub fn isNativeCpu(self: CrossTarget) bool {
551 return self.cpu_arch == null and
552 (self.cpu_model == .native or self.cpu_model == .determined_by_cpu_arch) and
553 self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty();
554}
555
556pub fn isNativeOs(self: CrossTarget) bool {
557 return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and
558 self.dynamic_linker.get() == null and self.glibc_version == null;
559}
560
561pub fn isNativeAbi(self: CrossTarget) bool {
562 return self.os_tag == null and self.abi == null;
563}
564
565pub fn isNative(self: CrossTarget) bool {
566 return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi();
567}
568
569/// Formats a version with the patch component omitted if it is zero,
570/// unlike SemanticVersion.format which formats all its version components regardless.
571fn formatVersion(version: SemanticVersion, writer: anytype) !void {
572 if (version.patch == 0) {
573 try writer.print("{d}.{d}", .{ version.major, version.minor });
574 } else {
575 try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
576 }
577}
578
579pub fn zigTriple(self: CrossTarget, allocator: mem.Allocator) error{OutOfMemory}![]u8 {
580 if (self.isNative()) {
581 return allocator.dupe(u8, "native");
582 }
583
584 const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
585 const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
586
587 var result = std.ArrayList(u8).init(allocator);
588 defer result.deinit();
589
590 try result.writer().print("{s}-{s}", .{ arch_name, os_name });
591
592 // The zig target syntax does not allow specifying a max os version with no min, so
593 // if either are present, we need the min.
594 if (self.os_version_min != null or self.os_version_max != null) {
595 switch (self.getOsVersionMin()) {
596 .none => {},
597 .semver => |v| {
598 try result.writer().writeAll(".");
599 try formatVersion(v, result.writer());
600 },
601 .windows => |v| try result.writer().print("{s}", .{v}),
602 }
603 }
604 if (self.os_version_max) |max| {
605 switch (max) {
606 .none => {},
607 .semver => |v| {
608 try result.writer().writeAll("...");
609 try formatVersion(v, result.writer());
610 },
611 .windows => |v| try result.writer().print("..{s}", .{v}),
612 }
613 }
614
615 if (self.glibc_version) |v| {
616 try result.writer().print("-{s}.", .{@tagName(self.getAbi())});
617 try formatVersion(v, result.writer());
618 } else if (self.abi) |abi| {
619 try result.writer().print("-{s}", .{@tagName(abi)});
620 }
621
622 return result.toOwnedSlice();
623}
624
625pub fn allocDescription(self: CrossTarget, allocator: mem.Allocator) ![]u8 {
626 // TODO is there anything else worthy of the description that is not
627 // already captured in the triple?
628 return self.zigTriple(allocator);
629}
630
631pub fn linuxTriple(self: CrossTarget, allocator: mem.Allocator) ![]u8 {
632 return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi());
633}
634
635pub fn isGnuLibC(self: CrossTarget) bool {
636 return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi());
637}
638
639pub fn setGnuLibCVersion(self: *CrossTarget, major: u32, minor: u32, patch: u32) void {
640 assert(self.isGnuLibC());
641 self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch };
642}
643
644pub fn getObjectFormat(self: CrossTarget) Target.ObjectFormat {
645 return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch());
646}
647
648pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void {
649 set.removeFeatureSet(self.cpu_features_sub);
650 set.addFeatureSet(self.cpu_features_add);
651 set.populateDependencies(self.getCpuArch().allFeaturesList());
652 set.removeFeatureSet(self.cpu_features_sub);
653}
654
655fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const u8) !void {
656 var it = mem.splitScalar(u8, text, '.');
657 const os_name = it.first();
658 diags.os_name = os_name;
659 const os_is_native = mem.eql(u8, os_name, "native");
660 if (!os_is_native) {
661 result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse
662 return error.UnknownOperatingSystem;
663 }
664 const tag = result.getOsTag();
665 diags.os_tag = tag;
666
667 const version_text = it.rest();
668 if (it.next() == null) return;
669
670 switch (tag) {
671 .freestanding,
672 .ananas,
673 .cloudabi,
674 .fuchsia,
675 .kfreebsd,
676 .lv2,
677 .solaris,
678 .illumos,
679 .zos,
680 .haiku,
681 .minix,
682 .rtems,
683 .nacl,
684 .aix,
685 .cuda,
686 .nvcl,
687 .amdhsa,
688 .ps4,
689 .ps5,
690 .elfiamcu,
691 .mesa3d,
692 .contiki,
693 .amdpal,
694 .hermit,
695 .hurd,
696 .wasi,
697 .emscripten,
698 .uefi,
699 .opencl,
700 .glsl450,
701 .vulkan,
702 .plan9,
703 .driverkit,
704 .shadermodel,
705 .liteos,
706 .other,
707 => return error.InvalidOperatingSystemVersion,
708
709 .freebsd,
710 .macos,
711 .ios,
712 .tvos,
713 .watchos,
714 .netbsd,
715 .openbsd,
716 .linux,
717 .dragonfly,
718 => {
719 var range_it = mem.splitSequence(u8, version_text, "...");
720
721 const min_text = range_it.next().?;
722 const min_ver = parseVersion(min_text) catch |err| switch (err) {
723 error.Overflow => return error.InvalidOperatingSystemVersion,
724 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
725 };
726 result.os_version_min = .{ .semver = min_ver };
727
728 const max_text = range_it.next() orelse return;
729 const max_ver = parseVersion(max_text) catch |err| switch (err) {
730 error.Overflow => return error.InvalidOperatingSystemVersion,
731 error.InvalidVersion => return error.InvalidOperatingSystemVersion,
732 };
733 result.os_version_max = .{ .semver = max_ver };
734 },
735
736 .windows => {
737 var range_it = mem.splitSequence(u8, version_text, "...");
738
739 const min_text = range_it.first();
740 const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse
741 return error.InvalidOperatingSystemVersion;
742 result.os_version_min = .{ .windows = min_ver };
743
744 const max_text = range_it.next() orelse return;
745 const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse
746 return error.InvalidOperatingSystemVersion;
747 result.os_version_max = .{ .windows = max_ver };
748 },
749 }
750}
751
752test "CrossTarget.parse" {
753 if (builtin.target.isGnuLibC()) {
754 var cross_target = try CrossTarget.parse(.{});
755 cross_target.setGnuLibCVersion(2, 1, 1);
756
757 const text = try cross_target.zigTriple(std.testing.allocator);
758 defer std.testing.allocator.free(text);
759
760 var buf: [256]u8 = undefined;
761 const triple = std.fmt.bufPrint(
762 buf[0..],
763 "native-native-{s}.2.1.1",
764 .{@tagName(builtin.abi)},
765 ) catch unreachable;
766
767 try std.testing.expectEqualSlices(u8, triple, text);
768 }
769 {
770 const cross_target = try CrossTarget.parse(.{
771 .arch_os_abi = "aarch64-linux",
772 .cpu_features = "native",
773 });
774
775 try std.testing.expect(cross_target.cpu_arch.? == .aarch64);
776 try std.testing.expect(cross_target.cpu_model == .native);
777 }
778 {
779 const cross_target = try CrossTarget.parse(.{ .arch_os_abi = "native" });
780
781 try std.testing.expect(cross_target.cpu_arch == null);
782 try std.testing.expect(cross_target.isNative());
783
784 const text = try cross_target.zigTriple(std.testing.allocator);
785 defer std.testing.allocator.free(text);
786 try std.testing.expectEqualSlices(u8, "native", text);
787 }
788 {
789 const cross_target = try CrossTarget.parse(.{
790 .arch_os_abi = "x86_64-linux-gnu",
791 .cpu_features = "x86_64-sse-sse2-avx-cx8",
792 });
793 const target = cross_target.toTarget();
794
795 try std.testing.expect(target.os.tag == .linux);
796 try std.testing.expect(target.abi == .gnu);
797 try std.testing.expect(target.cpu.arch == .x86_64);
798 try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse));
799 try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx));
800 try std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8));
801 try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov));
802 try std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr));
803
804 try std.testing.expect(Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx, .cmov }));
805 try std.testing.expect(!Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx }));
806 try std.testing.expect(Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87 }));
807 try std.testing.expect(!Target.x86.featureSetHasAll(target.cpu.features, .{ .mmx, .x87, .sse }));
808
809 const text = try cross_target.zigTriple(std.testing.allocator);
810 defer std.testing.allocator.free(text);
811 try std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text);
812 }
813 {
814 const cross_target = try CrossTarget.parse(.{
815 .arch_os_abi = "arm-linux-musleabihf",
816 .cpu_features = "generic+v8a",
817 });
818 const target = cross_target.toTarget();
819
820 try std.testing.expect(target.os.tag == .linux);
821 try std.testing.expect(target.abi == .musleabihf);
822 try std.testing.expect(target.cpu.arch == .arm);
823 try std.testing.expect(target.cpu.model == &Target.arm.cpu.generic);
824 try std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a));
825
826 const text = try cross_target.zigTriple(std.testing.allocator);
827 defer std.testing.allocator.free(text);
828 try std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text);
829 }
830 {
831 const cross_target = try CrossTarget.parse(.{
832 .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27",
833 .cpu_features = "generic+v8a",
834 });
835 const target = cross_target.toTarget();
836
837 try std.testing.expect(target.cpu.arch == .aarch64);
838 try std.testing.expect(target.os.tag == .linux);
839 try std.testing.expect(target.os.version_range.linux.range.min.major == 3);
840 try std.testing.expect(target.os.version_range.linux.range.min.minor == 10);
841 try std.testing.expect(target.os.version_range.linux.range.min.patch == 0);
842 try std.testing.expect(target.os.version_range.linux.range.max.major == 4);
843 try std.testing.expect(target.os.version_range.linux.range.max.minor == 4);
844 try std.testing.expect(target.os.version_range.linux.range.max.patch == 1);
845 try std.testing.expect(target.os.version_range.linux.glibc.major == 2);
846 try std.testing.expect(target.os.version_range.linux.glibc.minor == 27);
847 try std.testing.expect(target.os.version_range.linux.glibc.patch == 0);
848 try std.testing.expect(target.abi == .gnu);
849
850 const text = try cross_target.zigTriple(std.testing.allocator);
851 defer std.testing.allocator.free(text);
852 try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text);
853 }
854}
lib/std/zig/system/NativeTargetInfo.zig+53-53
......@@ -9,7 +9,6 @@ const native_endian = builtin.cpu.arch.endian();
99const NativeTargetInfo = @This();
1010const Target = std.Target;
1111const Allocator = std.mem.Allocator;
12const CrossTarget = std.zig.CrossTarget;
1312const windows = std.zig.system.windows;
1413const darwin = std.zig.system.darwin;
1514const linux = std.zig.system.linux;
......@@ -30,13 +29,14 @@ pub const DetectError = error{
3029 Unexpected,
3130};
3231
33/// Given a `CrossTarget`, which specifies in detail which parts of the target should be detected
34/// natively, which should be standard or default, and which are provided explicitly, this function
35/// resolves the native components by detecting the native system, and then resolves standard/default parts
36/// relative to that.
37pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
38 var os = cross_target.getOsTag().defaultVersionRange(cross_target.getCpuArch());
39 if (cross_target.os_tag == null) {
32/// Given a `Target.Query`, which specifies in detail which parts of the
33/// target should be detected natively, which should be standard or default,
34/// and which are provided explicitly, this function resolves the native
35/// components by detecting the native system, and then resolves
36/// standard/default parts relative to that.
37pub fn detect(query: Target.Query) DetectError!NativeTargetInfo {
38 var os = query.getOsTag().defaultVersionRange(query.getCpuArch());
39 if (query.os_tag == null) {
4040 switch (builtin.target.os.tag) {
4141 .linux => {
4242 const uts = std.os.uname();
......@@ -162,45 +162,45 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
162162 }
163163 }
164164
165 if (cross_target.os_version_min) |min| switch (min) {
165 if (query.os_version_min) |min| switch (min) {
166166 .none => {},
167 .semver => |semver| switch (cross_target.getOsTag()) {
167 .semver => |semver| switch (query.getOsTag()) {
168168 .linux => os.version_range.linux.range.min = semver,
169169 else => os.version_range.semver.min = semver,
170170 },
171171 .windows => |win_ver| os.version_range.windows.min = win_ver,
172172 };
173173
174 if (cross_target.os_version_max) |max| switch (max) {
174 if (query.os_version_max) |max| switch (max) {
175175 .none => {},
176 .semver => |semver| switch (cross_target.getOsTag()) {
176 .semver => |semver| switch (query.getOsTag()) {
177177 .linux => os.version_range.linux.range.max = semver,
178178 else => os.version_range.semver.max = semver,
179179 },
180180 .windows => |win_ver| os.version_range.windows.max = win_ver,
181181 };
182182
183 if (cross_target.glibc_version) |glibc| {
184 assert(cross_target.isGnuLibC());
183 if (query.glibc_version) |glibc| {
184 assert(query.isGnuLibC());
185185 os.version_range.linux.glibc = glibc;
186186 }
187187
188188 // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the
189189 // native CPU architecture as being different than the current target), we use this:
190 const cpu_arch = cross_target.getCpuArch();
190 const cpu_arch = query.getCpuArch();
191191
192 const cpu = switch (cross_target.cpu_model) {
193 .native => detectNativeCpuAndFeatures(cpu_arch, os, cross_target),
192 const cpu = switch (query.cpu_model) {
193 .native => detectNativeCpuAndFeatures(cpu_arch, os, query),
194194 .baseline => Target.Cpu.baseline(cpu_arch),
195 .determined_by_cpu_arch => if (cross_target.cpu_arch == null)
196 detectNativeCpuAndFeatures(cpu_arch, os, cross_target)
195 .determined_by_cpu_arch => if (query.cpu_arch == null)
196 detectNativeCpuAndFeatures(cpu_arch, os, query)
197197 else
198198 Target.Cpu.baseline(cpu_arch),
199199 .explicit => |model| model.toCpu(cpu_arch),
200200 } orelse backup_cpu_detection: {
201201 break :backup_cpu_detection Target.Cpu.baseline(cpu_arch);
202202 };
203 var result = try detectAbiAndDynamicLinker(cpu, os, cross_target);
203 var result = try detectAbiAndDynamicLinker(cpu, os, query);
204204 // For x86, we need to populate some CPU feature flags depending on architecture
205205 // and mode:
206206 // * 16bit_mode => if the abi is code16
......@@ -209,15 +209,15 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
209209 // sets one of them, that takes precedence.
210210 switch (cpu_arch) {
211211 .x86 => {
212 if (!std.Target.x86.featureSetHasAny(cross_target.cpu_features_add, .{
212 if (!Target.x86.featureSetHasAny(query.cpu_features_add, .{
213213 .@"16bit_mode", .@"32bit_mode",
214214 })) {
215215 switch (result.target.abi) {
216216 .code16 => result.target.cpu.features.addFeature(
217 @intFromEnum(std.Target.x86.Feature.@"16bit_mode"),
217 @intFromEnum(Target.x86.Feature.@"16bit_mode"),
218218 ),
219219 else => result.target.cpu.features.addFeature(
220 @intFromEnum(std.Target.x86.Feature.@"32bit_mode"),
220 @intFromEnum(Target.x86.Feature.@"32bit_mode"),
221221 ),
222222 }
223223 }
......@@ -228,12 +228,12 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
228228 },
229229 .thumb, .thumbeb => {
230230 result.target.cpu.features.addFeature(
231 @intFromEnum(std.Target.arm.Feature.thumb_mode),
231 @intFromEnum(Target.arm.Feature.thumb_mode),
232232 );
233233 },
234234 else => {},
235235 }
236 cross_target.updateCpuFeatures(&result.target.cpu.features);
236 query.updateCpuFeatures(&result.target.cpu.features);
237237 return result;
238238}
239239
......@@ -253,22 +253,22 @@ pub fn detect(cross_target: CrossTarget) DetectError!NativeTargetInfo {
253253fn detectAbiAndDynamicLinker(
254254 cpu: Target.Cpu,
255255 os: Target.Os,
256 cross_target: CrossTarget,
256 query: Target.Query,
257257) DetectError!NativeTargetInfo {
258258 const native_target_has_ld = comptime builtin.target.hasDynamicLinker();
259259 const is_linux = builtin.target.os.tag == .linux;
260260 const is_solarish = builtin.target.os.tag.isSolarish();
261 const have_all_info = cross_target.dynamic_linker.get() != null and
262 cross_target.abi != null and (!is_linux or cross_target.abi.?.isGnu());
263 const os_is_non_native = cross_target.os_tag != null;
261 const have_all_info = query.dynamic_linker.get() != null and
262 query.abi != null and (!is_linux or query.abi.?.isGnu());
263 const os_is_non_native = query.os_tag != null;
264264 // The Solaris/illumos environment is always the same.
265265 if (!native_target_has_ld or have_all_info or os_is_non_native or is_solarish) {
266 return defaultAbiAndDynamicLinker(cpu, os, cross_target);
266 return defaultAbiAndDynamicLinker(cpu, os, query);
267267 }
268 if (cross_target.abi) |abi| {
268 if (query.abi) |abi| {
269269 if (abi.isMusl()) {
270270 // musl implies static linking.
271 return defaultAbiAndDynamicLinker(cpu, os, cross_target);
271 return defaultAbiAndDynamicLinker(cpu, os, query);
272272 }
273273 }
274274 // The current target's ABI cannot be relied on for this. For example, we may build the zig
......@@ -287,7 +287,7 @@ fn detectAbiAndDynamicLinker(
287287 };
288288 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;
289289 var ld_info_list_len: usize = 0;
290 const ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch);
290 const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch);
291291
292292 for (all_abis) |abi| {
293293 // This may be a nonsensical parameter. We detect this with
......@@ -345,7 +345,7 @@ fn detectAbiAndDynamicLinker(
345345 error.Unexpected,
346346 => |e| {
347347 std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)});
348 return defaultAbiAndDynamicLinker(cpu, os, cross_target);
348 return defaultAbiAndDynamicLinker(cpu, os, query);
349349 },
350350
351351 else => |e| return e,
......@@ -363,7 +363,7 @@ fn detectAbiAndDynamicLinker(
363363 const line = buffer[0..newline];
364364 if (!mem.startsWith(u8, line, "#!")) break :blk file;
365365 var it = mem.tokenizeScalar(u8, line[2..], ' ');
366 file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, cross_target);
366 file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, query);
367367 file.close();
368368 }
369369 };
......@@ -373,7 +373,7 @@ fn detectAbiAndDynamicLinker(
373373 // trick (block self_exe) won't work. The next thing we fall back to is the same thing, but for elf_file.
374374 // TODO: inline this function and combine the buffer we already read above to find
375375 // the possible shebang line with the buffer we use for the ELF header.
376 return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, cross_target) catch |err| switch (err) {
376 return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, query) catch |err| switch (err) {
377377 error.FileSystem,
378378 error.SystemResources,
379379 error.SymLinkLoop,
......@@ -393,7 +393,7 @@ fn detectAbiAndDynamicLinker(
393393 // Finally, we fall back on the standard path.
394394 => |e| {
395395 std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)});
396 return defaultAbiAndDynamicLinker(cpu, os, cross_target);
396 return defaultAbiAndDynamicLinker(cpu, os, query);
397397 },
398398 };
399399}
......@@ -565,7 +565,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
565565 while (it.next()) |s| {
566566 if (mem.startsWith(u8, s, "GLIBC_2.")) {
567567 const chopped = s["GLIBC_".len..];
568 const ver = CrossTarget.parseVersion(chopped) catch |err| switch (err) {
568 const ver = Target.Query.parseVersion(chopped) catch |err| switch (err) {
569569 error.Overflow => return error.InvalidGnuLibCVersion,
570570 error.InvalidVersion => return error.InvalidGnuLibCVersion,
571571 };
......@@ -588,7 +588,7 @@ fn glibcVerFromLinkName(link_name: []const u8, prefix: []const u8) error{ Unreco
588588 }
589589 // chop off "libc-" and ".so"
590590 const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len];
591 return CrossTarget.parseVersion(link_name_chopped) catch |err| switch (err) {
591 return Target.Query.parseVersion(link_name_chopped) catch |err| switch (err) {
592592 error.Overflow => return error.InvalidGnuLibCVersion,
593593 error.InvalidVersion => return error.InvalidGnuLibCVersion,
594594 };
......@@ -627,7 +627,7 @@ pub fn abiAndDynamicLinkerFromFile(
627627 cpu: Target.Cpu,
628628 os: Target.Os,
629629 ld_info_list: []const LdInfo,
630 cross_target: CrossTarget,
630 query: Target.Query,
631631) AbiAndDynamicLinkerFromFileError!NativeTargetInfo {
632632 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
633633 _ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
......@@ -655,13 +655,13 @@ pub fn abiAndDynamicLinkerFromFile(
655655 .target = .{
656656 .cpu = cpu,
657657 .os = os,
658 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
659 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
658 .abi = query.abi orelse Target.Abi.default(cpu.arch, os),
659 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
660660 },
661 .dynamic_linker = cross_target.dynamic_linker,
661 .dynamic_linker = query.dynamic_linker,
662662 };
663663 var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC
664 const look_for_ld = cross_target.dynamic_linker.get() == null;
664 const look_for_ld = query.dynamic_linker.get() == null;
665665
666666 var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined;
667667 if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile;
......@@ -706,7 +706,7 @@ pub fn abiAndDynamicLinkerFromFile(
706706 },
707707 // We only need this for detecting glibc version.
708708 elf.PT_DYNAMIC => if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and
709 cross_target.glibc_version == null)
709 query.glibc_version == null)
710710 {
711711 var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
712712 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
......@@ -747,7 +747,7 @@ pub fn abiAndDynamicLinkerFromFile(
747747 }
748748
749749 if (builtin.target.os.tag == .linux and result.target.isGnuLibC() and
750 cross_target.glibc_version == null)
750 query.glibc_version == null)
751751 {
752752 const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);
753753
......@@ -927,19 +927,19 @@ fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
927927 return i;
928928}
929929
930fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, cross_target: CrossTarget) !NativeTargetInfo {
930fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Query) !NativeTargetInfo {
931931 const target: Target = .{
932932 .cpu = cpu,
933933 .os = os,
934 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
935 .ofmt = cross_target.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
934 .abi = query.abi orelse Target.Abi.default(cpu.arch, os),
935 .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
936936 };
937937 return NativeTargetInfo{
938938 .target = target,
939 .dynamic_linker = if (cross_target.dynamic_linker.get() == null)
939 .dynamic_linker = if (query.dynamic_linker.get() == null)
940940 target.standardDynamicLinkerPath()
941941 else
942 cross_target.dynamic_linker,
942 query.dynamic_linker,
943943 };
944944}
945945
......@@ -964,13 +964,13 @@ pub fn elfInt(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @
964964 }
965965}
966966
967fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) ?Target.Cpu {
967fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu {
968968 // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`,
969969 // although it is a runtime value, is guaranteed to be one of the architectures in the set
970970 // of the respective switch prong.
971971 switch (builtin.cpu.arch) {
972972 .x86_64, .x86 => {
973 return @import("x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, cross_target);
973 return @import("x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, query);
974974 },
975975 else => {},
976976 }
lib/std/zig/system/darwin/macos.zig+1-1
......@@ -87,7 +87,7 @@ fn parseSystemVersion(buf: []const u8) !std.SemanticVersion {
8787 const ver = try svt.expectContent();
8888 try svt.skipUntilTag(.end, "string");
8989
90 return try std.zig.CrossTarget.parseVersion(ver);
90 return try std.Target.Query.parseVersion(ver);
9191}
9292
9393const SystemVersionTokenizer = struct {
lib/std/zig/system/linux.zig-3
......@@ -5,10 +5,7 @@ const io = std.io;
55const fs = std.fs;
66const fmt = std.fmt;
77const testing = std.testing;
8
98const Target = std.Target;
10const CrossTarget = std.zig.CrossTarget;
11
129const assert = std.debug.assert;
1310
1411const SparcCpuinfoImpl = struct {
lib/std/zig/system/x86.zig+2-3
......@@ -1,7 +1,6 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const Target = std.Target;
4const CrossTarget = std.zig.CrossTarget;
54
65const XCR0_XMM = 0x02;
76const XCR0_YMM = 0x04;
......@@ -23,8 +22,8 @@ inline fn hasMask(input: u32, mask: u32) bool {
2322 return (input & mask) == mask;
2423}
2524
26pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, cross_target: CrossTarget) Target.Cpu {
27 _ = cross_target;
25pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) Target.Cpu {
26 _ = query;
2827 var cpu = Target.Cpu{
2928 .arch = arch,
3029 .model = Target.Cpu.Model.generic(arch),
src/libc_installation.zig+1-1
......@@ -41,7 +41,7 @@ pub const LibCInstallation = struct {
4141 pub fn parse(
4242 allocator: Allocator,
4343 libc_file: []const u8,
44 target: std.zig.CrossTarget,
44 target: std.Target.Query,
4545 ) !LibCInstallation {
4646 var self: LibCInstallation = .{};
4747
src/main.zig+37-37
......@@ -2551,7 +2551,7 @@ fn buildOutputType(
25512551 }
25522552 };
25532553
2554 var target_parse_options: std.zig.CrossTarget.ParseOptions = .{
2554 var target_parse_options: std.Target.Query.ParseOptions = .{
25552555 .arch_os_abi = target_arch_os_abi,
25562556 .cpu_features = target_mcpu,
25572557 .dynamic_linker = target_dynamic_linker,
......@@ -2563,7 +2563,7 @@ fn buildOutputType(
25632563 if (llvm_m_args.items.len != 0) {
25642564 // If this returns null, we let it fall through to the case below which will
25652565 // run the full parse function and do proper error handling.
2566 if (std.zig.CrossTarget.parseCpuArch(target_parse_options)) |cpu_arch| {
2566 if (std.Target.Query.parseCpuArch(target_parse_options)) |cpu_arch| {
25672567 var llvm_to_zig_name = std.StringHashMap([]const u8).init(gpa);
25682568 defer llvm_to_zig_name.deinit();
25692569
......@@ -2607,8 +2607,8 @@ fn buildOutputType(
26072607 }
26082608 }
26092609
2610 const cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options);
2611 const target_info = try detectNativeTargetInfo(cross_target);
2610 const target_query = try parseTargetQueryOrReportFatalError(arena, target_parse_options);
2611 const target_info = try detectNativeTargetInfo(target_query);
26122612
26132613 if (target_info.target.os.tag != .freestanding) {
26142614 if (ensure_libc_on_non_freestanding)
......@@ -2695,13 +2695,13 @@ fn buildOutputType(
26952695 }
26962696
26972697 if (use_lld) |opt| {
2698 if (opt and cross_target.isDarwin()) {
2698 if (opt and target_query.isDarwin()) {
26992699 fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{});
27002700 }
27012701 }
27022702
27032703 if (want_lto) |opt| {
2704 if (opt and cross_target.isDarwin()) {
2704 if (opt and target_query.isDarwin()) {
27052705 fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{});
27062706 }
27072707 }
......@@ -2771,7 +2771,7 @@ fn buildOutputType(
27712771
27722772 var libc_installation: ?LibCInstallation = null;
27732773 if (libc_paths_file) |paths_file| {
2774 libc_installation = LibCInstallation.parse(arena, paths_file, cross_target) catch |err| {
2774 libc_installation = LibCInstallation.parse(arena, paths_file, target_query) catch |err| {
27752775 fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) });
27762776 };
27772777 }
......@@ -2835,7 +2835,7 @@ fn buildOutputType(
28352835 // After this point, external_system_libs is used instead of system_libs.
28362836
28372837 // Trigger native system library path detection if necessary.
2838 if (sysroot == null and cross_target.isNativeOs() and cross_target.isNativeAbi() and
2838 if (sysroot == null and target_query.isNativeOs() and target_query.isNativeAbi() and
28392839 (external_system_libs.len != 0 or want_native_include_dirs))
28402840 {
28412841 const paths = std.zig.system.NativePaths.detect(arena, target_info) catch |err| {
......@@ -2864,7 +2864,7 @@ fn buildOutputType(
28642864 libc_installation = try LibCInstallation.findNative(.{
28652865 .allocator = arena,
28662866 .verbose = true,
2867 .target = cross_target.toTarget(),
2867 .target = target_query.toTarget(),
28682868 });
28692869
28702870 try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? });
......@@ -3455,8 +3455,8 @@ fn buildOutputType(
34553455 .global_cache_directory = global_cache_directory,
34563456 .root_name = root_name,
34573457 .target = target_info.target,
3458 .is_native_os = cross_target.isNativeOs(),
3459 .is_native_abi = cross_target.isNativeAbi(),
3458 .is_native_os = target_query.isNativeOs(),
3459 .is_native_abi = target_query.isNativeAbi(),
34603460 .dynamic_linker = target_info.dynamic_linker.get(),
34613461 .sysroot = sysroot,
34623462 .output_mode = output_mode,
......@@ -4013,16 +4013,16 @@ const ModuleDepIterator = struct {
40134013 }
40144014};
40154015
4016fn parseCrossTargetOrReportFatalError(
4016fn parseTargetQueryOrReportFatalError(
40174017 allocator: Allocator,
4018 opts: std.zig.CrossTarget.ParseOptions,
4019) !std.zig.CrossTarget {
4018 opts: std.Target.Query.ParseOptions,
4019) !std.Target.Query {
40204020 var opts_with_diags = opts;
4021 var diags: std.zig.CrossTarget.ParseOptions.Diagnostics = .{};
4021 var diags: std.Target.Query.ParseOptions.Diagnostics = .{};
40224022 if (opts_with_diags.diagnostics == null) {
40234023 opts_with_diags.diagnostics = &diags;
40244024 }
4025 return std.zig.CrossTarget.parse(opts_with_diags) catch |err| switch (err) {
4025 return std.Target.Query.parse(opts_with_diags) catch |err| switch (err) {
40264026 error.UnknownCpuModel => {
40274027 help: {
40284028 var help_text = std.ArrayList(u8).init(allocator);
......@@ -4666,9 +4666,9 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes:
46664666 while (true) {
46674667 switch (cur_includes) {
46684668 .any, .msvc => {
4669 const cross_target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "native-windows-msvc" }) catch unreachable;
4670 const target = cross_target.toTarget();
4671 const is_native_abi = cross_target.isNativeAbi();
4669 const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-msvc" }) catch unreachable;
4670 const target = target_query.toTarget();
4671 const is_native_abi = target_query.isNativeAbi();
46724672 const detected_libc = Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null) catch |err| {
46734673 if (cur_includes == .any) {
46744674 // fall back to mingw
......@@ -4691,9 +4691,9 @@ fn detectRcIncludeDirs(arena: Allocator, zig_lib_dir: []const u8, auto_includes:
46914691 };
46924692 },
46934693 .gnu => {
4694 const cross_target = std.zig.CrossTarget.parse(.{ .arch_os_abi = "native-windows-gnu" }) catch unreachable;
4695 const target = cross_target.toTarget();
4696 const is_native_abi = cross_target.isNativeAbi();
4694 const target_query = std.Target.Query.parse(.{ .arch_os_abi = "native-windows-gnu" }) catch unreachable;
4695 const target = target_query.toTarget();
4696 const is_native_abi = target_query.isNativeAbi();
46974697 const detected_libc = try Compilation.detectLibCIncludeDirs(arena, zig_lib_dir, target, is_native_abi, true, null);
46984698 return .{
46994699 .include_paths = detected_libc.libc_include_dir_list,
......@@ -4754,7 +4754,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
47544754 }
47554755 }
47564756
4757 const cross_target = try parseCrossTargetOrReportFatalError(gpa, .{
4757 const target_query = try parseTargetQueryOrReportFatalError(gpa, .{
47584758 .arch_os_abi = target_arch_os_abi,
47594759 });
47604760
......@@ -4766,7 +4766,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
47664766 const libc_installation: ?*LibCInstallation = libc: {
47674767 if (input_file) |libc_file| {
47684768 const libc = try arena.create(LibCInstallation);
4769 libc.* = LibCInstallation.parse(arena, libc_file, cross_target) catch |err| {
4769 libc.* = LibCInstallation.parse(arena, libc_file, target_query) catch |err| {
47704770 fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });
47714771 };
47724772 break :libc libc;
......@@ -4781,8 +4781,8 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
47814781 };
47824782 defer zig_lib_directory.handle.close();
47834783
4784 const target = cross_target.toTarget();
4785 const is_native_abi = cross_target.isNativeAbi();
4784 const target = target_query.toTarget();
4785 const is_native_abi = target_query.isNativeAbi();
47864786
47874787 const libc_dirs = Compilation.detectLibCIncludeDirs(
47884788 arena,
......@@ -4812,15 +4812,15 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
48124812 }
48134813
48144814 if (input_file) |libc_file| {
4815 var libc = LibCInstallation.parse(gpa, libc_file, cross_target) catch |err| {
4815 var libc = LibCInstallation.parse(gpa, libc_file, target_query) catch |err| {
48164816 fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });
48174817 };
48184818 defer libc.deinit(gpa);
48194819 } else {
4820 if (!cross_target.isNative()) {
4820 if (!target_query.isNative()) {
48214821 fatal("unable to detect libc for non-native target", .{});
48224822 }
4823 const target_info = try detectNativeTargetInfo(cross_target);
4823 const target_info = try detectNativeTargetInfo(target_query);
48244824
48254825 var libc = LibCInstallation.findNative(.{
48264826 .allocator = gpa,
......@@ -5113,8 +5113,8 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
51135113
51145114 gimmeMoreOfThoseSweetSweetFileDescriptors();
51155115
5116 const cross_target: std.zig.CrossTarget = .{};
5117 const target_info = try detectNativeTargetInfo(cross_target);
5116 const target_query: std.Target.Query = .{};
5117 const target_info = try detectNativeTargetInfo(target_query);
51185118
51195119 const exe_basename = try std.zig.binNameAlloc(arena, .{
51205120 .root_name = "build",
......@@ -5283,8 +5283,8 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
52835283 .global_cache_directory = global_cache_directory,
52845284 .root_name = "build",
52855285 .target = target_info.target,
5286 .is_native_os = cross_target.isNativeOs(),
5287 .is_native_abi = cross_target.isNativeAbi(),
5286 .is_native_os = target_query.isNativeOs(),
5287 .is_native_abi = target_query.isNativeAbi(),
52885288 .dynamic_linker = target_info.dynamic_linker.get(),
52895289 .output_mode = .Exe,
52905290 .main_mod = &main_mod,
......@@ -6269,8 +6269,8 @@ test "fds" {
62696269 gimmeMoreOfThoseSweetSweetFileDescriptors();
62706270}
62716271
6272fn detectNativeTargetInfo(cross_target: std.zig.CrossTarget) !std.zig.system.NativeTargetInfo {
6273 return std.zig.system.NativeTargetInfo.detect(cross_target);
6272fn detectNativeTargetInfo(target_query: std.Target.Query) !std.zig.system.NativeTargetInfo {
6273 return std.zig.system.NativeTargetInfo.detect(target_query);
62746274}
62756275
62766276const usage_ast_check =
......@@ -6672,8 +6672,8 @@ fn warnAboutForeignBinaries(
66726672 target_info: *const std.zig.system.NativeTargetInfo,
66736673 link_libc: bool,
66746674) !void {
6675 const host_cross_target: std.zig.CrossTarget = .{};
6676 const host_target_info = try detectNativeTargetInfo(host_cross_target);
6675 const host_query: std.Target.Query = .{};
6676 const host_target_info = try detectNativeTargetInfo(host_query);
66776677
66786678 switch (host_target_info.getExternalExecutor(target_info, .{ .link_libc = link_libc })) {
66796679 .native => return,
test/cbe.zig+1-1
......@@ -5,7 +5,7 @@ const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n";
55pub fn addCases(ctx: *Cases, b: *std.Build) !void {
66 // These tests should work with all platforms, but we're using linux_x64 for
77 // now for consistency. Will be expanded eventually.
8 const linux_x64: std.zig.CrossTarget = .{
8 const linux_x64: std.Target.Query = .{
99 .cpu_arch = .x86_64,
1010 .os_tag = .linux,
1111 };
test/link/elf.zig-1
......@@ -3833,7 +3833,6 @@ const link = @import("link.zig");
38333833const std = @import("std");
38343834
38353835const Build = std.Build;
3836const CrossTarget = std.zig.CrossTarget;
38373836const Options = link.Options;
38383837const Step = Build.Step;
38393838const WriteFile = Step.WriteFile;
test/link/glibc_compat/build.zig+1-1
......@@ -8,7 +8,7 @@ pub fn build(b: *std.Build) void {
88 const exe = b.addExecutable(.{
99 .name = t,
1010 .root_source_file = .{ .path = "main.c" },
11 .target = b.resolveTargetQuery(std.zig.CrossTarget.parse(
11 .target = b.resolveTargetQuery(std.Target.Query.parse(
1212 .{ .arch_os_abi = t },
1313 ) catch unreachable),
1414 });
test/link/link.zig-1
......@@ -199,7 +199,6 @@ const std = @import("std");
199199
200200const Build = std.Build;
201201const Compile = Step.Compile;
202const CrossTarget = std.zig.CrossTarget;
203202const Run = Step.Run;
204203const Step = Build.Step;
205204const WriteFile = Step.WriteFile;
test/link/macho.zig-2
......@@ -95,7 +95,5 @@ const addExecutable = link.addExecutable;
9595const expectLinkErrors = link.expectLinkErrors;
9696const link = @import("link.zig");
9797const std = @import("std");
98
99const CrossTarget = std.zig.CrossTarget;
10098const Options = link.Options;
10199const Step = std.Build.Step;
test/llvm_targets.zig+1-1
......@@ -1,7 +1,7 @@
11const std = @import("std");
22const Cases = @import("src/Cases.zig");
33
4const targets = [_]std.zig.CrossTarget{
4const targets = [_]std.Target.Query{
55 .{ .cpu_arch = .aarch64, .os_tag = .freestanding, .abi = .none },
66 .{ .cpu_arch = .aarch64, .os_tag = .ios, .abi = .none },
77 .{ .cpu_arch = .aarch64, .os_tag = .ios, .abi = .simulator },
test/src/Cases.zig+6-6
......@@ -188,7 +188,7 @@ pub fn exe(ctx: *Cases, name: []const u8, target: std.Build.ResolvedTarget) *Cas
188188 return ctx.addExe(name, target);
189189}
190190
191pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target_query: std.zig.CrossTarget, b: *std.Build) *Case {
191pub fn exeFromCompiledC(ctx: *Cases, name: []const u8, target_query: std.Target.Query, b: *std.Build) *Case {
192192 var adjusted_query = target_query;
193193 adjusted_query.ofmt = .c;
194194 ctx.cases.append(Case{
......@@ -423,7 +423,7 @@ fn addFromDirInner(
423423 var manifest = try TestManifest.parse(ctx.arena, src);
424424
425425 const backends = try manifest.getConfigForKeyAlloc(ctx.arena, "backend", Backend);
426 const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.zig.CrossTarget);
426 const targets = try manifest.getConfigForKeyAlloc(ctx.arena, "target", std.Target.Query);
427427 const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend);
428428 const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool);
429429 const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool);
......@@ -1160,9 +1160,9 @@ const TestManifest = struct {
11601160 }
11611161
11621162 fn getDefaultParser(comptime T: type) ParseFn(T) {
1163 if (T == std.zig.CrossTarget) return struct {
1163 if (T == std.Target.Query) return struct {
11641164 fn parse(str: []const u8) anyerror!T {
1165 return std.zig.CrossTarget.parse(.{ .arch_os_abi = str });
1165 return std.Target.Query.parse(.{ .arch_os_abi = str });
11661166 }
11671167 }.parse;
11681168
......@@ -1287,7 +1287,7 @@ pub fn main() !void {
12871287
12881288 if (cases.items.len == 0) {
12891289 const backends = try manifest.getConfigForKeyAlloc(arena, "backend", Backend);
1290 const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.zig.CrossTarget);
1290 const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.Target.Query);
12911291 const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend);
12921292 const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool);
12931293 const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool);
......@@ -1385,7 +1385,7 @@ pub fn main() !void {
13851385 return runCases(&ctx, zig_exe_path);
13861386}
13871387
1388fn resolveTargetQuery(query: std.zig.CrossTarget) std.Build.ResolvedTarget {
1388fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget {
13891389 const result = std.zig.system.NativeTargetInfo.detect(query) catch
13901390 @panic("unable to resolve target query");
13911391
test/src/translate_c.zig+2-3
......@@ -5,7 +5,6 @@ const ArrayList = std.ArrayList;
55const fmt = std.fmt;
66const mem = std.mem;
77const fs = std.fs;
8const CrossTarget = std.zig.CrossTarget;
98
109pub const TranslateCContext = struct {
1110 b: *std.Build,
......@@ -18,7 +17,7 @@ pub const TranslateCContext = struct {
1817 sources: ArrayList(SourceFile),
1918 expected_lines: ArrayList([]const u8),
2019 allow_warnings: bool,
21 target: CrossTarget = .{},
20 target: std.Target.Query = .{},
2221
2322 const SourceFile = struct {
2423 filename: []const u8,
......@@ -74,7 +73,7 @@ pub const TranslateCContext = struct {
7473 pub fn addWithTarget(
7574 self: *TranslateCContext,
7675 name: []const u8,
77 target: CrossTarget,
76 target: std.Target.Query,
7877 source: []const u8,
7978 expected_lines: []const []const u8,
8079 ) void {
test/standalone.zig+1-1
......@@ -2,7 +2,7 @@ pub const SimpleCase = struct {
22 src_path: []const u8,
33 link_libc: bool = false,
44 all_modes: bool = false,
5 target: std.zig.CrossTarget = .{},
5 target: std.Target.Query = .{},
66 is_test: bool = false,
77 is_exe: bool = true,
88 /// Run only on this OS.
test/standalone/windows_resources/build.zig+3-3
......@@ -4,17 +4,17 @@ pub fn build(b: *std.Build) void {
44 const test_step = b.step("test", "Test it");
55 b.default_step = test_step;
66
7 const cross_target = b.resolveTargetQuery(.{
7 const target = b.resolveTargetQuery(.{
88 .cpu_arch = .x86_64,
99 .os_tag = .windows,
1010 .abi = .gnu,
1111 });
1212
1313 add(b, b.host, .any, test_step);
14 add(b, cross_target, .any, test_step);
14 add(b, target, .any, test_step);
1515
1616 add(b, b.host, .gnu, test_step);
17 add(b, cross_target, .gnu, test_step);
17 add(b, target, .gnu, test_step);
1818}
1919
2020fn add(
test/tests.zig+6-6
......@@ -21,7 +21,7 @@ pub const CompareOutputContext = @import("src/CompareOutput.zig");
2121pub const StackTracesContext = @import("src/StackTrace.zig");
2222
2323const TestTarget = struct {
24 target: std.zig.CrossTarget = .{},
24 target: std.Target.Query = .{},
2525 optimize_mode: std.builtin.OptimizeMode = .Debug,
2626 link_libc: ?bool = null,
2727 single_threaded: ?bool = null,
......@@ -145,7 +145,7 @@ const test_targets = blk: {
145145 //},
146146 // https://github.com/ziglang/zig/issues/13623
147147 //.{
148 // .target = std.zig.CrossTarget.parse(.{
148 // .target = std.Target.Query.parse(.{
149149 // .arch_os_abi = "arm-linux-none",
150150 // .cpu_features = "generic+v8a",
151151 // }) catch unreachable,
......@@ -286,13 +286,13 @@ const test_targets = blk: {
286286 },
287287
288288 .{
289 .target = std.zig.CrossTarget.parse(.{
289 .target = std.Target.Query.parse(.{
290290 .arch_os_abi = "arm-linux-none",
291291 .cpu_features = "generic+v8a",
292292 }) catch unreachable,
293293 },
294294 .{
295 .target = std.zig.CrossTarget.parse(.{
295 .target = std.Target.Query.parse(.{
296296 .arch_os_abi = "arm-linux-musleabihf",
297297 .cpu_features = "generic+v8a",
298298 }) catch unreachable,
......@@ -300,7 +300,7 @@ const test_targets = blk: {
300300 },
301301 // https://github.com/ziglang/zig/issues/3287
302302 //.{
303 // .target = std.zig.CrossTarget.parse(.{
303 // .target = std.Target.Query.parse(.{
304304 // .arch_os_abi = "arm-linux-gnueabihf",
305305 // .cpu_features = "generic+v8a",
306306 // }) catch unreachable,
......@@ -494,7 +494,7 @@ const test_targets = blk: {
494494};
495495
496496const CAbiTarget = struct {
497 target: std.zig.CrossTarget = .{},
497 target: std.Target.Query = .{},
498498 use_llvm: ?bool = null,
499499 use_lld: ?bool = null,
500500 pic: ?bool = null,
test/translate_c.zig+2-3
......@@ -1,7 +1,6 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const tests = @import("tests.zig");
4const CrossTarget = std.zig.CrossTarget;
54
65// ********************************************************
76// * *
......@@ -1846,7 +1845,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18461845 \\pub extern fn foo5(a: [*c]f32) callconv(.Thiscall) void;
18471846 });
18481847
1849 cases.addWithTarget("Calling convention", CrossTarget.parse(.{
1848 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{
18501849 .arch_os_abi = "arm-linux-none",
18511850 .cpu_features = "generic+v8_5a",
18521851 }) catch unreachable,
......@@ -1857,7 +1856,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18571856 \\pub extern fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void;
18581857 });
18591858
1860 cases.addWithTarget("Calling convention", CrossTarget.parse(.{
1859 cases.addWithTarget("Calling convention", std.Target.Query.parse(.{
18611860 .arch_os_abi = "aarch64-linux-none",
18621861 .cpu_features = "generic+v8_5a",
18631862 }) catch unreachable,