authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-04 20:30:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:18-07:00
log8c44954bc6a91ae66f5aea92ea8380c28b50b3f0
tree561158f17f27378a0bbd7d572a347082cacc464c
parentdbdb87502d6936597424fe86842c15978ba86918

std.Target.Query: remove deprecated API

These functions have been doomed for a long time. Finally I figured out what the proper relationship between this API and std.Target is.

10 files changed, 275 insertions(+), 373 deletions(-)

deps/aro/aro/Driver.zig+6-3
...@@ -366,12 +366,15 @@ pub fn parseArgs(...@@ -366,12 +366,15 @@ pub fn parseArgs(
366 } else if (mem.eql(u8, arg, "-S") or mem.eql(u8, arg, "--assemble")) {366 } else if (mem.eql(u8, arg, "-S") or mem.eql(u8, arg, "--assemble")) {
367 d.only_preprocess_and_compile = true;367 d.only_preprocess_and_compile = true;
368 } else if (option(arg, "--target=")) |triple| {368 } else if (option(arg, "--target=")) |triple| {
369 const cross = std.zig.CrossTarget.parse(.{ .arch_os_abi = triple }) catch {369 const query = std.Target.Query.parse(.{ .arch_os_abi = triple }) catch {
370 try d.comp.addDiagnostic(.{ .tag = .cli_invalid_target, .extra = .{ .str = arg } }, &.{});370 try d.comp.addDiagnostic(.{ .tag = .cli_invalid_target, .extra = .{ .str = arg } }, &.{});
371 continue;371 continue;
372 };372 };
373 d.comp.target = cross.toTarget(); // TODO deprecated373 const target = std.zig.system.resolveTargetQuery(query) catch |e| {
374 d.comp.langopts.setEmulatedCompiler(target_util.systemCompiler(d.comp.target));374 return d.fatal("unable to resolve target: {s}", .{errorDescription(e)});
375 };
376 d.comp.target = target;
377 d.comp.langopts.setEmulatedCompiler(target_util.systemCompiler(target));
375 d.raw_target_triple = triple;378 d.raw_target_triple = triple;
376 } else if (mem.eql(u8, arg, "--verbose-ast")) {379 } else if (mem.eql(u8, arg, "--verbose-ast")) {
377 d.verbose_ast = true;380 d.verbose_ast = true;
lib/std/Build.zig+26-110
...@@ -383,12 +383,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption...@@ -383,12 +383,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption
383 }) catch @panic("OOM");383 }) catch @panic("OOM");
384 user_input_options.put("cpu", .{384 user_input_options.put("cpu", .{
385 .name = "cpu",385 .name = "cpu",
386 .value = .{386 .value = .{ .scalar = v.serializeCpuAlloc(allocator) catch @panic("OOM") },
387 .scalar = if (v.isNativeCpu())
388 "native"
389 else
390 serializeCpu(allocator, v.getCpu()) catch unreachable,
391 },
392 .used = false,387 .used = false,
393 }) catch @panic("OOM");388 }) catch @panic("OOM");
394 },389 },
...@@ -400,12 +395,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption...@@ -400,12 +395,7 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption
400 }) catch @panic("OOM");395 }) catch @panic("OOM");
401 user_input_options.put("cpu", .{396 user_input_options.put("cpu", .{
402 .name = "cpu",397 .name = "cpu",
403 .value = .{398 .value = .{ .scalar = v.query.serializeCpuAlloc(allocator) catch @panic("OOM") },
404 .scalar = if (v.query.isNativeCpu())
405 "native"
406 else
407 serializeCpu(allocator, v.target.cpu) catch unreachable,
408 },
409 .used = false,399 .used = false,
410 }) catch @panic("OOM");400 }) catch @panic("OOM");
411 },401 },
...@@ -1196,7 +1186,6 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio...@@ -1196,7 +1186,6 @@ pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptio
11961186
1197pub const StandardTargetOptionsArgs = struct {1187pub const StandardTargetOptionsArgs = struct {
1198 whitelist: ?[]const Target.Query = null,1188 whitelist: ?[]const Target.Query = null,
1199
1200 default_target: Target.Query = .{},1189 default_target: Target.Query = .{},
1201};1190};
12021191
...@@ -1208,13 +1197,13 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve...@@ -1208,13 +1197,13 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve
1208}1197}
12091198
1210/// Exposes standard `zig build` options for choosing a target.1199/// Exposes standard `zig build` options for choosing a target.
1211pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsArgs) Target.Query {1200pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query {
1212 const maybe_triple = self.option(1201 const maybe_triple = b.option(
1213 []const u8,1202 []const u8,
1214 "target",1203 "target",
1215 "The CPU architecture, OS, and ABI to build for",1204 "The CPU architecture, OS, and ABI to build for",
1216 );1205 );
1217 const mcpu = self.option([]const u8, "cpu", "Target CPU features to add or subtract");1206 const mcpu = b.option([]const u8, "cpu", "Target CPU features to add or subtract");
12181207
1219 if (maybe_triple == null and mcpu == null) {1208 if (maybe_triple == null and mcpu == null) {
1220 return args.default_target;1209 return args.default_target;
...@@ -1236,7 +1225,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA...@@ -1236,7 +1225,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
1236 for (diags.arch.?.allCpuModels()) |cpu| {1225 for (diags.arch.?.allCpuModels()) |cpu| {
1237 log.err(" {s}", .{cpu.name});1226 log.err(" {s}", .{cpu.name});
1238 }1227 }
1239 self.markInvalidUserInput();1228 b.markInvalidUserInput();
1240 return args.default_target;1229 return args.default_target;
1241 },1230 },
1242 error.UnknownCpuFeature => {1231 error.UnknownCpuFeature => {
...@@ -1251,7 +1240,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA...@@ -1251,7 +1240,7 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
1251 for (diags.arch.?.allFeaturesList()) |feature| {1240 for (diags.arch.?.allFeaturesList()) |feature| {
1252 log.err(" {s}: {s}", .{ feature.name, feature.description });1241 log.err(" {s}: {s}", .{ feature.name, feature.description });
1253 }1242 }
1254 self.markInvalidUserInput();1243 b.markInvalidUserInput();
1255 return args.default_target;1244 return args.default_target;
1256 },1245 },
1257 error.UnknownOperatingSystem => {1246 error.UnknownOperatingSystem => {
...@@ -1263,80 +1252,35 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA...@@ -1263,80 +1252,35 @@ pub fn standardTargetOptionsQueryOnly(self: *Build, args: StandardTargetOptionsA
1263 inline for (std.meta.fields(Target.Os.Tag)) |field| {1252 inline for (std.meta.fields(Target.Os.Tag)) |field| {
1264 log.err(" {s}", .{field.name});1253 log.err(" {s}", .{field.name});
1265 }1254 }
1266 self.markInvalidUserInput();1255 b.markInvalidUserInput();
1267 return args.default_target;1256 return args.default_target;
1268 },1257 },
1269 else => |e| {1258 else => |e| {
1270 log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) });1259 log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) });
1271 self.markInvalidUserInput();1260 b.markInvalidUserInput();
1272 return args.default_target;1261 return args.default_target;
1273 },1262 },
1274 };1263 };
12751264
1276 const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch @panic("OOM");1265 const whitelist = args.whitelist orelse return selected_target;
12771266
1278 if (args.whitelist) |list| whitelist_check: {1267 // Make sure it's a match of one of the list.
1279 // Make sure it's a match of one of the list.1268 for (whitelist) |q| {
1280 var mismatch_triple = true;1269 if (q.eql(selected_target))
1281 var mismatch_cpu_features = true;1270 return selected_target;
1282 var whitelist_item: Target.Query = .{};
1283 for (list) |t| {
1284 mismatch_cpu_features = true;
1285 mismatch_triple = true;
1286
1287 const t_triple = t.zigTriple(self.allocator) catch @panic("OOM");
1288 if (mem.eql(u8, t_triple, selected_canonicalized_triple)) {
1289 mismatch_triple = false;
1290 whitelist_item = t;
1291 if (t.getCpuFeatures().isSuperSetOf(selected_target.getCpuFeatures())) {
1292 mismatch_cpu_features = false;
1293 break :whitelist_check;
1294 } else {
1295 break;
1296 }
1297 }
1298 }
1299 if (mismatch_triple) {
1300 log.err("Chosen target '{s}' does not match one of the supported targets:", .{
1301 selected_canonicalized_triple,
1302 });
1303 for (list) |t| {
1304 const t_triple = t.zigTriple(self.allocator) catch @panic("OOM");
1305 log.err(" {s}", .{t_triple});
1306 }
1307 } else {
1308 assert(mismatch_cpu_features);
1309 const whitelist_cpu = whitelist_item.getCpu();
1310 const selected_cpu = selected_target.getCpu();
1311 log.err("Chosen CPU model '{s}' does not match one of the supported targets:", .{
1312 selected_cpu.model.name,
1313 });
1314 log.err(" Supported feature Set: ", .{});
1315 const all_features = whitelist_cpu.arch.allFeaturesList();
1316 var populated_cpu_features = whitelist_cpu.model.features;
1317 populated_cpu_features.populateDependencies(all_features);
1318 for (all_features, 0..) |feature, i_usize| {
1319 const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
1320 const in_cpu_set = populated_cpu_features.isEnabled(i);
1321 if (in_cpu_set) {
1322 log.err("{s} ", .{feature.name});
1323 }
1324 }
1325 log.err(" Remove: ", .{});
1326 for (all_features, 0..) |feature, i_usize| {
1327 const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
1328 const in_cpu_set = populated_cpu_features.isEnabled(i);
1329 const in_actual_set = selected_cpu.features.isEnabled(i);
1330 if (in_actual_set and !in_cpu_set) {
1331 log.err("{s} ", .{feature.name});
1332 }
1333 }
1334 }
1335 self.markInvalidUserInput();
1336 return args.default_target;
1337 }1271 }
13381272
1339 return selected_target;1273 for (whitelist) |q| {
1274 log.info("allowed target: -Dtarget={s} -Dcpu={s}", .{
1275 q.zigTriple(b.allocator) catch @panic("OOM"),
1276 q.serializeCpuAlloc(b.allocator) catch @panic("OOM"),
1277 });
1278 }
1279 log.err("chosen target '{s}' does not match one of the allowed targets", .{
1280 selected_target.zigTriple(b.allocator) catch @panic("OOM"),
1281 });
1282 b.markInvalidUserInput();
1283 return args.default_target;
1340}1284}
13411285
1342pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const u8) !bool {1286pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const u8) !bool {
...@@ -2064,34 +2008,6 @@ pub const InstalledFile = struct {...@@ -2064,34 +2008,6 @@ pub const InstalledFile = struct {
2064 }2008 }
2065};2009};
20662010
2067pub fn serializeCpu(allocator: Allocator, cpu: Target.Cpu) ![]const u8 {
2068 // TODO this logic can disappear if cpu model + features becomes part of the target triple
2069 const all_features = cpu.arch.allFeaturesList();
2070 var populated_cpu_features = cpu.model.features;
2071 populated_cpu_features.populateDependencies(all_features);
2072
2073 if (populated_cpu_features.eql(cpu.features)) {
2074 // The CPU name alone is sufficient.
2075 return cpu.model.name;
2076 } else {
2077 var mcpu_buffer = ArrayList(u8).init(allocator);
2078 try mcpu_buffer.appendSlice(cpu.model.name);
2079
2080 for (all_features, 0..) |feature, i_usize| {
2081 const i = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
2082 const in_cpu_set = populated_cpu_features.isEnabled(i);
2083 const in_actual_set = cpu.features.isEnabled(i);
2084 if (in_cpu_set and !in_actual_set) {
2085 try mcpu_buffer.writer().print("-{s}", .{feature.name});
2086 } else if (!in_cpu_set and in_actual_set) {
2087 try mcpu_buffer.writer().print("+{s}", .{feature.name});
2088 }
2089 }
2090
2091 return try mcpu_buffer.toOwnedSlice();
2092 }
2093}
2094
2095/// This function is intended to be called in the `configure` phase only.2011/// This function is intended to be called in the `configure` phase only.
2096/// It returns an absolute directory path, which is potentially going to be a2012/// It returns an absolute directory path, which is potentially going to be a
2097/// source of API breakage in the future, so keep that in mind when using this2013/// source of API breakage in the future, so keep that in mind when using this
lib/std/Build/Module.zig+2-2
...@@ -627,12 +627,12 @@ pub fn appendZigProcessFlags(...@@ -627,12 +627,12 @@ pub fn appendZigProcessFlags(
627 try zig_args.append(@tagName(m.code_model));627 try zig_args.append(@tagName(m.code_model));
628 }628 }
629629
630 if (m.target) |target| {630 if (m.target) |*target| {
631 // Communicate the query via CLI since it's more compact.631 // Communicate the query via CLI since it's more compact.
632 if (!target.query.isNative()) {632 if (!target.query.isNative()) {
633 try zig_args.appendSlice(&.{633 try zig_args.appendSlice(&.{
634 "-target", try target.query.zigTriple(b.allocator),634 "-target", try target.query.zigTriple(b.allocator),
635 "-mcpu", try std.Build.serializeCpu(b.allocator, target.query.getCpu()),635 "-mcpu", try target.query.serializeCpuAlloc(b.allocator),
636 });636 });
637637
638 if (target.query.dynamic_linker.get()) |dynamic_linker| {638 if (target.query.dynamic_linker.get()) |dynamic_linker| {
lib/std/Target.zig+11-2
...@@ -1394,7 +1394,7 @@ pub const Cpu = struct {...@@ -1394,7 +1394,7 @@ pub const Cpu = struct {
1394 }1394 }
1395};1395};
13961396
1397pub fn zigTriple(self: Target, allocator: Allocator) ![]u8 {1397pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 {
1398 return Query.fromTarget(self).zigTriple(allocator);1398 return Query.fromTarget(self).zigTriple(allocator);
1399}1399}
14001400
...@@ -1566,11 +1566,20 @@ pub const DynamicLinker = struct {...@@ -1566,11 +1566,20 @@ pub const DynamicLinker = struct {
1566 pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {1566 pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {
1567 if (dl_or_null) |dl| {1567 if (dl_or_null) |dl| {
1568 @memcpy(self.buffer[0..dl.len], dl);1568 @memcpy(self.buffer[0..dl.len], dl);
1569 self.max_byte = @as(u8, @intCast(dl.len - 1));1569 self.max_byte = @intCast(dl.len - 1);
1570 } else {1570 } else {
1571 self.max_byte = null;1571 self.max_byte = null;
1572 }1572 }
1573 }1573 }
1574
1575 pub fn eql(a: DynamicLinker, b: DynamicLinker) bool {
1576 const a_m = a.max_byte orelse return b.max_byte == null;
1577 const b_m = b.max_byte orelse return false;
1578 if (a_m != b_m) return false;
1579 const a_s = a.buffer[0 .. a_m + 1];
1580 const b_s = b.buffer[0 .. a_m + 1];
1581 return std.mem.eql(u8, a_s, b_s);
1582 }
1574};1583};
15751584
1576pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {1585pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
lib/std/Target/Query.zig+128-206
...@@ -51,12 +51,41 @@ pub const CpuModel = union(enum) {...@@ -51,12 +51,41 @@ pub const CpuModel = union(enum) {
51 determined_by_cpu_arch,51 determined_by_cpu_arch,
5252
53 explicit: *const Target.Cpu.Model,53 explicit: *const Target.Cpu.Model,
54
55 pub fn eql(a: CpuModel, b: CpuModel) bool {
56 const Tag = @typeInfo(CpuModel).Union.tag_type.?;
57 const a_tag: Tag = a;
58 const b_tag: Tag = b;
59 if (a_tag != b_tag) return false;
60 return switch (a) {
61 .native, .baseline, .determined_by_cpu_arch => true,
62 .explicit => |a_model| a_model == b.explicit,
63 };
64 }
54};65};
5566
56pub const OsVersion = union(enum) {67pub const OsVersion = union(enum) {
57 none: void,68 none: void,
58 semver: SemanticVersion,69 semver: SemanticVersion,
59 windows: Target.Os.WindowsVersion,70 windows: Target.Os.WindowsVersion,
71
72 pub fn eql(a: OsVersion, b: OsVersion) bool {
73 const Tag = @typeInfo(OsVersion).Union.tag_type.?;
74 const a_tag: Tag = a;
75 const b_tag: Tag = b;
76 if (a_tag != b_tag) return false;
77 return switch (a) {
78 .none => true,
79 .semver => |a_semver| a_semver.order(b.semver) == .eq,
80 .windows => |a_windows| a_windows == b.windows,
81 };
82 }
83
84 pub fn eqlOpt(a: ?OsVersion, b: ?OsVersion) bool {
85 if (a == null and b == null) return true;
86 if (a == null or b == null) return false;
87 return OsVersion.eql(a.?, b.?);
88 }
60};89};
6190
62pub const SemanticVersion = std.SemanticVersion;91pub const SemanticVersion = std.SemanticVersion;
...@@ -162,16 +191,6 @@ fn updateOsVersionRange(self: *Query, os: Target.Os) void {...@@ -162,16 +191,6 @@ fn updateOsVersionRange(self: *Query, os: Target.Os) void {
162 }191 }
163}192}
164193
165/// TODO deprecated, use `std.zig.system.resolveTargetQuery`.
166pub fn toTarget(self: Query) Target {
167 return .{
168 .cpu = self.getCpu(),
169 .os = self.getOs(),
170 .abi = self.getAbi(),
171 .ofmt = self.getObjectFormat(),
172 };
173}
174
175pub const ParseOptions = struct {194pub const ParseOptions = struct {
176 /// This is sometimes called a "triple". It looks roughly like this:195 /// This is sometimes called a "triple". It looks roughly like this:
177 /// riscv64-linux-musl196 /// riscv64-linux-musl
...@@ -240,7 +259,7 @@ pub fn parse(args: ParseOptions) !Query {...@@ -240,7 +259,7 @@ pub fn parse(args: ParseOptions) !Query {
240 result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse259 result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse
241 return error.UnknownArchitecture;260 return error.UnknownArchitecture;
242 }261 }
243 const arch = result.getCpuArch();262 const arch = result.cpu_arch orelse builtin.cpu.arch;
244 diags.arch = arch;263 diags.arch = arch;
245264
246 if (it.next()) |os_text| {265 if (it.next()) |os_text| {
...@@ -259,7 +278,7 @@ pub fn parse(args: ParseOptions) !Query {...@@ -259,7 +278,7 @@ pub fn parse(args: ParseOptions) !Query {
259278
260 const abi_ver_text = abi_it.rest();279 const abi_ver_text = abi_it.rest();
261 if (abi_it.next() != null) {280 if (abi_it.next() != null) {
262 if (result.isGnuLibC()) {281 if (Target.isGnuLibC_os_tag_abi(result.os_tag orelse builtin.os.tag, abi)) {
263 result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {282 result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
264 error.Overflow => return error.InvalidAbiVersion,283 error.Overflow => return error.InvalidAbiVersion,
265 error.InvalidVersion => return error.InvalidAbiVersion,284 error.InvalidVersion => return error.InvalidAbiVersion,
...@@ -377,168 +396,6 @@ test parseVersion {...@@ -377,168 +396,6 @@ test parseVersion {
377 try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4"));396 try std.testing.expectError(error.InvalidVersion, parseVersion("1.2.3.4"));
378}397}
379398
380/// TODO deprecated, use `std.zig.system.resolveTargetQuery`.
381pub fn getCpu(self: Query) Target.Cpu {
382 switch (self.cpu_model) {
383 .native => {
384 // This works when doing `zig build` because Zig generates a build executable using
385 // native CPU model & features. However this will not be accurate otherwise, and
386 // will need to be integrated with `std.zig.system.resolveTargetQuery`.
387 return builtin.cpu;
388 },
389 .baseline => {
390 var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch());
391 self.updateCpuFeatures(&adjusted_baseline.features);
392 return adjusted_baseline;
393 },
394 .determined_by_cpu_arch => if (self.cpu_arch == null) {
395 // This works when doing `zig build` because Zig generates a build executable using
396 // native CPU model & features. However this will not be accurate otherwise, and
397 // will need to be integrated with `std.zig.system.resolveTargetQuery`.
398 return builtin.cpu;
399 } else {
400 var adjusted_baseline = Target.Cpu.baseline(self.getCpuArch());
401 self.updateCpuFeatures(&adjusted_baseline.features);
402 return adjusted_baseline;
403 },
404 .explicit => |model| {
405 var adjusted_model = model.toCpu(self.getCpuArch());
406 self.updateCpuFeatures(&adjusted_model.features);
407 return adjusted_model;
408 },
409 }
410}
411
412pub fn getCpuArch(self: Query) Target.Cpu.Arch {
413 return self.cpu_arch orelse builtin.cpu.arch;
414}
415
416pub fn getCpuModel(self: Query) *const Target.Cpu.Model {
417 return switch (self.cpu_model) {
418 .explicit => |cpu_model| cpu_model,
419 else => self.getCpu().model,
420 };
421}
422
423pub fn getCpuFeatures(self: Query) Target.Cpu.Feature.Set {
424 return self.getCpu().features;
425}
426
427/// TODO deprecated, use `std.zig.system.resolveTargetQuery`.
428pub fn getOs(self: Query) Target.Os {
429 // `builtin.os` works when doing `zig build` because Zig generates a build executable using
430 // native OS version range. However this will not be accurate otherwise, and
431 // will need to be integrated with `std.zig.system.resolveTargetQuery`.
432 var adjusted_os = if (self.os_tag) |os_tag| os_tag.defaultVersionRange(self.getCpuArch()) else builtin.os;
433
434 if (self.os_version_min) |min| switch (min) {
435 .none => {},
436 .semver => |semver| switch (self.getOsTag()) {
437 .linux => adjusted_os.version_range.linux.range.min = semver,
438 else => adjusted_os.version_range.semver.min = semver,
439 },
440 .windows => |win_ver| adjusted_os.version_range.windows.min = win_ver,
441 };
442
443 if (self.os_version_max) |max| switch (max) {
444 .none => {},
445 .semver => |semver| switch (self.getOsTag()) {
446 .linux => adjusted_os.version_range.linux.range.max = semver,
447 else => adjusted_os.version_range.semver.max = semver,
448 },
449 .windows => |win_ver| adjusted_os.version_range.windows.max = win_ver,
450 };
451
452 if (self.glibc_version) |glibc| {
453 assert(self.isGnuLibC());
454 adjusted_os.version_range.linux.glibc = glibc;
455 }
456
457 return adjusted_os;
458}
459
460pub fn getOsTag(self: Query) Target.Os.Tag {
461 return self.os_tag orelse builtin.os.tag;
462}
463
464/// TODO deprecated, use `std.zig.system.resolveTargetQuery`.
465pub fn getOsVersionMin(self: Query) OsVersion {
466 if (self.os_version_min) |version_min| return version_min;
467 var tmp: Query = undefined;
468 tmp.updateOsVersionRange(self.getOs());
469 return tmp.os_version_min.?;
470}
471
472/// TODO deprecated, use `std.zig.system.resolveTargetQuery`.
473pub fn getOsVersionMax(self: Query) OsVersion {
474 if (self.os_version_max) |version_max| return version_max;
475 var tmp: Query = undefined;
476 tmp.updateOsVersionRange(self.getOs());
477 return tmp.os_version_max.?;
478}
479
480/// TODO deprecated, use `std.zig.system.resolveTargetQuery`.
481pub fn getAbi(self: Query) Target.Abi {
482 if (self.abi) |abi| return abi;
483
484 if (self.os_tag == null) {
485 // This works when doing `zig build` because Zig generates a build executable using
486 // native CPU model & features. However this will not be accurate otherwise, and
487 // will need to be integrated with `std.zig.system.resolveTargetQuery`.
488 return builtin.abi;
489 }
490
491 return Target.Abi.default(self.getCpuArch(), self.getOs());
492}
493
494pub fn isFreeBSD(self: Query) bool {
495 return self.getOsTag() == .freebsd;
496}
497
498pub fn isDarwin(self: Query) bool {
499 return self.getOsTag().isDarwin();
500}
501
502pub fn isNetBSD(self: Query) bool {
503 return self.getOsTag() == .netbsd;
504}
505
506pub fn isOpenBSD(self: Query) bool {
507 return self.getOsTag() == .openbsd;
508}
509
510pub fn isUefi(self: Query) bool {
511 return self.getOsTag() == .uefi;
512}
513
514pub fn isDragonFlyBSD(self: Query) bool {
515 return self.getOsTag() == .dragonfly;
516}
517
518pub fn isLinux(self: Query) bool {
519 return self.getOsTag() == .linux;
520}
521
522pub fn isWindows(self: Query) bool {
523 return self.getOsTag() == .windows;
524}
525
526pub fn exeFileExt(self: Query) [:0]const u8 {
527 return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag());
528}
529
530pub fn staticLibSuffix(self: Query) [:0]const u8 {
531 return Target.staticLibSuffix_os_abi(self.getOsTag(), self.getAbi());
532}
533
534pub fn dynamicLibSuffix(self: Query) [:0]const u8 {
535 return self.getOsTag().dynamicLibSuffix();
536}
537
538pub fn libPrefix(self: Query) [:0]const u8 {
539 return Target.libPrefix_os_abi(self.getOsTag(), self.getAbi());
540}
541
542pub fn isNativeCpu(self: Query) bool {399pub fn isNativeCpu(self: Query) bool {
543 return self.cpu_arch == null and400 return self.cpu_arch == null and
544 (self.cpu_model == .native or self.cpu_model == .determined_by_cpu_arch) and401 (self.cpu_model == .native or self.cpu_model == .determined_by_cpu_arch) and
...@@ -568,7 +425,7 @@ fn formatVersion(version: SemanticVersion, writer: anytype) !void {...@@ -568,7 +425,7 @@ fn formatVersion(version: SemanticVersion, writer: anytype) !void {
568 }425 }
569}426}
570427
571pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8 {428pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
572 if (self.isNative()) {429 if (self.isNative()) {
573 return allocator.dupe(u8, "native");430 return allocator.dupe(u8, "native");
574 }431 }
...@@ -583,14 +440,16 @@ pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8...@@ -583,14 +440,16 @@ pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8
583440
584 // The zig target syntax does not allow specifying a max os version with no min, so441 // The zig target syntax does not allow specifying a max os version with no min, so
585 // if either are present, we need the min.442 // if either are present, we need the min.
586 if (self.os_version_min != null or self.os_version_max != null) {443 if (self.os_version_min) |min| {
587 switch (self.getOsVersionMin()) {444 switch (min) {
588 .none => {},445 .none => {},
589 .semver => |v| {446 .semver => |v| {
590 try result.writer().writeAll(".");447 try result.writer().writeAll(".");
591 try formatVersion(v, result.writer());448 try formatVersion(v, result.writer());
592 },449 },
593 .windows => |v| try result.writer().print("{s}", .{v}),450 .windows => |v| {
451 try result.writer().print("{s}", .{v});
452 },
594 }453 }
595 }454 }
596 if (self.os_version_max) |max| {455 if (self.os_version_max) |max| {
...@@ -600,48 +459,88 @@ pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8...@@ -600,48 +459,88 @@ pub fn zigTriple(self: Query, allocator: mem.Allocator) error{OutOfMemory}![]u8
600 try result.writer().writeAll("...");459 try result.writer().writeAll("...");
601 try formatVersion(v, result.writer());460 try formatVersion(v, result.writer());
602 },461 },
603 .windows => |v| try result.writer().print("..{s}", .{v}),462 .windows => |v| {
463 try result.writer().print("...{s}", .{v});
464 },
604 }465 }
605 }466 }
606467
607 if (self.glibc_version) |v| {468 if (self.glibc_version) |v| {
608 try result.writer().print("-{s}.", .{@tagName(self.getAbi())});469 const name = @tagName(self.abi orelse builtin.target.abi);
470 try result.ensureUnusedCapacity(name.len + 2);
471 result.appendAssumeCapacity('-');
472 result.appendSliceAssumeCapacity(name);
473 result.appendAssumeCapacity('.');
609 try formatVersion(v, result.writer());474 try formatVersion(v, result.writer());
610 } else if (self.abi) |abi| {475 } else if (self.abi) |abi| {
611 try result.writer().print("-{s}", .{@tagName(abi)});476 const name = @tagName(abi);
477 try result.ensureUnusedCapacity(name.len + 1);
478 result.appendAssumeCapacity('-');
479 result.appendSliceAssumeCapacity(name);
612 }480 }
613481
614 return result.toOwnedSlice();482 return result.toOwnedSlice();
615}483}
616484
617pub fn allocDescription(self: Query, allocator: mem.Allocator) ![]u8 {485/// Renders the query into a textual representation that can be parsed via the
618 // TODO is there anything else worthy of the description that is not486/// `-mcpu` flag passed to the Zig compiler.
619 // already captured in the triple?487/// Appends the result to `buffer`.
620 return self.zigTriple(allocator);488pub fn serializeCpu(q: Query, buffer: *std.ArrayList(u8)) Allocator.Error!void {
621}489 try buffer.ensureUnusedCapacity(8);
490 switch (q.cpu_model) {
491 .native => {
492 buffer.appendSliceAssumeCapacity("native");
493 },
494 .baseline => {
495 buffer.appendSliceAssumeCapacity("baseline");
496 },
497 .determined_by_cpu_arch => {
498 if (q.cpu_arch == null) {
499 buffer.appendSliceAssumeCapacity("native");
500 } else {
501 buffer.appendSliceAssumeCapacity("baseline");
502 }
503 },
504 .explicit => |model| {
505 try buffer.appendSlice(model.name);
506 },
507 }
622508
623pub fn linuxTriple(self: Query, allocator: mem.Allocator) ![]u8 {509 if (q.cpu_features_add.isEmpty() and q.cpu_features_sub.isEmpty()) {
624 return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi());510 // The CPU name alone is sufficient.
625}511 return;
512 }
626513
627pub fn isGnuLibC(self: Query) bool {514 const cpu_arch = q.cpu_arch orelse builtin.cpu.arch;
628 return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi());515 const all_features = cpu_arch.allFeaturesList();
516
517 for (all_features, 0..) |feature, i_usize| {
518 const i: Target.Cpu.Feature.Set.Index = @intCast(i_usize);
519 try buffer.ensureUnusedCapacity(feature.name.len + 1);
520 if (q.cpu_features_sub.isEnabled(i)) {
521 buffer.appendAssumeCapacity('-');
522 buffer.appendSliceAssumeCapacity(feature.name);
523 } else if (q.cpu_features_add.isEnabled(i)) {
524 buffer.appendAssumeCapacity('+');
525 buffer.appendSliceAssumeCapacity(feature.name);
526 }
527 }
629}528}
630529
631pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void {530pub fn serializeCpuAlloc(q: Query, ally: Allocator) Allocator.Error![]u8 {
632 assert(self.isGnuLibC());531 var buffer = std.ArrayList(u8).init(ally);
633 self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch };532 try serializeCpu(q, &buffer);
533 return buffer.toOwnedSlice();
634}534}
635535
636pub fn getObjectFormat(self: Query) Target.ObjectFormat {536pub fn allocDescription(self: Query, allocator: Allocator) ![]u8 {
637 return self.ofmt orelse Target.ObjectFormat.default(self.getOsTag(), self.getCpuArch());537 // TODO is there anything else worthy of the description that is not
538 // already captured in the triple?
539 return self.zigTriple(allocator);
638}540}
639541
640pub fn updateCpuFeatures(self: Query, set: *Target.Cpu.Feature.Set) void {542pub fn setGnuLibCVersion(self: *Query, major: u32, minor: u32, patch: u32) void {
641 set.removeFeatureSet(self.cpu_features_sub);543 self.glibc_version = SemanticVersion{ .major = major, .minor = minor, .patch = patch };
642 set.addFeatureSet(self.cpu_features_add);
643 set.populateDependencies(self.getCpuArch().allFeaturesList());
644 set.removeFeatureSet(self.cpu_features_sub);
645}544}
646545
647fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !void {546fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !void {
...@@ -653,7 +552,7 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !...@@ -653,7 +552,7 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
653 result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse552 result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse
654 return error.UnknownOperatingSystem;553 return error.UnknownOperatingSystem;
655 }554 }
656 const tag = result.getOsTag();555 const tag = result.os_tag orelse builtin.os.tag;
657 diags.os_tag = tag;556 diags.os_tag = tag;
658557
659 const version_text = it.rest();558 const version_text = it.rest();
...@@ -741,12 +640,35 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !...@@ -741,12 +640,35 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
741 }640 }
742}641}
743642
643pub fn eql(a: Query, b: Query) bool {
644 if (a.cpu_arch != b.cpu_arch) return false;
645 if (!a.cpu_model.eql(b.cpu_model)) return false;
646 if (!a.cpu_features_add.eql(b.cpu_features_add)) return false;
647 if (!a.cpu_features_sub.eql(b.cpu_features_sub)) return false;
648 if (a.os_tag != b.os_tag) return false;
649 if (!OsVersion.eqlOpt(a.os_version_min, b.os_version_min)) return false;
650 if (!OsVersion.eqlOpt(a.os_version_max, b.os_version_max)) return false;
651 if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false;
652 if (a.abi != b.abi) return false;
653 if (!a.dynamic_linker.eql(b.dynamic_linker)) return false;
654 if (a.ofmt != b.ofmt) return false;
655
656 return true;
657}
658
659fn versionEqualOpt(a: ?SemanticVersion, b: ?SemanticVersion) bool {
660 if (a == null and b == null) return true;
661 if (a == null or b == null) return false;
662 return SemanticVersion.order(a.?, b.?) == .eq;
663}
664
744const Query = @This();665const Query = @This();
745const std = @import("../std.zig");666const std = @import("../std.zig");
746const builtin = @import("builtin");667const builtin = @import("builtin");
747const assert = std.debug.assert;668const assert = std.debug.assert;
748const Target = std.Target;669const Target = std.Target;
749const mem = std.mem;670const mem = std.mem;
671const Allocator = std.mem.Allocator;
750672
751test parse {673test parse {
752 if (builtin.target.isGnuLibC()) {674 if (builtin.target.isGnuLibC()) {
...@@ -760,7 +682,7 @@ test parse {...@@ -760,7 +682,7 @@ test parse {
760 const triple = std.fmt.bufPrint(682 const triple = std.fmt.bufPrint(
761 buf[0..],683 buf[0..],
762 "native-native-{s}.2.1.1",684 "native-native-{s}.2.1.1",
763 .{@tagName(builtin.abi)},685 .{@tagName(builtin.target.abi)},
764 ) catch unreachable;686 ) catch unreachable;
765687
766 try std.testing.expectEqualSlices(u8, triple, text);688 try std.testing.expectEqualSlices(u8, triple, text);
...@@ -789,7 +711,7 @@ test parse {...@@ -789,7 +711,7 @@ test parse {
789 .arch_os_abi = "x86_64-linux-gnu",711 .arch_os_abi = "x86_64-linux-gnu",
790 .cpu_features = "x86_64-sse-sse2-avx-cx8",712 .cpu_features = "x86_64-sse-sse2-avx-cx8",
791 });713 });
792 const target = query.toTarget();714 const target = try std.zig.system.resolveTargetQuery(query);
793715
794 try std.testing.expect(target.os.tag == .linux);716 try std.testing.expect(target.os.tag == .linux);
795 try std.testing.expect(target.abi == .gnu);717 try std.testing.expect(target.abi == .gnu);
...@@ -814,7 +736,7 @@ test parse {...@@ -814,7 +736,7 @@ test parse {
814 .arch_os_abi = "arm-linux-musleabihf",736 .arch_os_abi = "arm-linux-musleabihf",
815 .cpu_features = "generic+v8a",737 .cpu_features = "generic+v8a",
816 });738 });
817 const target = query.toTarget();739 const target = try std.zig.system.resolveTargetQuery(query);
818740
819 try std.testing.expect(target.os.tag == .linux);741 try std.testing.expect(target.os.tag == .linux);
820 try std.testing.expect(target.abi == .musleabihf);742 try std.testing.expect(target.abi == .musleabihf);
...@@ -831,7 +753,7 @@ test parse {...@@ -831,7 +753,7 @@ test parse {
831 .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27",753 .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27",
832 .cpu_features = "generic+v8a",754 .cpu_features = "generic+v8a",
833 });755 });
834 const target = query.toTarget();756 const target = try std.zig.system.resolveTargetQuery(query);
835757
836 try std.testing.expect(target.cpu.arch == .aarch64);758 try std.testing.expect(target.cpu.arch == .aarch64);
837 try std.testing.expect(target.os.tag == .linux);759 try std.testing.expect(target.os.tag == .linux);
lib/std/zig.zig+42-4
...@@ -1,7 +1,4 @@...@@ -1,7 +1,4 @@
1const std = @import("std.zig");
2const tokenizer = @import("zig/tokenizer.zig");
3pub const fmt = @import("zig/fmt.zig");1pub const fmt = @import("zig/fmt.zig");
4const assert = std.debug.assert;
52
6pub const ErrorBundle = @import("zig/ErrorBundle.zig");3pub const ErrorBundle = @import("zig/ErrorBundle.zig");
7pub const Server = @import("zig/Server.zig");4pub const Server = @import("zig/Server.zig");
...@@ -115,7 +112,7 @@ pub const BinNameOptions = struct {...@@ -115,7 +112,7 @@ pub const BinNameOptions = struct {
115};112};
116113
117/// Returns the standard file system basename of a binary generated by the Zig compiler.114/// Returns the standard file system basename of a binary generated by the Zig compiler.
118pub fn binNameAlloc(allocator: std.mem.Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 {115pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 {
119 const root_name = options.root_name;116 const root_name = options.root_name;
120 const target = options.target;117 const target = options.target;
121 switch (target.ofmt) {118 switch (target.ofmt) {
...@@ -281,6 +278,47 @@ pub const BuildId = union(enum) {...@@ -281,6 +278,47 @@ pub const BuildId = union(enum) {
281 }278 }
282};279};
283280
281/// Renders a `std.Target.Cpu` value into a textual representation that can be parsed
282/// via the `-mcpu` flag passed to the Zig compiler.
283/// Appends the result to `buffer`.
284pub fn serializeCpu(buffer: *std.ArrayList(u8), cpu: std.Target.Cpu) Allocator.Error!void {
285 const all_features = cpu.arch.allFeaturesList();
286 var populated_cpu_features = cpu.model.features;
287 populated_cpu_features.populateDependencies(all_features);
288
289 try buffer.appendSlice(cpu.model.name);
290
291 if (populated_cpu_features.eql(cpu.features)) {
292 // The CPU name alone is sufficient.
293 return;
294 }
295
296 for (all_features, 0..) |feature, i_usize| {
297 const i: std.Target.Cpu.Feature.Set.Index = @intCast(i_usize);
298 const in_cpu_set = populated_cpu_features.isEnabled(i);
299 const in_actual_set = cpu.features.isEnabled(i);
300 try buffer.ensureUnusedCapacity(feature.name.len + 1);
301 if (in_cpu_set and !in_actual_set) {
302 buffer.appendAssumeCapacity('-');
303 buffer.appendSliceAssumeCapacity(feature.name);
304 } else if (!in_cpu_set and in_actual_set) {
305 buffer.appendAssumeCapacity('+');
306 buffer.appendSliceAssumeCapacity(feature.name);
307 }
308 }
309}
310
311pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![]u8 {
312 var buffer = std.ArrayList(u8).init(ally);
313 try serializeCpu(&buffer, cpu);
314 return buffer.toOwnedSlice();
315}
316
317const std = @import("std.zig");
318const tokenizer = @import("zig/tokenizer.zig");
319const assert = std.debug.assert;
320const Allocator = std.mem.Allocator;
321
284test {322test {
285 @import("std").testing.refAllDecls(@This());323 @import("std").testing.refAllDecls(@This());
286}324}
lib/std/zig/system.zig+23-6
...@@ -163,7 +163,8 @@ pub const DetectError = error{...@@ -163,7 +163,8 @@ pub const DetectError = error{
163/// components by detecting the native system, and then resolves163/// components by detecting the native system, and then resolves
164/// standard/default parts relative to that.164/// standard/default parts relative to that.
165pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {165pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
166 var os = query.getOsTag().defaultVersionRange(query.getCpuArch());166 const query_os_tag = query.os_tag orelse builtin.os.tag;
167 var os = query_os_tag.defaultVersionRange(query.cpu_arch orelse builtin.cpu.arch);
167 if (query.os_tag == null) {168 if (query.os_tag == null) {
168 switch (builtin.target.os.tag) {169 switch (builtin.target.os.tag) {
169 .linux => {170 .linux => {
...@@ -292,7 +293,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {...@@ -292,7 +293,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
292293
293 if (query.os_version_min) |min| switch (min) {294 if (query.os_version_min) |min| switch (min) {
294 .none => {},295 .none => {},
295 .semver => |semver| switch (query.getOsTag()) {296 .semver => |semver| switch (os.tag) {
296 .linux => os.version_range.linux.range.min = semver,297 .linux => os.version_range.linux.range.min = semver,
297 else => os.version_range.semver.min = semver,298 else => os.version_range.semver.min = semver,
298 },299 },
...@@ -301,7 +302,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {...@@ -301,7 +302,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
301302
302 if (query.os_version_max) |max| switch (max) {303 if (query.os_version_max) |max| switch (max) {
303 .none => {},304 .none => {},
304 .semver => |semver| switch (query.getOsTag()) {305 .semver => |semver| switch (os.tag) {
305 .linux => os.version_range.linux.range.max = semver,306 .linux => os.version_range.linux.range.max = semver,
306 else => os.version_range.semver.max = semver,307 else => os.version_range.semver.max = semver,
307 },308 },
...@@ -309,13 +310,12 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {...@@ -309,13 +310,12 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
309 };310 };
310311
311 if (query.glibc_version) |glibc| {312 if (query.glibc_version) |glibc| {
312 assert(query.isGnuLibC());
313 os.version_range.linux.glibc = glibc;313 os.version_range.linux.glibc = glibc;
314 }314 }
315315
316 // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the316 // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the
317 // native CPU architecture as being different than the current target), we use this:317 // native CPU architecture as being different than the current target), we use this:
318 const cpu_arch = query.getCpuArch();318 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;
319319
320 const cpu = switch (query.cpu_model) {320 const cpu = switch (query.cpu_model) {
321 .native => detectNativeCpuAndFeatures(cpu_arch, os, query),321 .native => detectNativeCpuAndFeatures(cpu_arch, os, query),
...@@ -361,10 +361,27 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {...@@ -361,10 +361,27 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
361 },361 },
362 else => {},362 else => {},
363 }363 }
364 query.updateCpuFeatures(&result.cpu.features);364 updateCpuFeatures(
365 &result.cpu.features,
366 cpu_arch.allFeaturesList(),
367 query.cpu_features_add,
368 query.cpu_features_sub,
369 );
365 return result;370 return result;
366}371}
367372
373fn updateCpuFeatures(
374 set: *Target.Cpu.Feature.Set,
375 all_features_list: []const Target.Cpu.Feature,
376 add_set: Target.Cpu.Feature.Set,
377 sub_set: Target.Cpu.Feature.Set,
378) void {
379 set.removeFeatureSet(sub_set);
380 set.addFeatureSet(add_set);
381 set.populateDependencies(all_features_list);
382 set.removeFeatureSet(sub_set);
383}
384
368fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu {385fn detectNativeCpuAndFeatures(cpu_arch: Target.Cpu.Arch, os: Target.Os, query: Target.Query) ?Target.Cpu {
369 // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`,386 // Here we switch on a comptime value rather than `cpu_arch`. This is valid because `cpu_arch`,
370 // although it is a runtime value, is guaranteed to be one of the architectures in the set387 // although it is a runtime value, is guaranteed to be one of the architectures in the set
src/libc_installation.zig+6-7
...@@ -41,7 +41,7 @@ pub const LibCInstallation = struct {...@@ -41,7 +41,7 @@ pub const LibCInstallation = struct {
41 pub fn parse(41 pub fn parse(
42 allocator: Allocator,42 allocator: Allocator,
43 libc_file: []const u8,43 libc_file: []const u8,
44 target: std.Target.Query,44 target: std.Target,
45 ) !LibCInstallation {45 ) !LibCInstallation {
46 var self: LibCInstallation = .{};46 var self: LibCInstallation = .{};
4747
...@@ -95,24 +95,23 @@ pub const LibCInstallation = struct {...@@ -95,24 +95,23 @@ pub const LibCInstallation = struct {
95 return error.ParseError;95 return error.ParseError;
96 }96 }
9797
98 const os_tag = target.getOsTag();98 const os_tag = target.os.tag;
99 if (self.crt_dir == null and !target.isDarwin()) {99 if (self.crt_dir == null and !target.isDarwin()) {
100 log.err("crt_dir may not be empty for {s}\n", .{@tagName(os_tag)});100 log.err("crt_dir may not be empty for {s}\n", .{@tagName(os_tag)});
101 return error.ParseError;101 return error.ParseError;
102 }102 }
103103
104 const abi = target.getAbi();104 if (self.msvc_lib_dir == null and os_tag == .windows and target.abi == .msvc) {
105 if (self.msvc_lib_dir == null and target.isWindows() and abi == .msvc) {
106 log.err("msvc_lib_dir may not be empty for {s}-{s}\n", .{105 log.err("msvc_lib_dir may not be empty for {s}-{s}\n", .{
107 @tagName(os_tag),106 @tagName(os_tag),
108 @tagName(abi),107 @tagName(target.abi),
109 });108 });
110 return error.ParseError;109 return error.ParseError;
111 }110 }
112 if (self.kernel32_lib_dir == null and target.isWindows() and abi == .msvc) {111 if (self.kernel32_lib_dir == null and os_tag == .windows and target.abi == .msvc) {
113 log.err("kernel32_lib_dir may not be empty for {s}-{s}\n", .{112 log.err("kernel32_lib_dir may not be empty for {s}-{s}\n", .{
114 @tagName(os_tag),113 @tagName(os_tag),
115 @tagName(abi),114 @tagName(target.abi),
116 });115 });
117 return error.ParseError;116 return error.ParseError;
118 }117 }
src/main.zig+8-8
...@@ -2696,13 +2696,13 @@ fn buildOutputType(...@@ -2696,13 +2696,13 @@ fn buildOutputType(
2696 }2696 }
26972697
2698 if (use_lld) |opt| {2698 if (use_lld) |opt| {
2699 if (opt and target_query.isDarwin()) {2699 if (opt and target.isDarwin()) {
2700 fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{});2700 fatal("LLD requested with Mach-O object format. Only the self-hosted linker is supported for this target.", .{});
2701 }2701 }
2702 }2702 }
27032703
2704 if (want_lto) |opt| {2704 if (want_lto) |opt| {
2705 if (opt and target_query.isDarwin()) {2705 if (opt and target.isDarwin()) {
2706 fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{});2706 fatal("LTO is not yet supported with the Mach-O object format. More details: https://github.com/ziglang/zig/issues/8680", .{});
2707 }2707 }
2708 }2708 }
...@@ -2772,7 +2772,7 @@ fn buildOutputType(...@@ -2772,7 +2772,7 @@ fn buildOutputType(
27722772
2773 var libc_installation: ?LibCInstallation = null;2773 var libc_installation: ?LibCInstallation = null;
2774 if (libc_paths_file) |paths_file| {2774 if (libc_paths_file) |paths_file| {
2775 libc_installation = LibCInstallation.parse(arena, paths_file, target_query) catch |err| {2775 libc_installation = LibCInstallation.parse(arena, paths_file, target) catch |err| {
2776 fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) });2776 fatal("unable to parse libc paths file at path {s}: {s}", .{ paths_file, @errorName(err) });
2777 };2777 };
2778 }2778 }
...@@ -2865,7 +2865,7 @@ fn buildOutputType(...@@ -2865,7 +2865,7 @@ fn buildOutputType(
2865 libc_installation = try LibCInstallation.findNative(.{2865 libc_installation = try LibCInstallation.findNative(.{
2866 .allocator = arena,2866 .allocator = arena,
2867 .verbose = true,2867 .verbose = true,
2868 .target = target_query.toTarget(),2868 .target = target,
2869 });2869 });
28702870
2871 try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? });2871 try lib_dirs.appendSlice(&.{ libc_installation.?.msvc_lib_dir.?, libc_installation.?.kernel32_lib_dir.? });
...@@ -4755,6 +4755,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {...@@ -4755,6 +4755,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
4755 const target_query = try parseTargetQueryOrReportFatalError(gpa, .{4755 const target_query = try parseTargetQueryOrReportFatalError(gpa, .{
4756 .arch_os_abi = target_arch_os_abi,4756 .arch_os_abi = target_arch_os_abi,
4757 });4757 });
4758 const target = try std.zig.system.resolveTargetQuery(target_query);
47584759
4759 if (print_includes) {4760 if (print_includes) {
4760 var arena_state = std.heap.ArenaAllocator.init(gpa);4761 var arena_state = std.heap.ArenaAllocator.init(gpa);
...@@ -4764,7 +4765,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {...@@ -4764,7 +4765,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
4764 const libc_installation: ?*LibCInstallation = libc: {4765 const libc_installation: ?*LibCInstallation = libc: {
4765 if (input_file) |libc_file| {4766 if (input_file) |libc_file| {
4766 const libc = try arena.create(LibCInstallation);4767 const libc = try arena.create(LibCInstallation);
4767 libc.* = LibCInstallation.parse(arena, libc_file, target_query) catch |err| {4768 libc.* = LibCInstallation.parse(arena, libc_file, target) catch |err| {
4768 fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });4769 fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });
4769 };4770 };
4770 break :libc libc;4771 break :libc libc;
...@@ -4779,7 +4780,6 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {...@@ -4779,7 +4780,6 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
4779 };4780 };
4780 defer zig_lib_directory.handle.close();4781 defer zig_lib_directory.handle.close();
47814782
4782 const target = target_query.toTarget();
4783 const is_native_abi = target_query.isNativeAbi();4783 const is_native_abi = target_query.isNativeAbi();
47844784
4785 const libc_dirs = Compilation.detectLibCIncludeDirs(4785 const libc_dirs = Compilation.detectLibCIncludeDirs(
...@@ -4810,7 +4810,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {...@@ -4810,7 +4810,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
4810 }4810 }
48114811
4812 if (input_file) |libc_file| {4812 if (input_file) |libc_file| {
4813 var libc = LibCInstallation.parse(gpa, libc_file, target_query) catch |err| {4813 var libc = LibCInstallation.parse(gpa, libc_file, target) catch |err| {
4814 fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });4814 fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });
4815 };4815 };
4816 defer libc.deinit(gpa);4816 defer libc.deinit(gpa);
...@@ -4821,7 +4821,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {...@@ -4821,7 +4821,7 @@ pub fn cmdLibC(gpa: Allocator, args: []const []const u8) !void {
4821 var libc = LibCInstallation.findNative(.{4821 var libc = LibCInstallation.findNative(.{
4822 .allocator = gpa,4822 .allocator = gpa,
4823 .verbose = true,4823 .verbose = true,
4824 .target = try std.zig.system.resolveTargetQuery(target_query),4824 .target = target,
4825 }) catch |err| {4825 }) catch |err| {
4826 fatal("unable to detect native libc: {s}", .{@errorName(err)});4826 fatal("unable to detect native libc: {s}", .{@errorName(err)});
4827 };4827 };
test/tests.zig+23-25
...@@ -1036,14 +1036,17 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1036,14 +1036,17 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
10361036
1037 for (test_targets) |test_target| {1037 for (test_targets) |test_target| {
1038 const is_native = test_target.target.isNative() or1038 const is_native = test_target.target.isNative() or
1039 (test_target.target.getOsTag() == builtin.os.tag and1039 (test_target.target.os_tag == builtin.os.tag and
1040 test_target.target.getCpuArch() == builtin.cpu.arch);1040 test_target.target.cpu_arch == builtin.cpu.arch);
10411041
1042 if (options.skip_non_native and !is_native)1042 if (options.skip_non_native and !is_native)
1043 continue;1043 continue;
10441044
1045 const resolved_target = b.resolveTargetQuery(test_target.target);
1046 const target = resolved_target.target;
1047
1045 if (options.skip_cross_glibc and !test_target.target.isNative() and1048 if (options.skip_cross_glibc and !test_target.target.isNative() and
1046 test_target.target.isGnuLibC() and test_target.link_libc == true)1049 target.isGnuLibC() and test_target.link_libc == true)
1047 continue;1050 continue;
10481051
1049 if (options.skip_libc and test_target.link_libc == true)1052 if (options.skip_libc and test_target.link_libc == true)
...@@ -1053,35 +1056,30 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1053,35 +1056,30 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
1053 continue;1056 continue;
10541057
1055 // TODO get compiler-rt tests passing for self-hosted backends.1058 // TODO get compiler-rt tests passing for self-hosted backends.
1056 if ((test_target.target.getCpuArch() != .x86_64 or1059 if ((target.cpu.arch != .x86_64 or target.ofmt != .elf) and
1057 test_target.target.getObjectFormat() != .elf) and
1058 test_target.use_llvm == false and mem.eql(u8, options.name, "compiler-rt"))1060 test_target.use_llvm == false and mem.eql(u8, options.name, "compiler-rt"))
1059 continue;1061 continue;
10601062
1061 // TODO get compiler-rt tests passing for wasm32-wasi1063 // TODO get compiler-rt tests passing for wasm32-wasi
1062 // currently causes "LLVM ERROR: Unable to expand fixed point multiplication."1064 // currently causes "LLVM ERROR: Unable to expand fixed point multiplication."
1063 if (test_target.target.getCpuArch() == .wasm32 and1065 if (target.cpu.arch == .wasm32 and target.os.tag == .wasi and
1064 test_target.target.getOsTag() == .wasi and
1065 mem.eql(u8, options.name, "compiler-rt"))1066 mem.eql(u8, options.name, "compiler-rt"))
1066 {1067 {
1067 continue;1068 continue;
1068 }1069 }
10691070
1070 // TODO get universal-libc tests passing for other self-hosted backends.1071 // TODO get universal-libc tests passing for other self-hosted backends.
1071 if (test_target.target.getCpuArch() != .x86_64 and1072 if (target.cpu.arch != .x86_64 and
1072 test_target.use_llvm == false and mem.eql(u8, options.name, "universal-libc"))1073 test_target.use_llvm == false and mem.eql(u8, options.name, "universal-libc"))
1073 continue;1074 continue;
10741075
1075 // TODO get std lib tests passing for other self-hosted backends.1076 // TODO get std lib tests passing for other self-hosted backends.
1076 if ((test_target.target.getCpuArch() != .x86_64 or1077 if ((target.cpu.arch != .x86_64 or target.os.tag != .linux) and
1077 test_target.target.getOsTag() != .linux) and
1078 test_target.use_llvm == false and mem.eql(u8, options.name, "std"))1078 test_target.use_llvm == false and mem.eql(u8, options.name, "std"))
1079 continue;1079 continue;
10801080
1081 if (test_target.target.getCpuArch() == .x86_64 and1081 if (target.cpu.arch == .x86_64 and target.os.tag == .windows and
1082 test_target.target.getOsTag() == .windows and1082 test_target.target.cpu_arch == null and test_target.optimize_mode != .Debug and
1083 test_target.target.cpu_arch == null and
1084 test_target.optimize_mode != .Debug and
1085 mem.eql(u8, options.name, "std"))1083 mem.eql(u8, options.name, "std"))
1086 {1084 {
1087 // https://github.com/ziglang/zig/issues/179021085 // https://github.com/ziglang/zig/issues/17902
...@@ -1094,11 +1092,11 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1094,11 +1092,11 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
1094 if (!want_this_mode) continue;1092 if (!want_this_mode) continue;
10951093
1096 const libc_suffix = if (test_target.link_libc == true) "-libc" else "";1094 const libc_suffix = if (test_target.link_libc == true) "-libc" else "";
1097 const triple_txt = test_target.target.zigTriple(b.allocator) catch @panic("OOM");1095 const triple_txt = target.zigTriple(b.allocator) catch @panic("OOM");
1098 const model_txt = test_target.target.getCpuModel().name;1096 const model_txt = target.cpu.model.name;
10991097
1100 // wasm32-wasi builds need more RAM, idk why1098 // wasm32-wasi builds need more RAM, idk why
1101 const max_rss = if (test_target.target.getOs().tag == .wasi)1099 const max_rss = if (target.os.tag == .wasi)
1102 options.max_rss * 21100 options.max_rss * 2
1103 else1101 else
1104 options.max_rss;1102 options.max_rss;
...@@ -1106,7 +1104,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1106,7 +1104,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
1106 const these_tests = b.addTest(.{1104 const these_tests = b.addTest(.{
1107 .root_source_file = .{ .path = options.root_src },1105 .root_source_file = .{ .path = options.root_src },
1108 .optimize = test_target.optimize_mode,1106 .optimize = test_target.optimize_mode,
1109 .target = b.resolveTargetQuery(test_target.target),1107 .target = resolved_target,
1110 .max_rss = max_rss,1108 .max_rss = max_rss,
1111 .filter = options.test_filter,1109 .filter = options.test_filter,
1112 .link_libc = test_target.link_libc,1110 .link_libc = test_target.link_libc,
...@@ -1120,7 +1118,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1120,7 +1118,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
1120 const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else "";1118 const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else "";
1121 const backend_suffix = if (test_target.use_llvm == true)1119 const backend_suffix = if (test_target.use_llvm == true)
1122 "-llvm"1120 "-llvm"
1123 else if (test_target.target.ofmt == std.Target.ObjectFormat.c)1121 else if (target.ofmt == std.Target.ObjectFormat.c)
1124 "-cbe"1122 "-cbe"
1125 else if (test_target.use_llvm == false)1123 else if (test_target.use_llvm == false)
1126 "-selfhosted"1124 "-selfhosted"
...@@ -1131,7 +1129,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1131,7 +1129,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
11311129
1132 these_tests.addIncludePath(.{ .path = "test" });1130 these_tests.addIncludePath(.{ .path = "test" });
11331131
1134 if (test_target.target.getOs().tag == .wasi) {1132 if (target.os.tag == .wasi) {
1135 // WASI's default stack size can be too small for some big tests.1133 // WASI's default stack size can be too small for some big tests.
1136 these_tests.stack_size = 2 * 1024 * 1024;1134 these_tests.stack_size = 2 * 1024 * 1024;
1137 }1135 }
...@@ -1148,14 +1146,14 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1148,14 +1146,14 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
1148 use_pic,1146 use_pic,
1149 });1147 });
11501148
1151 if (test_target.target.ofmt == std.Target.ObjectFormat.c) {1149 if (target.ofmt == std.Target.ObjectFormat.c) {
1152 var altered_target = test_target.target;1150 var altered_query = test_target.target;
1153 altered_target.ofmt = null;1151 altered_query.ofmt = null;
11541152
1155 const compile_c = b.addExecutable(.{1153 const compile_c = b.addExecutable(.{
1156 .name = qualified_name,1154 .name = qualified_name,
1157 .link_libc = test_target.link_libc,1155 .link_libc = test_target.link_libc,
1158 .target = b.resolveTargetQuery(altered_target),1156 .target = b.resolveTargetQuery(altered_query),
1159 .zig_lib_dir = .{ .path = "lib" },1157 .zig_lib_dir = .{ .path = "lib" },
1160 });1158 });
1161 compile_c.addCSourceFile(.{1159 compile_c.addCSourceFile(.{
...@@ -1179,7 +1177,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1179,7 +1177,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
1179 },1177 },
1180 });1178 });
1181 compile_c.addIncludePath(.{ .path = "lib" }); // for zig.h1179 compile_c.addIncludePath(.{ .path = "lib" }); // for zig.h
1182 if (test_target.target.getOsTag() == .windows) {1180 if (target.os.tag == .windows) {
1183 if (true) {1181 if (true) {
1184 // Unfortunately this requires about 8G of RAM for clang to compile1182 // Unfortunately this requires about 8G of RAM for clang to compile
1185 // and our Windows CI runners do not have this much.1183 // and our Windows CI runners do not have this much.