authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-11-02 02:00:25+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-11-02 02:00:25+01:00
logab89af3d397291f0126ad17d3787a51284457884
tree4f418bfe9a67189e4b67c3365a1e746d5bf0bde5
parentaaf54ce6a7e5c69c92fe30e9ca0e8ffb7765f824
parent3c1ccbdf3990b6d802cdc8a0db7c11eaac0960e8
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21860 from alexrp/llvm-triple-stuff

More support for OS/libc version ranges in `std.Target` and improvements to LLVM target triple construction

7 files changed, 328 insertions(+), 139 deletions(-)

lib/std/Build/Cache.zig+1
...@@ -221,6 +221,7 @@ pub const HashHelper = struct {...@@ -221,6 +221,7 @@ pub const HashHelper = struct {
221 hh.add(linux.range.min);221 hh.add(linux.range.min);
222 hh.add(linux.range.max);222 hh.add(linux.range.max);
223 hh.add(linux.glibc);223 hh.add(linux.glibc);
224 hh.add(linux.android);
224 },225 },
225 .windows => |windows| {226 .windows => |windows| {
226 hh.add(windows.min);227 hh.add(windows.min);
lib/std/Target.zig+205-112
...@@ -160,49 +160,62 @@ pub const Os = struct {...@@ -160,49 +160,62 @@ pub const Os = struct {
160 pub inline fn versionRangeTag(tag: Tag) @typeInfo(TaggedVersionRange).@"union".tag_type.? {160 pub inline fn versionRangeTag(tag: Tag) @typeInfo(TaggedVersionRange).@"union".tag_type.? {
161 return switch (tag) {161 return switch (tag) {
162 .freestanding,162 .freestanding,
163 .fuchsia,163 .other,
164 .ps3,164
165 .zos,165 .elfiamcu,
166
166 .haiku,167 .haiku,
167 .rtems,168 .plan9,
168 .aix,169 .serenity,
169 .cuda,170
170 .nvcl,171 // This should use semver once we determine the version history.
171 .amdhsa,172 .bridgeos,
173
174 .illumos,
175
176 .ps3,
172 .ps4,177 .ps4,
173 .ps5,178 .ps5,
174 .elfiamcu,179
180 .emscripten,
181
175 .mesa3d,182 .mesa3d,
183 => .none,
184
176 .contiki,185 .contiki,
177 .amdpal,186 .fuchsia,
178 .hermit,187 .hermit,
188
189 .aix,
179 .hurd,190 .hurd,
180 .emscripten,191 .rtems,
181 .uefi,192 .zos,
182 .opencl, // TODO: OpenCL versions
183 .opengl, // TODO: GLSL versions
184 .vulkan,
185 .plan9,
186 .illumos,
187 .serenity,
188 .other,
189 => .none,
190193
191 // This should use semver once we determine the version history.194 .dragonfly,
192 .bridgeos => .none,195 .freebsd,
196 .netbsd,
197 .openbsd,
193198
194 .driverkit,199 .driverkit,
195 .freebsd,
196 .macos,200 .macos,
197 .ios,201 .ios,
198 .tvos,202 .tvos,
199 .watchos,
200 .visionos,203 .visionos,
201 .netbsd,204 .watchos,
202 .openbsd,205
203 .dragonfly,
204 .solaris,206 .solaris,
207
208 .uefi,
209
205 .wasi,210 .wasi,
211
212 .amdhsa,
213 .amdpal,
214 .cuda,
215 .nvcl,
216 .opencl,
217 .opengl,
218 .vulkan,
206 => .semver,219 => .semver,
207220
208 .linux => .linux,221 .linux => .linux,
...@@ -257,10 +270,11 @@ pub const Os = struct {...@@ -257,10 +270,11 @@ pub const Os = struct {
257 win11_zn = 0x0A00000E, //aka win11_21h2270 win11_zn = 0x0A00000E, //aka win11_21h2
258 win11_ga = 0x0A00000F, //aka win11_22h2271 win11_ga = 0x0A00000F, //aka win11_22h2
259 win11_ge = 0x0A000010, //aka win11_23h2272 win11_ge = 0x0A000010, //aka win11_23h2
273 win11_dt = 0x0A000011, //aka win11_24h2
260 _,274 _,
261275
262 /// Latest Windows version that the Zig Standard Library is aware of276 /// Latest Windows version that the Zig Standard Library is aware of
263 pub const latest = WindowsVersion.win11_ge;277 pub const latest = WindowsVersion.win11_dt;
264278
265 /// Compared against build numbers reported by the runtime to distinguish win10 versions,279 /// Compared against build numbers reported by the runtime to distinguish win10 versions,
266 /// where 0x0A000000 + index corresponds to the WindowsVersion u32 value.280 /// where 0x0A000000 + index corresponds to the WindowsVersion u32 value.
...@@ -282,6 +296,7 @@ pub const Os = struct {...@@ -282,6 +296,7 @@ pub const Os = struct {
282 22000, //win11_zn aka win11_21h2296 22000, //win11_zn aka win11_21h2
283 22621, //win11_ga aka win11_22h2297 22621, //win11_ga aka win11_22h2
284 22631, //win11_ge aka win11_23h2298 22631, //win11_ge aka win11_23h2
299 26100, //win11_dt aka win11_24h2
285 };300 };
286301
287 /// Returns whether the first version `ver` is newer (greater) than or equal to the second version `ver`.302 /// Returns whether the first version `ver` is newer (greater) than or equal to the second version `ver`.
...@@ -344,6 +359,8 @@ pub const Os = struct {...@@ -344,6 +359,8 @@ pub const Os = struct {
344 pub const LinuxVersionRange = struct {359 pub const LinuxVersionRange = struct {
345 range: std.SemanticVersion.Range,360 range: std.SemanticVersion.Range,
346 glibc: std.SemanticVersion,361 glibc: std.SemanticVersion,
362 /// Android API level.
363 android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated.
347364
348 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {365 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
349 return range.range.includesVersion(ver);366 return range.range.includesVersion(ver);
...@@ -391,84 +408,106 @@ pub const Os = struct {...@@ -391,84 +408,106 @@ pub const Os = struct {
391 pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange {408 pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange {
392 return switch (tag) {409 return switch (tag) {
393 .freestanding,410 .freestanding,
394 .fuchsia,411 .other,
395 .ps3,412
396 .zos,
397 .haiku,
398 .rtems,
399 .aix,
400 .cuda,
401 .nvcl,
402 .amdhsa,
403 .ps4,
404 .ps5,
405 .elfiamcu,413 .elfiamcu,
406 .mesa3d,414
407 .contiki,415 .haiku,
408 .amdpal,
409 .hermit,
410 .hurd,
411 .emscripten,
412 .uefi,
413 .opencl, // TODO: OpenCL versions
414 .opengl, // TODO: GLSL versions
415 .vulkan,
416 .plan9,416 .plan9,
417 .illumos,
418 .serenity,417 .serenity,
418
419 // This should use semver once we determine the version history.
419 .bridgeos,420 .bridgeos,
420 .other,421
422 .illumos,
423
424 .ps3,
425 .ps4,
426 .ps5,
427
428 .emscripten,
429
430 .mesa3d,
421 => .{ .none = {} },431 => .{ .none = {} },
422432
423 .freebsd => .{433 .contiki => .{
424 .semver = std.SemanticVersion.Range{434 .semver = .{
425 .min = .{ .major = 12, .minor = 0, .patch = 0 },435 .min = .{ .major = 4, .minor = 0, .patch = 0 },
426 .max = .{ .major = 14, .minor = 0, .patch = 0 },436 .max = .{ .major = 4, .minor = 9, .patch = 0 },
427 },437 },
428 },438 },
429 .driverkit => .{439 .fuchsia => .{
430 .semver = .{440 .semver = .{
431 .min = .{ .major = 19, .minor = 0, .patch = 0 },441 .min = .{ .major = 1, .minor = 1, .patch = 0 },
432 .max = .{ .major = 24, .minor = 0, .patch = 0 },442 .max = .{ .major = 20, .minor = 1, .patch = 0 },
433 },443 },
434 },444 },
435 .macos => switch (arch) {445 .hermit => .{
436 .aarch64 => VersionRange{446 .semver = .{
437 .semver = .{447 .min = .{ .major = 0, .minor = 4, .patch = 0 },
438 .min = .{ .major = 11, .minor = 7, .patch = 1 },448 .max = .{ .major = 0, .minor = 8, .patch = 0 },
439 .max = .{ .major = 14, .minor = 6, .patch = 1 },449 },
440 },450 },
451
452 .aix => .{
453 .semver = .{
454 .min = .{ .major = 7, .minor = 2, .patch = 5 },
455 .max = .{ .major = 7, .minor = 3, .patch = 2 },
441 },456 },
442 .x86_64 => VersionRange{457 },
443 .semver = .{458 .hurd => .{
444 .min = .{ .major = 11, .minor = 7, .patch = 1 },459 .semver = .{
445 .max = .{ .major = 14, .minor = 6, .patch = 1 },460 .min = .{ .major = 0, .minor = 9, .patch = 0 },
461 .max = .{ .major = 0, .minor = 9, .patch = 0 },
462 },
463 },
464 .linux => .{
465 .linux = .{
466 .range = .{
467 .min = .{ .major = 4, .minor = 19, .patch = 0 },
468 .max = .{ .major = 6, .minor = 11, .patch = 5 },
446 },469 },
470 .glibc = blk: {
471 const default_min: std.SemanticVersion = .{ .major = 2, .minor = 28, .patch = 0 };
472
473 for (std.zig.target.available_libcs) |libc| {
474 // We don't know the ABI here. We can get away with not checking it
475 // for now, but that may not always remain true.
476 if (libc.os != tag or libc.arch != arch) continue;
477
478 if (libc.glibc_min) |min| {
479 if (min.order(default_min) == .gt) break :blk min;
480 }
481 }
482
483 break :blk default_min;
484 },
485 .android = 14,
447 },486 },
448 else => unreachable,
449 },487 },
450 .ios => .{488 .rtems => .{
451 .semver = .{489 .semver = .{
452 .min = .{ .major = 12, .minor = 0, .patch = 0 },490 .min = .{ .major = 5, .minor = 1, .patch = 0 },
453 .max = .{ .major = 17, .minor = 6, .patch = 1 },491 .max = .{ .major = 5, .minor = 3, .patch = 0 },
454 },492 },
455 },493 },
456 .watchos => .{494 .zos => .{
457 .semver = .{495 .semver = .{
458 .min = .{ .major = 6, .minor = 0, .patch = 0 },496 .min = .{ .major = 2, .minor = 5, .patch = 0 },
459 .max = .{ .major = 10, .minor = 6, .patch = 0 },497 .max = .{ .major = 3, .minor = 1, .patch = 0 },
460 },498 },
461 },499 },
462 .tvos => .{500
501 .dragonfly => .{
463 .semver = .{502 .semver = .{
464 .min = .{ .major = 13, .minor = 0, .patch = 0 },503 .min = .{ .major = 5, .minor = 8, .patch = 0 },
465 .max = .{ .major = 17, .minor = 6, .patch = 0 },504 .max = .{ .major = 6, .minor = 4, .patch = 0 },
466 },505 },
467 },506 },
468 .visionos => .{507 .freebsd => .{
469 .semver = .{508 .semver = .{
470 .min = .{ .major = 1, .minor = 0, .patch = 0 },509 .min = .{ .major = 12, .minor = 0, .patch = 0 },
471 .max = .{ .major = 1, .minor = 3, .patch = 0 },510 .max = .{ .major = 14, .minor = 1, .patch = 0 },
472 },511 },
473 },512 },
474 .netbsd => .{513 .netbsd => .{
...@@ -480,49 +519,51 @@ pub const Os = struct {...@@ -480,49 +519,51 @@ pub const Os = struct {
480 .openbsd => .{519 .openbsd => .{
481 .semver = .{520 .semver = .{
482 .min = .{ .major = 7, .minor = 3, .patch = 0 },521 .min = .{ .major = 7, .minor = 3, .patch = 0 },
483 .max = .{ .major = 7, .minor = 5, .patch = 0 },522 .max = .{ .major = 7, .minor = 6, .patch = 0 },
484 },523 },
485 },524 },
486 .dragonfly => .{525
526 .driverkit => .{
487 .semver = .{527 .semver = .{
488 .min = .{ .major = 5, .minor = 8, .patch = 0 },528 .min = .{ .major = 19, .minor = 0, .patch = 0 },
489 .max = .{ .major = 6, .minor = 4, .patch = 0 },529 .max = .{ .major = 24, .minor = 2, .patch = 0 },
490 },530 },
491 },531 },
492 .solaris => .{532 .macos => .{
493 .semver = .{533 .semver = .{
494 .min = .{ .major = 11, .minor = 0, .patch = 0 },534 .min = .{ .major = 11, .minor = 7, .patch = 1 },
495 .max = .{ .major = 11, .minor = 4, .patch = 0 },535 .max = .{ .major = 15, .minor = 2, .patch = 0 },
496 },536 },
497 },537 },
498 .wasi => .{538 .ios => .{
499 .semver = .{539 .semver = .{
500 .min = .{ .major = 0, .minor = 1, .patch = 0 },540 .min = .{ .major = 12, .minor = 0, .patch = 0 },
501 .max = .{ .major = 0, .minor = 1, .patch = 0 },541 .max = .{ .major = 18, .minor = 1, .patch = 0 },
542 },
543 },
544 .tvos => .{
545 .semver = .{
546 .min = .{ .major = 13, .minor = 0, .patch = 0 },
547 .max = .{ .major = 18, .minor = 1, .patch = 0 },
548 },
549 },
550 .visionos => .{
551 .semver = .{
552 .min = .{ .major = 1, .minor = 0, .patch = 0 },
553 .max = .{ .major = 2, .minor = 1, .patch = 0 },
554 },
555 },
556 .watchos => .{
557 .semver = .{
558 .min = .{ .major = 6, .minor = 0, .patch = 0 },
559 .max = .{ .major = 11, .minor = 1, .patch = 0 },
502 },560 },
503 },561 },
504562
505 .linux => .{563 .solaris => .{
506 .linux = .{564 .semver = .{
507 .range = .{565 .min = .{ .major = 11, .minor = 0, .patch = 0 },
508 .min = .{ .major = 4, .minor = 19, .patch = 0 },566 .max = .{ .major = 11, .minor = 4, .patch = 0 },
509 .max = .{ .major = 6, .minor = 10, .patch = 3 },
510 },
511 .glibc = blk: {
512 const default_min: std.SemanticVersion = .{ .major = 2, .minor = 28, .patch = 0 };
513
514 for (std.zig.target.available_libcs) |libc| {
515 // We don't know the ABI here. We can get away with not checking it
516 // for now, but that may not always remain true.
517 if (libc.os != tag or libc.arch != arch) continue;
518
519 if (libc.glibc_min) |min| {
520 if (min.order(default_min) == .gt) break :blk min;
521 }
522 }
523
524 break :blk default_min;
525 },
526 },567 },
527 },568 },
528569
...@@ -532,6 +573,58 @@ pub const Os = struct {...@@ -532,6 +573,58 @@ pub const Os = struct {
532 .max = WindowsVersion.latest,573 .max = WindowsVersion.latest,
533 },574 },
534 },575 },
576 .uefi => .{
577 .semver = .{
578 .min = .{ .major = 2, .minor = 0, .patch = 0 },
579 .max = .{ .major = 2, .minor = 9, .patch = 0 },
580 },
581 },
582
583 .wasi => .{
584 .semver = .{
585 .min = .{ .major = 0, .minor = 1, .patch = 0 },
586 .max = .{ .major = 0, .minor = 2, .patch = 2 },
587 },
588 },
589
590 .amdhsa => .{
591 .semver = .{
592 .min = .{ .major = 5, .minor = 0, .patch = 2 },
593 .max = .{ .major = 6, .minor = 2, .patch = 2 },
594 },
595 },
596 .amdpal => .{
597 .semver = .{
598 .min = .{ .major = 1, .minor = 1, .patch = 0 },
599 .max = .{ .major = 3, .minor = 5, .patch = 0 },
600 },
601 },
602 .cuda => .{
603 .semver = .{
604 .min = .{ .major = 11, .minor = 0, .patch = 1 },
605 .max = .{ .major = 12, .minor = 6, .patch = 1 },
606 },
607 },
608 .nvcl,
609 .opencl,
610 => .{
611 .semver = .{
612 .min = .{ .major = 2, .minor = 2, .patch = 0 },
613 .max = .{ .major = 3, .minor = 0, .patch = 0 },
614 },
615 },
616 .opengl => .{
617 .semver = .{
618 .min = .{ .major = 4, .minor = 5, .patch = 0 },
619 .max = .{ .major = 4, .minor = 6, .patch = 0 },
620 },
621 },
622 .vulkan => .{
623 .semver = .{
624 .min = .{ .major = 1, .minor = 2, .patch = 0 },
625 .max = .{ .major = 1, .minor = 3, .patch = 0 },
626 },
627 },
535 };628 };
536 }629 }
537 };630 };
lib/std/Target/Query.zig+52-7
...@@ -25,10 +25,14 @@ os_version_min: ?OsVersion = null,...@@ -25,10 +25,14 @@ os_version_min: ?OsVersion = null,
25/// When `os_tag` is native, `null` means equal to the native OS version.25/// When `os_tag` is native, `null` means equal to the native OS version.
26os_version_max: ?OsVersion = null,26os_version_max: ?OsVersion = null,
2727
28/// `null` means default when cross compiling, or native when os_tag is native.28/// `null` means default when cross compiling, or native when `os_tag` is native.
29/// If `isGnuLibC()` is `false`, this must be `null` and is ignored.29/// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
30glibc_version: ?SemanticVersion = null,30glibc_version: ?SemanticVersion = null,
3131
32/// `null` means default when cross compiling, or native when `os_tag` is native.
33/// If `isAndroid()` is `false`, this must be `null` and is ignored.
34android_api_level: ?u32 = null,
35
32/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.36/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
33abi: ?Target.Abi = null,37abi: ?Target.Abi = null,
3438
...@@ -98,10 +102,8 @@ pub fn fromTarget(target: Target) Query {...@@ -98,10 +102,8 @@ pub fn fromTarget(target: Target) Query {
98 .os_version_min = undefined,102 .os_version_min = undefined,
99 .os_version_max = undefined,103 .os_version_max = undefined,
100 .abi = target.abi,104 .abi = target.abi,
101 .glibc_version = if (target.isGnuLibC())105 .glibc_version = if (target.isGnuLibC()) target.os.version_range.linux.glibc else null,
102 target.os.version_range.linux.glibc106 .android_api_level = if (target.abi.isAndroid()) target.os.version_range.linux.android else null,
103 else
104 null,
105 };107 };
106 result.updateOsVersionRange(target.os);108 result.updateOsVersionRange(target.os);
107109
...@@ -147,7 +149,7 @@ pub const ParseOptions = struct {...@@ -147,7 +149,7 @@ pub const ParseOptions = struct {
147 /// The fields are, respectively:149 /// The fields are, respectively:
148 /// * CPU Architecture150 /// * CPU Architecture
149 /// * Operating System (and optional version range)151 /// * Operating System (and optional version range)
150 /// * C ABI (optional, with optional glibc version)152 /// * C ABI (optional, with optional glibc version or Android API level)
151 /// The string "native" can be used for CPU architecture as well as Operating System.153 /// The string "native" can be used for CPU architecture as well as Operating System.
152 /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted.154 /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted.
153 arch_os_abi: []const u8 = "native",155 arch_os_abi: []const u8 = "native",
...@@ -234,6 +236,11 @@ pub fn parse(args: ParseOptions) !Query {...@@ -234,6 +236,11 @@ pub fn parse(args: ParseOptions) !Query {
234 error.Overflow => return error.InvalidAbiVersion,236 error.Overflow => return error.InvalidAbiVersion,
235 error.InvalidVersion => return error.InvalidAbiVersion,237 error.InvalidVersion => return error.InvalidAbiVersion,
236 };238 };
239 } else if (abi.isAndroid()) {
240 result.android_api_level = std.fmt.parseUnsigned(u32, abi_ver_text, 10) catch |err| switch (err) {
241 error.InvalidCharacter => return error.InvalidVersion,
242 error.Overflow => return error.Overflow,
243 };
237 } else {244 } else {
238 return error.InvalidAbiVersion;245 return error.InvalidAbiVersion;
239 }246 }
...@@ -355,7 +362,7 @@ pub fn isNativeCpu(self: Query) bool {...@@ -355,7 +362,7 @@ pub fn isNativeCpu(self: Query) bool {
355362
356pub fn isNativeOs(self: Query) bool {363pub fn isNativeOs(self: Query) bool {
357 return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and364 return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and
358 self.dynamic_linker.get() == null and self.glibc_version == null;365 self.dynamic_linker.get() == null and self.glibc_version == null and self.android_api_level == null;
359}366}
360367
361pub fn isNativeAbi(self: Query) bool {368pub fn isNativeAbi(self: Query) bool {
...@@ -439,6 +446,13 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {...@@ -439,6 +446,13 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
439 result.appendSliceAssumeCapacity(name);446 result.appendSliceAssumeCapacity(name);
440 result.appendAssumeCapacity('.');447 result.appendAssumeCapacity('.');
441 try formatVersion(v, result.writer());448 try formatVersion(v, result.writer());
449 } else if (self.android_api_level) |lvl| {
450 const name = if (self.abi) |abi| @tagName(abi) else "android";
451 try result.ensureUnusedCapacity(name.len + 2);
452 result.appendAssumeCapacity('-');
453 result.appendSliceAssumeCapacity(name);
454 result.appendAssumeCapacity('.');
455 try result.writer().print("{d}", .{lvl});
442 } else if (self.abi) |abi| {456 } else if (self.abi) |abi| {
443 const name = @tagName(abi);457 const name = @tagName(abi);
444 try result.ensureUnusedCapacity(name.len + 1);458 try result.ensureUnusedCapacity(name.len + 1);
...@@ -561,6 +575,7 @@ pub fn eql(a: Query, b: Query) bool {...@@ -561,6 +575,7 @@ pub fn eql(a: Query, b: Query) bool {
561 if (!OsVersion.eqlOpt(a.os_version_min, b.os_version_min)) return false;575 if (!OsVersion.eqlOpt(a.os_version_min, b.os_version_min)) return false;
562 if (!OsVersion.eqlOpt(a.os_version_max, b.os_version_max)) return false;576 if (!OsVersion.eqlOpt(a.os_version_max, b.os_version_max)) return false;
563 if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false;577 if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false;
578 if (a.android_api_level != b.android_api_level) return false;
564 if (a.abi != b.abi) return false;579 if (a.abi != b.abi) return false;
565 if (!a.dynamic_linker.eql(b.dynamic_linker)) return false;580 if (!a.dynamic_linker.eql(b.dynamic_linker)) return false;
566 if (a.ofmt != b.ofmt) return false;581 if (a.ofmt != b.ofmt) return false;
...@@ -592,6 +607,15 @@ test parse {...@@ -592,6 +607,15 @@ test parse {
592607
593 try std.testing.expectEqualSlices(u8, "native-native-gnu.2.1.1", text);608 try std.testing.expectEqualSlices(u8, "native-native-gnu.2.1.1", text);
594 }609 }
610 if (builtin.target.abi.isAndroid()) {
611 var query = try Query.parse(.{});
612 query.android_api_level = 30;
613
614 const text = try query.zigTriple(std.testing.allocator);
615 defer std.testing.allocator.free(text);
616
617 try std.testing.expectEqualSlices(u8, "native-native-android.30", text);
618 }
595 {619 {
596 const query = try Query.parse(.{620 const query = try Query.parse(.{
597 .arch_os_abi = "aarch64-linux",621 .arch_os_abi = "aarch64-linux",
...@@ -677,4 +701,25 @@ test parse {...@@ -677,4 +701,25 @@ test parse {
677 defer std.testing.allocator.free(text);701 defer std.testing.allocator.free(text);
678 try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text);702 try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text);
679 }703 }
704 {
705 const query = try Query.parse(.{
706 .arch_os_abi = "aarch64-linux.3.10...4.4.1-android.30",
707 });
708 const target = try std.zig.system.resolveTargetQuery(query);
709
710 try std.testing.expect(target.cpu.arch == .aarch64);
711 try std.testing.expect(target.os.tag == .linux);
712 try std.testing.expect(target.os.version_range.linux.range.min.major == 3);
713 try std.testing.expect(target.os.version_range.linux.range.min.minor == 10);
714 try std.testing.expect(target.os.version_range.linux.range.min.patch == 0);
715 try std.testing.expect(target.os.version_range.linux.range.max.major == 4);
716 try std.testing.expect(target.os.version_range.linux.range.max.minor == 4);
717 try std.testing.expect(target.os.version_range.linux.range.max.patch == 1);
718 try std.testing.expect(target.os.version_range.linux.android == 30);
719 try std.testing.expect(target.abi == .android);
720
721 const text = try query.zigTriple(std.testing.allocator);
722 defer std.testing.allocator.free(text);
723 try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-android.30", text);
724 }
680}725}
lib/std/c.zig+11-7
...@@ -44,22 +44,26 @@ comptime {...@@ -44,22 +44,26 @@ comptime {
44 }44 }
45}45}
4646
47/// If not linking libc, returns false.47/// * If not linking libc, returns `false`.
48/// If linking musl libc, returns true.48/// * If linking musl libc, returns `true`.
49/// If linking gnu libc (glibc), returns true if the target version is greater49/// * If linking GNU libc (glibc), returns `true` if the target version is greater than or equal to
50/// than or equal to `glibc_version`.50/// `version`.
51/// If linking a libc other than these, returns `false`.51/// * If linking Android libc (bionic), returns `true` if the target API level is greater than or
52pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool {52/// equal to `version.major`, ignoring other components.
53/// * If linking a libc other than these, returns `false`.
54pub inline fn versionCheck(comptime version: std.SemanticVersion) bool {
53 return comptime blk: {55 return comptime blk: {
54 if (!builtin.link_libc) break :blk false;56 if (!builtin.link_libc) break :blk false;
55 if (native_abi.isMusl()) break :blk true;57 if (native_abi.isMusl()) break :blk true;
56 if (builtin.target.isGnuLibC()) {58 if (builtin.target.isGnuLibC()) {
57 const ver = builtin.os.version_range.linux.glibc;59 const ver = builtin.os.version_range.linux.glibc;
58 const order = ver.order(glibc_version);60 const order = ver.order(version);
59 break :blk switch (order) {61 break :blk switch (order) {
60 .gt, .eq => true,62 .gt, .eq => true,
61 .lt => false,63 .lt => false,
62 };64 };
65 } else if (builtin.abi.isAndroid()) {
66 break :blk builtin.os.version_range.linux.android >= version.major;
63 } else {67 } else {
64 break :blk false;68 break :blk false;
65 }69 }
lib/std/zig/system.zig+4
...@@ -331,6 +331,10 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {...@@ -331,6 +331,10 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
331 os.version_range.linux.glibc = glibc;331 os.version_range.linux.glibc = glibc;
332 }332 }
333333
334 if (query.android_api_level) |android| {
335 os.version_range.linux.android = android;
336 }
337
334 // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the338 // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the
335 // native CPU architecture as being different than the current target), we use this:339 // native CPU architecture as being different than the current target), we use this:
336 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;340 const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;
src/Builtin.zig+3
...@@ -124,6 +124,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -124,6 +124,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
124 \\ .minor = {},124 \\ .minor = {},
125 \\ .patch = {},125 \\ .patch = {},
126 \\ }},126 \\ }},
127 \\ .android = {},
127 \\ }}}},128 \\ }}}},
128 \\129 \\
129 , .{130 , .{
...@@ -138,6 +139,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {...@@ -138,6 +139,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
138 linux.glibc.major,139 linux.glibc.major,
139 linux.glibc.minor,140 linux.glibc.minor,
140 linux.glibc.patch,141 linux.glibc.patch,
142
143 linux.android,
141 }),144 }),
142 .windows => |windows| try buffer.writer().print(145 .windows => |windows| try buffer.writer().print(
143 \\ .windows = .{{146 \\ .windows = .{{
src/codegen/llvm.zig+52-13
...@@ -164,14 +164,34 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {...@@ -164,14 +164,34 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
164 };164 };
165165
166 if (llvm_sub_arch) |sub| try llvm_triple.appendSlice(sub);166 if (llvm_sub_arch) |sub| try llvm_triple.appendSlice(sub);
167 try llvm_triple.append('-');
167168
168 // Unlike CPU backends, GPU backends actually care about the vendor tag.169 try llvm_triple.appendSlice(switch (target.os.tag) {
169 try llvm_triple.appendSlice(switch (target.cpu.arch) {170 .aix,
170 .amdgcn => if (target.os.tag == .mesa3d) "-mesa-" else "-amd-",171 .zos,
171 .nvptx, .nvptx64 => "-nvidia-",172 => "ibm",
172 .spirv64 => if (target.os.tag == .amdhsa) "-amd-" else "-unknown-",173 .bridgeos,
173 else => "-unknown-",174 .driverkit,
175 .ios,
176 .macos,
177 .tvos,
178 .visionos,
179 .watchos,
180 => "apple",
181 .ps4,
182 .ps5,
183 => "scei",
184 .amdhsa,
185 .amdpal,
186 => "amd",
187 .cuda,
188 .nvcl,
189 => "nvidia",
190 .mesa3d,
191 => "mesa",
192 else => "unknown",
174 });193 });
194 try llvm_triple.append('-');
175195
176 const llvm_os = switch (target.os.tag) {196 const llvm_os = switch (target.os.tag) {
177 .freestanding => "unknown",197 .freestanding => "unknown",
...@@ -219,13 +239,20 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {...@@ -219,13 +239,20 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
219 };239 };
220 try llvm_triple.appendSlice(llvm_os);240 try llvm_triple.appendSlice(llvm_os);
221241
222 if (target.os.tag.isDarwin()) {242 switch (target.os.versionRange()) {
223 const min_version = target.os.version_range.semver.min;243 .none,
224 try llvm_triple.writer().print("{d}.{d}.{d}", .{244 .windows,
225 min_version.major,245 => {},
226 min_version.minor,246 .semver => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
227 min_version.patch,247 ver.min.major,
228 });248 ver.min.minor,
249 ver.min.patch,
250 }),
251 .linux => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{
252 ver.range.min.major,
253 ver.range.min.minor,
254 ver.range.min.patch,
255 }),
229 }256 }
230 try llvm_triple.append('-');257 try llvm_triple.append('-');
231258
...@@ -259,6 +286,18 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {...@@ -259,6 +286,18 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
259 };286 };
260 try llvm_triple.appendSlice(llvm_abi);287 try llvm_triple.appendSlice(llvm_abi);
261288
289 switch (target.os.versionRange()) {
290 .none,
291 .semver,
292 .windows,
293 => {},
294 .linux => |ver| if (target.abi.isGnu()) try llvm_triple.writer().print("{d}.{d}.{d}", .{
295 ver.glibc.major,
296 ver.glibc.minor,
297 ver.glibc.patch,
298 }) else if (target.abi.isAndroid()) try llvm_triple.writer().print("{d}", .{ver.android}),
299 }
300
262 return llvm_triple.toOwnedSlice();301 return llvm_triple.toOwnedSlice();
263}302}
264303