| ... | ... | @@ -1,30 +1,53 @@ |
| 1 | 1 | const std = @import("std.zig"); |
| 2 | 2 | const mem = std.mem; |
| 3 | 3 | const builtin = std.builtin; |
| 4 | const Version = std.builtin.Version; |
| 4 | 5 | |
| 5 | 6 | /// TODO Nearly all the functions in this namespace would be |
| 6 | 7 | /// better off if https://github.com/ziglang/zig/issues/425 |
| 7 | 8 | /// was solved. |
| 8 | | pub const Target = union(enum) { |
| 9 | | Native: void, |
| 10 | | Cross: Cross, |
| 11 | | |
| 12 | | pub const Os = enum { |
| 9 | pub const Target = struct { |
| 10 | cpu: Cpu, |
| 11 | os: Os, |
| 12 | abi: Abi, |
| 13 | |
| 14 | /// The version ranges here represent the minimum OS version to be supported |
| 15 | /// and the maximum OS version to be supported. The default values represent |
| 16 | /// the range that the Zig Standard Library bases its abstractions on. |
| 17 | /// |
| 18 | /// The minimum version of the range is the main setting to tweak for a target. |
| 19 | /// Usually, the maximum target OS version will remain the default, which is |
| 20 | /// the latest released version of the OS. |
| 21 | /// |
| 22 | /// To test at compile time if the target is guaranteed to support a given OS feature, |
| 23 | /// one should check that the minimum version of the range is greater than or equal to |
| 24 | /// the version the feature was introduced in. |
| 25 | /// |
| 26 | /// To test at compile time if the target certainly will not support a given OS feature, |
| 27 | /// one should check that the maximum version of the range is less than the version the |
| 28 | /// feature was introduced in. |
| 29 | /// |
| 30 | /// If neither of these cases apply, a runtime check should be used to determine if the |
| 31 | /// target supports a given OS feature. |
| 32 | /// |
| 33 | /// Binaries built with a given maximum version will continue to function on newer operating system |
| 34 | /// versions. However, such a binary may not take full advantage of the newer operating system APIs. |
| 35 | pub const Os = union(enum) { |
| 13 | 36 | freestanding, |
| 14 | 37 | ananas, |
| 15 | 38 | cloudabi, |
| 16 | 39 | dragonfly, |
| 17 | | freebsd, |
| 40 | freebsd: Version.Range, |
| 18 | 41 | fuchsia, |
| 19 | 42 | ios, |
| 20 | 43 | kfreebsd, |
| 21 | | linux, |
| 44 | linux: LinuxVersionRange, |
| 22 | 45 | lv2, |
| 23 | | macosx, |
| 24 | | netbsd, |
| 25 | | openbsd, |
| 46 | macosx: Version.Range, |
| 47 | netbsd: Version.Range, |
| 48 | openbsd: Version.Range, |
| 26 | 49 | solaris, |
| 27 | | windows, |
| 50 | windows: WindowsVersion.Range, |
| 28 | 51 | haiku, |
| 29 | 52 | minix, |
| 30 | 53 | rtems, |
| ... | ... | @@ -48,14 +71,230 @@ pub const Target = union(enum) { |
| 48 | 71 | uefi, |
| 49 | 72 | other, |
| 50 | 73 | |
| 74 | /// See the documentation for `Os` for an explanation of the default version range. |
| 75 | pub fn defaultVersionRange(tag: @TagType(Os)) Os { |
| 76 | switch (tag) { |
| 77 | .freestanding => return .freestanding, |
| 78 | .ananas => return .ananas, |
| 79 | .cloudabi => return .cloudabi, |
| 80 | .dragonfly => return .dragonfly, |
| 81 | .freebsd => return .{ |
| 82 | .freebsd = Version.Range{ |
| 83 | .min = .{ .major = 12, .minor = 0 }, |
| 84 | .max = .{ .major = 12, .minor = 1 }, |
| 85 | }, |
| 86 | }, |
| 87 | .fuchsia => return .fuchsia, |
| 88 | .ios => return .ios, |
| 89 | .kfreebsd => return .kfreebsd, |
| 90 | .linux => return .{ |
| 91 | .linux = .{ |
| 92 | .range = .{ |
| 93 | .min = .{ .major = 3, .minor = 16 }, |
| 94 | .max = .{ .major = 5, .minor = 5, .patch = 5 }, |
| 95 | }, |
| 96 | .glibc = .{ .major = 2, .minor = 17 }, |
| 97 | }, |
| 98 | }, |
| 99 | .lv2 => return .lv2, |
| 100 | .macosx => return .{ |
| 101 | .min = .{ .major = 10, .minor = 13 }, |
| 102 | .max = .{ .major = 10, .minor = 15, .patch = 3 }, |
| 103 | }, |
| 104 | .netbsd => return .{ |
| 105 | .min = .{ .major = 8, .minor = 0 }, |
| 106 | .max = .{ .major = 9, .minor = 0 }, |
| 107 | }, |
| 108 | .openbsd => return .{ |
| 109 | .min = .{ .major = 6, .minor = 6 }, |
| 110 | .max = .{ .major = 6, .minor = 6 }, |
| 111 | }, |
| 112 | solaris => return .solaris, |
| 113 | windows => return .{ |
| 114 | .windows = .{ |
| 115 | .min = .win8_1, |
| 116 | .max = .win10_19h1, |
| 117 | }, |
| 118 | }, |
| 119 | haiku => return .haiku, |
| 120 | minix => return .minix, |
| 121 | rtems => return .rtems, |
| 122 | nacl => return .nacl, |
| 123 | cnk => return .cnk, |
| 124 | aix => return .aix, |
| 125 | cuda => return .cuda, |
| 126 | nvcl => return .nvcl, |
| 127 | amdhsa => return .amdhsa, |
| 128 | ps4 => return .ps4, |
| 129 | elfiamcu => return .elfiamcu, |
| 130 | tvos => return .tvos, |
| 131 | watchos => return .watchos, |
| 132 | mesa3d => return .mesa3d, |
| 133 | contiki => return .contiki, |
| 134 | amdpal => return .amdpal, |
| 135 | hermit => return .hermit, |
| 136 | hurd => return .hurd, |
| 137 | wasi => return .wasi, |
| 138 | emscripten => return .emscripten, |
| 139 | uefi => return .uefi, |
| 140 | other => return .other, |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | pub const LinuxVersionRange = struct { |
| 145 | range: Version.Range, |
| 146 | glibc: Version, |
| 147 | |
| 148 | pub fn includesVersion(self: LinuxVersionRange, ver: Version) bool { |
| 149 | return self.range.includesVersion(ver); |
| 150 | } |
| 151 | }; |
| 152 | |
| 153 | /// Based on NTDDI version constants from |
| 154 | /// https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt |
| 155 | pub const WindowsVersion = enum(u32) { |
| 156 | nt4 = 0x04000000, |
| 157 | win2k = 0x05000000, |
| 158 | xp = 0x05010000, |
| 159 | ws2003 = 0x05020000, |
| 160 | vista = 0x06000000, |
| 161 | win7 = 0x06010000, |
| 162 | win8 = 0x06020000, |
| 163 | win8_1 = 0x06030000, |
| 164 | win10 = 0x0A000000, |
| 165 | win10_th2 = 0x0A000001, |
| 166 | win10_rs1 = 0x0A000002, |
| 167 | win10_rs2 = 0x0A000003, |
| 168 | win10_rs3 = 0x0A000004, |
| 169 | win10_rs4 = 0x0A000005, |
| 170 | win10_rs5 = 0x0A000006, |
| 171 | win10_19h1 = 0x0A000007, |
| 172 | |
| 173 | pub const Range = struct { |
| 174 | min: WindowsVersion, |
| 175 | max: WindowsVersion, |
| 176 | |
| 177 | pub fn includesVersion(self: Range, ver: WindowsVersion) bool { |
| 178 | return @enumToInt(ver) >= @enumToInt(self.min) and @enumToInt(ver) <= @enumToInt(self.max); |
| 179 | } |
| 180 | }; |
| 181 | |
| 182 | pub fn nameToTag(name: []const u8) ?WindowsVersion { |
| 183 | const info = @typeInfo(WindowsVersion); |
| 184 | inline for (info.Enum.fields) |field| { |
| 185 | if (mem.eql(u8, name, field.name)) { |
| 186 | return @field(WindowsVersion, field.name); |
| 187 | } |
| 188 | } |
| 189 | return null; |
| 190 | } |
| 191 | }; |
| 192 | |
| 51 | 193 | pub fn parse(text: []const u8) !Os { |
| 194 | var it = mem.separate(text, "."); |
| 195 | const os_name = it.next().?; |
| 196 | const tag = nameToTag(os_name) orelse return error.UnknownOperatingSystem; |
| 197 | const version_text = it.rest(); |
| 198 | const S = struct { |
| 199 | fn parseNone(s: []const u8) !void { |
| 200 | if (s.len != 0) return error.InvalidOperatingSystemVersion; |
| 201 | } |
| 202 | fn parseSemVer(s: []const u8, default: Version.Range) !Version.Range { |
| 203 | if (s.len == 0) return default; |
| 204 | var range_it = mem.separate(s, "..."); |
| 205 | |
| 206 | const min_text = range_it.next().?; |
| 207 | const min_ver = Version.parse(min_text) catch |err| switch (err) { |
| 208 | error.Overflow => return error.InvalidOperatingSystemVersion, |
| 209 | error.InvalidCharacter => return error.InvalidOperatingSystemVersion, |
| 210 | error.InvalidVersion => return error.InvalidOperatingSystemVersion, |
| 211 | }; |
| 212 | |
| 213 | const max_text = range_it.next() orelse return Version.Range{ |
| 214 | .min = min_ver, |
| 215 | .max = default.max, |
| 216 | }; |
| 217 | const max_ver = Version.parse(max_text) catch |err| switch (err) { |
| 218 | error.Overflow => return error.InvalidOperatingSystemVersion, |
| 219 | error.InvalidCharacter => return error.InvalidOperatingSystemVersion, |
| 220 | error.InvalidVersion => return error.InvalidOperatingSystemVersion, |
| 221 | }; |
| 222 | |
| 223 | return Version.Range{ .min = min_ver, .max = max_ver }; |
| 224 | } |
| 225 | fn parseWindows(s: []const u8, default: WindowsVersion.Range) !WindowsVersion.Range { |
| 226 | if (s.len == 0) return default; |
| 227 | var range_it = mem.separate(s, "..."); |
| 228 | |
| 229 | const min_text = range_it.next().?; |
| 230 | const min_ver = WindowsVersion.nameToTag(min_text) orelse |
| 231 | return error.InvalidOperatingSystemVersion; |
| 232 | |
| 233 | const max_text = range_it.next() orelse return WindowsVersion.Range{ |
| 234 | .min = min_ver, |
| 235 | .max = default.max, |
| 236 | }; |
| 237 | const max_ver = WindowsVersion.nameToTag(max_text) orelse |
| 238 | return error.InvalidOperatingSystemVersion; |
| 239 | |
| 240 | return WindowsVersion.Range{ .min = min_ver, .max = max_ver }; |
| 241 | } |
| 242 | }; |
| 243 | const default = defaultVersionRange(tag); |
| 244 | switch (tag) { |
| 245 | .freestanding => return Os{ .freestanding = try S.parseNone(version_text) }, |
| 246 | .ananas => return Os{ .ananas = try S.parseNone(version_text) }, |
| 247 | .cloudabi => return Os{ .cloudabi = try S.parseNone(version_text) }, |
| 248 | .dragonfly => return Os{ .dragonfly = try S.parseNone(version_text) }, |
| 249 | .freebsd => return Os{ .freebsd = try S.parseSemVer(version_text, default.freebsd) }, |
| 250 | .fuchsia => return Os{ .fuchsia = try S.parseNone(version_text) }, |
| 251 | .ios => return Os{ .ios = try S.parseNone(version_text) }, |
| 252 | .kfreebsd => return Os{ .kfreebsd = try S.parseNone(version_text) }, |
| 253 | .linux => return Os{ |
| 254 | .linux = .{ |
| 255 | .range = try S.parseSemVer(version_text, default.linux.range), |
| 256 | .glibc = default.linux.glibc, |
| 257 | }, |
| 258 | }, |
| 259 | .lv2 => return Os{ .lv2 = try S.parseNone(version_text) }, |
| 260 | .macosx => return Os{ .macosx = try S.parseSemVer(version_text, default.macosx) }, |
| 261 | .netbsd => return Os{ .netbsd = try S.parseSemVer(version_text, default.netbsd) }, |
| 262 | .openbsd => return Os{ .openbsd = try S.parseSemVer(version_text, default.openbsd) }, |
| 263 | .solaris => return Os{ .solaris = try S.parseNone(version_text) }, |
| 264 | .windows => return Os{ .windows = try S.parseWindows(version_text, default.windows) }, |
| 265 | .haiku => return Os{ .haiku = try S.parseNone(version_text) }, |
| 266 | .minix => return Os{ .minix = try S.parseNone(version_text) }, |
| 267 | .rtems => return Os{ .rtems = try S.parseNone(version_text) }, |
| 268 | .nacl => return Os{ .nacl = try S.parseNone(version_text) }, |
| 269 | .cnk => return Os{ .cnk = try S.parseNone(version_text) }, |
| 270 | .aix => return Os{ .aix = try S.parseNone(version_text) }, |
| 271 | .cuda => return Os{ .cuda = try S.parseNone(version_text) }, |
| 272 | .nvcl => return Os{ .nvcl = try S.parseNone(version_text) }, |
| 273 | .amdhsa => return Os{ .amdhsa = try S.parseNone(version_text) }, |
| 274 | .ps4 => return Os{ .ps4 = try S.parseNone(version_text) }, |
| 275 | .elfiamcu => return Os{ .elfiamcu = try S.parseNone(version_text) }, |
| 276 | .tvos => return Os{ .tvos = try S.parseNone(version_text) }, |
| 277 | .watchos => return Os{ .watchos = try S.parseNone(version_text) }, |
| 278 | .mesa3d => return Os{ .mesa3d = try S.parseNone(version_text) }, |
| 279 | .contiki => return Os{ .contiki = try S.parseNone(version_text) }, |
| 280 | .amdpal => return Os{ .amdpal = try S.parseNone(version_text) }, |
| 281 | .hermit => return Os{ .hermit = try S.parseNone(version_text) }, |
| 282 | .hurd => return Os{ .hurd = try S.parseNone(version_text) }, |
| 283 | .wasi => return Os{ .wasi = try S.parseNone(version_text) }, |
| 284 | .emscripten => return Os{ .emscripten = try S.parseNone(version_text) }, |
| 285 | .uefi => return Os{ .uefi = try S.parseNone(version_text) }, |
| 286 | .other => return Os{ .other = try S.parseNone(version_text) }, |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | pub fn nameToTag(name: []const u8) ?@TagType(Os) { |
| 52 | 291 | const info = @typeInfo(Os); |
| 53 | | inline for (info.Enum.fields) |field| { |
| 54 | | if (mem.eql(u8, text, field.name)) { |
| 292 | inline for (info.Union.fields) |field| { |
| 293 | if (mem.eql(u8, name, field.name)) { |
| 55 | 294 | return @field(Os, field.name); |
| 56 | 295 | } |
| 57 | 296 | } |
| 58 | | return error.UnknownOperatingSystem; |
| 297 | return null; |
| 59 | 298 | } |
| 60 | 299 | }; |
| 61 | 300 | |
| ... | ... | @@ -149,14 +388,39 @@ pub const Target = union(enum) { |
| 149 | 388 | } |
| 150 | 389 | } |
| 151 | 390 | |
| 152 | | pub fn parse(text: []const u8) !Abi { |
| 391 | pub fn nameToTag(text: []const u8) ?Abi { |
| 153 | 392 | const info = @typeInfo(Abi); |
| 154 | 393 | inline for (info.Enum.fields) |field| { |
| 155 | 394 | if (mem.eql(u8, text, field.name)) { |
| 156 | 395 | return @field(Abi, field.name); |
| 157 | 396 | } |
| 158 | 397 | } |
| 159 | | return error.UnknownApplicationBinaryInterface; |
| 398 | return null; |
| 399 | } |
| 400 | |
| 401 | pub fn parse(text: []const u8, os: *Os) !Abi { |
| 402 | var it = mem.separate(text, "."); |
| 403 | const tag = nameToTag(it.next().?) orelse return error.UnknownApplicationBinaryInterface; |
| 404 | const version_text = it.rest(); |
| 405 | if (version_text.len != 0) { |
| 406 | if (@as(@TagType(Os), os.*) == .linux and tag.isGnu()) { |
| 407 | os.linux.glibc = Version.parse(version_text) catch |err| switch (err) { |
| 408 | error.Overflow => return error.InvalidGlibcVersion, |
| 409 | error.InvalidCharacter => return error.InvalidGlibcVersion, |
| 410 | error.InvalidVersion => return error.InvalidGlibcVersion, |
| 411 | }; |
| 412 | } else { |
| 413 | return error.InvalidAbiVersion; |
| 414 | } |
| 415 | } |
| 416 | return tag; |
| 417 | } |
| 418 | |
| 419 | pub fn isGnu(abi: Abi) bool { |
| 420 | return switch (abi) { |
| 421 | .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true, |
| 422 | else => false, |
| 423 | }; |
| 160 | 424 | } |
| 161 | 425 | }; |
| 162 | 426 | |
| ... | ... | @@ -179,12 +443,6 @@ pub const Target = union(enum) { |
| 179 | 443 | EfiRuntimeDriver, |
| 180 | 444 | }; |
| 181 | 445 | |
| 182 | | pub const Cross = struct { |
| 183 | | cpu: Cpu, |
| 184 | | os: Os, |
| 185 | | abi: Abi, |
| 186 | | }; |
| 187 | | |
| 188 | 446 | pub const Cpu = struct { |
| 189 | 447 | /// Architecture |
| 190 | 448 | arch: Arch, |
| ... | ... | @@ -641,20 +899,19 @@ pub const Target = union(enum) { |
| 641 | 899 | }; |
| 642 | 900 | |
| 643 | 901 | pub const current = Target{ |
| 644 | | .Cross = Cross{ |
| 645 | | .cpu = builtin.cpu, |
| 646 | | .os = builtin.os, |
| 647 | | .abi = builtin.abi, |
| 648 | | }, |
| 902 | .cpu = builtin.cpu, |
| 903 | .os = builtin.os, |
| 904 | .abi = builtin.abi, |
| 649 | 905 | }; |
| 650 | 906 | |
| 651 | 907 | pub const stack_align = 16; |
| 652 | 908 | |
| 909 | /// TODO add OS version ranges and glibc version |
| 653 | 910 | pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { |
| 654 | 911 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ |
| 655 | 912 | @tagName(self.getArch()), |
| 656 | | @tagName(self.getOs()), |
| 657 | | @tagName(self.getAbi()), |
| 913 | @tagName(self.os), |
| 914 | @tagName(self.abi), |
| 658 | 915 | }); |
| 659 | 916 | } |
| 660 | 917 | |
| ... | ... | @@ -678,7 +935,7 @@ pub const Target = union(enum) { |
| 678 | 935 | else => return error.VcpkgNoSuchArchitecture, |
| 679 | 936 | }; |
| 680 | 937 | |
| 681 | | const os = switch (target.getOs()) { |
| 938 | const os = switch (target.os) { |
| 682 | 939 | .windows => "windows", |
| 683 | 940 | .linux => "linux", |
| 684 | 941 | .macosx => "macos", |
| ... | ... | @@ -701,16 +958,16 @@ pub const Target = union(enum) { |
| 701 | 958 | pub fn zigTripleNoSubArch(self: Target, allocator: *mem.Allocator) ![]u8 { |
| 702 | 959 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ |
| 703 | 960 | @tagName(self.getArch()), |
| 704 | | @tagName(self.getOs()), |
| 705 | | @tagName(self.getAbi()), |
| 961 | @tagName(self.os), |
| 962 | @tagName(self.abi), |
| 706 | 963 | }); |
| 707 | 964 | } |
| 708 | 965 | |
| 709 | 966 | pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 { |
| 710 | 967 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ |
| 711 | 968 | @tagName(self.getArch()), |
| 712 | | @tagName(self.getOs()), |
| 713 | | @tagName(self.getAbi()), |
| 969 | @tagName(self.os), |
| 970 | @tagName(self.abi), |
| 714 | 971 | }); |
| 715 | 972 | } |
| 716 | 973 | |
| ... | ... | @@ -760,11 +1017,11 @@ pub const Target = union(enum) { |
| 760 | 1017 | diags.arch = arch; |
| 761 | 1018 | |
| 762 | 1019 | const os_name = it.next() orelse return error.MissingOperatingSystem; |
| 763 | | const os = try Os.parse(os_name); |
| 1020 | var os = try Os.parse(os_name); // var because Abi.parse can update linux.glibc version |
| 764 | 1021 | diags.os = os; |
| 765 | 1022 | |
| 766 | 1023 | const abi_name = it.next(); |
| 767 | | const abi = if (abi_name) |n| try Abi.parse(n) else Abi.default(arch, os); |
| 1024 | const abi = if (abi_name) |n| try Abi.parse(n, &os) else Abi.default(arch, os); |
| 768 | 1025 | diags.abi = abi; |
| 769 | 1026 | |
| 770 | 1027 | if (it.next() != null) return error.UnexpectedExtraField; |
| ... | ... | @@ -817,16 +1074,15 @@ pub const Target = union(enum) { |
| 817 | 1074 | .features = set, |
| 818 | 1075 | }; |
| 819 | 1076 | }; |
| 820 | | var cross = Cross{ |
| 1077 | return Target{ |
| 821 | 1078 | .cpu = cpu, |
| 822 | 1079 | .os = os, |
| 823 | 1080 | .abi = abi, |
| 824 | 1081 | }; |
| 825 | | return Target{ .Cross = cross }; |
| 826 | 1082 | } |
| 827 | 1083 | |
| 828 | 1084 | pub fn oFileExt(self: Target) []const u8 { |
| 829 | | return switch (self.getAbi()) { |
| 1085 | return switch (self.abi) { |
| 830 | 1086 | .msvc => ".obj", |
| 831 | 1087 | else => ".o", |
| 832 | 1088 | }; |
| ... | ... | @@ -848,7 +1104,7 @@ pub const Target = union(enum) { |
| 848 | 1104 | if (self.isWasm()) { |
| 849 | 1105 | return ".wasm"; |
| 850 | 1106 | } |
| 851 | | switch (self.getAbi()) { |
| 1107 | switch (self.abi) { |
| 852 | 1108 | .msvc => return ".lib", |
| 853 | 1109 | else => return ".a", |
| 854 | 1110 | } |
| ... | ... | @@ -858,7 +1114,7 @@ pub const Target = union(enum) { |
| 858 | 1114 | if (self.isDarwin()) { |
| 859 | 1115 | return ".dylib"; |
| 860 | 1116 | } |
| 861 | | switch (self.getOs()) { |
| 1117 | switch (self.os) { |
| 862 | 1118 | .windows => return ".dll", |
| 863 | 1119 | else => return ".so", |
| 864 | 1120 | } |
| ... | ... | @@ -868,52 +1124,41 @@ pub const Target = union(enum) { |
| 868 | 1124 | if (self.isWasm()) { |
| 869 | 1125 | return ""; |
| 870 | 1126 | } |
| 871 | | switch (self.getAbi()) { |
| 1127 | switch (self.abi) { |
| 872 | 1128 | .msvc => return "", |
| 873 | 1129 | else => return "lib", |
| 874 | 1130 | } |
| 875 | 1131 | } |
| 876 | 1132 | |
| 877 | | pub fn getOs(self: Target) Os { |
| 878 | | return switch (self) { |
| 879 | | .Native => builtin.os, |
| 880 | | .Cross => |t| t.os, |
| 881 | | }; |
| 1133 | /// Deprecated; access the `os` field directly. |
| 1134 | pub fn getOs(self: Target) @TagType(Os) { |
| 1135 | return self.os; |
| 882 | 1136 | } |
| 883 | 1137 | |
| 1138 | /// Deprecated; access the `cpu` field directly. |
| 884 | 1139 | pub fn getCpu(self: Target) Cpu { |
| 885 | | return switch (self) { |
| 886 | | .Native => builtin.cpu, |
| 887 | | .Cross => |cross| cross.cpu, |
| 888 | | }; |
| 1140 | return self.cpu; |
| 889 | 1141 | } |
| 890 | 1142 | |
| 891 | | pub fn getArch(self: Target) Cpu.Arch { |
| 892 | | return self.getCpu().arch; |
| 1143 | /// Deprecated; access the `abi` field directly. |
| 1144 | pub fn getAbi(self: Target) Abi { |
| 1145 | return self.abi; |
| 893 | 1146 | } |
| 894 | 1147 | |
| 895 | | pub fn getAbi(self: Target) Abi { |
| 896 | | switch (self) { |
| 897 | | .Native => return builtin.abi, |
| 898 | | .Cross => |t| return t.abi, |
| 899 | | } |
| 1148 | pub fn getArch(self: Target) Cpu.Arch { |
| 1149 | return self.cpu.arch; |
| 900 | 1150 | } |
| 901 | 1151 | |
| 902 | 1152 | pub fn getObjectFormat(self: Target) ObjectFormat { |
| 903 | | switch (self) { |
| 904 | | .Native => return @import("builtin").object_format, |
| 905 | | .Cross => blk: { |
| 906 | | if (self.isWindows() or self.isUefi()) { |
| 907 | | return .coff; |
| 908 | | } else if (self.isDarwin()) { |
| 909 | | return .macho; |
| 910 | | } |
| 911 | | if (self.isWasm()) { |
| 912 | | return .wasm; |
| 913 | | } |
| 914 | | return .elf; |
| 915 | | }, |
| 1153 | if (self.isWindows() or self.isUefi()) { |
| 1154 | return .coff; |
| 1155 | } else if (self.isDarwin()) { |
| 1156 | return .macho; |
| 1157 | } |
| 1158 | if (self.isWasm()) { |
| 1159 | return .wasm; |
| 916 | 1160 | } |
| 1161 | return .elf; |
| 917 | 1162 | } |
| 918 | 1163 | |
| 919 | 1164 | pub fn isMinGW(self: Target) bool { |
| ... | ... | @@ -921,56 +1166,53 @@ pub const Target = union(enum) { |
| 921 | 1166 | } |
| 922 | 1167 | |
| 923 | 1168 | pub fn isGnu(self: Target) bool { |
| 924 | | return switch (self.getAbi()) { |
| 925 | | .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true, |
| 926 | | else => false, |
| 927 | | }; |
| 1169 | return self.abi.isGnu(); |
| 928 | 1170 | } |
| 929 | 1171 | |
| 930 | 1172 | pub fn isMusl(self: Target) bool { |
| 931 | | return switch (self.getAbi()) { |
| 1173 | return switch (self.abi) { |
| 932 | 1174 | .musl, .musleabi, .musleabihf => true, |
| 933 | 1175 | else => false, |
| 934 | 1176 | }; |
| 935 | 1177 | } |
| 936 | 1178 | |
| 937 | 1179 | pub fn isDarwin(self: Target) bool { |
| 938 | | return switch (self.getOs()) { |
| 1180 | return switch (self.os) { |
| 939 | 1181 | .ios, .macosx, .watchos, .tvos => true, |
| 940 | 1182 | else => false, |
| 941 | 1183 | }; |
| 942 | 1184 | } |
| 943 | 1185 | |
| 944 | 1186 | pub fn isWindows(self: Target) bool { |
| 945 | | return switch (self.getOs()) { |
| 1187 | return switch (self.os) { |
| 946 | 1188 | .windows => true, |
| 947 | 1189 | else => false, |
| 948 | 1190 | }; |
| 949 | 1191 | } |
| 950 | 1192 | |
| 951 | 1193 | pub fn isLinux(self: Target) bool { |
| 952 | | return switch (self.getOs()) { |
| 1194 | return switch (self.os) { |
| 953 | 1195 | .linux => true, |
| 954 | 1196 | else => false, |
| 955 | 1197 | }; |
| 956 | 1198 | } |
| 957 | 1199 | |
| 958 | 1200 | pub fn isAndroid(self: Target) bool { |
| 959 | | return switch (self.getAbi()) { |
| 1201 | return switch (self.abi) { |
| 960 | 1202 | .android => true, |
| 961 | 1203 | else => false, |
| 962 | 1204 | }; |
| 963 | 1205 | } |
| 964 | 1206 | |
| 965 | 1207 | pub fn isDragonFlyBSD(self: Target) bool { |
| 966 | | return switch (self.getOs()) { |
| 1208 | return switch (self.os) { |
| 967 | 1209 | .dragonfly => true, |
| 968 | 1210 | else => false, |
| 969 | 1211 | }; |
| 970 | 1212 | } |
| 971 | 1213 | |
| 972 | 1214 | pub fn isUefi(self: Target) bool { |
| 973 | | return switch (self.getOs()) { |
| 1215 | return switch (self.os) { |
| 974 | 1216 | .uefi => true, |
| 975 | 1217 | else => false, |
| 976 | 1218 | }; |
| ... | ... | @@ -984,14 +1226,14 @@ pub const Target = union(enum) { |
| 984 | 1226 | } |
| 985 | 1227 | |
| 986 | 1228 | pub fn isFreeBSD(self: Target) bool { |
| 987 | | return switch (self.getOs()) { |
| 1229 | return switch (self.os) { |
| 988 | 1230 | .freebsd => true, |
| 989 | 1231 | else => false, |
| 990 | 1232 | }; |
| 991 | 1233 | } |
| 992 | 1234 | |
| 993 | 1235 | pub fn isNetBSD(self: Target) bool { |
| 994 | | return switch (self.getOs()) { |
| 1236 | return switch (self.os) { |
| 995 | 1237 | .netbsd => true, |
| 996 | 1238 | else => false, |
| 997 | 1239 | }; |
| ... | ... | @@ -1081,7 +1323,7 @@ pub const Target = union(enum) { |
| 1081 | 1323 | if (@as(@TagType(Target), self) == .Native) return .native; |
| 1082 | 1324 | |
| 1083 | 1325 | // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture. |
| 1084 | | if (self.getOs() == builtin.os) { |
| 1326 | if (self.os == builtin.os) { |
| 1085 | 1327 | return switch (self.getArch()) { |
| 1086 | 1328 | .aarch64 => Executor{ .qemu = "qemu-aarch64" }, |
| 1087 | 1329 | .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, |
| ... | ... | @@ -1112,7 +1354,7 @@ pub const Target = union(enum) { |
| 1112 | 1354 | } |
| 1113 | 1355 | } |
| 1114 | 1356 | |
| 1115 | | if (self.getOs() == .wasi) { |
| 1357 | if (self.os == .wasi) { |
| 1116 | 1358 | switch (self.getArchPtrBitWidth()) { |
| 1117 | 1359 | 32 => return Executor{ .wasmtime = "wasmtime" }, |
| 1118 | 1360 | else => return .unavailable, |
| ... | ... | @@ -1129,7 +1371,7 @@ pub const Target = union(enum) { |
| 1129 | 1371 | }; |
| 1130 | 1372 | |
| 1131 | 1373 | pub fn getFloatAbi(self: Target) FloatAbi { |
| 1132 | | return switch (self.getAbi()) { |
| 1374 | return switch (self.abi) { |
| 1133 | 1375 | .gnueabihf, |
| 1134 | 1376 | .eabihf, |
| 1135 | 1377 | .musleabihf, |
| ... | ... | @@ -1145,7 +1387,7 @@ pub const Target = union(enum) { |
| 1145 | 1387 | => return false, |
| 1146 | 1388 | else => {}, |
| 1147 | 1389 | } |
| 1148 | | switch (self.getOs()) { |
| 1390 | switch (self.os) { |
| 1149 | 1391 | .freestanding, |
| 1150 | 1392 | .ios, |
| 1151 | 1393 | .tvos, |
| ... | ... | @@ -1200,7 +1442,7 @@ pub const Target = union(enum) { |
| 1200 | 1442 | return result.toOwnedSlice(); |
| 1201 | 1443 | } |
| 1202 | 1444 | |
| 1203 | | switch (self.getOs()) { |
| 1445 | switch (self.os) { |
| 1204 | 1446 | .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"), |
| 1205 | 1447 | .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"), |
| 1206 | 1448 | .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"), |
| ... | ... | @@ -1233,7 +1475,7 @@ pub const Target = union(enum) { |
| 1233 | 1475 | .powerpc64, .powerpc64le => return mem.dupeZ(a, u8, "/lib64/ld64.so.2"), |
| 1234 | 1476 | .s390x => return mem.dupeZ(a, u8, "/lib64/ld64.so.1"), |
| 1235 | 1477 | .sparcv9 => return mem.dupeZ(a, u8, "/lib64/ld-linux.so.2"), |
| 1236 | | .x86_64 => return mem.dupeZ(a, u8, switch (self.getAbi()) { |
| 1478 | .x86_64 => return mem.dupeZ(a, u8, switch (self.abi) { |
| 1237 | 1479 | .gnux32 => "/libx32/ld-linux-x32.so.2", |
| 1238 | 1480 | else => "/lib64/ld-linux-x86-64.so.2", |
| 1239 | 1481 | }), |
| ... | ... | @@ -1292,10 +1534,10 @@ pub const Target = union(enum) { |
| 1292 | 1534 | |
| 1293 | 1535 | test "Target.parse" { |
| 1294 | 1536 | { |
| 1295 | | const target = (try Target.parse(.{ |
| 1537 | const target = try Target.parse(.{ |
| 1296 | 1538 | .arch_os_abi = "x86_64-linux-gnu", |
| 1297 | 1539 | .cpu_features = "x86_64-sse-sse2-avx-cx8", |
| 1298 | | })).Cross; |
| 1540 | }); |
| 1299 | 1541 | |
| 1300 | 1542 | std.testing.expect(target.os == .linux); |
| 1301 | 1543 | std.testing.expect(target.abi == .gnu); |
| ... | ... | @@ -1307,10 +1549,10 @@ test "Target.parse" { |
| 1307 | 1549 | std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); |
| 1308 | 1550 | } |
| 1309 | 1551 | { |
| 1310 | | const target = (try Target.parse(.{ |
| 1552 | const target = try Target.parse(.{ |
| 1311 | 1553 | .arch_os_abi = "arm-linux-musleabihf", |
| 1312 | 1554 | .cpu_features = "generic+v8a", |
| 1313 | | })).Cross; |
| 1555 | }); |
| 1314 | 1556 | |
| 1315 | 1557 | std.testing.expect(target.os == .linux); |
| 1316 | 1558 | std.testing.expect(target.abi == .musleabihf); |