| ... | @@ -1,30 +1,53 @@ | ... | @@ -1,30 +1,53 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const mem = std.mem; | 2 | const mem = std.mem; |
| 3 | const builtin = std.builtin; | 3 | const builtin = std.builtin; |
| | 4 | const Version = std.builtin.Version; |
| 4 | | 5 | |
| 5 | /// TODO Nearly all the functions in this namespace would be | 6 | /// TODO Nearly all the functions in this namespace would be |
| 6 | /// better off if https://github.com/ziglang/zig/issues/425 | 7 | /// better off if https://github.com/ziglang/zig/issues/425 |
| 7 | /// was solved. | 8 | /// was solved. |
| 8 | pub const Target = union(enum) { | 9 | pub const Target = struct { |
| 9 | Native: void, | 10 | cpu: Cpu, |
| 10 | Cross: Cross, | 11 | os: Os, |
| 11 | | 12 | abi: Abi, |
| 12 | pub const Os = enum { | 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 | freestanding, | 36 | freestanding, |
| 14 | ananas, | 37 | ananas, |
| 15 | cloudabi, | 38 | cloudabi, |
| 16 | dragonfly, | 39 | dragonfly, |
| 17 | freebsd, | 40 | freebsd: Version.Range, |
| 18 | fuchsia, | 41 | fuchsia, |
| 19 | ios, | 42 | ios, |
| 20 | kfreebsd, | 43 | kfreebsd, |
| 21 | linux, | 44 | linux: LinuxVersionRange, |
| 22 | lv2, | 45 | lv2, |
| 23 | macosx, | 46 | macosx: Version.Range, |
| 24 | netbsd, | 47 | netbsd: Version.Range, |
| 25 | openbsd, | 48 | openbsd: Version.Range, |
| 26 | solaris, | 49 | solaris, |
| 27 | windows, | 50 | windows: WindowsVersion.Range, |
| 28 | haiku, | 51 | haiku, |
| 29 | minix, | 52 | minix, |
| 30 | rtems, | 53 | rtems, |
| ... | @@ -48,14 +71,230 @@ pub const Target = union(enum) { | ... | @@ -48,14 +71,230 @@ pub const Target = union(enum) { |
| 48 | uefi, | 71 | uefi, |
| 49 | other, | 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 | pub fn parse(text: []const u8) !Os { | 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 | const info = @typeInfo(Os); | 291 | const info = @typeInfo(Os); |
| 53 | inline for (info.Enum.fields) |field| { | 292 | inline for (info.Union.fields) |field| { |
| 54 | if (mem.eql(u8, text, field.name)) { | 293 | if (mem.eql(u8, name, field.name)) { |
| 55 | return @field(Os, field.name); | 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,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 | const info = @typeInfo(Abi); | 392 | const info = @typeInfo(Abi); |
| 154 | inline for (info.Enum.fields) |field| { | 393 | inline for (info.Enum.fields) |field| { |
| 155 | if (mem.eql(u8, text, field.name)) { | 394 | if (mem.eql(u8, text, field.name)) { |
| 156 | return @field(Abi, field.name); | 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,12 +443,6 @@ pub const Target = union(enum) { |
| 179 | EfiRuntimeDriver, | 443 | EfiRuntimeDriver, |
| 180 | }; | 444 | }; |
| 181 | | 445 | |
| 182 | pub const Cross = struct { | | |
| 183 | cpu: Cpu, | | |
| 184 | os: Os, | | |
| 185 | abi: Abi, | | |
| 186 | }; | | |
| 187 | | | |
| 188 | pub const Cpu = struct { | 446 | pub const Cpu = struct { |
| 189 | /// Architecture | 447 | /// Architecture |
| 190 | arch: Arch, | 448 | arch: Arch, |
| ... | @@ -641,20 +899,19 @@ pub const Target = union(enum) { | ... | @@ -641,20 +899,19 @@ pub const Target = union(enum) { |
| 641 | }; | 899 | }; |
| 642 | | 900 | |
| 643 | pub const current = Target{ | 901 | pub const current = Target{ |
| 644 | .Cross = Cross{ | 902 | .cpu = builtin.cpu, |
| 645 | .cpu = builtin.cpu, | 903 | .os = builtin.os, |
| 646 | .os = builtin.os, | 904 | .abi = builtin.abi, |
| 647 | .abi = builtin.abi, | | |
| 648 | }, | | |
| 649 | }; | 905 | }; |
| 650 | | 906 | |
| 651 | pub const stack_align = 16; | 907 | pub const stack_align = 16; |
| 652 | | 908 | |
| | 909 | /// TODO add OS version ranges and glibc version |
| 653 | pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { | 910 | pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { |
| 654 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ | 911 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ |
| 655 | @tagName(self.getArch()), | 912 | @tagName(self.getArch()), |
| 656 | @tagName(self.getOs()), | 913 | @tagName(self.os), |
| 657 | @tagName(self.getAbi()), | 914 | @tagName(self.abi), |
| 658 | }); | 915 | }); |
| 659 | } | 916 | } |
| 660 | | 917 | |
| ... | @@ -678,7 +935,7 @@ pub const Target = union(enum) { | ... | @@ -678,7 +935,7 @@ pub const Target = union(enum) { |
| 678 | else => return error.VcpkgNoSuchArchitecture, | 935 | else => return error.VcpkgNoSuchArchitecture, |
| 679 | }; | 936 | }; |
| 680 | | 937 | |
| 681 | const os = switch (target.getOs()) { | 938 | const os = switch (target.os) { |
| 682 | .windows => "windows", | 939 | .windows => "windows", |
| 683 | .linux => "linux", | 940 | .linux => "linux", |
| 684 | .macosx => "macos", | 941 | .macosx => "macos", |
| ... | @@ -701,16 +958,16 @@ pub const Target = union(enum) { | ... | @@ -701,16 +958,16 @@ pub const Target = union(enum) { |
| 701 | pub fn zigTripleNoSubArch(self: Target, allocator: *mem.Allocator) ![]u8 { | 958 | pub fn zigTripleNoSubArch(self: Target, allocator: *mem.Allocator) ![]u8 { |
| 702 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ | 959 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ |
| 703 | @tagName(self.getArch()), | 960 | @tagName(self.getArch()), |
| 704 | @tagName(self.getOs()), | 961 | @tagName(self.os), |
| 705 | @tagName(self.getAbi()), | 962 | @tagName(self.abi), |
| 706 | }); | 963 | }); |
| 707 | } | 964 | } |
| 708 | | 965 | |
| 709 | pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 { | 966 | pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 { |
| 710 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ | 967 | return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ |
| 711 | @tagName(self.getArch()), | 968 | @tagName(self.getArch()), |
| 712 | @tagName(self.getOs()), | 969 | @tagName(self.os), |
| 713 | @tagName(self.getAbi()), | 970 | @tagName(self.abi), |
| 714 | }); | 971 | }); |
| 715 | } | 972 | } |
| 716 | | 973 | |
| ... | @@ -760,11 +1017,11 @@ pub const Target = union(enum) { | ... | @@ -760,11 +1017,11 @@ pub const Target = union(enum) { |
| 760 | diags.arch = arch; | 1017 | diags.arch = arch; |
| 761 | | 1018 | |
| 762 | const os_name = it.next() orelse return error.MissingOperatingSystem; | 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 | diags.os = os; | 1021 | diags.os = os; |
| 765 | | 1022 | |
| 766 | const abi_name = it.next(); | 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 | diags.abi = abi; | 1025 | diags.abi = abi; |
| 769 | | 1026 | |
| 770 | if (it.next() != null) return error.UnexpectedExtraField; | 1027 | if (it.next() != null) return error.UnexpectedExtraField; |
| ... | @@ -817,16 +1074,15 @@ pub const Target = union(enum) { | ... | @@ -817,16 +1074,15 @@ pub const Target = union(enum) { |
| 817 | .features = set, | 1074 | .features = set, |
| 818 | }; | 1075 | }; |
| 819 | }; | 1076 | }; |
| 820 | var cross = Cross{ | 1077 | return Target{ |
| 821 | .cpu = cpu, | 1078 | .cpu = cpu, |
| 822 | .os = os, | 1079 | .os = os, |
| 823 | .abi = abi, | 1080 | .abi = abi, |
| 824 | }; | 1081 | }; |
| 825 | return Target{ .Cross = cross }; | | |
| 826 | } | 1082 | } |
| 827 | | 1083 | |
| 828 | pub fn oFileExt(self: Target) []const u8 { | 1084 | pub fn oFileExt(self: Target) []const u8 { |
| 829 | return switch (self.getAbi()) { | 1085 | return switch (self.abi) { |
| 830 | .msvc => ".obj", | 1086 | .msvc => ".obj", |
| 831 | else => ".o", | 1087 | else => ".o", |
| 832 | }; | 1088 | }; |
| ... | @@ -848,7 +1104,7 @@ pub const Target = union(enum) { | ... | @@ -848,7 +1104,7 @@ pub const Target = union(enum) { |
| 848 | if (self.isWasm()) { | 1104 | if (self.isWasm()) { |
| 849 | return ".wasm"; | 1105 | return ".wasm"; |
| 850 | } | 1106 | } |
| 851 | switch (self.getAbi()) { | 1107 | switch (self.abi) { |
| 852 | .msvc => return ".lib", | 1108 | .msvc => return ".lib", |
| 853 | else => return ".a", | 1109 | else => return ".a", |
| 854 | } | 1110 | } |
| ... | @@ -858,7 +1114,7 @@ pub const Target = union(enum) { | ... | @@ -858,7 +1114,7 @@ pub const Target = union(enum) { |
| 858 | if (self.isDarwin()) { | 1114 | if (self.isDarwin()) { |
| 859 | return ".dylib"; | 1115 | return ".dylib"; |
| 860 | } | 1116 | } |
| 861 | switch (self.getOs()) { | 1117 | switch (self.os) { |
| 862 | .windows => return ".dll", | 1118 | .windows => return ".dll", |
| 863 | else => return ".so", | 1119 | else => return ".so", |
| 864 | } | 1120 | } |
| ... | @@ -868,52 +1124,41 @@ pub const Target = union(enum) { | ... | @@ -868,52 +1124,41 @@ pub const Target = union(enum) { |
| 868 | if (self.isWasm()) { | 1124 | if (self.isWasm()) { |
| 869 | return ""; | 1125 | return ""; |
| 870 | } | 1126 | } |
| 871 | switch (self.getAbi()) { | 1127 | switch (self.abi) { |
| 872 | .msvc => return "", | 1128 | .msvc => return "", |
| 873 | else => return "lib", | 1129 | else => return "lib", |
| 874 | } | 1130 | } |
| 875 | } | 1131 | } |
| 876 | | 1132 | |
| 877 | pub fn getOs(self: Target) Os { | 1133 | /// Deprecated; access the `os` field directly. |
| 878 | return switch (self) { | 1134 | pub fn getOs(self: Target) @TagType(Os) { |
| 879 | .Native => builtin.os, | 1135 | return self.os; |
| 880 | .Cross => |t| t.os, | | |
| 881 | }; | | |
| 882 | } | 1136 | } |
| 883 | | 1137 | |
| | 1138 | /// Deprecated; access the `cpu` field directly. |
| 884 | pub fn getCpu(self: Target) Cpu { | 1139 | pub fn getCpu(self: Target) Cpu { |
| 885 | return switch (self) { | 1140 | return self.cpu; |
| 886 | .Native => builtin.cpu, | | |
| 887 | .Cross => |cross| cross.cpu, | | |
| 888 | }; | | |
| 889 | } | 1141 | } |
| 890 | | 1142 | |
| 891 | pub fn getArch(self: Target) Cpu.Arch { | 1143 | /// Deprecated; access the `abi` field directly. |
| 892 | return self.getCpu().arch; | 1144 | pub fn getAbi(self: Target) Abi { |
| | 1145 | return self.abi; |
| 893 | } | 1146 | } |
| 894 | | 1147 | |
| 895 | pub fn getAbi(self: Target) Abi { | 1148 | pub fn getArch(self: Target) Cpu.Arch { |
| 896 | switch (self) { | 1149 | return self.cpu.arch; |
| 897 | .Native => return builtin.abi, | | |
| 898 | .Cross => |t| return t.abi, | | |
| 899 | } | | |
| 900 | } | 1150 | } |
| 901 | | 1151 | |
| 902 | pub fn getObjectFormat(self: Target) ObjectFormat { | 1152 | pub fn getObjectFormat(self: Target) ObjectFormat { |
| 903 | switch (self) { | 1153 | if (self.isWindows() or self.isUefi()) { |
| 904 | .Native => return @import("builtin").object_format, | 1154 | return .coff; |
| 905 | .Cross => blk: { | 1155 | } else if (self.isDarwin()) { |
| 906 | if (self.isWindows() or self.isUefi()) { | 1156 | return .macho; |
| 907 | return .coff; | 1157 | } |
| 908 | } else if (self.isDarwin()) { | 1158 | if (self.isWasm()) { |
| 909 | return .macho; | 1159 | return .wasm; |
| 910 | } | | |
| 911 | if (self.isWasm()) { | | |
| 912 | return .wasm; | | |
| 913 | } | | |
| 914 | return .elf; | | |
| 915 | }, | | |
| 916 | } | 1160 | } |
| | 1161 | return .elf; |
| 917 | } | 1162 | } |
| 918 | | 1163 | |
| 919 | pub fn isMinGW(self: Target) bool { | 1164 | pub fn isMinGW(self: Target) bool { |
| ... | @@ -921,56 +1166,53 @@ pub const Target = union(enum) { | ... | @@ -921,56 +1166,53 @@ pub const Target = union(enum) { |
| 921 | } | 1166 | } |
| 922 | | 1167 | |
| 923 | pub fn isGnu(self: Target) bool { | 1168 | pub fn isGnu(self: Target) bool { |
| 924 | return switch (self.getAbi()) { | 1169 | return self.abi.isGnu(); |
| 925 | .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true, | | |
| 926 | else => false, | | |
| 927 | }; | | |
| 928 | } | 1170 | } |
| 929 | | 1171 | |
| 930 | pub fn isMusl(self: Target) bool { | 1172 | pub fn isMusl(self: Target) bool { |
| 931 | return switch (self.getAbi()) { | 1173 | return switch (self.abi) { |
| 932 | .musl, .musleabi, .musleabihf => true, | 1174 | .musl, .musleabi, .musleabihf => true, |
| 933 | else => false, | 1175 | else => false, |
| 934 | }; | 1176 | }; |
| 935 | } | 1177 | } |
| 936 | | 1178 | |
| 937 | pub fn isDarwin(self: Target) bool { | 1179 | pub fn isDarwin(self: Target) bool { |
| 938 | return switch (self.getOs()) { | 1180 | return switch (self.os) { |
| 939 | .ios, .macosx, .watchos, .tvos => true, | 1181 | .ios, .macosx, .watchos, .tvos => true, |
| 940 | else => false, | 1182 | else => false, |
| 941 | }; | 1183 | }; |
| 942 | } | 1184 | } |
| 943 | | 1185 | |
| 944 | pub fn isWindows(self: Target) bool { | 1186 | pub fn isWindows(self: Target) bool { |
| 945 | return switch (self.getOs()) { | 1187 | return switch (self.os) { |
| 946 | .windows => true, | 1188 | .windows => true, |
| 947 | else => false, | 1189 | else => false, |
| 948 | }; | 1190 | }; |
| 949 | } | 1191 | } |
| 950 | | 1192 | |
| 951 | pub fn isLinux(self: Target) bool { | 1193 | pub fn isLinux(self: Target) bool { |
| 952 | return switch (self.getOs()) { | 1194 | return switch (self.os) { |
| 953 | .linux => true, | 1195 | .linux => true, |
| 954 | else => false, | 1196 | else => false, |
| 955 | }; | 1197 | }; |
| 956 | } | 1198 | } |
| 957 | | 1199 | |
| 958 | pub fn isAndroid(self: Target) bool { | 1200 | pub fn isAndroid(self: Target) bool { |
| 959 | return switch (self.getAbi()) { | 1201 | return switch (self.abi) { |
| 960 | .android => true, | 1202 | .android => true, |
| 961 | else => false, | 1203 | else => false, |
| 962 | }; | 1204 | }; |
| 963 | } | 1205 | } |
| 964 | | 1206 | |
| 965 | pub fn isDragonFlyBSD(self: Target) bool { | 1207 | pub fn isDragonFlyBSD(self: Target) bool { |
| 966 | return switch (self.getOs()) { | 1208 | return switch (self.os) { |
| 967 | .dragonfly => true, | 1209 | .dragonfly => true, |
| 968 | else => false, | 1210 | else => false, |
| 969 | }; | 1211 | }; |
| 970 | } | 1212 | } |
| 971 | | 1213 | |
| 972 | pub fn isUefi(self: Target) bool { | 1214 | pub fn isUefi(self: Target) bool { |
| 973 | return switch (self.getOs()) { | 1215 | return switch (self.os) { |
| 974 | .uefi => true, | 1216 | .uefi => true, |
| 975 | else => false, | 1217 | else => false, |
| 976 | }; | 1218 | }; |
| ... | @@ -984,14 +1226,14 @@ pub const Target = union(enum) { | ... | @@ -984,14 +1226,14 @@ pub const Target = union(enum) { |
| 984 | } | 1226 | } |
| 985 | | 1227 | |
| 986 | pub fn isFreeBSD(self: Target) bool { | 1228 | pub fn isFreeBSD(self: Target) bool { |
| 987 | return switch (self.getOs()) { | 1229 | return switch (self.os) { |
| 988 | .freebsd => true, | 1230 | .freebsd => true, |
| 989 | else => false, | 1231 | else => false, |
| 990 | }; | 1232 | }; |
| 991 | } | 1233 | } |
| 992 | | 1234 | |
| 993 | pub fn isNetBSD(self: Target) bool { | 1235 | pub fn isNetBSD(self: Target) bool { |
| 994 | return switch (self.getOs()) { | 1236 | return switch (self.os) { |
| 995 | .netbsd => true, | 1237 | .netbsd => true, |
| 996 | else => false, | 1238 | else => false, |
| 997 | }; | 1239 | }; |
| ... | @@ -1081,7 +1323,7 @@ pub const Target = union(enum) { | ... | @@ -1081,7 +1323,7 @@ pub const Target = union(enum) { |
| 1081 | if (@as(@TagType(Target), self) == .Native) return .native; | 1323 | if (@as(@TagType(Target), self) == .Native) return .native; |
| 1082 | | 1324 | |
| 1083 | // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture. | 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 | return switch (self.getArch()) { | 1327 | return switch (self.getArch()) { |
| 1086 | .aarch64 => Executor{ .qemu = "qemu-aarch64" }, | 1328 | .aarch64 => Executor{ .qemu = "qemu-aarch64" }, |
| 1087 | .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, | 1329 | .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" }, |
| ... | @@ -1112,7 +1354,7 @@ pub const Target = union(enum) { | ... | @@ -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 | switch (self.getArchPtrBitWidth()) { | 1358 | switch (self.getArchPtrBitWidth()) { |
| 1117 | 32 => return Executor{ .wasmtime = "wasmtime" }, | 1359 | 32 => return Executor{ .wasmtime = "wasmtime" }, |
| 1118 | else => return .unavailable, | 1360 | else => return .unavailable, |
| ... | @@ -1129,7 +1371,7 @@ pub const Target = union(enum) { | ... | @@ -1129,7 +1371,7 @@ pub const Target = union(enum) { |
| 1129 | }; | 1371 | }; |
| 1130 | | 1372 | |
| 1131 | pub fn getFloatAbi(self: Target) FloatAbi { | 1373 | pub fn getFloatAbi(self: Target) FloatAbi { |
| 1132 | return switch (self.getAbi()) { | 1374 | return switch (self.abi) { |
| 1133 | .gnueabihf, | 1375 | .gnueabihf, |
| 1134 | .eabihf, | 1376 | .eabihf, |
| 1135 | .musleabihf, | 1377 | .musleabihf, |
| ... | @@ -1145,7 +1387,7 @@ pub const Target = union(enum) { | ... | @@ -1145,7 +1387,7 @@ pub const Target = union(enum) { |
| 1145 | => return false, | 1387 | => return false, |
| 1146 | else => {}, | 1388 | else => {}, |
| 1147 | } | 1389 | } |
| 1148 | switch (self.getOs()) { | 1390 | switch (self.os) { |
| 1149 | .freestanding, | 1391 | .freestanding, |
| 1150 | .ios, | 1392 | .ios, |
| 1151 | .tvos, | 1393 | .tvos, |
| ... | @@ -1200,7 +1442,7 @@ pub const Target = union(enum) { | ... | @@ -1200,7 +1442,7 @@ pub const Target = union(enum) { |
| 1200 | return result.toOwnedSlice(); | 1442 | return result.toOwnedSlice(); |
| 1201 | } | 1443 | } |
| 1202 | | 1444 | |
| 1203 | switch (self.getOs()) { | 1445 | switch (self.os) { |
| 1204 | .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"), | 1446 | .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"), |
| 1205 | .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"), | 1447 | .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"), |
| 1206 | .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"), | 1448 | .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"), |
| ... | @@ -1233,7 +1475,7 @@ pub const Target = union(enum) { | ... | @@ -1233,7 +1475,7 @@ pub const Target = union(enum) { |
| 1233 | .powerpc64, .powerpc64le => return mem.dupeZ(a, u8, "/lib64/ld64.so.2"), | 1475 | .powerpc64, .powerpc64le => return mem.dupeZ(a, u8, "/lib64/ld64.so.2"), |
| 1234 | .s390x => return mem.dupeZ(a, u8, "/lib64/ld64.so.1"), | 1476 | .s390x => return mem.dupeZ(a, u8, "/lib64/ld64.so.1"), |
| 1235 | .sparcv9 => return mem.dupeZ(a, u8, "/lib64/ld-linux.so.2"), | 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 | .gnux32 => "/libx32/ld-linux-x32.so.2", | 1479 | .gnux32 => "/libx32/ld-linux-x32.so.2", |
| 1238 | else => "/lib64/ld-linux-x86-64.so.2", | 1480 | else => "/lib64/ld-linux-x86-64.so.2", |
| 1239 | }), | 1481 | }), |
| ... | @@ -1292,10 +1534,10 @@ pub const Target = union(enum) { | ... | @@ -1292,10 +1534,10 @@ pub const Target = union(enum) { |
| 1292 | | 1534 | |
| 1293 | test "Target.parse" { | 1535 | test "Target.parse" { |
| 1294 | { | 1536 | { |
| 1295 | const target = (try Target.parse(.{ | 1537 | const target = try Target.parse(.{ |
| 1296 | .arch_os_abi = "x86_64-linux-gnu", | 1538 | .arch_os_abi = "x86_64-linux-gnu", |
| 1297 | .cpu_features = "x86_64-sse-sse2-avx-cx8", | 1539 | .cpu_features = "x86_64-sse-sse2-avx-cx8", |
| 1298 | })).Cross; | 1540 | }); |
| 1299 | | 1541 | |
| 1300 | std.testing.expect(target.os == .linux); | 1542 | std.testing.expect(target.os == .linux); |
| 1301 | std.testing.expect(target.abi == .gnu); | 1543 | std.testing.expect(target.abi == .gnu); |
| ... | @@ -1307,10 +1549,10 @@ test "Target.parse" { | ... | @@ -1307,10 +1549,10 @@ test "Target.parse" { |
| 1307 | std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr)); | 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 | .arch_os_abi = "arm-linux-musleabihf", | 1553 | .arch_os_abi = "arm-linux-musleabihf", |
| 1312 | .cpu_features = "generic+v8a", | 1554 | .cpu_features = "generic+v8a", |
| 1313 | })).Cross; | 1555 | }); |
| 1314 | | 1556 | |
| 1315 | std.testing.expect(target.os == .linux); | 1557 | std.testing.expect(target.os == .linux); |
| 1316 | std.testing.expect(target.abi == .musleabihf); | 1558 | std.testing.expect(target.abi == .musleabihf); |