| author | |
| committer | |
| log | dbe4d72bcfb20fc43713781679a0d23aea0a17d9 |
| tree | 7ba5a5bc8683a089615d18ca9e5dcc73a2f0c899 |
| parent | 87b9e744dda465ecf7663e2463066ea26a44e63a |
| signature | Commit is signed but in an unrecognized format. |
Zig now supports a more fine-grained sense of what is native and what is
not. Some examples:
This is now allowed:
-target native
Different OS but native CPU, default Windows C ABI:
-target native-windows
This could be useful for example when running in Wine.
Different CPU but native OS, native C ABI.
-target x86_64-native -mcpu=skylake
Different C ABI but otherwise native target:
-target native-native-musl
-target native-native-gnu
Lots of breaking changes to related std lib APIs.
Calls to getOs() will need to be changed to getOsTag().
Calls to getArch() will need to be changed to getCpuArch().
Usage of Target.Cross and Target.Native need to be updated to use
CrossTarget API.
`std.build.Builder.standardTargetOptions` is changed to accept its
parameters as a struct with default values. It now has the ability to
specify a whitelist of targets allowed, as well as the default target.
Rather than two different ways of collecting the target, it's now always
a string that is validated, and prints helpful diagnostics for invalid
targets. This feature should now be actually useful, and contributions
welcome to further improve the user experience.
`std.build.LibExeObjStep.setTheTarget` is removed.
`std.build.LibExeObjStep.setTarget` is updated to take a CrossTarget
parameter.
`std.build.LibExeObjStep.setTargetGLibC` is removed. glibc versions are
handled in the CrossTarget API and can be specified with the `-target`
triple.
`std.builtin.Version` gains a `format` method.14 files changed, 1286 insertions(+), 937 deletions(-)
build.zig+1-1| ... | @@ -298,7 +298,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { | ... | @@ -298,7 +298,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 298 | } | 298 | } |
| 299 | dependOnLib(b, exe, ctx.llvm); | 299 | dependOnLib(b, exe, ctx.llvm); |
| 300 | 300 | ||
| 301 | if (exe.target.getOs() == .linux) { | 301 | if (exe.target.getOsTag() == .linux) { |
| 302 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", | 302 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", |
| 303 | \\Unable to determine path to libstdc++.a | 303 | \\Unable to determine path to libstdc++.a |
| 304 | \\On Fedora, install libstdc++-static and try again. | 304 | \\On Fedora, install libstdc++-static and try again. |
doc/docgen.zig+2-2| ... | @@ -10,8 +10,8 @@ const testing = std.testing; | ... | @@ -10,8 +10,8 @@ const testing = std.testing; |
| 10 | 10 | ||
| 11 | const max_doc_file_size = 10 * 1024 * 1024; | 11 | const max_doc_file_size = 10 * 1024 * 1024; |
| 12 | 12 | ||
| 13 | const exe_ext = @as(std.build.Target, std.build.Target.Native).exeFileExt(); | 13 | const exe_ext = @as(std.zig.CrossTarget, .{}).exeFileExt(); |
| 14 | const obj_ext = @as(std.build.Target, std.build.Target.Native).oFileExt(); | 14 | const obj_ext = @as(std.zig.CrossTarget, .{}).oFileExt(); |
| 15 | const tmp_dir_name = "docgen_tmp"; | 15 | const tmp_dir_name = "docgen_tmp"; |
| 16 | const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext; | 16 | const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext; |
| 17 | 17 |
lib/std/build.zig+108-190| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = std.builtin; |
| 3 | const io = std.io; | 3 | const io = std.io; |
| 4 | const fs = std.fs; | 4 | const fs = std.fs; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| ... | @@ -15,6 +15,7 @@ const BufSet = std.BufSet; | ... | @@ -15,6 +15,7 @@ const BufSet = std.BufSet; |
| 15 | const BufMap = std.BufMap; | 15 | const BufMap = std.BufMap; |
| 16 | const fmt_lib = std.fmt; | 16 | const fmt_lib = std.fmt; |
| 17 | const File = std.fs.File; | 17 | const File = std.fs.File; |
| 18 | const CrossTarget = std.zig.CrossTarget; | ||
| 18 | 19 | ||
| 19 | pub const FmtStep = @import("build/fmt.zig").FmtStep; | 20 | pub const FmtStep = @import("build/fmt.zig").FmtStep; |
| 20 | pub const TranslateCStep = @import("build/translate_c.zig").TranslateCStep; | 21 | pub const TranslateCStep = @import("build/translate_c.zig").TranslateCStep; |
| ... | @@ -521,24 +522,77 @@ pub const Builder = struct { | ... | @@ -521,24 +522,77 @@ pub const Builder = struct { |
| 521 | return mode; | 522 | return mode; |
| 522 | } | 523 | } |
| 523 | 524 | ||
| 524 | /// Exposes standard `zig build` options for choosing a target. Pass `null` to support all targets. | 525 | pub const StandardTargetOptionsArgs = struct { |
| 525 | pub fn standardTargetOptions(self: *Builder, supported_targets: ?[]const Target) Target { | 526 | whitelist: ?[]const CrossTarget = null, |
| 526 | if (supported_targets) |target_list| { | 527 | |
| 527 | // TODO detect multiple args and emit an error message | 528 | default_target: CrossTarget = .{}, |
| 528 | // there's probably a better way to collect the target | 529 | }; |
| 529 | for (target_list) |targ| { | 530 | |
| 530 | const targ_str = targ.zigTriple(self.allocator) catch unreachable; | 531 | /// Exposes standard `zig build` options for choosing a target. |
| 531 | const targ_desc = targ.allocDescription(self.allocator) catch unreachable; | 532 | pub fn standardTargetOptions(self: *Builder, args: StandardTargetOptionsArgs) CrossTarget { |
| 532 | const this_targ_opt = self.option(bool, targ_str, targ_desc) orelse false; | 533 | const triple = self.option( |
| 533 | if (this_targ_opt) { | 534 | []const u8, |
| 534 | return targ; | 535 | "target", |
| 536 | "The Arch, OS, and ABI to build for.", | ||
| 537 | ) orelse return args.default_target; | ||
| 538 | |||
| 539 | // TODO add cpu and features as part of the target triple | ||
| 540 | |||
| 541 | var diags: std.Target.ParseOptions.Diagnostics = .{}; | ||
| 542 | const selected_target = CrossTarget.parse(.{ | ||
| 543 | .arch_os_abi = triple, | ||
| 544 | .diagnostics = &diags, | ||
| 545 | }) catch |err| switch (err) { | ||
| 546 | error.UnknownCpuModel => { | ||
| 547 | std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ | ||
| 548 | diags.cpu_name.?, | ||
| 549 | @tagName(diags.arch.?), | ||
| 550 | }); | ||
| 551 | for (diags.arch.?.allCpuModels()) |cpu| { | ||
| 552 | std.debug.warn(" {}\n", .{cpu.name}); | ||
| 553 | } | ||
| 554 | process.exit(1); | ||
| 555 | }, | ||
| 556 | error.UnknownCpuFeature => { | ||
| 557 | std.debug.warn( | ||
| 558 | \\Unknown CPU feature: '{}' | ||
| 559 | \\Available CPU features for architecture '{}': | ||
| 560 | \\ | ||
| 561 | , .{ | ||
| 562 | diags.unknown_feature_name, | ||
| 563 | @tagName(diags.arch.?), | ||
| 564 | }); | ||
| 565 | for (diags.arch.?.allFeaturesList()) |feature| { | ||
| 566 | std.debug.warn(" {}: {}\n", .{ feature.name, feature.description }); | ||
| 567 | } | ||
| 568 | process.exit(1); | ||
| 569 | }, | ||
| 570 | else => |e| return e, | ||
| 571 | }; | ||
| 572 | |||
| 573 | const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch unreachable; | ||
| 574 | |||
| 575 | if (args.whitelist) |list| whitelist_check: { | ||
| 576 | // Make sure it's a match of one of the list. | ||
| 577 | for (list) |t| { | ||
| 578 | const t_triple = t.zigTriple(self.allocator) catch unreachable; | ||
| 579 | if (mem.eql(u8, t_triple, selected_canonicalized_triple)) { | ||
| 580 | break :whitelist_check; | ||
| 535 | } | 581 | } |
| 536 | } | 582 | } |
| 537 | return Target.Native; | 583 | std.debug.warn("Chosen target '{}' does not match one of the supported targets:\n", .{ |
| 538 | } else { | 584 | selected_canonicalized_triple, |
| 539 | const target_str = self.option([]const u8, "target", "the target to build for") orelse return Target.Native; | 585 | }); |
| 540 | return Target.parse(.{ .arch_os_abi = target_str }) catch unreachable; // TODO better error message for bad target | 586 | for (list) |t| { |
| 587 | const t_triple = t.zigTriple(self.allocator) catch unreachable; | ||
| 588 | std.debug.warn(" {}\n", t_triple); | ||
| 589 | } | ||
| 590 | // TODO instead of process exit, return error and have a zig build flag implemented by | ||
| 591 | // the build runner that turns process exits into error return traces | ||
| 592 | process.exit(1); | ||
| 541 | } | 593 | } |
| 594 | |||
| 595 | return selected_target; | ||
| 542 | } | 596 | } |
| 543 | 597 | ||
| 544 | pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool { | 598 | pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool { |
| ... | @@ -796,7 +850,7 @@ pub const Builder = struct { | ... | @@ -796,7 +850,7 @@ pub const Builder = struct { |
| 796 | 850 | ||
| 797 | pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 { | 851 | pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 { |
| 798 | // TODO report error for ambiguous situations | 852 | // TODO report error for ambiguous situations |
| 799 | const exe_extension = (Target{ .Native = {} }).exeFileExt(); | 853 | const exe_extension = @as(CrossTarget, .{}).exeFileExt(); |
| 800 | for (self.search_prefixes.toSliceConst()) |search_prefix| { | 854 | for (self.search_prefixes.toSliceConst()) |search_prefix| { |
| 801 | for (names) |name| { | 855 | for (names) |name| { |
| 802 | if (fs.path.isAbsolute(name)) { | 856 | if (fs.path.isAbsolute(name)) { |
| ... | @@ -978,111 +1032,11 @@ test "builder.findProgram compiles" { | ... | @@ -978,111 +1032,11 @@ test "builder.findProgram compiles" { |
| 978 | _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null; | 1032 | _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null; |
| 979 | } | 1033 | } |
| 980 | 1034 | ||
| 981 | /// Deprecated. Use `builtin.Version`. | 1035 | /// Deprecated. Use `std.builtin.Version`. |
| 982 | pub const Version = builtin.Version; | 1036 | pub const Version = builtin.Version; |
| 983 | 1037 | ||
| 984 | /// Deprecated. Use `std.Target`. | 1038 | /// Deprecated. Use `std.zig.CrossTarget`. |
| 985 | pub const CrossTarget = std.Target; | 1039 | pub const Target = std.zig.CrossTarget; |
| 986 | |||
| 987 | /// Wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target. | ||
| 988 | pub const Target = union(enum) { | ||
| 989 | Native, | ||
| 990 | Cross: std.Target, | ||
| 991 | |||
| 992 | pub fn getTarget(self: Target) std.Target { | ||
| 993 | return switch (self) { | ||
| 994 | .Native => std.Target.current, | ||
| 995 | .Cross => |t| t, | ||
| 996 | }; | ||
| 997 | } | ||
| 998 | |||
| 999 | pub fn getOs(self: Target) std.Target.Os.Tag { | ||
| 1000 | return self.getTarget().os.tag; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | pub fn getCpu(self: Target) std.Target.Cpu { | ||
| 1004 | return self.getTarget().cpu; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | pub fn getAbi(self: Target) std.Target.Abi { | ||
| 1008 | return self.getTarget().abi; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | pub fn getArch(self: Target) std.Target.Cpu.Arch { | ||
| 1012 | return self.getCpu().arch; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | pub fn isFreeBSD(self: Target) bool { | ||
| 1016 | return self.getTarget().os.tag == .freebsd; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | pub fn isDarwin(self: Target) bool { | ||
| 1020 | return self.getTarget().os.tag.isDarwin(); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | pub fn isNetBSD(self: Target) bool { | ||
| 1024 | return self.getTarget().os.tag == .netbsd; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | pub fn isUefi(self: Target) bool { | ||
| 1028 | return self.getTarget().os.tag == .uefi; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | pub fn isDragonFlyBSD(self: Target) bool { | ||
| 1032 | return self.getTarget().os.tag == .dragonfly; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | pub fn isLinux(self: Target) bool { | ||
| 1036 | return self.getTarget().os.tag == .linux; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | pub fn isWindows(self: Target) bool { | ||
| 1040 | return self.getTarget().os.tag == .windows; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | pub fn oFileExt(self: Target) []const u8 { | ||
| 1044 | return self.getTarget().oFileExt(); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | pub fn exeFileExt(self: Target) []const u8 { | ||
| 1048 | return self.getTarget().exeFileExt(); | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | pub fn staticLibSuffix(self: Target) []const u8 { | ||
| 1052 | return self.getTarget().staticLibSuffix(); | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | pub fn libPrefix(self: Target) []const u8 { | ||
| 1056 | return self.getTarget().libPrefix(); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { | ||
| 1060 | return self.getTarget().zigTriple(allocator); | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 { | ||
| 1064 | return self.getTarget().linuxTriple(allocator); | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | pub fn wantSharedLibSymLinks(self: Target) bool { | ||
| 1068 | return self.getTarget().wantSharedLibSymLinks(); | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | pub fn vcpkgTriplet(self: Target, allocator: *mem.Allocator, linkage: std.build.VcpkgLinkage) ![]const u8 { | ||
| 1072 | return self.getTarget().vcpkgTriplet(allocator, linkage); | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | pub fn getExternalExecutor(self: Target) std.Target.Executor { | ||
| 1076 | switch (self) { | ||
| 1077 | .Native => return .native, | ||
| 1078 | .Cross => |t| return t.getExternalExecutor(), | ||
| 1079 | } | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | pub fn isGnuLibC(self: Target) bool { | ||
| 1083 | return self.getTarget().isGnuLibC(); | ||
| 1084 | } | ||
| 1085 | }; | ||
| 1086 | 1040 | ||
| 1087 | pub const Pkg = struct { | 1041 | pub const Pkg = struct { |
| 1088 | name: []const u8, | 1042 | name: []const u8, |
| ... | @@ -1135,7 +1089,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1135,7 +1089,7 @@ pub const LibExeObjStep = struct { |
| 1135 | step: Step, | 1089 | step: Step, |
| 1136 | builder: *Builder, | 1090 | builder: *Builder, |
| 1137 | name: []const u8, | 1091 | name: []const u8, |
| 1138 | target: Target, | 1092 | target: CrossTarget = CrossTarget{}, |
| 1139 | linker_script: ?[]const u8 = null, | 1093 | linker_script: ?[]const u8 = null, |
| 1140 | version_script: ?[]const u8 = null, | 1094 | version_script: ?[]const u8 = null, |
| 1141 | out_filename: []const u8, | 1095 | out_filename: []const u8, |
| ... | @@ -1188,7 +1142,6 @@ pub const LibExeObjStep = struct { | ... | @@ -1188,7 +1142,6 @@ pub const LibExeObjStep = struct { |
| 1188 | install_step: ?*InstallArtifactStep, | 1142 | install_step: ?*InstallArtifactStep, |
| 1189 | 1143 | ||
| 1190 | libc_file: ?[]const u8 = null, | 1144 | libc_file: ?[]const u8 = null, |
| 1191 | target_glibc: ?Version = null, | ||
| 1192 | 1145 | ||
| 1193 | valgrind_support: ?bool = null, | 1146 | valgrind_support: ?bool = null, |
| 1194 | 1147 | ||
| ... | @@ -1288,7 +1241,6 @@ pub const LibExeObjStep = struct { | ... | @@ -1288,7 +1241,6 @@ pub const LibExeObjStep = struct { |
| 1288 | .kind = kind, | 1241 | .kind = kind, |
| 1289 | .root_src = root_src, | 1242 | .root_src = root_src, |
| 1290 | .name = name, | 1243 | .name = name, |
| 1291 | .target = Target.Native, | ||
| 1292 | .frameworks = BufSet.init(builder.allocator), | 1244 | .frameworks = BufSet.init(builder.allocator), |
| 1293 | .step = Step.init(name, builder.allocator, make), | 1245 | .step = Step.init(name, builder.allocator, make), |
| 1294 | .version = ver, | 1246 | .version = ver, |
| ... | @@ -1379,36 +1331,11 @@ pub const LibExeObjStep = struct { | ... | @@ -1379,36 +1331,11 @@ pub const LibExeObjStep = struct { |
| 1379 | } | 1331 | } |
| 1380 | } | 1332 | } |
| 1381 | 1333 | ||
| 1382 | /// Deprecated. Use `setTheTarget`. | 1334 | pub fn setTarget(self: *LibExeObjStep, target: CrossTarget) void { |
| 1383 | pub fn setTarget( | ||
| 1384 | self: *LibExeObjStep, | ||
| 1385 | target_arch: builtin.Arch, | ||
| 1386 | target_os: builtin.Os, | ||
| 1387 | target_abi: builtin.Abi, | ||
| 1388 | ) void { | ||
| 1389 | return self.setTheTarget(Target{ | ||
| 1390 | .Cross = CrossTarget{ | ||
| 1391 | .arch = target_arch, | ||
| 1392 | .os = target_os, | ||
| 1393 | .abi = target_abi, | ||
| 1394 | .cpu_features = target_arch.getBaselineCpuFeatures(), | ||
| 1395 | }, | ||
| 1396 | }); | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | pub fn setTheTarget(self: *LibExeObjStep, target: Target) void { | ||
| 1400 | self.target = target; | 1335 | self.target = target; |
| 1401 | self.computeOutFileNames(); | 1336 | self.computeOutFileNames(); |
| 1402 | } | 1337 | } |
| 1403 | 1338 | ||
| 1404 | pub fn setTargetGLibC(self: *LibExeObjStep, major: u32, minor: u32, patch: u32) void { | ||
| 1405 | self.target_glibc = Version{ | ||
| 1406 | .major = major, | ||
| 1407 | .minor = minor, | ||
| 1408 | .patch = patch, | ||
| 1409 | }; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | pub fn setOutputDir(self: *LibExeObjStep, dir: []const u8) void { | 1339 | pub fn setOutputDir(self: *LibExeObjStep, dir: []const u8) void { |
| 1413 | self.output_dir = self.builder.dupePath(dir); | 1340 | self.output_dir = self.builder.dupePath(dir); |
| 1414 | } | 1341 | } |
| ... | @@ -2002,47 +1929,41 @@ pub const LibExeObjStep = struct { | ... | @@ -2002,47 +1929,41 @@ pub const LibExeObjStep = struct { |
| 2002 | try zig_args.append(@tagName(self.code_model)); | 1929 | try zig_args.append(@tagName(self.code_model)); |
| 2003 | } | 1930 | } |
| 2004 | 1931 | ||
| 2005 | switch (self.target) { | 1932 | if (!self.target.isNative()) { |
| 2006 | .Native => {}, | 1933 | try zig_args.append("-target"); |
| 2007 | .Cross => |cross| { | 1934 | try zig_args.append(try self.target.zigTriple(builder.allocator)); |
| 2008 | try zig_args.append("-target"); | ||
| 2009 | try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable); | ||
| 2010 | 1935 | ||
| 2011 | const all_features = self.target.getArch().allFeaturesList(); | 1936 | // TODO this logic can disappear if cpu model + features becomes part of the target triple |
| 2012 | var populated_cpu_features = cross.cpu.model.features; | 1937 | const cross = self.target.toTarget(); |
| 2013 | populated_cpu_features.populateDependencies(all_features); | 1938 | const all_features = cross.cpu.arch.allFeaturesList(); |
| 1939 | var populated_cpu_features = cross.cpu.model.features; | ||
| 1940 | populated_cpu_features.populateDependencies(all_features); | ||
| 2014 | 1941 | ||
| 2015 | if (populated_cpu_features.eql(cross.cpu.features)) { | 1942 | if (populated_cpu_features.eql(cross.cpu.features)) { |
| 2016 | // The CPU name alone is sufficient. | 1943 | // The CPU name alone is sufficient. |
| 2017 | // If it is the baseline CPU, no command line args are required. | 1944 | // If it is the baseline CPU, no command line args are required. |
| 2018 | if (cross.cpu.model != std.Target.Cpu.baseline(self.target.getArch()).model) { | 1945 | if (cross.cpu.model != std.Target.Cpu.baseline(cross.cpu.arch).model) { |
| 2019 | try zig_args.append("-mcpu"); | 1946 | try zig_args.append("-mcpu"); |
| 2020 | try zig_args.append(cross.cpu.model.name); | 1947 | try zig_args.append(cross.cpu.model.name); |
| 2021 | } | 1948 | } |
| 2022 | } else { | 1949 | } else { |
| 2023 | var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu="); | 1950 | var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu="); |
| 2024 | try mcpu_buffer.append(cross.cpu.model.name); | 1951 | try mcpu_buffer.append(cross.cpu.model.name); |
| 2025 | 1952 | ||
| 2026 | for (all_features) |feature, i_usize| { | 1953 | for (all_features) |feature, i_usize| { |
| 2027 | const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize); | 1954 | const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize); |
| 2028 | const in_cpu_set = populated_cpu_features.isEnabled(i); | 1955 | const in_cpu_set = populated_cpu_features.isEnabled(i); |
| 2029 | const in_actual_set = cross.cpu.features.isEnabled(i); | 1956 | const in_actual_set = cross.cpu.features.isEnabled(i); |
| 2030 | if (in_cpu_set and !in_actual_set) { | 1957 | if (in_cpu_set and !in_actual_set) { |
| 2031 | try mcpu_buffer.appendByte('-'); | 1958 | try mcpu_buffer.appendByte('-'); |
| 2032 | try mcpu_buffer.append(feature.name); | 1959 | try mcpu_buffer.append(feature.name); |
| 2033 | } else if (!in_cpu_set and in_actual_set) { | 1960 | } else if (!in_cpu_set and in_actual_set) { |
| 2034 | try mcpu_buffer.appendByte('+'); | 1961 | try mcpu_buffer.appendByte('+'); |
| 2035 | try mcpu_buffer.append(feature.name); | 1962 | try mcpu_buffer.append(feature.name); |
| 2036 | } | ||
| 2037 | } | 1963 | } |
| 2038 | try zig_args.append(mcpu_buffer.toSliceConst()); | ||
| 2039 | } | 1964 | } |
| 2040 | }, | 1965 | try zig_args.append(mcpu_buffer.toSliceConst()); |
| 2041 | } | 1966 | } |
| 2042 | |||
| 2043 | if (self.target_glibc) |ver| { | ||
| 2044 | try zig_args.append("-target-glibc"); | ||
| 2045 | try zig_args.append(builder.fmt("{}.{}.{}", .{ ver.major, ver.minor, ver.patch })); | ||
| 2046 | } | 1967 | } |
| 2047 | 1968 | ||
| 2048 | if (self.linker_script) |linker_script| { | 1969 | if (self.linker_script) |linker_script| { |
| ... | @@ -2517,10 +2438,7 @@ const VcpkgRootStatus = enum { | ... | @@ -2517,10 +2438,7 @@ const VcpkgRootStatus = enum { |
| 2517 | Found, | 2438 | Found, |
| 2518 | }; | 2439 | }; |
| 2519 | 2440 | ||
| 2520 | pub const VcpkgLinkage = enum { | 2441 | pub const VcpkgLinkage = std.builtin.LinkMode; |
| 2521 | Static, | ||
| 2522 | Dynamic, | ||
| 2523 | }; | ||
| 2524 | 2442 | ||
| 2525 | pub const InstallDir = enum { | 2443 | pub const InstallDir = enum { |
| 2526 | Prefix, | 2444 | Prefix, |
lib/std/build/translate_c.zig+6-8| ... | @@ -7,6 +7,7 @@ const LibExeObjStep = build.LibExeObjStep; | ... | @@ -7,6 +7,7 @@ const LibExeObjStep = build.LibExeObjStep; |
| 7 | const CheckFileStep = build.CheckFileStep; | 7 | const CheckFileStep = build.CheckFileStep; |
| 8 | const fs = std.fs; | 8 | const fs = std.fs; |
| 9 | const mem = std.mem; | 9 | const mem = std.mem; |
| 10 | const CrossTarget = std.zig.CrossTarget; | ||
| 10 | 11 | ||
| 11 | pub const TranslateCStep = struct { | 12 | pub const TranslateCStep = struct { |
| 12 | step: Step, | 13 | step: Step, |
| ... | @@ -14,7 +15,7 @@ pub const TranslateCStep = struct { | ... | @@ -14,7 +15,7 @@ pub const TranslateCStep = struct { |
| 14 | source: build.FileSource, | 15 | source: build.FileSource, |
| 15 | output_dir: ?[]const u8, | 16 | output_dir: ?[]const u8, |
| 16 | out_basename: []const u8, | 17 | out_basename: []const u8, |
| 17 | target: build.Target = .Native, | 18 | target: CrossTarget = CrossTarget{}, |
| 18 | 19 | ||
| 19 | pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep { | 20 | pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep { |
| 20 | const self = builder.allocator.create(TranslateCStep) catch unreachable; | 21 | const self = builder.allocator.create(TranslateCStep) catch unreachable; |
| ... | @@ -39,7 +40,7 @@ pub const TranslateCStep = struct { | ... | @@ -39,7 +40,7 @@ pub const TranslateCStep = struct { |
| 39 | ) catch unreachable; | 40 | ) catch unreachable; |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | pub fn setTarget(self: *TranslateCStep, target: build.Target) void { | 43 | pub fn setTarget(self: *TranslateCStep, target: CrossTarget) void { |
| 43 | self.target = target; | 44 | self.target = target; |
| 44 | } | 45 | } |
| 45 | 46 | ||
| ... | @@ -63,12 +64,9 @@ pub const TranslateCStep = struct { | ... | @@ -63,12 +64,9 @@ pub const TranslateCStep = struct { |
| 63 | try argv_list.append("--cache"); | 64 | try argv_list.append("--cache"); |
| 64 | try argv_list.append("on"); | 65 | try argv_list.append("on"); |
| 65 | 66 | ||
| 66 | switch (self.target) { | 67 | if (!self.target.isNative()) { |
| 67 | .Native => {}, | 68 | try argv_list.append("-target"); |
| 68 | .Cross => { | 69 | try argv_list.append(try self.target.zigTriple(self.builder.allocator)); |
| 69 | try argv_list.append("-target"); | ||
| 70 | try argv_list.append(try self.target.zigTriple(self.builder.allocator)); | ||
| 71 | }, | ||
| 72 | } | 70 | } |
| 73 | 71 | ||
| 74 | try argv_list.append(self.source.getPath(self.builder)); | 72 | try argv_list.append(self.source.getPath(self.builder)); |
lib/std/builtin.zig+23| ... | @@ -429,6 +429,29 @@ pub const Version = struct { | ... | @@ -429,6 +429,29 @@ pub const Version = struct { |
| 429 | .patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10), | 429 | .patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10), |
| 430 | }; | 430 | }; |
| 431 | } | 431 | } |
| 432 | |||
| 433 | pub fn format( | ||
| 434 | self: Version, | ||
| 435 | comptime fmt: []const u8, | ||
| 436 | options: std.fmt.FormatOptions, | ||
| 437 | context: var, | ||
| 438 | comptime Error: type, | ||
| 439 | comptime output: fn (@TypeOf(context), []const u8) Error!void, | ||
| 440 | ) Error!void { | ||
| 441 | if (fmt.len == 0) { | ||
| 442 | if (self.patch == 0) { | ||
| 443 | if (self.minor == 0) { | ||
| 444 | return std.fmt.format(context, Error, output, "{}", .{self.major}); | ||
| 445 | } else { | ||
| 446 | return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor }); | ||
| 447 | } | ||
| 448 | } else { | ||
| 449 | return std.fmt.format(context, Error, output, "{}.{}.{}", .{ self.major, self.minor, self.patch }); | ||
| 450 | } | ||
| 451 | } else { | ||
| 452 | @compileError("Unknown format string: '" ++ fmt ++ "'"); | ||
| 453 | } | ||
| 454 | } | ||
| 432 | }; | 455 | }; |
| 433 | 456 | ||
| 434 | /// This data structure is used by the Zig language code generation and | 457 | /// This data structure is used by the Zig language code generation and |
lib/std/target.zig+186-499| ... | @@ -60,6 +60,16 @@ pub const Target = struct { | ... | @@ -60,6 +60,16 @@ pub const Target = struct { |
| 60 | else => false, | 60 | else => false, |
| 61 | }; | 61 | }; |
| 62 | } | 62 | } |
| 63 | |||
| 64 | pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 { | ||
| 65 | if (tag.isDarwin()) { | ||
| 66 | return ".dylib"; | ||
| 67 | } | ||
| 68 | switch (tag) { | ||
| 69 | .windows => return ".dll", | ||
| 70 | else => return ".so", | ||
| 71 | } | ||
| 72 | } | ||
| 63 | }; | 73 | }; |
| 64 | 74 | ||
| 65 | /// Based on NTDDI version constants from | 75 | /// Based on NTDDI version constants from |
| ... | @@ -210,64 +220,31 @@ pub const Target = struct { | ... | @@ -210,64 +220,31 @@ pub const Target = struct { |
| 210 | } | 220 | } |
| 211 | }; | 221 | }; |
| 212 | 222 | ||
| 213 | pub fn parse(text: []const u8) !Os { | 223 | pub fn defaultVersionRange(tag: Tag) Os { |
| 214 | var it = mem.separate(text, "."); | 224 | return .{ |
| 215 | const os_name = it.next().?; | 225 | .tag = tag, |
| 216 | const tag = std.meta.stringToEnum(Tag, os_name) orelse return error.UnknownOperatingSystem; | 226 | .version_range = VersionRange.default(tag), |
| 217 | const version_text = it.rest(); | 227 | }; |
| 218 | const S = struct { | 228 | } |
| 219 | fn parseNone(s: []const u8) !void { | ||
| 220 | if (s.len != 0) return error.InvalidOperatingSystemVersion; | ||
| 221 | } | ||
| 222 | fn parseSemVer(s: []const u8, d_range: Version.Range) !Version.Range { | ||
| 223 | if (s.len == 0) return d_range; | ||
| 224 | var range_it = mem.separate(s, "..."); | ||
| 225 | |||
| 226 | const min_text = range_it.next().?; | ||
| 227 | const min_ver = Version.parse(min_text) catch |err| switch (err) { | ||
| 228 | error.Overflow => return error.InvalidOperatingSystemVersion, | ||
| 229 | error.InvalidCharacter => return error.InvalidOperatingSystemVersion, | ||
| 230 | error.InvalidVersion => return error.InvalidOperatingSystemVersion, | ||
| 231 | }; | ||
| 232 | |||
| 233 | const max_text = range_it.next() orelse return Version.Range{ | ||
| 234 | .min = min_ver, | ||
| 235 | .max = d_range.max, | ||
| 236 | }; | ||
| 237 | const max_ver = Version.parse(max_text) catch |err| switch (err) { | ||
| 238 | error.Overflow => return error.InvalidOperatingSystemVersion, | ||
| 239 | error.InvalidCharacter => return error.InvalidOperatingSystemVersion, | ||
| 240 | error.InvalidVersion => return error.InvalidOperatingSystemVersion, | ||
| 241 | }; | ||
| 242 | |||
| 243 | return Version.Range{ .min = min_ver, .max = max_ver }; | ||
| 244 | } | ||
| 245 | fn parseWindows(s: []const u8, d_range: WindowsVersion.Range) !WindowsVersion.Range { | ||
| 246 | if (s.len == 0) return d_range; | ||
| 247 | var range_it = mem.separate(s, "..."); | ||
| 248 | |||
| 249 | const min_text = range_it.next().?; | ||
| 250 | const min_ver = std.meta.stringToEnum(WindowsVersion, min_text) orelse | ||
| 251 | return error.InvalidOperatingSystemVersion; | ||
| 252 | 229 | ||
| 253 | const max_text = range_it.next() orelse return WindowsVersion.Range{ | 230 | pub fn requiresLibC(os: Os) bool { |
| 254 | .min = min_ver, | 231 | return switch (os.tag) { |
| 255 | .max = d_range.max, | 232 | .freebsd, |
| 256 | }; | 233 | .netbsd, |
| 257 | const max_ver = std.meta.stringToEnum(WindowsVersion, max_text) orelse | 234 | .macosx, |
| 258 | return error.InvalidOperatingSystemVersion; | 235 | .ios, |
| 236 | .tvos, | ||
| 237 | .watchos, | ||
| 238 | .dragonfly, | ||
| 239 | .openbsd, | ||
| 240 | => true, | ||
| 259 | 241 | ||
| 260 | return WindowsVersion.Range{ .min = min_ver, .max = max_ver }; | 242 | .linux, |
| 261 | } | 243 | .windows, |
| 262 | }; | ||
| 263 | const d_range = VersionRange.default(tag); | ||
| 264 | switch (tag) { | ||
| 265 | .freestanding, | 244 | .freestanding, |
| 266 | .ananas, | 245 | .ananas, |
| 267 | .cloudabi, | 246 | .cloudabi, |
| 268 | .dragonfly, | ||
| 269 | .fuchsia, | 247 | .fuchsia, |
| 270 | .ios, | ||
| 271 | .kfreebsd, | 248 | .kfreebsd, |
| 272 | .lv2, | 249 | .lv2, |
| 273 | .solaris, | 250 | .solaris, |
| ... | @@ -282,8 +259,6 @@ pub const Target = struct { | ... | @@ -282,8 +259,6 @@ pub const Target = struct { |
| 282 | .amdhsa, | 259 | .amdhsa, |
| 283 | .ps4, | 260 | .ps4, |
| 284 | .elfiamcu, | 261 | .elfiamcu, |
| 285 | .tvos, | ||
| 286 | .watchos, | ||
| 287 | .mesa3d, | 262 | .mesa3d, |
| 288 | .contiki, | 263 | .contiki, |
| 289 | .amdpal, | 264 | .amdpal, |
| ... | @@ -293,41 +268,7 @@ pub const Target = struct { | ... | @@ -293,41 +268,7 @@ pub const Target = struct { |
| 293 | .emscripten, | 268 | .emscripten, |
| 294 | .uefi, | 269 | .uefi, |
| 295 | .other, | 270 | .other, |
| 296 | => return Os{ | 271 | => false, |
| 297 | .tag = tag, | ||
| 298 | .version_range = .{ .none = try S.parseNone(version_text) }, | ||
| 299 | }, | ||
| 300 | |||
| 301 | .freebsd, | ||
| 302 | .macosx, | ||
| 303 | .netbsd, | ||
| 304 | .openbsd, | ||
| 305 | => return Os{ | ||
| 306 | .tag = tag, | ||
| 307 | .version_range = .{ .semver = try S.parseSemVer(version_text, d_range.semver) }, | ||
| 308 | }, | ||
| 309 | |||
| 310 | .linux => return Os{ | ||
| 311 | .tag = tag, | ||
| 312 | .version_range = .{ | ||
| 313 | .linux = .{ | ||
| 314 | .range = try S.parseSemVer(version_text, d_range.linux.range), | ||
| 315 | .glibc = d_range.linux.glibc, | ||
| 316 | }, | ||
| 317 | }, | ||
| 318 | }, | ||
| 319 | |||
| 320 | .windows => return Os{ | ||
| 321 | .tag = tag, | ||
| 322 | .version_range = .{ .windows = try S.parseWindows(version_text, d_range.windows) }, | ||
| 323 | }, | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | pub fn defaultVersionRange(tag: Tag) Os { | ||
| 328 | return .{ | ||
| 329 | .tag = tag, | ||
| 330 | .version_range = VersionRange.default(tag), | ||
| 331 | }; | 272 | }; |
| 332 | } | 273 | } |
| 333 | }; | 274 | }; |
| ... | @@ -434,6 +375,13 @@ pub const Target = struct { | ... | @@ -434,6 +375,13 @@ pub const Target = struct { |
| 434 | else => false, | 375 | else => false, |
| 435 | }; | 376 | }; |
| 436 | } | 377 | } |
| 378 | |||
| 379 | pub fn oFileExt(abi: Abi) [:0]const u8 { | ||
| 380 | return switch (abi) { | ||
| 381 | .msvc => ".obj", | ||
| 382 | else => ".o", | ||
| 383 | }; | ||
| 384 | } | ||
| 437 | }; | 385 | }; |
| 438 | 386 | ||
| 439 | pub const ObjectFormat = enum { | 387 | pub const ObjectFormat = enum { |
| ... | @@ -500,6 +448,12 @@ pub const Target = struct { | ... | @@ -500,6 +448,12 @@ pub const Target = struct { |
| 500 | return Set{ .ints = [1]usize{0} ** usize_count }; | 448 | return Set{ .ints = [1]usize{0} ** usize_count }; |
| 501 | } | 449 | } |
| 502 | 450 | ||
| 451 | pub fn isEmpty(set: Set) bool { | ||
| 452 | return for (set.ints) |x| { | ||
| 453 | if (x != 0) break false; | ||
| 454 | } else true; | ||
| 455 | } | ||
| 456 | |||
| 503 | pub fn isEnabled(set: Set, arch_feature_index: Index) bool { | 457 | pub fn isEnabled(set: Set, arch_feature_index: Index) bool { |
| 504 | const usize_index = arch_feature_index / @bitSizeOf(usize); | 458 | const usize_index = arch_feature_index / @bitSizeOf(usize); |
| 505 | const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize)); | 459 | const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize)); |
| ... | @@ -526,6 +480,15 @@ pub const Target = struct { | ... | @@ -526,6 +480,15 @@ pub const Target = struct { |
| 526 | set.ints[usize_index] &= ~(@as(usize, 1) << bit_index); | 480 | set.ints[usize_index] &= ~(@as(usize, 1) << bit_index); |
| 527 | } | 481 | } |
| 528 | 482 | ||
| 483 | /// Removes the specified feature but not its dependents. | ||
| 484 | pub fn removeFeatureSet(set: *Set, other_set: Set) void { | ||
| 485 | // TODO should be able to use binary not on @Vector type. | ||
| 486 | // https://github.com/ziglang/zig/issues/903 | ||
| 487 | for (set.ints) |*int, i| { | ||
| 488 | int.* &= ~other_set.ints[i]; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 529 | pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { | 492 | pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { |
| 530 | @setEvalBranchQuota(1000000); | 493 | @setEvalBranchQuota(1000000); |
| 531 | 494 | ||
| ... | @@ -663,7 +626,7 @@ pub const Target = struct { | ... | @@ -663,7 +626,7 @@ pub const Target = struct { |
| 663 | return cpu; | 626 | return cpu; |
| 664 | } | 627 | } |
| 665 | } | 628 | } |
| 666 | return error.UnknownCpu; | 629 | return error.UnknownCpuModel; |
| 667 | } | 630 | } |
| 668 | 631 | ||
| 669 | pub fn toElfMachine(arch: Arch) std.elf.EM { | 632 | pub fn toElfMachine(arch: Arch) std.elf.EM { |
| ... | @@ -779,6 +742,66 @@ pub const Target = struct { | ... | @@ -779,6 +742,66 @@ pub const Target = struct { |
| 779 | }; | 742 | }; |
| 780 | } | 743 | } |
| 781 | 744 | ||
| 745 | pub fn ptrBitWidth(arch: Arch) u32 { | ||
| 746 | switch (arch) { | ||
| 747 | .avr, | ||
| 748 | .msp430, | ||
| 749 | => return 16, | ||
| 750 | |||
| 751 | .arc, | ||
| 752 | .arm, | ||
| 753 | .armeb, | ||
| 754 | .hexagon, | ||
| 755 | .le32, | ||
| 756 | .mips, | ||
| 757 | .mipsel, | ||
| 758 | .powerpc, | ||
| 759 | .r600, | ||
| 760 | .riscv32, | ||
| 761 | .sparc, | ||
| 762 | .sparcel, | ||
| 763 | .tce, | ||
| 764 | .tcele, | ||
| 765 | .thumb, | ||
| 766 | .thumbeb, | ||
| 767 | .i386, | ||
| 768 | .xcore, | ||
| 769 | .nvptx, | ||
| 770 | .amdil, | ||
| 771 | .hsail, | ||
| 772 | .spir, | ||
| 773 | .kalimba, | ||
| 774 | .shave, | ||
| 775 | .lanai, | ||
| 776 | .wasm32, | ||
| 777 | .renderscript32, | ||
| 778 | .aarch64_32, | ||
| 779 | => return 32, | ||
| 780 | |||
| 781 | .aarch64, | ||
| 782 | .aarch64_be, | ||
| 783 | .mips64, | ||
| 784 | .mips64el, | ||
| 785 | .powerpc64, | ||
| 786 | .powerpc64le, | ||
| 787 | .riscv64, | ||
| 788 | .x86_64, | ||
| 789 | .nvptx64, | ||
| 790 | .le64, | ||
| 791 | .amdil64, | ||
| 792 | .hsail64, | ||
| 793 | .spir64, | ||
| 794 | .wasm64, | ||
| 795 | .renderscript64, | ||
| 796 | .amdgcn, | ||
| 797 | .bpfel, | ||
| 798 | .bpfeb, | ||
| 799 | .sparcv9, | ||
| 800 | .s390x, | ||
| 801 | => return 64, | ||
| 802 | } | ||
| 803 | } | ||
| 804 | |||
| 782 | /// Returns a name that matches the lib/std/target/* directory name. | 805 | /// Returns a name that matches the lib/std/target/* directory name. |
| 783 | pub fn genericName(arch: Arch) []const u8 { | 806 | pub fn genericName(arch: Arch) []const u8 { |
| 784 | return switch (arch) { | 807 | return switch (arch) { |
| ... | @@ -846,16 +869,6 @@ pub const Target = struct { | ... | @@ -846,16 +869,6 @@ pub const Target = struct { |
| 846 | else => &[0]*const Model{}, | 869 | else => &[0]*const Model{}, |
| 847 | }; | 870 | }; |
| 848 | } | 871 | } |
| 849 | |||
| 850 | pub fn parse(text: []const u8) !Arch { | ||
| 851 | const info = @typeInfo(Arch); | ||
| 852 | inline for (info.Enum.fields) |field| { | ||
| 853 | if (mem.eql(u8, text, field.name)) { | ||
| 854 | return @as(Arch, @field(Arch, field.name)); | ||
| 855 | } | ||
| 856 | } | ||
| 857 | return error.UnknownArchitecture; | ||
| 858 | } | ||
| 859 | }; | 872 | }; |
| 860 | 873 | ||
| 861 | pub const Model = struct { | 874 | pub const Model = struct { |
| ... | @@ -872,41 +885,44 @@ pub const Target = struct { | ... | @@ -872,41 +885,44 @@ pub const Target = struct { |
| 872 | .features = features, | 885 | .features = features, |
| 873 | }; | 886 | }; |
| 874 | } | 887 | } |
| 888 | |||
| 889 | pub fn baseline(arch: Arch) *const Model { | ||
| 890 | const S = struct { | ||
| 891 | const generic_model = Model{ | ||
| 892 | .name = "generic", | ||
| 893 | .llvm_name = null, | ||
| 894 | .features = Cpu.Feature.Set.empty, | ||
| 895 | }; | ||
| 896 | }; | ||
| 897 | return switch (arch) { | ||
| 898 | .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline, | ||
| 899 | .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic, | ||
| 900 | .avr => &avr.cpu.avr1, | ||
| 901 | .bpfel, .bpfeb => &bpf.cpu.generic, | ||
| 902 | .hexagon => &hexagon.cpu.generic, | ||
| 903 | .mips, .mipsel => &mips.cpu.mips32, | ||
| 904 | .mips64, .mips64el => &mips.cpu.mips64, | ||
| 905 | .msp430 => &msp430.cpu.generic, | ||
| 906 | .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic, | ||
| 907 | .amdgcn => &amdgpu.cpu.generic, | ||
| 908 | .riscv32 => &riscv.cpu.baseline_rv32, | ||
| 909 | .riscv64 => &riscv.cpu.baseline_rv64, | ||
| 910 | .sparc, .sparcv9, .sparcel => &sparc.cpu.generic, | ||
| 911 | .s390x => &systemz.cpu.generic, | ||
| 912 | .i386 => &x86.cpu.pentium4, | ||
| 913 | .x86_64 => &x86.cpu.x86_64, | ||
| 914 | .nvptx, .nvptx64 => &nvptx.cpu.sm_20, | ||
| 915 | .wasm32, .wasm64 => &wasm.cpu.generic, | ||
| 916 | |||
| 917 | else => &S.generic_model, | ||
| 918 | }; | ||
| 919 | } | ||
| 875 | }; | 920 | }; |
| 876 | 921 | ||
| 877 | /// The "default" set of CPU features for cross-compiling. A conservative set | 922 | /// The "default" set of CPU features for cross-compiling. A conservative set |
| 878 | /// of features that is expected to be supported on most available hardware. | 923 | /// of features that is expected to be supported on most available hardware. |
| 879 | pub fn baseline(arch: Arch) Cpu { | 924 | pub fn baseline(arch: Arch) Cpu { |
| 880 | const S = struct { | 925 | return Model.baseline(arch).toCpu(arch); |
| 881 | const generic_model = Model{ | ||
| 882 | .name = "generic", | ||
| 883 | .llvm_name = null, | ||
| 884 | .features = Cpu.Feature.Set.empty, | ||
| 885 | }; | ||
| 886 | }; | ||
| 887 | const model = switch (arch) { | ||
| 888 | .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline, | ||
| 889 | .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic, | ||
| 890 | .avr => &avr.cpu.avr1, | ||
| 891 | .bpfel, .bpfeb => &bpf.cpu.generic, | ||
| 892 | .hexagon => &hexagon.cpu.generic, | ||
| 893 | .mips, .mipsel => &mips.cpu.mips32, | ||
| 894 | .mips64, .mips64el => &mips.cpu.mips64, | ||
| 895 | .msp430 => &msp430.cpu.generic, | ||
| 896 | .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic, | ||
| 897 | .amdgcn => &amdgpu.cpu.generic, | ||
| 898 | .riscv32 => &riscv.cpu.baseline_rv32, | ||
| 899 | .riscv64 => &riscv.cpu.baseline_rv64, | ||
| 900 | .sparc, .sparcv9, .sparcel => &sparc.cpu.generic, | ||
| 901 | .s390x => &systemz.cpu.generic, | ||
| 902 | .i386 => &x86.cpu.pentium4, | ||
| 903 | .x86_64 => &x86.cpu.x86_64, | ||
| 904 | .nvptx, .nvptx64 => &nvptx.cpu.sm_20, | ||
| 905 | .wasm32, .wasm64 => &wasm.cpu.generic, | ||
| 906 | |||
| 907 | else => &S.generic_model, | ||
| 908 | }; | ||
| 909 | return model.toCpu(arch); | ||
| 910 | } | 926 | } |
| 911 | }; | 927 | }; |
| 912 | 928 | ||
| ... | @@ -918,239 +934,70 @@ pub const Target = struct { | ... | @@ -918,239 +934,70 @@ pub const Target = struct { |
| 918 | 934 | ||
| 919 | pub const stack_align = 16; | 935 | pub const stack_align = 16; |
| 920 | 936 | ||
| 921 | /// TODO add OS version ranges and glibc version | 937 | pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 { |
| 922 | pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { | 938 | return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator); |
| 923 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ | ||
| 924 | @tagName(self.cpu.arch), | ||
| 925 | @tagName(self.os.tag), | ||
| 926 | @tagName(self.abi), | ||
| 927 | }); | ||
| 928 | } | 939 | } |
| 929 | 940 | ||
| 930 | /// Returned slice must be freed by the caller. | 941 | pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 { |
| 931 | pub fn vcpkgTriplet(target: Target, allocator: *mem.Allocator, linkage: std.build.VcpkgLinkage) ![]const u8 { | 942 | return std.fmt.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) }); |
| 932 | const arch = switch (target.cpu.arch) { | ||
| 933 | .i386 => "x86", | ||
| 934 | .x86_64 => "x64", | ||
| 935 | |||
| 936 | .arm, | ||
| 937 | .armeb, | ||
| 938 | .thumb, | ||
| 939 | .thumbeb, | ||
| 940 | .aarch64_32, | ||
| 941 | => "arm", | ||
| 942 | |||
| 943 | .aarch64, | ||
| 944 | .aarch64_be, | ||
| 945 | => "arm64", | ||
| 946 | |||
| 947 | else => return error.VcpkgNoSuchArchitecture, | ||
| 948 | }; | ||
| 949 | |||
| 950 | const os = switch (target.os) { | ||
| 951 | .windows => "windows", | ||
| 952 | .linux => "linux", | ||
| 953 | .macosx => "macos", | ||
| 954 | else => return error.VcpkgNoSuchOs, | ||
| 955 | }; | ||
| 956 | |||
| 957 | if (linkage == .Static) { | ||
| 958 | return try mem.join(allocator, "-", &[_][]const u8{ arch, os, "static" }); | ||
| 959 | } else { | ||
| 960 | return try mem.join(allocator, "-", &[_][]const u8{ arch, os }); | ||
| 961 | } | ||
| 962 | } | 943 | } |
| 963 | 944 | ||
| 964 | pub fn allocDescription(self: Target, allocator: *mem.Allocator) ![]u8 { | 945 | pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 { |
| 965 | // TODO is there anything else worthy of the description that is not | 946 | return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi); |
| 966 | // already captured in the triple? | ||
| 967 | return self.zigTriple(allocator); | ||
| 968 | } | 947 | } |
| 969 | 948 | ||
| 970 | pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 { | 949 | pub fn oFileExt(self: Target) [:0]const u8 { |
| 971 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ | 950 | return self.abi.oFileExt(); |
| 972 | @tagName(self.cpu.arch), | ||
| 973 | @tagName(self.os.tag), | ||
| 974 | @tagName(self.abi), | ||
| 975 | }); | ||
| 976 | } | 951 | } |
| 977 | 952 | ||
| 978 | pub const ParseOptions = struct { | 953 | pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 { |
| 979 | /// This is sometimes called a "triple". It looks roughly like this: | 954 | switch (os_tag) { |
| 980 | /// riscv64-linux-gnu | 955 | .windows => return ".exe", |
| 981 | /// The fields are, respectively: | 956 | .uefi => return ".efi", |
| 982 | /// * CPU Architecture | 957 | else => if (cpu_arch.isWasm()) { |
| 983 | /// * Operating System | 958 | return ".wasm"; |
| 984 | /// * C ABI (optional) | 959 | } else { |
| 985 | arch_os_abi: []const u8, | 960 | return ""; |
| 986 | 961 | }, | |
| 987 | /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" | ||
| 988 | /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features | ||
| 989 | /// to remove from the set. | ||
| 990 | cpu_features: []const u8 = "baseline", | ||
| 991 | |||
| 992 | /// If this is provided, the function will populate some information about parsing failures, | ||
| 993 | /// so that user-friendly error messages can be delivered. | ||
| 994 | diagnostics: ?*Diagnostics = null, | ||
| 995 | |||
| 996 | pub const Diagnostics = struct { | ||
| 997 | /// If the architecture was determined, this will be populated. | ||
| 998 | arch: ?Cpu.Arch = null, | ||
| 999 | |||
| 1000 | /// If the OS was determined, this will be populated. | ||
| 1001 | os: ?Os = null, | ||
| 1002 | |||
| 1003 | /// If the ABI was determined, this will be populated. | ||
| 1004 | abi: ?Abi = null, | ||
| 1005 | |||
| 1006 | /// If the CPU name was determined, this will be populated. | ||
| 1007 | cpu_name: ?[]const u8 = null, | ||
| 1008 | |||
| 1009 | /// If error.UnknownCpuFeature is returned, this will be populated. | ||
| 1010 | unknown_feature_name: ?[]const u8 = null, | ||
| 1011 | }; | ||
| 1012 | }; | ||
| 1013 | |||
| 1014 | pub fn parse(args: ParseOptions) !Target { | ||
| 1015 | var dummy_diags: ParseOptions.Diagnostics = undefined; | ||
| 1016 | var diags = args.diagnostics orelse &dummy_diags; | ||
| 1017 | |||
| 1018 | var it = mem.separate(args.arch_os_abi, "-"); | ||
| 1019 | const arch_name = it.next() orelse return error.MissingArchitecture; | ||
| 1020 | const arch = try Cpu.Arch.parse(arch_name); | ||
| 1021 | diags.arch = arch; | ||
| 1022 | |||
| 1023 | const os_name = it.next() orelse return error.MissingOperatingSystem; | ||
| 1024 | var os = try Os.parse(os_name); | ||
| 1025 | diags.os = os; | ||
| 1026 | |||
| 1027 | const opt_abi_text = it.next(); | ||
| 1028 | const abi = if (opt_abi_text) |abi_text| blk: { | ||
| 1029 | var abi_it = mem.separate(abi_text, "."); | ||
| 1030 | const abi = std.meta.stringToEnum(Abi, abi_it.next().?) orelse | ||
| 1031 | return error.UnknownApplicationBinaryInterface; | ||
| 1032 | const abi_ver_text = abi_it.rest(); | ||
| 1033 | if (abi_ver_text.len != 0) { | ||
| 1034 | if (os.tag == .linux and abi.isGnu()) { | ||
| 1035 | os.version_range.linux.glibc = Version.parse(abi_ver_text) catch |err| switch (err) { | ||
| 1036 | error.Overflow => return error.InvalidAbiVersion, | ||
| 1037 | error.InvalidCharacter => return error.InvalidAbiVersion, | ||
| 1038 | error.InvalidVersion => return error.InvalidAbiVersion, | ||
| 1039 | }; | ||
| 1040 | } else { | ||
| 1041 | return error.InvalidAbiVersion; | ||
| 1042 | } | ||
| 1043 | } | ||
| 1044 | break :blk abi; | ||
| 1045 | } else Abi.default(arch, os); | ||
| 1046 | diags.abi = abi; | ||
| 1047 | |||
| 1048 | if (it.next() != null) return error.UnexpectedExtraField; | ||
| 1049 | |||
| 1050 | const all_features = arch.allFeaturesList(); | ||
| 1051 | var index: usize = 0; | ||
| 1052 | while (index < args.cpu_features.len and | ||
| 1053 | args.cpu_features[index] != '+' and | ||
| 1054 | args.cpu_features[index] != '-') | ||
| 1055 | { | ||
| 1056 | index += 1; | ||
| 1057 | } | 962 | } |
| 1058 | const cpu_name = args.cpu_features[0..index]; | ||
| 1059 | diags.cpu_name = cpu_name; | ||
| 1060 | |||
| 1061 | const cpu: Cpu = if (mem.eql(u8, cpu_name, "baseline")) Cpu.baseline(arch) else blk: { | ||
| 1062 | const cpu_model = try arch.parseCpuModel(cpu_name); | ||
| 1063 | |||
| 1064 | var set = cpu_model.features; | ||
| 1065 | while (index < args.cpu_features.len) { | ||
| 1066 | const op = args.cpu_features[index]; | ||
| 1067 | index += 1; | ||
| 1068 | const start = index; | ||
| 1069 | while (index < args.cpu_features.len and | ||
| 1070 | args.cpu_features[index] != '+' and | ||
| 1071 | args.cpu_features[index] != '-') | ||
| 1072 | { | ||
| 1073 | index += 1; | ||
| 1074 | } | ||
| 1075 | const feature_name = args.cpu_features[start..index]; | ||
| 1076 | for (all_features) |feature, feat_index_usize| { | ||
| 1077 | const feat_index = @intCast(Cpu.Feature.Set.Index, feat_index_usize); | ||
| 1078 | if (mem.eql(u8, feature_name, feature.name)) { | ||
| 1079 | switch (op) { | ||
| 1080 | '+' => set.addFeature(feat_index), | ||
| 1081 | '-' => set.removeFeature(feat_index), | ||
| 1082 | else => unreachable, | ||
| 1083 | } | ||
| 1084 | break; | ||
| 1085 | } | ||
| 1086 | } else { | ||
| 1087 | diags.unknown_feature_name = feature_name; | ||
| 1088 | return error.UnknownCpuFeature; | ||
| 1089 | } | ||
| 1090 | } | ||
| 1091 | set.populateDependencies(all_features); | ||
| 1092 | break :blk .{ | ||
| 1093 | .arch = arch, | ||
| 1094 | .model = cpu_model, | ||
| 1095 | .features = set, | ||
| 1096 | }; | ||
| 1097 | }; | ||
| 1098 | return Target{ | ||
| 1099 | .cpu = cpu, | ||
| 1100 | .os = os, | ||
| 1101 | .abi = abi, | ||
| 1102 | }; | ||
| 1103 | } | 963 | } |
| 1104 | 964 | ||
| 1105 | pub fn oFileExt(self: Target) []const u8 { | 965 | pub fn exeFileExt(self: Target) [:0]const u8 { |
| 1106 | return switch (self.abi) { | 966 | return exeFileExtSimple(self.cpu.arch, self.os.tag); |
| 1107 | .msvc => ".obj", | ||
| 1108 | else => ".o", | ||
| 1109 | }; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | pub fn exeFileExt(self: Target) []const u8 { | ||
| 1113 | if (self.os.tag == .windows) { | ||
| 1114 | return ".exe"; | ||
| 1115 | } else if (self.os.tag == .uefi) { | ||
| 1116 | return ".efi"; | ||
| 1117 | } else if (self.cpu.arch.isWasm()) { | ||
| 1118 | return ".wasm"; | ||
| 1119 | } else { | ||
| 1120 | return ""; | ||
| 1121 | } | ||
| 1122 | } | 967 | } |
| 1123 | 968 | ||
| 1124 | pub fn staticLibSuffix(self: Target) []const u8 { | 969 | pub fn staticLibSuffix_cpu_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) [:0]const u8 { |
| 1125 | if (self.cpu.arch.isWasm()) { | 970 | if (cpu_arch.isWasm()) { |
| 1126 | return ".wasm"; | 971 | return ".wasm"; |
| 1127 | } | 972 | } |
| 1128 | switch (self.abi) { | 973 | switch (abi) { |
| 1129 | .msvc => return ".lib", | 974 | .msvc => return ".lib", |
| 1130 | else => return ".a", | 975 | else => return ".a", |
| 1131 | } | 976 | } |
| 1132 | } | 977 | } |
| 1133 | 978 | ||
| 1134 | pub fn dynamicLibSuffix(self: Target) []const u8 { | 979 | pub fn staticLibSuffix(self: Target) [:0]const u8 { |
| 1135 | if (self.isDarwin()) { | 980 | return staticLibSuffix_cpu_arch_abi(self.cpu.arch, self.abi); |
| 1136 | return ".dylib"; | ||
| 1137 | } | ||
| 1138 | switch (self.os) { | ||
| 1139 | .windows => return ".dll", | ||
| 1140 | else => return ".so", | ||
| 1141 | } | ||
| 1142 | } | 981 | } |
| 1143 | 982 | ||
| 1144 | pub fn libPrefix(self: Target) []const u8 { | 983 | pub fn dynamicLibSuffix(self: Target) [:0]const u8 { |
| 1145 | if (self.cpu.arch.isWasm()) { | 984 | return self.os.tag.dynamicLibSuffix(); |
| 985 | } | ||
| 986 | |||
| 987 | pub fn libPrefix_cpu_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) [:0]const u8 { | ||
| 988 | if (cpu_arch.isWasm()) { | ||
| 1146 | return ""; | 989 | return ""; |
| 1147 | } | 990 | } |
| 1148 | switch (self.abi) { | 991 | switch (abi) { |
| 1149 | .msvc => return "", | 992 | .msvc => return "", |
| 1150 | else => return "lib", | 993 | else => return "lib", |
| 1151 | } | 994 | } |
| 1152 | } | 995 | } |
| 1153 | 996 | ||
| 997 | pub fn libPrefix(self: Target) [:0]const u8 { | ||
| 998 | return libPrefix_cpu_arch_abi(self.cpu.arch, self.abi); | ||
| 999 | } | ||
| 1000 | |||
| 1154 | pub fn getObjectFormat(self: Target) ObjectFormat { | 1001 | pub fn getObjectFormat(self: Target) ObjectFormat { |
| 1155 | if (self.os.tag == .windows or self.os.tag == .uefi) { | 1002 | if (self.os.tag == .windows or self.os.tag == .uefi) { |
| 1156 | return .coff; | 1003 | return .coff; |
| ... | @@ -1190,129 +1037,18 @@ pub const Target = struct { | ... | @@ -1190,129 +1037,18 @@ pub const Target = struct { |
| 1190 | return self.os.tag.isDarwin(); | 1037 | return self.os.tag.isDarwin(); |
| 1191 | } | 1038 | } |
| 1192 | 1039 | ||
| 1193 | pub fn isGnuLibC(self: Target) bool { | 1040 | pub fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool { |
| 1194 | return self.os.tag == .linux and self.abi.isGnu(); | 1041 | return os_tag == .linux and abi.isGnu(); |
| 1195 | } | 1042 | } |
| 1196 | 1043 | ||
| 1197 | pub fn wantSharedLibSymLinks(self: Target) bool { | 1044 | pub fn isGnuLibC(self: Target) bool { |
| 1198 | return self.os.tag != .windows; | 1045 | return isGnuLibC_os_tag_abi(self.os.tag, self.abi); |
| 1199 | } | ||
| 1200 | |||
| 1201 | pub fn osRequiresLibC(self: Target) bool { | ||
| 1202 | return self.isDarwin() or self.os.tag == .freebsd or self.os.tag == .netbsd; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | pub fn getArchPtrBitWidth(self: Target) u32 { | ||
| 1206 | switch (self.cpu.arch) { | ||
| 1207 | .avr, | ||
| 1208 | .msp430, | ||
| 1209 | => return 16, | ||
| 1210 | |||
| 1211 | .arc, | ||
| 1212 | .arm, | ||
| 1213 | .armeb, | ||
| 1214 | .hexagon, | ||
| 1215 | .le32, | ||
| 1216 | .mips, | ||
| 1217 | .mipsel, | ||
| 1218 | .powerpc, | ||
| 1219 | .r600, | ||
| 1220 | .riscv32, | ||
| 1221 | .sparc, | ||
| 1222 | .sparcel, | ||
| 1223 | .tce, | ||
| 1224 | .tcele, | ||
| 1225 | .thumb, | ||
| 1226 | .thumbeb, | ||
| 1227 | .i386, | ||
| 1228 | .xcore, | ||
| 1229 | .nvptx, | ||
| 1230 | .amdil, | ||
| 1231 | .hsail, | ||
| 1232 | .spir, | ||
| 1233 | .kalimba, | ||
| 1234 | .shave, | ||
| 1235 | .lanai, | ||
| 1236 | .wasm32, | ||
| 1237 | .renderscript32, | ||
| 1238 | .aarch64_32, | ||
| 1239 | => return 32, | ||
| 1240 | |||
| 1241 | .aarch64, | ||
| 1242 | .aarch64_be, | ||
| 1243 | .mips64, | ||
| 1244 | .mips64el, | ||
| 1245 | .powerpc64, | ||
| 1246 | .powerpc64le, | ||
| 1247 | .riscv64, | ||
| 1248 | .x86_64, | ||
| 1249 | .nvptx64, | ||
| 1250 | .le64, | ||
| 1251 | .amdil64, | ||
| 1252 | .hsail64, | ||
| 1253 | .spir64, | ||
| 1254 | .wasm64, | ||
| 1255 | .renderscript64, | ||
| 1256 | .amdgcn, | ||
| 1257 | .bpfel, | ||
| 1258 | .bpfeb, | ||
| 1259 | .sparcv9, | ||
| 1260 | .s390x, | ||
| 1261 | => return 64, | ||
| 1262 | } | ||
| 1263 | } | 1046 | } |
| 1264 | 1047 | ||
| 1265 | pub fn supportsNewStackCall(self: Target) bool { | 1048 | pub fn supportsNewStackCall(self: Target) bool { |
| 1266 | return !self.cpu.arch.isWasm(); | 1049 | return !self.cpu.arch.isWasm(); |
| 1267 | } | 1050 | } |
| 1268 | 1051 | ||
| 1269 | pub const Executor = union(enum) { | ||
| 1270 | native, | ||
| 1271 | qemu: []const u8, | ||
| 1272 | wine: []const u8, | ||
| 1273 | wasmtime: []const u8, | ||
| 1274 | unavailable, | ||
| 1275 | }; | ||
| 1276 | |||
| 1277 | pub fn getExternalExecutor(self: Target) Executor { | ||
| 1278 | // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture. | ||
| 1279 | if (self.os.tag == builtin.os.tag) { | ||
| 1280 | return switch (self.cpu.arch) { | ||
| 1281 | .aarch64 => Executor{ .qemu = "qemu-aarch64" }, | ||
| 1282 | .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, | ||
| 1283 | .arm => Executor{ .qemu = "qemu-arm" }, | ||
| 1284 | .armeb => Executor{ .qemu = "qemu-armeb" }, | ||
| 1285 | .i386 => Executor{ .qemu = "qemu-i386" }, | ||
| 1286 | .mips => Executor{ .qemu = "qemu-mips" }, | ||
| 1287 | .mipsel => Executor{ .qemu = "qemu-mipsel" }, | ||
| 1288 | .mips64 => Executor{ .qemu = "qemu-mips64" }, | ||
| 1289 | .mips64el => Executor{ .qemu = "qemu-mips64el" }, | ||
| 1290 | .powerpc => Executor{ .qemu = "qemu-ppc" }, | ||
| 1291 | .powerpc64 => Executor{ .qemu = "qemu-ppc64" }, | ||
| 1292 | .powerpc64le => Executor{ .qemu = "qemu-ppc64le" }, | ||
| 1293 | .riscv32 => Executor{ .qemu = "qemu-riscv32" }, | ||
| 1294 | .riscv64 => Executor{ .qemu = "qemu-riscv64" }, | ||
| 1295 | .s390x => Executor{ .qemu = "qemu-s390x" }, | ||
| 1296 | .sparc => Executor{ .qemu = "qemu-sparc" }, | ||
| 1297 | .x86_64 => Executor{ .qemu = "qemu-x86_64" }, | ||
| 1298 | else => return .unavailable, | ||
| 1299 | }; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | switch (self.os.tag) { | ||
| 1303 | .windows => switch (self.getArchPtrBitWidth()) { | ||
| 1304 | 32 => return Executor{ .wine = "wine" }, | ||
| 1305 | 64 => return Executor{ .wine = "wine64" }, | ||
| 1306 | else => return .unavailable, | ||
| 1307 | }, | ||
| 1308 | .wasi => switch (self.getArchPtrBitWidth()) { | ||
| 1309 | 32 => return Executor{ .wasmtime = "wasmtime" }, | ||
| 1310 | else => return .unavailable, | ||
| 1311 | }, | ||
| 1312 | else => return .unavailable, | ||
| 1313 | } | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | pub const FloatAbi = enum { | 1052 | pub const FloatAbi = enum { |
| 1317 | hard, | 1053 | hard, |
| 1318 | soft, | 1054 | soft, |
| ... | @@ -1359,7 +1095,7 @@ pub const Target = struct { | ... | @@ -1359,7 +1095,7 @@ pub const Target = struct { |
| 1359 | }![:0]u8 { | 1095 | }![:0]u8 { |
| 1360 | const a = allocator; | 1096 | const a = allocator; |
| 1361 | if (self.isAndroid()) { | 1097 | if (self.isAndroid()) { |
| 1362 | return mem.dupeZ(a, u8, if (self.getArchPtrBitWidth() == 64) | 1098 | return mem.dupeZ(a, u8, if (self.cpu.arch.ptrBitWidth() == 64) |
| 1363 | "/system/bin/linker64" | 1099 | "/system/bin/linker64" |
| 1364 | else | 1100 | else |
| 1365 | "/system/bin/linker"); | 1101 | "/system/bin/linker"); |
| ... | @@ -1477,52 +1213,3 @@ pub const Target = struct { | ... | @@ -1477,52 +1213,3 @@ pub const Target = struct { |
| 1477 | } | 1213 | } |
| 1478 | } | 1214 | } |
| 1479 | }; | 1215 | }; |
| 1480 | |||
| 1481 | test "Target.parse" { | ||
| 1482 | { | ||
| 1483 | const target = try Target.parse(.{ | ||
| 1484 | .arch_os_abi = "x86_64-linux-gnu", | ||
| 1485 | .cpu_features = "x86_64-sse-sse2-avx-cx8", | ||
| 1486 | }); | ||
| 1487 | |||
| 1488 | std.testing.expect(target.os.tag == .linux); | ||
| 1489 | std.testing.expect(target.abi == .gnu); | ||
| 1490 | std.testing.expect(target.cpu.arch == .x86_64); | ||
| 1491 | std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse)); | ||
| 1492 | std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx)); | ||
| 1493 | std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8)); | ||
| 1494 | std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov)); | ||
| 1495 | std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); | ||
| 1496 | } | ||
| 1497 | { | ||
| 1498 | const target = try Target.parse(.{ | ||
| 1499 | .arch_os_abi = "arm-linux-musleabihf", | ||
| 1500 | .cpu_features = "generic+v8a", | ||
| 1501 | }); | ||
| 1502 | |||
| 1503 | std.testing.expect(target.os.tag == .linux); | ||
| 1504 | std.testing.expect(target.abi == .musleabihf); | ||
| 1505 | std.testing.expect(target.cpu.arch == .arm); | ||
| 1506 | std.testing.expect(target.cpu.model == &Target.arm.cpu.generic); | ||
| 1507 | std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a)); | ||
| 1508 | } | ||
| 1509 | { | ||
| 1510 | const target = try Target.parse(.{ | ||
| 1511 | .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", | ||
| 1512 | .cpu_features = "generic+v8a", | ||
| 1513 | }); | ||
| 1514 | |||
| 1515 | std.testing.expect(target.cpu.arch == .aarch64); | ||
| 1516 | std.testing.expect(target.os.tag == .linux); | ||
| 1517 | std.testing.expect(target.os.version_range.linux.range.min.major == 3); | ||
| 1518 | std.testing.expect(target.os.version_range.linux.range.min.minor == 10); | ||
| 1519 | std.testing.expect(target.os.version_range.linux.range.min.patch == 0); | ||
| 1520 | std.testing.expect(target.os.version_range.linux.range.max.major == 4); | ||
| 1521 | std.testing.expect(target.os.version_range.linux.range.max.minor == 4); | ||
| 1522 | std.testing.expect(target.os.version_range.linux.range.max.patch == 1); | ||
| 1523 | std.testing.expect(target.os.version_range.linux.glibc.major == 2); | ||
| 1524 | std.testing.expect(target.os.version_range.linux.glibc.minor == 27); | ||
| 1525 | std.testing.expect(target.os.version_range.linux.glibc.patch == 0); | ||
| 1526 | std.testing.expect(target.abi == .gnu); | ||
| 1527 | } | ||
| 1528 | } |
lib/std/testing.zig+4-6| ... | @@ -1,5 +1,3 @@ | ... | @@ -1,5 +1,3 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 2 | const TypeId = builtin.TypeId; | ||
| 3 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 4 | 2 | ||
| 5 | pub const LeakCountAllocator = @import("testing/leak_count_allocator.zig").LeakCountAllocator; | 3 | pub const LeakCountAllocator = @import("testing/leak_count_allocator.zig").LeakCountAllocator; |
| ... | @@ -65,16 +63,16 @@ pub fn expectEqual(expected: var, actual: @TypeOf(expected)) void { | ... | @@ -65,16 +63,16 @@ pub fn expectEqual(expected: var, actual: @TypeOf(expected)) void { |
| 65 | 63 | ||
| 66 | .Pointer => |pointer| { | 64 | .Pointer => |pointer| { |
| 67 | switch (pointer.size) { | 65 | switch (pointer.size) { |
| 68 | builtin.TypeInfo.Pointer.Size.One, | 66 | .One, |
| 69 | builtin.TypeInfo.Pointer.Size.Many, | 67 | .Many, |
| 70 | builtin.TypeInfo.Pointer.Size.C, | 68 | .C, |
| 71 | => { | 69 | => { |
| 72 | if (actual != expected) { | 70 | if (actual != expected) { |
| 73 | std.debug.panic("expected {*}, found {*}", .{ expected, actual }); | 71 | std.debug.panic("expected {*}, found {*}", .{ expected, actual }); |
| 74 | } | 72 | } |
| 75 | }, | 73 | }, |
| 76 | 74 | ||
| 77 | builtin.TypeInfo.Pointer.Size.Slice => { | 75 | .Slice => { |
| 78 | if (actual.ptr != expected.ptr) { | 76 | if (actual.ptr != expected.ptr) { |
| 79 | std.debug.panic("expected slice ptr {}, found {}", .{ expected.ptr, actual.ptr }); | 77 | std.debug.panic("expected slice ptr {}, found {}", .{ expected.ptr, actual.ptr }); |
| 80 | } | 78 | } |
lib/std/zig.zig+3-6| ... | @@ -6,11 +6,8 @@ pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStri | ... | @@ -6,11 +6,8 @@ pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStri |
| 6 | pub const render = @import("zig/render.zig").render; | 6 | pub const render = @import("zig/render.zig").render; |
| 7 | pub const ast = @import("zig/ast.zig"); | 7 | pub const ast = @import("zig/ast.zig"); |
| 8 | pub const system = @import("zig/system.zig"); | 8 | pub const system = @import("zig/system.zig"); |
| 9 | pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget; | ||
| 9 | 10 | ||
| 10 | test "std.zig tests" { | 11 | test "" { |
| 11 | _ = @import("zig/ast.zig"); | 12 | @import("std").meta.refAllDecls(@This()); |
| 12 | _ = @import("zig/parse.zig"); | ||
| 13 | _ = @import("zig/render.zig"); | ||
| 14 | _ = @import("zig/tokenizer.zig"); | ||
| 15 | _ = @import("zig/parse_string_literal.zig"); | ||
| 16 | } | 13 | } |
lib/std/zig/cross_target.zig created+766| ... | @@ -0,0 +1,766 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const Target = std.Target; | ||
| 4 | const mem = std.mem; | ||
| 5 | |||
| 6 | /// Contains all the same data as `Target`, additionally introducing the concept of "the native target". | ||
| 7 | /// The purpose of this abstraction is to provide meaningful and unsurprising defaults. | ||
| 8 | pub const CrossTarget = struct { | ||
| 9 | /// `null` means native. | ||
| 10 | cpu_arch: ?Target.Cpu.Arch = null, | ||
| 11 | |||
| 12 | /// If `cpu_arch` is native, `null` means native. Otherwise it means baseline. | ||
| 13 | /// If this is non-null, `cpu_arch` must be specified. | ||
| 14 | cpu_model: ?*const Target.Cpu.Model = null, | ||
| 15 | |||
| 16 | /// Sparse set of CPU features to add to the set from `cpu_model`. | ||
| 17 | /// If this is non-empty, `cpu_arch` must be specified. | ||
| 18 | cpu_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`. | ||
| 21 | /// If this is non-empty, `cpu_arch` must be specified. | ||
| 22 | cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty, | ||
| 23 | |||
| 24 | /// `null` means native. | ||
| 25 | os_tag: ?Target.Os.Tag = null, | ||
| 26 | |||
| 27 | /// `null` means the default version range for `os_tag`. If `os_tag` is `null` (native) | ||
| 28 | /// then `null` for this field means native. | ||
| 29 | os_version_min: ?OsVersion = null, | ||
| 30 | |||
| 31 | /// When cross compiling, `null` means default (latest known OS version). | ||
| 32 | /// When `os_tag` is native, `null` means equal to the native OS version. | ||
| 33 | os_version_max: ?OsVersion = null, | ||
| 34 | |||
| 35 | /// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI. | ||
| 36 | abi: ?Target.Abi = null, | ||
| 37 | |||
| 38 | /// `null` means default when cross compiling, or native when os_tag is native. | ||
| 39 | /// If `isGnuLibC()` is `false`, this must be `null` and is ignored. | ||
| 40 | glibc_version: ?SemVer = null, | ||
| 41 | |||
| 42 | pub const OsVersion = union(enum) { | ||
| 43 | none: void, | ||
| 44 | semver: SemVer, | ||
| 45 | windows: Target.Os.WindowsVersion, | ||
| 46 | }; | ||
| 47 | |||
| 48 | pub const SemVer = std.builtin.Version; | ||
| 49 | |||
| 50 | pub fn fromTarget(target: Target) CrossTarget { | ||
| 51 | var result: CrossTarget = .{ | ||
| 52 | .cpu_arch = target.cpu.arch, | ||
| 53 | .cpu_model = target.cpu.model, | ||
| 54 | .os_tag = target.os.tag, | ||
| 55 | .os_version_min = undefined, | ||
| 56 | .os_version_max = undefined, | ||
| 57 | .abi = target.abi, | ||
| 58 | .glibc_version = if (target.isGnuLibC()) | ||
| 59 | target.os.version_range.linux.glibc | ||
| 60 | else | ||
| 61 | null, | ||
| 62 | }; | ||
| 63 | result.updateOsVersionRange(target.os); | ||
| 64 | |||
| 65 | const all_features = target.cpu.arch.allFeaturesList(); | ||
| 66 | var cpu_model_set = target.cpu.model.features; | ||
| 67 | cpu_model_set.populateDependencies(all_features); | ||
| 68 | { | ||
| 69 | // The "add" set is the full set with the CPU Model set removed. | ||
| 70 | const add_set = &result.cpu_features_add; | ||
| 71 | add_set.* = target.cpu.features; | ||
| 72 | add_set.removeFeatureSet(cpu_model_set); | ||
| 73 | } | ||
| 74 | { | ||
| 75 | // The "sub" set is the features that are on in CPU Model set and off in the full set. | ||
| 76 | const sub_set = &result.cpu_features_sub; | ||
| 77 | sub_set.* = cpu_model_set; | ||
| 78 | sub_set.removeFeatureSet(target.cpu.features); | ||
| 79 | } | ||
| 80 | return result; | ||
| 81 | } | ||
| 82 | |||
| 83 | fn updateOsVersionRange(self: *CrossTarget, os: Target.Os) void { | ||
| 84 | switch (os.tag) { | ||
| 85 | .freestanding, | ||
| 86 | .ananas, | ||
| 87 | .cloudabi, | ||
| 88 | .dragonfly, | ||
| 89 | .fuchsia, | ||
| 90 | .ios, | ||
| 91 | .kfreebsd, | ||
| 92 | .lv2, | ||
| 93 | .solaris, | ||
| 94 | .haiku, | ||
| 95 | .minix, | ||
| 96 | .rtems, | ||
| 97 | .nacl, | ||
| 98 | .cnk, | ||
| 99 | .aix, | ||
| 100 | .cuda, | ||
| 101 | .nvcl, | ||
| 102 | .amdhsa, | ||
| 103 | .ps4, | ||
| 104 | .elfiamcu, | ||
| 105 | .tvos, | ||
| 106 | .watchos, | ||
| 107 | .mesa3d, | ||
| 108 | .contiki, | ||
| 109 | .amdpal, | ||
| 110 | .hermit, | ||
| 111 | .hurd, | ||
| 112 | .wasi, | ||
| 113 | .emscripten, | ||
| 114 | .uefi, | ||
| 115 | .other, | ||
| 116 | => { | ||
| 117 | self.os_version_min = .{ .none = {} }; | ||
| 118 | self.os_version_max = .{ .none = {} }; | ||
| 119 | }, | ||
| 120 | |||
| 121 | .freebsd, | ||
| 122 | .macosx, | ||
| 123 | .netbsd, | ||
| 124 | .openbsd, | ||
| 125 | => { | ||
| 126 | self.os_version_min = .{ .semver = os.version_range.semver.min }; | ||
| 127 | self.os_version_max = .{ .semver = os.version_range.semver.max }; | ||
| 128 | }, | ||
| 129 | |||
| 130 | .linux => { | ||
| 131 | self.os_version_min = .{ .semver = os.version_range.linux.range.min }; | ||
| 132 | self.os_version_max = .{ .semver = os.version_range.linux.range.max }; | ||
| 133 | }, | ||
| 134 | |||
| 135 | .windows => { | ||
| 136 | self.os_version_min = .{ .windows = os.version_range.windows.min }; | ||
| 137 | self.os_version_max = .{ .windows = os.version_range.windows.max }; | ||
| 138 | }, | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | pub fn toTarget(self: CrossTarget) Target { | ||
| 143 | return .{ | ||
| 144 | .cpu = self.getCpu(), | ||
| 145 | .os = self.getOs(), | ||
| 146 | .abi = self.getAbi(), | ||
| 147 | }; | ||
| 148 | } | ||
| 149 | |||
| 150 | pub const ParseOptions = struct { | ||
| 151 | /// This is sometimes called a "triple". It looks roughly like this: | ||
| 152 | /// riscv64-linux-musl | ||
| 153 | /// The fields are, respectively: | ||
| 154 | /// * CPU Architecture | ||
| 155 | /// * Operating System (and optional version range) | ||
| 156 | /// * C ABI (optional, with optional glibc version) | ||
| 157 | /// The string "native" can be used for CPU architecture as well as Operating System. | ||
| 158 | /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted. | ||
| 159 | arch_os_abi: []const u8 = "native", | ||
| 160 | |||
| 161 | /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e" | ||
| 162 | /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features | ||
| 163 | /// to remove from the set. | ||
| 164 | /// The following special strings are recognized for CPU Model name: | ||
| 165 | /// * "baseline" - The "default" set of CPU features for cross-compiling. A conservative set | ||
| 166 | /// of features that is expected to be supported on most available hardware. | ||
| 167 | /// * "native" - The native CPU model is to be detected when compiling. | ||
| 168 | /// If this field is not provided (`null`), then the value will depend on the | ||
| 169 | /// parsed CPU Architecture. If native, then this will be "native". Otherwise, it will be "baseline". | ||
| 170 | cpu_features: ?[]const u8 = null, | ||
| 171 | |||
| 172 | /// If this is provided, the function will populate some information about parsing failures, | ||
| 173 | /// so that user-friendly error messages can be delivered. | ||
| 174 | diagnostics: ?*Diagnostics = null, | ||
| 175 | |||
| 176 | pub const Diagnostics = struct { | ||
| 177 | /// If the architecture was determined, this will be populated. | ||
| 178 | arch: ?Target.Cpu.Arch = null, | ||
| 179 | |||
| 180 | /// If the OS tag was determined, this will be populated. | ||
| 181 | os_tag: ?Target.Os.Tag = null, | ||
| 182 | |||
| 183 | /// If the ABI was determined, this will be populated. | ||
| 184 | abi: ?Target.Abi = null, | ||
| 185 | |||
| 186 | /// If the CPU name was determined, this will be populated. | ||
| 187 | cpu_name: ?[]const u8 = null, | ||
| 188 | |||
| 189 | /// If error.UnknownCpuFeature is returned, this will be populated. | ||
| 190 | unknown_feature_name: ?[]const u8 = null, | ||
| 191 | }; | ||
| 192 | }; | ||
| 193 | |||
| 194 | pub fn parse(args: ParseOptions) !CrossTarget { | ||
| 195 | var dummy_diags: ParseOptions.Diagnostics = undefined; | ||
| 196 | const diags = args.diagnostics orelse &dummy_diags; | ||
| 197 | |||
| 198 | // Start with everything initialized to default values. | ||
| 199 | var result: CrossTarget = .{}; | ||
| 200 | |||
| 201 | var it = mem.separate(args.arch_os_abi, "-"); | ||
| 202 | const arch_name = it.next().?; | ||
| 203 | const arch_is_native = mem.eql(u8, arch_name, "native"); | ||
| 204 | if (!arch_is_native) { | ||
| 205 | result.cpu_arch = std.meta.stringToEnum(Target.Cpu.Arch, arch_name) orelse | ||
| 206 | return error.UnknownArchitecture; | ||
| 207 | } | ||
| 208 | const arch = result.getCpuArch(); | ||
| 209 | diags.arch = arch; | ||
| 210 | |||
| 211 | if (it.next()) |os_text| { | ||
| 212 | try parseOs(&result, diags, os_text); | ||
| 213 | } else if (!arch_is_native) { | ||
| 214 | return error.MissingOperatingSystem; | ||
| 215 | } | ||
| 216 | |||
| 217 | const opt_abi_text = it.next(); | ||
| 218 | if (opt_abi_text) |abi_text| { | ||
| 219 | var abi_it = mem.separate(abi_text, "."); | ||
| 220 | const abi = std.meta.stringToEnum(Target.Abi, abi_it.next().?) orelse | ||
| 221 | return error.UnknownApplicationBinaryInterface; | ||
| 222 | diags.abi = abi; | ||
| 223 | |||
| 224 | const abi_ver_text = abi_it.rest(); | ||
| 225 | if (abi_it.next() != null) { | ||
| 226 | if (result.isGnuLibC()) { | ||
| 227 | result.glibc_version = SemVer.parse(abi_ver_text) catch |err| switch (err) { | ||
| 228 | error.Overflow => return error.InvalidAbiVersion, | ||
| 229 | error.InvalidCharacter => return error.InvalidAbiVersion, | ||
| 230 | error.InvalidVersion => return error.InvalidAbiVersion, | ||
| 231 | }; | ||
| 232 | } else { | ||
| 233 | return error.InvalidAbiVersion; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | if (it.next() != null) return error.UnexpectedExtraField; | ||
| 239 | |||
| 240 | if (args.cpu_features) |cpu_features| { | ||
| 241 | const all_features = arch.allFeaturesList(); | ||
| 242 | var index: usize = 0; | ||
| 243 | while (index < cpu_features.len and | ||
| 244 | cpu_features[index] != '+' and | ||
| 245 | cpu_features[index] != '-') | ||
| 246 | { | ||
| 247 | index += 1; | ||
| 248 | } | ||
| 249 | const cpu_name = cpu_features[0..index]; | ||
| 250 | diags.cpu_name = cpu_name; | ||
| 251 | |||
| 252 | const add_set = &result.cpu_features_add; | ||
| 253 | const sub_set = &result.cpu_features_sub; | ||
| 254 | if (mem.eql(u8, cpu_name, "native")) { | ||
| 255 | result.cpu_model = null; | ||
| 256 | } else if (mem.eql(u8, cpu_name, "baseline")) { | ||
| 257 | result.cpu_model = Target.Cpu.Model.baseline(arch); | ||
| 258 | } else { | ||
| 259 | result.cpu_model = try arch.parseCpuModel(cpu_name); | ||
| 260 | } | ||
| 261 | |||
| 262 | while (index < cpu_features.len) { | ||
| 263 | const op = cpu_features[index]; | ||
| 264 | const set = switch (op) { | ||
| 265 | '+' => add_set, | ||
| 266 | '-' => sub_set, | ||
| 267 | else => unreachable, | ||
| 268 | }; | ||
| 269 | index += 1; | ||
| 270 | const start = index; | ||
| 271 | while (index < cpu_features.len and | ||
| 272 | cpu_features[index] != '+' and | ||
| 273 | cpu_features[index] != '-') | ||
| 274 | { | ||
| 275 | index += 1; | ||
| 276 | } | ||
| 277 | const feature_name = cpu_features[start..index]; | ||
| 278 | for (all_features) |feature, feat_index_usize| { | ||
| 279 | const feat_index = @intCast(Target.Cpu.Feature.Set.Index, feat_index_usize); | ||
| 280 | if (mem.eql(u8, feature_name, feature.name)) { | ||
| 281 | set.addFeature(feat_index); | ||
| 282 | break; | ||
| 283 | } | ||
| 284 | } else { | ||
| 285 | diags.unknown_feature_name = feature_name; | ||
| 286 | return error.UnknownCpuFeature; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | return result; | ||
| 292 | } | ||
| 293 | |||
| 294 | pub fn getCpu(self: CrossTarget) Target.Cpu { | ||
| 295 | if (self.cpu_arch) |arch| { | ||
| 296 | if (self.cpu_model) |model| { | ||
| 297 | var adjusted_model = model.toCpu(arch); | ||
| 298 | self.updateCpuFeatures(&adjusted_model.features); | ||
| 299 | return adjusted_model; | ||
| 300 | } else { | ||
| 301 | var adjusted_baseline = Target.Cpu.baseline(arch); | ||
| 302 | self.updateCpuFeatures(&adjusted_baseline.features); | ||
| 303 | return adjusted_baseline; | ||
| 304 | } | ||
| 305 | } else { | ||
| 306 | assert(self.cpu_model == null); | ||
| 307 | assert(self.cpu_features_sub.isEmpty()); | ||
| 308 | assert(self.cpu_features_add.isEmpty()); | ||
| 309 | // This works when doing `zig build` because Zig generates a build executable using | ||
| 310 | // native CPU model & features. However this will not be accurate otherwise, and | ||
| 311 | // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. | ||
| 312 | return Target.current.cpu; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | pub fn getCpuArch(self: CrossTarget) Target.Cpu.Arch { | ||
| 317 | return self.cpu_arch orelse Target.current.cpu.arch; | ||
| 318 | } | ||
| 319 | |||
| 320 | pub fn getCpuModel(self: CrossTarget) *const Target.Cpu.Model { | ||
| 321 | if (self.cpu_model) |cpu_model| return cpu_model; | ||
| 322 | return self.getCpu().model; | ||
| 323 | } | ||
| 324 | |||
| 325 | pub fn getCpuFeatures(self: CrossTarget) Target.Cpu.Feature.Set { | ||
| 326 | return self.getCpu().features; | ||
| 327 | } | ||
| 328 | |||
| 329 | pub fn getOs(self: CrossTarget) Target.Os { | ||
| 330 | // `Target.current.os` works when doing `zig build` because Zig generates a build executable using | ||
| 331 | // native OS version range. However this will not be accurate otherwise, and | ||
| 332 | // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. | ||
| 333 | var adjusted_os = if (self.os_tag) |os_tag| Target.Os.defaultVersionRange(os_tag) else Target.current.os; | ||
| 334 | |||
| 335 | if (self.os_version_min) |min| switch (min) { | ||
| 336 | .none => {}, | ||
| 337 | .semver => |semver| switch (self.getOsTag()) { | ||
| 338 | .linux => adjusted_os.version_range.linux.range.min = semver, | ||
| 339 | else => adjusted_os.version_range.semver.min = semver, | ||
| 340 | }, | ||
| 341 | .windows => |win_ver| adjusted_os.version_range.windows.min = win_ver, | ||
| 342 | }; | ||
| 343 | |||
| 344 | if (self.os_version_max) |max| switch (max) { | ||
| 345 | .none => {}, | ||
| 346 | .semver => |semver| switch (self.getOsTag()) { | ||
| 347 | .linux => adjusted_os.version_range.linux.range.max = semver, | ||
| 348 | else => adjusted_os.version_range.semver.max = semver, | ||
| 349 | }, | ||
| 350 | .windows => |win_ver| adjusted_os.version_range.windows.max = win_ver, | ||
| 351 | }; | ||
| 352 | |||
| 353 | if (self.glibc_version) |glibc| { | ||
| 354 | assert(self.isGnuLibC()); | ||
| 355 | adjusted_os.version_range.linux.glibc = glibc; | ||
| 356 | } | ||
| 357 | |||
| 358 | return adjusted_os; | ||
| 359 | } | ||
| 360 | |||
| 361 | pub fn getOsTag(self: CrossTarget) Target.Os.Tag { | ||
| 362 | return self.os_tag orelse Target.current.os.tag; | ||
| 363 | } | ||
| 364 | |||
| 365 | pub fn getOsVersionMin(self: CrossTarget) OsVersion { | ||
| 366 | if (self.os_version_min) |version_min| return version_min; | ||
| 367 | var tmp: CrossTarget = undefined; | ||
| 368 | tmp.updateOsVersionRange(self.getOs()); | ||
| 369 | return tmp.os_version_min.?; | ||
| 370 | } | ||
| 371 | |||
| 372 | pub fn getOsVersionMax(self: CrossTarget) OsVersion { | ||
| 373 | if (self.os_version_max) |version_max| return version_max; | ||
| 374 | var tmp: CrossTarget = undefined; | ||
| 375 | tmp.updateOsVersionRange(self.getOs()); | ||
| 376 | return tmp.os_version_max.?; | ||
| 377 | } | ||
| 378 | |||
| 379 | pub fn getAbi(self: CrossTarget) Target.Abi { | ||
| 380 | if (self.abi) |abi| return abi; | ||
| 381 | |||
| 382 | if (self.isNativeOs()) { | ||
| 383 | // This works when doing `zig build` because Zig generates a build executable using | ||
| 384 | // native CPU model & features. However this will not be accurate otherwise, and | ||
| 385 | // will need to be integrated with `std.zig.system.NativeTargetInfo.detect`. | ||
| 386 | return Target.current.abi; | ||
| 387 | } | ||
| 388 | |||
| 389 | return Target.Abi.default(self.getCpuArch(), self.getOs()); | ||
| 390 | } | ||
| 391 | |||
| 392 | pub fn isFreeBSD(self: CrossTarget) bool { | ||
| 393 | return self.getOsTag() == .freebsd; | ||
| 394 | } | ||
| 395 | |||
| 396 | pub fn isDarwin(self: CrossTarget) bool { | ||
| 397 | return self.getOsTag().isDarwin(); | ||
| 398 | } | ||
| 399 | |||
| 400 | pub fn isNetBSD(self: CrossTarget) bool { | ||
| 401 | return self.getOsTag() == .netbsd; | ||
| 402 | } | ||
| 403 | |||
| 404 | pub fn isUefi(self: CrossTarget) bool { | ||
| 405 | return self.getOsTag() == .uefi; | ||
| 406 | } | ||
| 407 | |||
| 408 | pub fn isDragonFlyBSD(self: CrossTarget) bool { | ||
| 409 | return self.getOsTag() == .dragonfly; | ||
| 410 | } | ||
| 411 | |||
| 412 | pub fn isLinux(self: CrossTarget) bool { | ||
| 413 | return self.getOsTag() == .linux; | ||
| 414 | } | ||
| 415 | |||
| 416 | pub fn isWindows(self: CrossTarget) bool { | ||
| 417 | return self.getOsTag() == .windows; | ||
| 418 | } | ||
| 419 | |||
| 420 | pub fn oFileExt(self: CrossTarget) [:0]const u8 { | ||
| 421 | return self.getAbi().oFileExt(); | ||
| 422 | } | ||
| 423 | |||
| 424 | pub fn exeFileExt(self: CrossTarget) [:0]const u8 { | ||
| 425 | return Target.exeFileExtSimple(self.getCpuArch(), self.getOsTag()); | ||
| 426 | } | ||
| 427 | |||
| 428 | pub fn staticLibSuffix(self: CrossTarget) [:0]const u8 { | ||
| 429 | return Target.staticLibSuffix_cpu_arch_abi(self.getCpuArch(), self.getAbi()); | ||
| 430 | } | ||
| 431 | |||
| 432 | pub fn dynamicLibSuffix(self: CrossTarget) [:0]const u8 { | ||
| 433 | return self.getOsTag().dynamicLibSuffix(); | ||
| 434 | } | ||
| 435 | |||
| 436 | pub fn libPrefix(self: CrossTarget) [:0]const u8 { | ||
| 437 | return Target.libPrefix_cpu_arch_abi(self.getCpuArch(), self.getAbi()); | ||
| 438 | } | ||
| 439 | |||
| 440 | pub fn isNativeCpu(self: CrossTarget) bool { | ||
| 441 | return self.cpu_arch == null and self.cpu_model == null and | ||
| 442 | self.cpu_features_sub.isEmpty() and self.cpu_features_add.isEmpty(); | ||
| 443 | } | ||
| 444 | |||
| 445 | pub fn isNativeOs(self: CrossTarget) bool { | ||
| 446 | return self.os_tag == null and self.os_version_min == null and self.os_version_max == null; | ||
| 447 | } | ||
| 448 | |||
| 449 | pub fn isNativeAbi(self: CrossTarget) bool { | ||
| 450 | return self.abi == null and self.glibc_version == null; | ||
| 451 | } | ||
| 452 | |||
| 453 | pub fn isNative(self: CrossTarget) bool { | ||
| 454 | return self.isNativeCpu() and self.isNativeOs() and self.isNativeAbi(); | ||
| 455 | } | ||
| 456 | |||
| 457 | pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![:0]u8 { | ||
| 458 | if (self.isNative()) { | ||
| 459 | return mem.dupeZ(allocator, u8, "native"); | ||
| 460 | } | ||
| 461 | |||
| 462 | const arch_name = if (self.isNativeCpu()) "native" else @tagName(self.getCpuArch()); | ||
| 463 | const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native"; | ||
| 464 | |||
| 465 | var result = try std.Buffer.allocPrint(allocator, "{}-{}", .{ arch_name, os_name }); | ||
| 466 | defer result.deinit(); | ||
| 467 | |||
| 468 | // The zig target syntax does not allow specifying a max os version with no min, so | ||
| 469 | // if either are present, we need the min. | ||
| 470 | if (self.os_version_min != null or self.os_version_max != null) { | ||
| 471 | switch (self.getOsVersionMin()) { | ||
| 472 | .none => {}, | ||
| 473 | .semver => |v| try result.print(".{}", .{v}), | ||
| 474 | .windows => |v| try result.print(".{}", .{@tagName(v)}), | ||
| 475 | } | ||
| 476 | } | ||
| 477 | if (self.os_version_max) |max| { | ||
| 478 | switch (max) { | ||
| 479 | .none => {}, | ||
| 480 | .semver => |v| try result.print("...{}", .{v}), | ||
| 481 | .windows => |v| try result.print("...{}", .{@tagName(v)}), | ||
| 482 | } | ||
| 483 | } | ||
| 484 | |||
| 485 | if (self.abi) |abi| { | ||
| 486 | try result.print("-{}", .{@tagName(abi)}); | ||
| 487 | if (self.glibc_version) |v| { | ||
| 488 | try result.print(".{}", .{v}); | ||
| 489 | } | ||
| 490 | } else { | ||
| 491 | assert(self.glibc_version == null); | ||
| 492 | } | ||
| 493 | |||
| 494 | return result.toOwnedSlice(); | ||
| 495 | } | ||
| 496 | |||
| 497 | pub fn allocDescription(self: CrossTarget, allocator: *mem.Allocator) ![:0]u8 { | ||
| 498 | // TODO is there anything else worthy of the description that is not | ||
| 499 | // already captured in the triple? | ||
| 500 | return self.zigTriple(allocator); | ||
| 501 | } | ||
| 502 | |||
| 503 | pub fn linuxTriple(self: CrossTarget, allocator: *mem.Allocator) ![:0]u8 { | ||
| 504 | return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); | ||
| 505 | } | ||
| 506 | |||
| 507 | pub fn wantSharedLibSymLinks(self: CrossTarget) bool { | ||
| 508 | return self.getOsTag() != .windows; | ||
| 509 | } | ||
| 510 | |||
| 511 | pub const VcpkgLinkage = std.builtin.LinkMode; | ||
| 512 | |||
| 513 | /// Returned slice must be freed by the caller. | ||
| 514 | pub fn vcpkgTriplet(self: CrossTarget, allocator: *mem.Allocator, linkage: VcpkgLinkage) ![:0]u8 { | ||
| 515 | const arch = switch (self.getCpuArch()) { | ||
| 516 | .i386 => "x86", | ||
| 517 | .x86_64 => "x64", | ||
| 518 | |||
| 519 | .arm, | ||
| 520 | .armeb, | ||
| 521 | .thumb, | ||
| 522 | .thumbeb, | ||
| 523 | .aarch64_32, | ||
| 524 | => "arm", | ||
| 525 | |||
| 526 | .aarch64, | ||
| 527 | .aarch64_be, | ||
| 528 | => "arm64", | ||
| 529 | |||
| 530 | else => return error.UnsupportedVcpkgArchitecture, | ||
| 531 | }; | ||
| 532 | |||
| 533 | const os = switch (self.getOsTag()) { | ||
| 534 | .windows => "windows", | ||
| 535 | .linux => "linux", | ||
| 536 | .macosx => "macos", | ||
| 537 | else => return error.UnsupportedVcpkgOperatingSystem, | ||
| 538 | }; | ||
| 539 | |||
| 540 | const static_suffix = switch (linkage) { | ||
| 541 | .Static => "-static", | ||
| 542 | .Dynamic => "", | ||
| 543 | }; | ||
| 544 | |||
| 545 | return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix }); | ||
| 546 | } | ||
| 547 | |||
| 548 | pub const Executor = union(enum) { | ||
| 549 | native, | ||
| 550 | qemu: []const u8, | ||
| 551 | wine: []const u8, | ||
| 552 | wasmtime: []const u8, | ||
| 553 | unavailable, | ||
| 554 | }; | ||
| 555 | |||
| 556 | pub fn getExternalExecutor(self: CrossTarget) Executor { | ||
| 557 | const os_tag = self.getOsTag(); | ||
| 558 | const cpu_arch = self.getCpuArch(); | ||
| 559 | |||
| 560 | // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture. | ||
| 561 | if (os_tag == Target.current.os.tag) { | ||
| 562 | return switch (cpu_arch) { | ||
| 563 | .aarch64 => Executor{ .qemu = "qemu-aarch64" }, | ||
| 564 | .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, | ||
| 565 | .arm => Executor{ .qemu = "qemu-arm" }, | ||
| 566 | .armeb => Executor{ .qemu = "qemu-armeb" }, | ||
| 567 | .i386 => Executor{ .qemu = "qemu-i386" }, | ||
| 568 | .mips => Executor{ .qemu = "qemu-mips" }, | ||
| 569 | .mipsel => Executor{ .qemu = "qemu-mipsel" }, | ||
| 570 | .mips64 => Executor{ .qemu = "qemu-mips64" }, | ||
| 571 | .mips64el => Executor{ .qemu = "qemu-mips64el" }, | ||
| 572 | .powerpc => Executor{ .qemu = "qemu-ppc" }, | ||
| 573 | .powerpc64 => Executor{ .qemu = "qemu-ppc64" }, | ||
| 574 | .powerpc64le => Executor{ .qemu = "qemu-ppc64le" }, | ||
| 575 | .riscv32 => Executor{ .qemu = "qemu-riscv32" }, | ||
| 576 | .riscv64 => Executor{ .qemu = "qemu-riscv64" }, | ||
| 577 | .s390x => Executor{ .qemu = "qemu-s390x" }, | ||
| 578 | .sparc => Executor{ .qemu = "qemu-sparc" }, | ||
| 579 | .x86_64 => Executor{ .qemu = "qemu-x86_64" }, | ||
| 580 | else => return .unavailable, | ||
| 581 | }; | ||
| 582 | } | ||
| 583 | |||
| 584 | switch (os_tag) { | ||
| 585 | .windows => switch (cpu_arch.ptrBitWidth()) { | ||
| 586 | 32 => return Executor{ .wine = "wine" }, | ||
| 587 | 64 => return Executor{ .wine = "wine64" }, | ||
| 588 | else => return .unavailable, | ||
| 589 | }, | ||
| 590 | .wasi => switch (cpu_arch.ptrBitWidth()) { | ||
| 591 | 32 => return Executor{ .wasmtime = "wasmtime" }, | ||
| 592 | else => return .unavailable, | ||
| 593 | }, | ||
| 594 | else => return .unavailable, | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 598 | pub fn isGnuLibC(self: CrossTarget) bool { | ||
| 599 | return Target.isGnuLibC_os_tag_abi(self.getOsTag(), self.getAbi()); | ||
| 600 | } | ||
| 601 | |||
| 602 | pub fn setGnuLibCVersion(self: CrossTarget, major: u32, minor: u32, patch: u32) void { | ||
| 603 | assert(self.isGnuLibC()); | ||
| 604 | self.glibc_version = SemVer{ .major = major, .minor = minor, .patch = patch }; | ||
| 605 | } | ||
| 606 | |||
| 607 | fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void { | ||
| 608 | set.removeFeatureSet(self.cpu_features_sub); | ||
| 609 | set.addFeatureSet(self.cpu_features_add); | ||
| 610 | set.populateDependencies(self.getCpuArch().allFeaturesList()); | ||
| 611 | set.removeFeatureSet(self.cpu_features_sub); | ||
| 612 | } | ||
| 613 | |||
| 614 | fn parseOs(result: *CrossTarget, diags: *ParseOptions.Diagnostics, text: []const u8) !void { | ||
| 615 | var it = mem.separate(text, "."); | ||
| 616 | const os_name = it.next().?; | ||
| 617 | const os_is_native = mem.eql(u8, os_name, "native"); | ||
| 618 | if (!os_is_native) { | ||
| 619 | result.os_tag = std.meta.stringToEnum(Target.Os.Tag, os_name) orelse | ||
| 620 | return error.UnknownOperatingSystem; | ||
| 621 | } | ||
| 622 | const tag = result.getOsTag(); | ||
| 623 | diags.os_tag = tag; | ||
| 624 | |||
| 625 | const version_text = it.rest(); | ||
| 626 | if (it.next() == null) return; | ||
| 627 | |||
| 628 | switch (tag) { | ||
| 629 | .freestanding, | ||
| 630 | .ananas, | ||
| 631 | .cloudabi, | ||
| 632 | .dragonfly, | ||
| 633 | .fuchsia, | ||
| 634 | .ios, | ||
| 635 | .kfreebsd, | ||
| 636 | .lv2, | ||
| 637 | .solaris, | ||
| 638 | .haiku, | ||
| 639 | .minix, | ||
| 640 | .rtems, | ||
| 641 | .nacl, | ||
| 642 | .cnk, | ||
| 643 | .aix, | ||
| 644 | .cuda, | ||
| 645 | .nvcl, | ||
| 646 | .amdhsa, | ||
| 647 | .ps4, | ||
| 648 | .elfiamcu, | ||
| 649 | .tvos, | ||
| 650 | .watchos, | ||
| 651 | .mesa3d, | ||
| 652 | .contiki, | ||
| 653 | .amdpal, | ||
| 654 | .hermit, | ||
| 655 | .hurd, | ||
| 656 | .wasi, | ||
| 657 | .emscripten, | ||
| 658 | .uefi, | ||
| 659 | .other, | ||
| 660 | => return error.InvalidOperatingSystemVersion, | ||
| 661 | |||
| 662 | .freebsd, | ||
| 663 | .macosx, | ||
| 664 | .netbsd, | ||
| 665 | .openbsd, | ||
| 666 | .linux, | ||
| 667 | => { | ||
| 668 | var range_it = mem.separate(version_text, "..."); | ||
| 669 | |||
| 670 | const min_text = range_it.next().?; | ||
| 671 | const min_ver = SemVer.parse(min_text) catch |err| switch (err) { | ||
| 672 | error.Overflow => return error.InvalidOperatingSystemVersion, | ||
| 673 | error.InvalidCharacter => return error.InvalidOperatingSystemVersion, | ||
| 674 | error.InvalidVersion => return error.InvalidOperatingSystemVersion, | ||
| 675 | }; | ||
| 676 | result.os_version_min = .{ .semver = min_ver }; | ||
| 677 | |||
| 678 | const max_text = range_it.next() orelse return; | ||
| 679 | const max_ver = SemVer.parse(max_text) catch |err| switch (err) { | ||
| 680 | error.Overflow => return error.InvalidOperatingSystemVersion, | ||
| 681 | error.InvalidCharacter => return error.InvalidOperatingSystemVersion, | ||
| 682 | error.InvalidVersion => return error.InvalidOperatingSystemVersion, | ||
| 683 | }; | ||
| 684 | result.os_version_max = .{ .semver = max_ver }; | ||
| 685 | }, | ||
| 686 | |||
| 687 | .windows => { | ||
| 688 | var range_it = mem.separate(version_text, "..."); | ||
| 689 | |||
| 690 | const min_text = range_it.next().?; | ||
| 691 | const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse | ||
| 692 | return error.InvalidOperatingSystemVersion; | ||
| 693 | result.os_version_min = .{ .windows = min_ver }; | ||
| 694 | |||
| 695 | const max_text = range_it.next() orelse return; | ||
| 696 | const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse | ||
| 697 | return error.InvalidOperatingSystemVersion; | ||
| 698 | result.os_version_max = .{ .windows = max_ver }; | ||
| 699 | }, | ||
| 700 | } | ||
| 701 | } | ||
| 702 | }; | ||
| 703 | |||
| 704 | test "CrossTarget.parse" { | ||
| 705 | { | ||
| 706 | const cross_target = try CrossTarget.parse(.{ | ||
| 707 | .arch_os_abi = "x86_64-linux-gnu", | ||
| 708 | .cpu_features = "x86_64-sse-sse2-avx-cx8", | ||
| 709 | }); | ||
| 710 | const target = cross_target.toTarget(); | ||
| 711 | |||
| 712 | std.testing.expect(target.os.tag == .linux); | ||
| 713 | std.testing.expect(target.abi == .gnu); | ||
| 714 | std.testing.expect(target.cpu.arch == .x86_64); | ||
| 715 | std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse)); | ||
| 716 | std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx)); | ||
| 717 | std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8)); | ||
| 718 | std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov)); | ||
| 719 | std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); | ||
| 720 | |||
| 721 | const text = try cross_target.zigTriple(std.testing.allocator); | ||
| 722 | defer std.testing.allocator.free(text); | ||
| 723 | std.testing.expectEqualSlices(u8, "x86_64-linux-gnu", text); | ||
| 724 | } | ||
| 725 | { | ||
| 726 | const cross_target = try CrossTarget.parse(.{ | ||
| 727 | .arch_os_abi = "arm-linux-musleabihf", | ||
| 728 | .cpu_features = "generic+v8a", | ||
| 729 | }); | ||
| 730 | const target = cross_target.toTarget(); | ||
| 731 | |||
| 732 | std.testing.expect(target.os.tag == .linux); | ||
| 733 | std.testing.expect(target.abi == .musleabihf); | ||
| 734 | std.testing.expect(target.cpu.arch == .arm); | ||
| 735 | std.testing.expect(target.cpu.model == &Target.arm.cpu.generic); | ||
| 736 | std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a)); | ||
| 737 | |||
| 738 | const text = try cross_target.zigTriple(std.testing.allocator); | ||
| 739 | defer std.testing.allocator.free(text); | ||
| 740 | std.testing.expectEqualSlices(u8, "arm-linux-musleabihf", text); | ||
| 741 | } | ||
| 742 | { | ||
| 743 | const cross_target = try CrossTarget.parse(.{ | ||
| 744 | .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27", | ||
| 745 | .cpu_features = "generic+v8a", | ||
| 746 | }); | ||
| 747 | const target = cross_target.toTarget(); | ||
| 748 | |||
| 749 | std.testing.expect(target.cpu.arch == .aarch64); | ||
| 750 | std.testing.expect(target.os.tag == .linux); | ||
| 751 | std.testing.expect(target.os.version_range.linux.range.min.major == 3); | ||
| 752 | std.testing.expect(target.os.version_range.linux.range.min.minor == 10); | ||
| 753 | std.testing.expect(target.os.version_range.linux.range.min.patch == 0); | ||
| 754 | std.testing.expect(target.os.version_range.linux.range.max.major == 4); | ||
| 755 | std.testing.expect(target.os.version_range.linux.range.max.minor == 4); | ||
| 756 | std.testing.expect(target.os.version_range.linux.range.max.patch == 1); | ||
| 757 | std.testing.expect(target.os.version_range.linux.glibc.major == 2); | ||
| 758 | std.testing.expect(target.os.version_range.linux.glibc.minor == 27); | ||
| 759 | std.testing.expect(target.os.version_range.linux.glibc.patch == 0); | ||
| 760 | std.testing.expect(target.abi == .gnu); | ||
| 761 | |||
| 762 | const text = try cross_target.zigTriple(std.testing.allocator); | ||
| 763 | defer std.testing.allocator.free(text); | ||
| 764 | std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text); | ||
| 765 | } | ||
| 766 | } | ||
src-self-hosted/stage2.zig+77-66| ... | @@ -10,6 +10,7 @@ const Allocator = mem.Allocator; | ... | @@ -10,6 +10,7 @@ const Allocator = mem.Allocator; |
| 10 | const ArrayList = std.ArrayList; | 10 | const ArrayList = std.ArrayList; |
| 11 | const Buffer = std.Buffer; | 11 | const Buffer = std.Buffer; |
| 12 | const Target = std.Target; | 12 | const Target = std.Target; |
| 13 | const CrossTarget = std.zig.CrossTarget; | ||
| 13 | const self_hosted_main = @import("main.zig"); | 14 | const self_hosted_main = @import("main.zig"); |
| 14 | const errmsg = @import("errmsg.zig"); | 15 | const errmsg = @import("errmsg.zig"); |
| 15 | const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; | 16 | const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; |
| ... | @@ -87,7 +88,7 @@ const Error = extern enum { | ... | @@ -87,7 +88,7 @@ const Error = extern enum { |
| 87 | NotLazy, | 88 | NotLazy, |
| 88 | IsAsync, | 89 | IsAsync, |
| 89 | ImportOutsidePkgPath, | 90 | ImportOutsidePkgPath, |
| 90 | UnknownCpu, | 91 | UnknownCpuModel, |
| 91 | UnknownCpuFeature, | 92 | UnknownCpuFeature, |
| 92 | InvalidCpuFeatures, | 93 | InvalidCpuFeatures, |
| 93 | InvalidLlvmCpuFeaturesFormat, | 94 | InvalidLlvmCpuFeaturesFormat, |
| ... | @@ -634,13 +635,9 @@ export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { | ... | @@ -634,13 +635,9 @@ export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { |
| 634 | } | 635 | } |
| 635 | 636 | ||
| 636 | fn cmdTargets(zig_triple: [*:0]const u8) !void { | 637 | fn cmdTargets(zig_triple: [*:0]const u8) !void { |
| 637 | var target = try Target.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) }); | 638 | var cross_target = try CrossTarget.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) }); |
| 638 | target.cpu = blk: { | 639 | var dynamic_linker: ?[*:0]u8 = null; |
| 639 | const llvm = @import("llvm.zig"); | 640 | const target = try crossTargetToTarget(cross_target, &dynamic_linker); |
| 640 | const llvm_cpu_name = llvm.GetHostCPUName(); | ||
| 641 | const llvm_cpu_features = llvm.GetNativeFeatures(); | ||
| 642 | break :blk try detectNativeCpuWithLLVM(target.cpu.arch, llvm_cpu_name, llvm_cpu_features); | ||
| 643 | }; | ||
| 644 | return @import("print_targets.zig").cmdTargets( | 641 | return @import("print_targets.zig").cmdTargets( |
| 645 | std.heap.c_allocator, | 642 | std.heap.c_allocator, |
| 646 | &[0][]u8{}, | 643 | &[0][]u8{}, |
| ... | @@ -661,7 +658,6 @@ export fn stage2_target_parse( | ... | @@ -661,7 +658,6 @@ export fn stage2_target_parse( |
| 661 | error.UnknownOperatingSystem => return .UnknownOperatingSystem, | 658 | error.UnknownOperatingSystem => return .UnknownOperatingSystem, |
| 662 | error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, | 659 | error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, |
| 663 | error.MissingOperatingSystem => return .MissingOperatingSystem, | 660 | error.MissingOperatingSystem => return .MissingOperatingSystem, |
| 664 | error.MissingArchitecture => return .MissingArchitecture, | ||
| 665 | error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, | 661 | error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, |
| 666 | error.UnexpectedExtraField => return .SemanticAnalyzeFail, | 662 | error.UnexpectedExtraField => return .SemanticAnalyzeFail, |
| 667 | error.InvalidAbiVersion => return .InvalidAbiVersion, | 663 | error.InvalidAbiVersion => return .InvalidAbiVersion, |
| ... | @@ -681,44 +677,42 @@ fn stage2TargetParse( | ... | @@ -681,44 +677,42 @@ fn stage2TargetParse( |
| 681 | zig_triple_oz: ?[*:0]const u8, | 677 | zig_triple_oz: ?[*:0]const u8, |
| 682 | mcpu_oz: ?[*:0]const u8, | 678 | mcpu_oz: ?[*:0]const u8, |
| 683 | ) !void { | 679 | ) !void { |
| 684 | const target: std.build.Target = if (zig_triple_oz) |zig_triple_z| blk: { | 680 | const target: CrossTarget = if (zig_triple_oz) |zig_triple_z| blk: { |
| 685 | const zig_triple = mem.toSliceConst(u8, zig_triple_z); | 681 | const zig_triple = mem.toSliceConst(u8, zig_triple_z); |
| 686 | const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline"; | 682 | const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline"; |
| 687 | var diags: std.Target.ParseOptions.Diagnostics = .{}; | 683 | var diags: CrossTarget.ParseOptions.Diagnostics = .{}; |
| 688 | break :blk std.build.Target{ | 684 | break :blk CrossTarget.parse(.{ |
| 689 | .Cross = Target.parse(.{ | 685 | .arch_os_abi = zig_triple, |
| 690 | .arch_os_abi = zig_triple, | 686 | .cpu_features = mcpu, |
| 691 | .cpu_features = mcpu, | 687 | .diagnostics = &diags, |
| 692 | .diagnostics = &diags, | 688 | }) catch |err| switch (err) { |
| 693 | }) catch |err| switch (err) { | 689 | error.UnknownCpuModel => { |
| 694 | error.UnknownCpu => { | 690 | std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ |
| 695 | std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ | 691 | diags.cpu_name.?, |
| 696 | diags.cpu_name.?, | 692 | @tagName(diags.arch.?), |
| 697 | @tagName(diags.arch.?), | 693 | }); |
| 698 | }); | 694 | for (diags.arch.?.allCpuModels()) |cpu| { |
| 699 | for (diags.arch.?.allCpuModels()) |cpu| { | 695 | std.debug.warn(" {}\n", .{cpu.name}); |
| 700 | std.debug.warn(" {}\n", .{cpu.name}); | 696 | } |
| 701 | } | 697 | process.exit(1); |
| 702 | process.exit(1); | ||
| 703 | }, | ||
| 704 | error.UnknownCpuFeature => { | ||
| 705 | std.debug.warn( | ||
| 706 | \\Unknown CPU feature: '{}' | ||
| 707 | \\Available CPU features for architecture '{}': | ||
| 708 | \\ | ||
| 709 | , .{ | ||
| 710 | diags.unknown_feature_name, | ||
| 711 | @tagName(diags.arch.?), | ||
| 712 | }); | ||
| 713 | for (diags.arch.?.allFeaturesList()) |feature| { | ||
| 714 | std.debug.warn(" {}: {}\n", .{ feature.name, feature.description }); | ||
| 715 | } | ||
| 716 | process.exit(1); | ||
| 717 | }, | ||
| 718 | else => |e| return e, | ||
| 719 | }, | 698 | }, |
| 699 | error.UnknownCpuFeature => { | ||
| 700 | std.debug.warn( | ||
| 701 | \\Unknown CPU feature: '{}' | ||
| 702 | \\Available CPU features for architecture '{}': | ||
| 703 | \\ | ||
| 704 | , .{ | ||
| 705 | diags.unknown_feature_name, | ||
| 706 | @tagName(diags.arch.?), | ||
| 707 | }); | ||
| 708 | for (diags.arch.?.allFeaturesList()) |feature| { | ||
| 709 | std.debug.warn(" {}: {}\n", .{ feature.name, feature.description }); | ||
| 710 | } | ||
| 711 | process.exit(1); | ||
| 712 | }, | ||
| 713 | else => |e| return e, | ||
| 720 | }; | 714 | }; |
| 721 | } else std.build.Target.Native; | 715 | } else .{}; |
| 722 | 716 | ||
| 723 | try stage1_target.fromTarget(target); | 717 | try stage1_target.fromTarget(target); |
| 724 | } | 718 | } |
| ... | @@ -908,8 +902,8 @@ const Stage2Target = extern struct { | ... | @@ -908,8 +902,8 @@ const Stage2Target = extern struct { |
| 908 | 902 | ||
| 909 | dynamic_linker: ?[*:0]const u8, | 903 | dynamic_linker: ?[*:0]const u8, |
| 910 | 904 | ||
| 911 | fn toTarget(in_target: Stage2Target) std.build.Target { | 905 | fn toTarget(in_target: Stage2Target) CrossTarget { |
| 912 | if (in_target.is_native) return .Native; | 906 | if (in_target.is_native) return .{}; |
| 913 | 907 | ||
| 914 | const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch | 908 | const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch |
| 915 | const in_os = in_target.os; | 909 | const in_os = in_target.os; |
| ... | @@ -924,28 +918,11 @@ const Stage2Target = extern struct { | ... | @@ -924,28 +918,11 @@ const Stage2Target = extern struct { |
| 924 | }; | 918 | }; |
| 925 | } | 919 | } |
| 926 | 920 | ||
| 927 | fn fromTarget(self: *Stage2Target, build_target: std.build.Target) !void { | 921 | fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void { |
| 928 | const allocator = std.heap.c_allocator; | 922 | const allocator = std.heap.c_allocator; |
| 929 | var dynamic_linker: ?[*:0]u8 = null; | ||
| 930 | const target = switch (build_target) { | ||
| 931 | .Native => blk: { | ||
| 932 | const info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator); | ||
| 933 | if (info.dynamic_linker) |dl| { | ||
| 934 | dynamic_linker = dl.ptr; | ||
| 935 | } | ||
| 936 | 923 | ||
| 937 | // TODO we want to just use info.target but implementing CPU model & feature detection is todo | 924 | var dynamic_linker: ?[*:0]u8 = null; |
| 938 | // so here we rely on LLVM | 925 | const target = try crossTargetToTarget(cross_target, &dynamic_linker); |
| 939 | const llvm = @import("llvm.zig"); | ||
| 940 | const llvm_cpu_name = llvm.GetHostCPUName(); | ||
| 941 | const llvm_cpu_features = llvm.GetNativeFeatures(); | ||
| 942 | const arch = std.Target.current.cpu.arch; | ||
| 943 | var t = info.target; | ||
| 944 | t.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features); | ||
| 945 | break :blk t; | ||
| 946 | }, | ||
| 947 | .Cross => |t| t, | ||
| 948 | }; | ||
| 949 | 926 | ||
| 950 | var cache_hash = try std.Buffer.allocPrint(allocator, "{}\n{}\n", .{ | 927 | var cache_hash = try std.Buffer.allocPrint(allocator, "{}\n{}\n", .{ |
| 951 | target.cpu.model.name, | 928 | target.cpu.model.name, |
| ... | @@ -1145,7 +1122,7 @@ const Stage2Target = extern struct { | ... | @@ -1145,7 +1122,7 @@ const Stage2Target = extern struct { |
| 1145 | .cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr, | 1122 | .cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr, |
| 1146 | .os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr, | 1123 | .os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr, |
| 1147 | .cache_hash = cache_hash.toOwnedSlice().ptr, | 1124 | .cache_hash = cache_hash.toOwnedSlice().ptr, |
| 1148 | .is_native = build_target == .Native, | 1125 | .is_native = cross_target.isNative(), |
| 1149 | .glibc_version = glibc_version, | 1126 | .glibc_version = glibc_version, |
| 1150 | .dynamic_linker = dynamic_linker, | 1127 | .dynamic_linker = dynamic_linker, |
| 1151 | }; | 1128 | }; |
| ... | @@ -1156,6 +1133,40 @@ fn enumInt(comptime Enum: type, int: c_int) Enum { | ... | @@ -1156,6 +1133,40 @@ fn enumInt(comptime Enum: type, int: c_int) Enum { |
| 1156 | return @intToEnum(Enum, @intCast(@TagType(Enum), int)); | 1133 | return @intToEnum(Enum, @intCast(@TagType(Enum), int)); |
| 1157 | } | 1134 | } |
| 1158 | 1135 | ||
| 1136 | /// TODO move dynamic linker to be part of the target | ||
| 1137 | /// TODO self-host this function | ||
| 1138 | fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target { | ||
| 1139 | var adjusted_target = cross_target.toTarget(); | ||
| 1140 | if (cross_target.isNativeCpu() or cross_target.isNativeOs()) { | ||
| 1141 | const detected_info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator); | ||
| 1142 | if (cross_target.isNativeCpu()) { | ||
| 1143 | adjusted_target.cpu = detected_info.target.cpu; | ||
| 1144 | |||
| 1145 | // TODO We want to just use detected_info.target but implementing | ||
| 1146 | // CPU model & feature detection is todo so here we rely on LLVM. | ||
| 1147 | // There is another occurrence of this; search for detectNativeCpuWithLLVM. | ||
| 1148 | const llvm = @import("llvm.zig"); | ||
| 1149 | const llvm_cpu_name = llvm.GetHostCPUName(); | ||
| 1150 | const llvm_cpu_features = llvm.GetNativeFeatures(); | ||
| 1151 | const arch = std.Target.current.cpu.arch; | ||
| 1152 | adjusted_target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features); | ||
| 1153 | } | ||
| 1154 | if (cross_target.isNativeOs()) { | ||
| 1155 | adjusted_target.os = detected_info.target.os; | ||
| 1156 | |||
| 1157 | if (detected_info.dynamic_linker) |dl| { | ||
| 1158 | dynamic_linker_ptr.* = dl.ptr; | ||
| 1159 | } | ||
| 1160 | if (cross_target.abi == null) { | ||
| 1161 | adjusted_target.abi = detected_info.target.abi; | ||
| 1162 | } | ||
| 1163 | } else if (cross_target.abi == null) { | ||
| 1164 | adjusted_target.abi = Target.Abi.default(adjusted_target.cpu.arch, adjusted_target.os); | ||
| 1165 | } | ||
| 1166 | } | ||
| 1167 | return adjusted_target; | ||
| 1168 | } | ||
| 1169 | |||
| 1159 | // ABI warning | 1170 | // ABI warning |
| 1160 | const Stage2GLibCVersion = extern struct { | 1171 | const Stage2GLibCVersion = extern struct { |
| 1161 | major: u32, | 1172 | major: u32, |
test/compile_errors.zig+10-14| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | const Target = @import("std").Target; | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addTest("type mismatch with tuple concatenation", | 5 | cases.addTest("type mismatch with tuple concatenation", |
| ... | @@ -386,12 +386,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -386,12 +386,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 386 | , &[_][]const u8{ | 386 | , &[_][]const u8{ |
| 387 | "tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack", | 387 | "tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack", |
| 388 | }); | 388 | }); |
| 389 | tc.target = tests.Target{ | 389 | tc.target = std.zig.CrossTarget{ |
| 390 | .Cross = .{ | 390 | .cpu_arch = .wasm32, |
| 391 | .cpu = Target.Cpu.baseline(.wasm32), | 391 | .os_tag = .wasi, |
| 392 | .os = Target.Os.defaultVersionRange(.wasi), | 392 | .abi = .none, |
| 393 | .abi = .none, | ||
| 394 | }, | ||
| 395 | }; | 393 | }; |
| 396 | break :x tc; | 394 | break :x tc; |
| 397 | }); | 395 | }); |
| ... | @@ -787,12 +785,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -787,12 +785,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 787 | , &[_][]const u8{ | 785 | , &[_][]const u8{ |
| 788 | "tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs", | 786 | "tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs", |
| 789 | }); | 787 | }); |
| 790 | tc.target = tests.Target{ | 788 | tc.target = std.zig.CrossTarget{ |
| 791 | .Cross = .{ | 789 | .cpu_arch = .x86_64, |
| 792 | .cpu = Target.Cpu.baseline(.x86_64), | 790 | .os_tag = .linux, |
| 793 | .os = Target.Os.defaultVersionRange(.linux), | 791 | .abi = .gnu, |
| 794 | .abi = .gnu, | ||
| 795 | }, | ||
| 796 | }; | 792 | }; |
| 797 | break :x tc; | 793 | break :x tc; |
| 798 | }); | 794 | }); |
| ... | @@ -1452,7 +1448,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -1452,7 +1448,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1452 | "tmp.zig:2:18: error: invalid operands to binary expression: 'error{A}' and 'error{B}'", | 1448 | "tmp.zig:2:18: error: invalid operands to binary expression: 'error{A}' and 'error{B}'", |
| 1453 | }); | 1449 | }); |
| 1454 | 1450 | ||
| 1455 | if (Target.current.os.tag == .linux) { | 1451 | if (std.Target.current.os.tag == .linux) { |
| 1456 | cases.addTest("implicit dependency on libc", | 1452 | cases.addTest("implicit dependency on libc", |
| 1457 | \\extern "c" fn exit(u8) void; | 1453 | \\extern "c" fn exit(u8) void; |
| 1458 | \\export fn entry() void { | 1454 | \\export fn entry() void { |
test/src/translate_c.zig+3-2| ... | @@ -7,6 +7,7 @@ const fmt = std.fmt; | ... | @@ -7,6 +7,7 @@ const fmt = std.fmt; |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| 8 | const fs = std.fs; | 8 | const fs = std.fs; |
| 9 | const warn = std.debug.warn; | 9 | const warn = std.debug.warn; |
| 10 | const CrossTarget = std.zig.CrossTarget; | ||
| 10 | 11 | ||
| 11 | pub const TranslateCContext = struct { | 12 | pub const TranslateCContext = struct { |
| 12 | b: *build.Builder, | 13 | b: *build.Builder, |
| ... | @@ -19,7 +20,7 @@ pub const TranslateCContext = struct { | ... | @@ -19,7 +20,7 @@ pub const TranslateCContext = struct { |
| 19 | sources: ArrayList(SourceFile), | 20 | sources: ArrayList(SourceFile), |
| 20 | expected_lines: ArrayList([]const u8), | 21 | expected_lines: ArrayList([]const u8), |
| 21 | allow_warnings: bool, | 22 | allow_warnings: bool, |
| 22 | target: build.Target = .Native, | 23 | target: CrossTarget = CrossTarget{}, |
| 23 | 24 | ||
| 24 | const SourceFile = struct { | 25 | const SourceFile = struct { |
| 25 | filename: []const u8, | 26 | filename: []const u8, |
| ... | @@ -75,7 +76,7 @@ pub const TranslateCContext = struct { | ... | @@ -75,7 +76,7 @@ pub const TranslateCContext = struct { |
| 75 | pub fn addWithTarget( | 76 | pub fn addWithTarget( |
| 76 | self: *TranslateCContext, | 77 | self: *TranslateCContext, |
| 77 | name: []const u8, | 78 | name: []const u8, |
| 78 | target: build.Target, | 79 | target: CrossTarget, |
| 79 | source: []const u8, | 80 | source: []const u8, |
| 80 | expected_lines: []const []const u8, | 81 | expected_lines: []const []const u8, |
| 81 | ) void { | 82 | ) void { |
test/tests.zig+82-122| ... | @@ -3,7 +3,7 @@ const builtin = std.builtin; | ... | @@ -3,7 +3,7 @@ const builtin = std.builtin; |
| 3 | const debug = std.debug; | 3 | const debug = std.debug; |
| 4 | const warn = debug.warn; | 4 | const warn = debug.warn; |
| 5 | const build = std.build; | 5 | const build = std.build; |
| 6 | pub const Target = build.Target; | 6 | const CrossTarget = std.zig.CrossTarget; |
| 7 | const Buffer = std.Buffer; | 7 | const Buffer = std.Buffer; |
| 8 | const io = std.io; | 8 | const io = std.io; |
| 9 | const fs = std.fs; | 9 | const fs = std.fs; |
| ... | @@ -30,7 +30,7 @@ pub const RunTranslatedCContext = @import("src/run_translated_c.zig").RunTransla | ... | @@ -30,7 +30,7 @@ pub const RunTranslatedCContext = @import("src/run_translated_c.zig").RunTransla |
| 30 | pub const CompareOutputContext = @import("src/compare_output.zig").CompareOutputContext; | 30 | pub const CompareOutputContext = @import("src/compare_output.zig").CompareOutputContext; |
| 31 | 31 | ||
| 32 | const TestTarget = struct { | 32 | const TestTarget = struct { |
| 33 | target: build.Target = .Native, | 33 | target: CrossTarget = @as(CrossTarget, .{}), |
| 34 | mode: builtin.Mode = .Debug, | 34 | mode: builtin.Mode = .Debug, |
| 35 | link_libc: bool = false, | 35 | link_libc: bool = false, |
| 36 | single_threaded: bool = false, | 36 | single_threaded: bool = false, |
| ... | @@ -52,105 +52,85 @@ const test_targets = blk: { | ... | @@ -52,105 +52,85 @@ const test_targets = blk: { |
| 52 | }, | 52 | }, |
| 53 | 53 | ||
| 54 | TestTarget{ | 54 | TestTarget{ |
| 55 | .target = Target{ | 55 | .target = .{ |
| 56 | .Cross = .{ | 56 | .cpu_arch = .x86_64, |
| 57 | .cpu = std.Target.Cpu.baseline(.x86_64), | 57 | .os_tag = .linux, |
| 58 | .os = std.Target.Os.defaultVersionRange(.linux), | 58 | .abi = .none, |
| 59 | .abi = .none, | ||
| 60 | }, | ||
| 61 | }, | 59 | }, |
| 62 | }, | 60 | }, |
| 63 | TestTarget{ | 61 | TestTarget{ |
| 64 | .target = Target{ | 62 | .target = .{ |
| 65 | .Cross = .{ | 63 | .cpu_arch = .x86_64, |
| 66 | .cpu = std.Target.Cpu.baseline(.x86_64), | 64 | .os_tag = .linux, |
| 67 | .os = std.Target.Os.defaultVersionRange(.linux), | 65 | .abi = .gnu, |
| 68 | .abi = .gnu, | ||
| 69 | }, | ||
| 70 | }, | 66 | }, |
| 71 | .link_libc = true, | 67 | .link_libc = true, |
| 72 | }, | 68 | }, |
| 73 | TestTarget{ | 69 | TestTarget{ |
| 74 | .target = Target{ | 70 | .target = .{ |
| 75 | .Cross = .{ | 71 | .cpu_arch = .x86_64, |
| 76 | .cpu = std.Target.Cpu.baseline(.x86_64), | 72 | .os_tag = .linux, |
| 77 | .os = std.Target.Os.defaultVersionRange(.linux), | 73 | .abi = .musl, |
| 78 | .abi = .musl, | ||
| 79 | }, | ||
| 80 | }, | 74 | }, |
| 81 | .link_libc = true, | 75 | .link_libc = true, |
| 82 | }, | 76 | }, |
| 83 | 77 | ||
| 84 | TestTarget{ | 78 | TestTarget{ |
| 85 | .target = Target{ | 79 | .target = .{ |
| 86 | .Cross = .{ | 80 | .cpu_arch = .i386, |
| 87 | .cpu = std.Target.Cpu.baseline(.i386), | 81 | .os_tag = .linux, |
| 88 | .os = std.Target.Os.defaultVersionRange(.linux), | 82 | .abi = .none, |
| 89 | .abi = .none, | ||
| 90 | }, | ||
| 91 | }, | 83 | }, |
| 92 | }, | 84 | }, |
| 93 | TestTarget{ | 85 | TestTarget{ |
| 94 | .target = Target{ | 86 | .target = .{ |
| 95 | .Cross = .{ | 87 | .cpu_arch = .i386, |
| 96 | .cpu = std.Target.Cpu.baseline(.i386), | 88 | .os_tag = .linux, |
| 97 | .os = std.Target.Os.defaultVersionRange(.linux), | 89 | .abi = .musl, |
| 98 | .abi = .musl, | ||
| 99 | }, | ||
| 100 | }, | 90 | }, |
| 101 | .link_libc = true, | 91 | .link_libc = true, |
| 102 | }, | 92 | }, |
| 103 | 93 | ||
| 104 | TestTarget{ | 94 | TestTarget{ |
| 105 | .target = Target{ | 95 | .target = .{ |
| 106 | .Cross = .{ | 96 | .cpu_arch = .aarch64, |
| 107 | .cpu = std.Target.Cpu.baseline(.aarch64), | 97 | .os_tag = .linux, |
| 108 | .os = std.Target.Os.defaultVersionRange(.linux), | 98 | .abi = .none, |
| 109 | .abi = .none, | ||
| 110 | }, | ||
| 111 | }, | 99 | }, |
| 112 | }, | 100 | }, |
| 113 | TestTarget{ | 101 | TestTarget{ |
| 114 | .target = Target{ | 102 | .target = .{ |
| 115 | .Cross = .{ | 103 | .cpu_arch = .aarch64, |
| 116 | .cpu = std.Target.Cpu.baseline(.aarch64), | 104 | .os_tag = .linux, |
| 117 | .os = std.Target.Os.defaultVersionRange(.linux), | 105 | .abi = .musl, |
| 118 | .abi = .musl, | ||
| 119 | }, | ||
| 120 | }, | 106 | }, |
| 121 | .link_libc = true, | 107 | .link_libc = true, |
| 122 | }, | 108 | }, |
| 123 | TestTarget{ | 109 | TestTarget{ |
| 124 | .target = Target{ | 110 | .target = .{ |
| 125 | .Cross = .{ | 111 | .cpu_arch = .aarch64, |
| 126 | .cpu = std.Target.Cpu.baseline(.aarch64), | 112 | .os_tag = .linux, |
| 127 | .os = std.Target.Os.defaultVersionRange(.linux), | 113 | .abi = .gnu, |
| 128 | .abi = .gnu, | ||
| 129 | }, | ||
| 130 | }, | 114 | }, |
| 131 | .link_libc = true, | 115 | .link_libc = true, |
| 132 | }, | 116 | }, |
| 133 | 117 | ||
| 134 | TestTarget{ | 118 | TestTarget{ |
| 135 | .target = .{ | 119 | .target = CrossTarget.parse(.{ |
| 136 | .Cross = std.Target.parse(.{ | 120 | .arch_os_abi = "arm-linux-none", |
| 137 | .arch_os_abi = "arm-linux-none", | 121 | .cpu_features = "generic+v8a", |
| 138 | .cpu_features = "generic+v8a", | 122 | }) catch unreachable, |
| 139 | }) catch unreachable, | ||
| 140 | }, | ||
| 141 | }, | 123 | }, |
| 142 | TestTarget{ | 124 | TestTarget{ |
| 143 | .target = .{ | 125 | .target = CrossTarget.parse(.{ |
| 144 | .Cross = std.Target.parse(.{ | 126 | .arch_os_abi = "arm-linux-musleabihf", |
| 145 | .arch_os_abi = "arm-linux-musleabihf", | 127 | .cpu_features = "generic+v8a", |
| 146 | .cpu_features = "generic+v8a", | 128 | }) catch unreachable, |
| 147 | }) catch unreachable, | ||
| 148 | }, | ||
| 149 | .link_libc = true, | 129 | .link_libc = true, |
| 150 | }, | 130 | }, |
| 151 | // TODO https://github.com/ziglang/zig/issues/3287 | 131 | // TODO https://github.com/ziglang/zig/issues/3287 |
| 152 | //TestTarget{ | 132 | //TestTarget{ |
| 153 | // .target = std.Target.parse(.{ | 133 | // .target = CrossTarget.parse(.{ |
| 154 | // .arch_os_abi = "arm-linux-gnueabihf", | 134 | // .arch_os_abi = "arm-linux-gnueabihf", |
| 155 | // .cpu_features = "generic+v8a", | 135 | // .cpu_features = "generic+v8a", |
| 156 | // }) catch unreachable, | 136 | // }) catch unreachable, |
| ... | @@ -158,75 +138,61 @@ const test_targets = blk: { | ... | @@ -158,75 +138,61 @@ const test_targets = blk: { |
| 158 | //}, | 138 | //}, |
| 159 | 139 | ||
| 160 | TestTarget{ | 140 | TestTarget{ |
| 161 | .target = Target{ | 141 | .target = .{ |
| 162 | .Cross = .{ | 142 | .cpu_arch = .mipsel, |
| 163 | .cpu = std.Target.Cpu.baseline(.mipsel), | 143 | .os_tag = .linux, |
| 164 | .os = std.Target.Os.defaultVersionRange(.linux), | 144 | .abi = .none, |
| 165 | .abi = .none, | ||
| 166 | }, | ||
| 167 | }, | 145 | }, |
| 168 | }, | 146 | }, |
| 169 | TestTarget{ | 147 | TestTarget{ |
| 170 | .target = Target{ | 148 | .target = .{ |
| 171 | .Cross = .{ | 149 | .cpu_arch = .mipsel, |
| 172 | .cpu = std.Target.Cpu.baseline(.mipsel), | 150 | .os_tag = .linux, |
| 173 | .os = std.Target.Os.defaultVersionRange(.linux), | 151 | .abi = .musl, |
| 174 | .abi = .musl, | ||
| 175 | }, | ||
| 176 | }, | 152 | }, |
| 177 | .link_libc = true, | 153 | .link_libc = true, |
| 178 | }, | 154 | }, |
| 179 | 155 | ||
| 180 | TestTarget{ | 156 | TestTarget{ |
| 181 | .target = Target{ | 157 | .target = .{ |
| 182 | .Cross = .{ | 158 | .cpu_arch = .x86_64, |
| 183 | .cpu = std.Target.Cpu.baseline(.x86_64), | 159 | .os_tag = .macosx, |
| 184 | .os = std.Target.Os.defaultVersionRange(.macosx), | 160 | .abi = .gnu, |
| 185 | .abi = .gnu, | ||
| 186 | }, | ||
| 187 | }, | 161 | }, |
| 188 | // TODO https://github.com/ziglang/zig/issues/3295 | 162 | // TODO https://github.com/ziglang/zig/issues/3295 |
| 189 | .disable_native = true, | 163 | .disable_native = true, |
| 190 | }, | 164 | }, |
| 191 | 165 | ||
| 192 | TestTarget{ | 166 | TestTarget{ |
| 193 | .target = Target{ | 167 | .target = .{ |
| 194 | .Cross = .{ | 168 | .cpu_arch = .i386, |
| 195 | .cpu = std.Target.Cpu.baseline(.i386), | 169 | .os_tag = .windows, |
| 196 | .os = std.Target.Os.defaultVersionRange(.windows), | 170 | .abi = .msvc, |
| 197 | .abi = .msvc, | ||
| 198 | }, | ||
| 199 | }, | 171 | }, |
| 200 | }, | 172 | }, |
| 201 | 173 | ||
| 202 | TestTarget{ | 174 | TestTarget{ |
| 203 | .target = Target{ | 175 | .target = .{ |
| 204 | .Cross = .{ | 176 | .cpu_arch = .x86_64, |
| 205 | .cpu = std.Target.Cpu.baseline(.x86_64), | 177 | .os_tag = .windows, |
| 206 | .os = std.Target.Os.defaultVersionRange(.windows), | 178 | .abi = .msvc, |
| 207 | .abi = .msvc, | ||
| 208 | }, | ||
| 209 | }, | 179 | }, |
| 210 | }, | 180 | }, |
| 211 | 181 | ||
| 212 | TestTarget{ | 182 | TestTarget{ |
| 213 | .target = Target{ | 183 | .target = .{ |
| 214 | .Cross = .{ | 184 | .cpu_arch = .i386, |
| 215 | .cpu = std.Target.Cpu.baseline(.i386), | 185 | .os_tag = .windows, |
| 216 | .os = std.Target.Os.defaultVersionRange(.windows), | 186 | .abi = .gnu, |
| 217 | .abi = .gnu, | ||
| 218 | }, | ||
| 219 | }, | 187 | }, |
| 220 | .link_libc = true, | 188 | .link_libc = true, |
| 221 | }, | 189 | }, |
| 222 | 190 | ||
| 223 | TestTarget{ | 191 | TestTarget{ |
| 224 | .target = Target{ | 192 | .target = .{ |
| 225 | .Cross = .{ | 193 | .cpu_arch = .x86_64, |
| 226 | .cpu = std.Target.Cpu.baseline(.x86_64), | 194 | .os_tag = .windows, |
| 227 | .os = std.Target.Os.defaultVersionRange(.windows), | 195 | .abi = .gnu, |
| 228 | .abi = .gnu, | ||
| 229 | }, | ||
| 230 | }, | 196 | }, |
| 231 | .link_libc = true, | 197 | .link_libc = true, |
| 232 | }, | 198 | }, |
| ... | @@ -435,13 +401,13 @@ pub fn addPkgTests( | ... | @@ -435,13 +401,13 @@ pub fn addPkgTests( |
| 435 | const step = b.step(b.fmt("test-{}", .{name}), desc); | 401 | const step = b.step(b.fmt("test-{}", .{name}), desc); |
| 436 | 402 | ||
| 437 | for (test_targets) |test_target| { | 403 | for (test_targets) |test_target| { |
| 438 | if (skip_non_native and test_target.target != .Native) | 404 | if (skip_non_native and !test_target.target.isNative()) |
| 439 | continue; | 405 | continue; |
| 440 | 406 | ||
| 441 | if (skip_libc and test_target.link_libc) | 407 | if (skip_libc and test_target.link_libc) |
| 442 | continue; | 408 | continue; |
| 443 | 409 | ||
| 444 | if (test_target.link_libc and test_target.target.getTarget().osRequiresLibC()) { | 410 | if (test_target.link_libc and test_target.target.getOs().requiresLibC()) { |
| 445 | // This would be a redundant test. | 411 | // This would be a redundant test. |
| 446 | continue; | 412 | continue; |
| 447 | } | 413 | } |
| ... | @@ -451,8 +417,8 @@ pub fn addPkgTests( | ... | @@ -451,8 +417,8 @@ pub fn addPkgTests( |
| 451 | 417 | ||
| 452 | const ArchTag = @TagType(builtin.Arch); | 418 | const ArchTag = @TagType(builtin.Arch); |
| 453 | if (test_target.disable_native and | 419 | if (test_target.disable_native and |
| 454 | test_target.target.getOs() == std.Target.current.os.tag and | 420 | test_target.target.getOsTag() == std.Target.current.os.tag and |
| 455 | test_target.target.getArch() == std.Target.current.cpu.arch) | 421 | test_target.target.getCpuArch() == std.Target.current.cpu.arch) |
| 456 | { | 422 | { |
| 457 | continue; | 423 | continue; |
| 458 | } | 424 | } |
| ... | @@ -462,17 +428,14 @@ pub fn addPkgTests( | ... | @@ -462,17 +428,14 @@ pub fn addPkgTests( |
| 462 | } else false; | 428 | } else false; |
| 463 | if (!want_this_mode) continue; | 429 | if (!want_this_mode) continue; |
| 464 | 430 | ||
| 465 | const libc_prefix = if (test_target.target.getTarget().osRequiresLibC()) | 431 | const libc_prefix = if (test_target.target.getOs().requiresLibC()) |
| 466 | "" | 432 | "" |
| 467 | else if (test_target.link_libc) | 433 | else if (test_target.link_libc) |
| 468 | "c" | 434 | "c" |
| 469 | else | 435 | else |
| 470 | "bare"; | 436 | "bare"; |
| 471 | 437 | ||
| 472 | const triple_prefix = if (test_target.target == .Native) | 438 | const triple_prefix = test_target.target.zigTriple(b.allocator) catch unreachable; |
| 473 | @as([]const u8, "native") | ||
| 474 | else | ||
| 475 | test_target.target.zigTriple(b.allocator) catch unreachable; | ||
| 476 | 439 | ||
| 477 | const these_tests = b.addTest(root_src); | 440 | const these_tests = b.addTest(root_src); |
| 478 | const single_threaded_txt = if (test_target.single_threaded) "single" else "multi"; | 441 | const single_threaded_txt = if (test_target.single_threaded) "single" else "multi"; |
| ... | @@ -486,7 +449,7 @@ pub fn addPkgTests( | ... | @@ -486,7 +449,7 @@ pub fn addPkgTests( |
| 486 | these_tests.single_threaded = test_target.single_threaded; | 449 | these_tests.single_threaded = test_target.single_threaded; |
| 487 | these_tests.setFilter(test_filter); | 450 | these_tests.setFilter(test_filter); |
| 488 | these_tests.setBuildMode(test_target.mode); | 451 | these_tests.setBuildMode(test_target.mode); |
| 489 | these_tests.setTheTarget(test_target.target); | 452 | these_tests.setTarget(test_target.target); |
| 490 | if (test_target.link_libc) { | 453 | if (test_target.link_libc) { |
| 491 | these_tests.linkSystemLibrary("c"); | 454 | these_tests.linkSystemLibrary("c"); |
| 492 | } | 455 | } |
| ... | @@ -716,7 +679,7 @@ pub const CompileErrorContext = struct { | ... | @@ -716,7 +679,7 @@ pub const CompileErrorContext = struct { |
| 716 | link_libc: bool, | 679 | link_libc: bool, |
| 717 | is_exe: bool, | 680 | is_exe: bool, |
| 718 | is_test: bool, | 681 | is_test: bool, |
| 719 | target: Target = .Native, | 682 | target: CrossTarget = CrossTarget{}, |
| 720 | 683 | ||
| 721 | const SourceFile = struct { | 684 | const SourceFile = struct { |
| 722 | filename: []const u8, | 685 | filename: []const u8, |
| ... | @@ -808,12 +771,9 @@ pub const CompileErrorContext = struct { | ... | @@ -808,12 +771,9 @@ pub const CompileErrorContext = struct { |
| 808 | zig_args.append("--output-dir") catch unreachable; | 771 | zig_args.append("--output-dir") catch unreachable; |
| 809 | zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable; | 772 | zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable; |
| 810 | 773 | ||
| 811 | switch (self.case.target) { | 774 | if (!self.case.target.isNative()) { |
| 812 | .Native => {}, | 775 | try zig_args.append("-target"); |
| 813 | .Cross => { | 776 | try zig_args.append(try self.case.target.zigTriple(b.allocator)); |
| 814 | try zig_args.append("-target"); | ||
| 815 | try zig_args.append(try self.case.target.zigTriple(b.allocator)); | ||
| 816 | }, | ||
| 817 | } | 777 | } |
| 818 | 778 | ||
| 819 | switch (self.build_mode) { | 779 | switch (self.build_mode) { |
test/translate_c.zig+15-21| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const Target = std.Target; | 3 | const CrossTarget = std.zig.CrossTarget; |
| 4 | 4 | ||
| 5 | pub fn addCases(cases: *tests.TranslateCContext) void { | 5 | pub fn addCases(cases: *tests.TranslateCContext) void { |
| 6 | cases.add("macro line continuation", | 6 | cases.add("macro line continuation", |
| ... | @@ -665,7 +665,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -665,7 +665,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 665 | \\} | 665 | \\} |
| 666 | }); | 666 | }); |
| 667 | 667 | ||
| 668 | if (Target.current.os.tag != .windows) { | 668 | if (std.Target.current.os.tag != .windows) { |
| 669 | // Windows treats this as an enum with type c_int | 669 | // Windows treats this as an enum with type c_int |
| 670 | cases.add("big negative enum init values when C ABI supports long long enums", | 670 | cases.add("big negative enum init values when C ABI supports long long enums", |
| 671 | \\enum EnumWithInits { | 671 | \\enum EnumWithInits { |
| ... | @@ -1064,7 +1064,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1064,7 +1064,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1064 | \\} | 1064 | \\} |
| 1065 | }); | 1065 | }); |
| 1066 | 1066 | ||
| 1067 | if (Target.current.os.tag != .windows) { | 1067 | if (std.Target.current.os.tag != .windows) { |
| 1068 | // sysv_abi not currently supported on windows | 1068 | // sysv_abi not currently supported on windows |
| 1069 | cases.add("Macro qualified functions", | 1069 | cases.add("Macro qualified functions", |
| 1070 | \\void __attribute__((sysv_abi)) foo(void); | 1070 | \\void __attribute__((sysv_abi)) foo(void); |
| ... | @@ -1094,11 +1094,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1094,11 +1094,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1094 | }); | 1094 | }); |
| 1095 | 1095 | ||
| 1096 | cases.addWithTarget("Calling convention", .{ | 1096 | cases.addWithTarget("Calling convention", .{ |
| 1097 | .Cross = .{ | 1097 | .cpu_arch = .i386, |
| 1098 | .cpu = Target.Cpu.baseline(.i386), | 1098 | .os_tag = .linux, |
| 1099 | .os = Target.Os.defaultVersionRange(.linux), | 1099 | .abi = .none, |
| 1100 | .abi = .none, | ||
| 1101 | }, | ||
| 1102 | }, | 1100 | }, |
| 1103 | \\void __attribute__((fastcall)) foo1(float *a); | 1101 | \\void __attribute__((fastcall)) foo1(float *a); |
| 1104 | \\void __attribute__((stdcall)) foo2(float *a); | 1102 | \\void __attribute__((stdcall)) foo2(float *a); |
| ... | @@ -1113,12 +1111,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1113,12 +1111,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1113 | \\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void; | 1111 | \\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void; |
| 1114 | }); | 1112 | }); |
| 1115 | 1113 | ||
| 1116 | cases.addWithTarget("Calling convention", .{ | 1114 | cases.addWithTarget("Calling convention", CrossTarget.parse(.{ |
| 1117 | .Cross = Target.parse(.{ | 1115 | .arch_os_abi = "arm-linux-none", |
| 1118 | .arch_os_abi = "arm-linux-none", | 1116 | .cpu_features = "generic+v8_5a", |
| 1119 | .cpu_features = "generic+v8_5a", | 1117 | }) catch unreachable, |
| 1120 | }) catch unreachable, | ||
| 1121 | }, | ||
| 1122 | \\void __attribute__((pcs("aapcs"))) foo1(float *a); | 1118 | \\void __attribute__((pcs("aapcs"))) foo1(float *a); |
| 1123 | \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a); | 1119 | \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a); |
| 1124 | , &[_][]const u8{ | 1120 | , &[_][]const u8{ |
| ... | @@ -1126,12 +1122,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1126,12 +1122,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1126 | \\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void; | 1122 | \\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void; |
| 1127 | }); | 1123 | }); |
| 1128 | 1124 | ||
| 1129 | cases.addWithTarget("Calling convention", .{ | 1125 | cases.addWithTarget("Calling convention", CrossTarget.parse(.{ |
| 1130 | .Cross = Target.parse(.{ | 1126 | .arch_os_abi = "aarch64-linux-none", |
| 1131 | .arch_os_abi = "aarch64-linux-none", | 1127 | .cpu_features = "generic+v8_5a", |
| 1132 | .cpu_features = "generic+v8_5a", | 1128 | }) catch unreachable, |
| 1133 | }) catch unreachable, | ||
| 1134 | }, | ||
| 1135 | \\void __attribute__((aarch64_vector_pcs)) foo1(float *a); | 1129 | \\void __attribute__((aarch64_vector_pcs)) foo1(float *a); |
| 1136 | , &[_][]const u8{ | 1130 | , &[_][]const u8{ |
| 1137 | \\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void; | 1131 | \\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void; |
| ... | @@ -1600,7 +1594,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1600,7 +1594,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1600 | \\} | 1594 | \\} |
| 1601 | }); | 1595 | }); |
| 1602 | 1596 | ||
| 1603 | if (Target.current.os.tag != .windows) { | 1597 | if (std.Target.current.os.tag != .windows) { |
| 1604 | // When clang uses the <arch>-windows-none triple it behaves as MSVC and | 1598 | // When clang uses the <arch>-windows-none triple it behaves as MSVC and |
| 1605 | // interprets the inner `struct Bar` as an anonymous structure | 1599 | // interprets the inner `struct Bar` as an anonymous structure |
| 1606 | cases.add("type referenced struct", | 1600 | cases.add("type referenced struct", |