From af48ce63795ca030a5eebd163af68746b8de2f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 30 Oct 2024 06:38:44 +0100 Subject: [PATCH 1/7] std.Target: Sort some OS switches according to the Os enum. --- lib/std/Target.zig | 214 +++++++++++++++++++++++++-------------------- 1 file changed, 118 insertions(+), 96 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 49111b761b23..8023418f02e2 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -160,48 +160,58 @@ pub const Os = struct { pub inline fn versionRangeTag(tag: Tag) @typeInfo(TaggedVersionRange).@"union".tag_type.? { return switch (tag) { .freestanding, + .other, + + .contiki, + .elfiamcu, .fuchsia, - .ps3, - .zos, + .hermit, + + .aix, .haiku, + .hurd, + .plan9, .rtems, - .aix, - .cuda, - .nvcl, - .amdhsa, + .serenity, + .zos, + + // This should use semver once we determine the version history. + .bridgeos, + + .illumos, + + .uefi, + + .ps3, .ps4, .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, + .emscripten, - .uefi, + + .amdhsa, + .amdpal, + .cuda, + .mesa3d, + .nvcl, .opencl, // TODO: OpenCL versions .opengl, // TODO: GLSL versions .vulkan, - .plan9, - .illumos, - .serenity, - .other, => .none, - // This should use semver once we determine the version history. - .bridgeos => .none, + .dragonfly, + .freebsd, + .netbsd, + .openbsd, .driverkit, - .freebsd, .macos, .ios, .tvos, - .watchos, .visionos, - .netbsd, - .openbsd, - .dragonfly, + .watchos, + .solaris, + .wasi, => .semver, @@ -391,41 +401,93 @@ pub const Os = struct { pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange { return switch (tag) { .freestanding, + .other, + + .contiki, + .elfiamcu, .fuchsia, - .ps3, - .zos, + .hermit, + + .aix, .haiku, + .hurd, + .plan9, .rtems, - .aix, - .cuda, - .nvcl, - .amdhsa, + .serenity, + .zos, + + // This should use semver once we determine the version history. + .bridgeos, + + .illumos, + + .uefi, + + .ps3, .ps4, .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, + .emscripten, - .uefi, + + .amdhsa, + .amdpal, + .cuda, + .mesa3d, + .nvcl, .opencl, // TODO: OpenCL versions .opengl, // TODO: GLSL versions .vulkan, - .plan9, - .illumos, - .serenity, - .bridgeos, - .other, => .{ .none = {} }, + .linux => .{ + .linux = .{ + .range = .{ + .min = .{ .major = 4, .minor = 19, .patch = 0 }, + .max = .{ .major = 6, .minor = 10, .patch = 3 }, + }, + .glibc = blk: { + const default_min: std.SemanticVersion = .{ .major = 2, .minor = 28, .patch = 0 }; + + for (std.zig.target.available_libcs) |libc| { + // We don't know the ABI here. We can get away with not checking it + // for now, but that may not always remain true. + if (libc.os != tag or libc.arch != arch) continue; + + if (libc.glibc_min) |min| { + if (min.order(default_min) == .gt) break :blk min; + } + } + + break :blk default_min; + }, + }, + }, + + .dragonfly => .{ + .semver = .{ + .min = .{ .major = 5, .minor = 8, .patch = 0 }, + .max = .{ .major = 6, .minor = 4, .patch = 0 }, + }, + }, .freebsd => .{ - .semver = std.SemanticVersion.Range{ + .semver = .{ .min = .{ .major = 12, .minor = 0, .patch = 0 }, .max = .{ .major = 14, .minor = 0, .patch = 0 }, }, }, + .netbsd => .{ + .semver = .{ + .min = .{ .major = 8, .minor = 0, .patch = 0 }, + .max = .{ .major = 10, .minor = 0, .patch = 0 }, + }, + }, + .openbsd => .{ + .semver = .{ + .min = .{ .major = 7, .minor = 3, .patch = 0 }, + .max = .{ .major = 7, .minor = 5, .patch = 0 }, + }, + }, + .driverkit => .{ .semver = .{ .min = .{ .major = 19, .minor = 0, .patch = 0 }, @@ -433,13 +495,13 @@ pub const Os = struct { }, }, .macos => switch (arch) { - .aarch64 => VersionRange{ + .aarch64 => .{ .semver = .{ .min = .{ .major = 11, .minor = 7, .patch = 1 }, .max = .{ .major = 14, .minor = 6, .patch = 1 }, }, }, - .x86_64 => VersionRange{ + .x86_64 => .{ .semver = .{ .min = .{ .major = 11, .minor = 7, .patch = 1 }, .max = .{ .major = 14, .minor = 6, .patch = 1 }, @@ -453,12 +515,6 @@ pub const Os = struct { .max = .{ .major = 17, .minor = 6, .patch = 1 }, }, }, - .watchos => .{ - .semver = .{ - .min = .{ .major = 6, .minor = 0, .patch = 0 }, - .max = .{ .major = 10, .minor = 6, .patch = 0 }, - }, - }, .tvos => .{ .semver = .{ .min = .{ .major = 13, .minor = 0, .patch = 0 }, @@ -471,60 +527,19 @@ pub const Os = struct { .max = .{ .major = 1, .minor = 3, .patch = 0 }, }, }, - .netbsd => .{ - .semver = .{ - .min = .{ .major = 8, .minor = 0, .patch = 0 }, - .max = .{ .major = 10, .minor = 0, .patch = 0 }, - }, - }, - .openbsd => .{ - .semver = .{ - .min = .{ .major = 7, .minor = 3, .patch = 0 }, - .max = .{ .major = 7, .minor = 5, .patch = 0 }, - }, - }, - .dragonfly => .{ + .watchos => .{ .semver = .{ - .min = .{ .major = 5, .minor = 8, .patch = 0 }, - .max = .{ .major = 6, .minor = 4, .patch = 0 }, + .min = .{ .major = 6, .minor = 0, .patch = 0 }, + .max = .{ .major = 10, .minor = 6, .patch = 0 }, }, }, + .solaris => .{ .semver = .{ .min = .{ .major = 11, .minor = 0, .patch = 0 }, .max = .{ .major = 11, .minor = 4, .patch = 0 }, }, }, - .wasi => .{ - .semver = .{ - .min = .{ .major = 0, .minor = 1, .patch = 0 }, - .max = .{ .major = 0, .minor = 1, .patch = 0 }, - }, - }, - - .linux => .{ - .linux = .{ - .range = .{ - .min = .{ .major = 4, .minor = 19, .patch = 0 }, - .max = .{ .major = 6, .minor = 10, .patch = 3 }, - }, - .glibc = blk: { - const default_min: std.SemanticVersion = .{ .major = 2, .minor = 28, .patch = 0 }; - - for (std.zig.target.available_libcs) |libc| { - // We don't know the ABI here. We can get away with not checking it - // for now, but that may not always remain true. - if (libc.os != tag or libc.arch != arch) continue; - - if (libc.glibc_min) |min| { - if (min.order(default_min) == .gt) break :blk min; - } - } - - break :blk default_min; - }, - }, - }, .windows => .{ .windows = .{ @@ -532,6 +547,13 @@ pub const Os = struct { .max = WindowsVersion.latest, }, }, + + .wasi => .{ + .semver = .{ + .min = .{ .major = 0, .minor = 1, .patch = 0 }, + .max = .{ .major = 0, .minor = 1, .patch = 0 }, + }, + }, }; } }; From ace26004a3a3cd6ac41e10e7e1fca2922952bf4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 30 Oct 2024 07:16:09 +0100 Subject: [PATCH 2/7] std.Target: Remove arch-specific handling for macos in Os.VersionRange.default(). The minimum is now the same for both aarch64 and x86_64. --- lib/std/Target.zig | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 8023418f02e2..79207f956048 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -494,20 +494,11 @@ pub const Os = struct { .max = .{ .major = 24, .minor = 0, .patch = 0 }, }, }, - .macos => switch (arch) { - .aarch64 => .{ - .semver = .{ - .min = .{ .major = 11, .minor = 7, .patch = 1 }, - .max = .{ .major = 14, .minor = 6, .patch = 1 }, - }, - }, - .x86_64 => .{ - .semver = .{ - .min = .{ .major = 11, .minor = 7, .patch = 1 }, - .max = .{ .major = 14, .minor = 6, .patch = 1 }, - }, + .macos => .{ + .semver = .{ + .min = .{ .major = 11, .minor = 7, .patch = 1 }, + .max = .{ .major = 14, .minor = 6, .patch = 1 }, }, - else => unreachable, }, .ios => .{ .semver = .{ From ed68083d8f286f7df7b33865b96e4decbda7b864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 30 Oct 2024 08:04:14 +0100 Subject: [PATCH 3/7] std.Target: Update known OS max versions. --- lib/std/Target.zig | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 79207f956048..96c296de4c80 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -267,10 +267,11 @@ pub const Os = struct { win11_zn = 0x0A00000E, //aka win11_21h2 win11_ga = 0x0A00000F, //aka win11_22h2 win11_ge = 0x0A000010, //aka win11_23h2 + win11_dt = 0x0A000011, //aka win11_24h2 _, /// Latest Windows version that the Zig Standard Library is aware of - pub const latest = WindowsVersion.win11_ge; + pub const latest = WindowsVersion.win11_dt; /// Compared against build numbers reported by the runtime to distinguish win10 versions, /// where 0x0A000000 + index corresponds to the WindowsVersion u32 value. @@ -292,6 +293,7 @@ pub const Os = struct { 22000, //win11_zn aka win11_21h2 22621, //win11_ga aka win11_22h2 22631, //win11_ge aka win11_23h2 + 26100, //win11_dt aka win11_24h2 }; /// Returns whether the first version `ver` is newer (greater) than or equal to the second version `ver`. @@ -443,7 +445,7 @@ pub const Os = struct { .linux = .{ .range = .{ .min = .{ .major = 4, .minor = 19, .patch = 0 }, - .max = .{ .major = 6, .minor = 10, .patch = 3 }, + .max = .{ .major = 6, .minor = 11, .patch = 5 }, }, .glibc = blk: { const default_min: std.SemanticVersion = .{ .major = 2, .minor = 28, .patch = 0 }; @@ -472,7 +474,7 @@ pub const Os = struct { .freebsd => .{ .semver = .{ .min = .{ .major = 12, .minor = 0, .patch = 0 }, - .max = .{ .major = 14, .minor = 0, .patch = 0 }, + .max = .{ .major = 14, .minor = 1, .patch = 0 }, }, }, .netbsd => .{ @@ -484,44 +486,44 @@ pub const Os = struct { .openbsd => .{ .semver = .{ .min = .{ .major = 7, .minor = 3, .patch = 0 }, - .max = .{ .major = 7, .minor = 5, .patch = 0 }, + .max = .{ .major = 7, .minor = 6, .patch = 0 }, }, }, .driverkit => .{ .semver = .{ .min = .{ .major = 19, .minor = 0, .patch = 0 }, - .max = .{ .major = 24, .minor = 0, .patch = 0 }, + .max = .{ .major = 24, .minor = 2, .patch = 0 }, }, }, .macos => .{ .semver = .{ .min = .{ .major = 11, .minor = 7, .patch = 1 }, - .max = .{ .major = 14, .minor = 6, .patch = 1 }, + .max = .{ .major = 15, .minor = 2, .patch = 0 }, }, }, .ios => .{ .semver = .{ .min = .{ .major = 12, .minor = 0, .patch = 0 }, - .max = .{ .major = 17, .minor = 6, .patch = 1 }, + .max = .{ .major = 18, .minor = 1, .patch = 0 }, }, }, .tvos => .{ .semver = .{ .min = .{ .major = 13, .minor = 0, .patch = 0 }, - .max = .{ .major = 17, .minor = 6, .patch = 0 }, + .max = .{ .major = 18, .minor = 1, .patch = 0 }, }, }, .visionos => .{ .semver = .{ .min = .{ .major = 1, .minor = 0, .patch = 0 }, - .max = .{ .major = 1, .minor = 3, .patch = 0 }, + .max = .{ .major = 2, .minor = 1, .patch = 0 }, }, }, .watchos => .{ .semver = .{ .min = .{ .major = 6, .minor = 0, .patch = 0 }, - .max = .{ .major = 10, .minor = 6, .patch = 0 }, + .max = .{ .major = 11, .minor = 1, .patch = 0 }, }, }, @@ -542,7 +544,7 @@ pub const Os = struct { .wasi => .{ .semver = .{ .min = .{ .major = 0, .minor = 1, .patch = 0 }, - .max = .{ .major = 0, .minor = 1, .patch = 0 }, + .max = .{ .major = 0, .minor = 2, .patch = 2 }, }, }, }; From f89982bf53d04d4f8e65a449c261eff2a8539169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 30 Oct 2024 09:44:02 +0100 Subject: [PATCH 4/7] std.Target: Add semver min/max versions for a bunch of OSs. --- lib/std/Target.zig | 139 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 32 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 96c296de4c80..5840f55c9e98 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -162,42 +162,35 @@ pub const Os = struct { .freestanding, .other, - .contiki, .elfiamcu, - .fuchsia, - .hermit, - .aix, .haiku, - .hurd, .plan9, - .rtems, .serenity, - .zos, // This should use semver once we determine the version history. .bridgeos, .illumos, - .uefi, - .ps3, .ps4, .ps5, .emscripten, - .amdhsa, - .amdpal, - .cuda, .mesa3d, - .nvcl, - .opencl, // TODO: OpenCL versions - .opengl, // TODO: GLSL versions - .vulkan, => .none, + .contiki, + .fuchsia, + .hermit, + + .aix, + .hurd, + .rtems, + .zos, + .dragonfly, .freebsd, .netbsd, @@ -212,7 +205,17 @@ pub const Os = struct { .solaris, + .uefi, + .wasi, + + .amdhsa, + .amdpal, + .cuda, + .nvcl, + .opencl, + .opengl, + .vulkan, => .semver, .linux => .linux, @@ -405,42 +408,57 @@ pub const Os = struct { .freestanding, .other, - .contiki, .elfiamcu, - .fuchsia, - .hermit, - .aix, .haiku, - .hurd, .plan9, - .rtems, .serenity, - .zos, // This should use semver once we determine the version history. .bridgeos, .illumos, - .uefi, - .ps3, .ps4, .ps5, .emscripten, - .amdhsa, - .amdpal, - .cuda, .mesa3d, - .nvcl, - .opencl, // TODO: OpenCL versions - .opengl, // TODO: GLSL versions - .vulkan, => .{ .none = {} }, + .contiki => .{ + .semver = .{ + .min = .{ .major = 4, .minor = 0, .patch = 0 }, + .max = .{ .major = 4, .minor = 9, .patch = 0 }, + }, + }, + .fuchsia => .{ + .semver = .{ + .min = .{ .major = 1, .minor = 1, .patch = 0 }, + .max = .{ .major = 20, .minor = 1, .patch = 0 }, + }, + }, + .hermit => .{ + .semver = .{ + .min = .{ .major = 0, .minor = 4, .patch = 0 }, + .max = .{ .major = 0, .minor = 8, .patch = 0 }, + }, + }, + + .aix => .{ + .semver = .{ + .min = .{ .major = 7, .minor = 2, .patch = 5 }, + .max = .{ .major = 7, .minor = 3, .patch = 2 }, + }, + }, + .hurd => .{ + .semver = .{ + .min = .{ .major = 0, .minor = 9, .patch = 0 }, + .max = .{ .major = 0, .minor = 9, .patch = 0 }, + }, + }, .linux => .{ .linux = .{ .range = .{ @@ -464,6 +482,18 @@ pub const Os = struct { }, }, }, + .rtems => .{ + .semver = .{ + .min = .{ .major = 5, .minor = 1, .patch = 0 }, + .max = .{ .major = 5, .minor = 3, .patch = 0 }, + }, + }, + .zos => .{ + .semver = .{ + .min = .{ .major = 2, .minor = 5, .patch = 0 }, + .max = .{ .major = 3, .minor = 1, .patch = 0 }, + }, + }, .dragonfly => .{ .semver = .{ @@ -540,6 +570,12 @@ pub const Os = struct { .max = WindowsVersion.latest, }, }, + .uefi => .{ + .semver = .{ + .min = .{ .major = 2, .minor = 0, .patch = 0 }, + .max = .{ .major = 2, .minor = 9, .patch = 0 }, + }, + }, .wasi => .{ .semver = .{ @@ -547,6 +583,45 @@ pub const Os = struct { .max = .{ .major = 0, .minor = 2, .patch = 2 }, }, }, + + .amdhsa => .{ + .semver = .{ + .min = .{ .major = 5, .minor = 0, .patch = 2 }, + .max = .{ .major = 6, .minor = 2, .patch = 2 }, + }, + }, + .amdpal => .{ + .semver = .{ + .min = .{ .major = 1, .minor = 1, .patch = 0 }, + .max = .{ .major = 3, .minor = 5, .patch = 0 }, + }, + }, + .cuda => .{ + .semver = .{ + .min = .{ .major = 11, .minor = 0, .patch = 1 }, + .max = .{ .major = 12, .minor = 6, .patch = 1 }, + }, + }, + .nvcl, + .opencl, + => .{ + .semver = .{ + .min = .{ .major = 2, .minor = 2, .patch = 0 }, + .max = .{ .major = 3, .minor = 0, .patch = 0 }, + }, + }, + .opengl => .{ + .semver = .{ + .min = .{ .major = 4, .minor = 5, .patch = 0 }, + .max = .{ .major = 4, .minor = 6, .patch = 0 }, + }, + }, + .vulkan => .{ + .semver = .{ + .min = .{ .major = 1, .minor = 2, .patch = 0 }, + .max = .{ .major = 1, .minor = 3, .patch = 0 }, + }, + }, }; } }; From 60c0f522d96ed455545552b567af6a6c345595a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 30 Oct 2024 06:11:06 +0100 Subject: [PATCH 5/7] llvm: Set vendor type in LLVM target triple for more OSs. Annoyingly, LLVM and Clang have various checks throughout that depend on these vendor types being set. --- src/codegen/llvm.zig | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index cec888fba955..682b96d31a34 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -164,14 +164,34 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { }; if (llvm_sub_arch) |sub| try llvm_triple.appendSlice(sub); + try llvm_triple.append('-'); - // Unlike CPU backends, GPU backends actually care about the vendor tag. - try llvm_triple.appendSlice(switch (target.cpu.arch) { - .amdgcn => if (target.os.tag == .mesa3d) "-mesa-" else "-amd-", - .nvptx, .nvptx64 => "-nvidia-", - .spirv64 => if (target.os.tag == .amdhsa) "-amd-" else "-unknown-", - else => "-unknown-", + try llvm_triple.appendSlice(switch (target.os.tag) { + .aix, + .zos, + => "ibm", + .bridgeos, + .driverkit, + .ios, + .macos, + .tvos, + .visionos, + .watchos, + => "apple", + .ps4, + .ps5, + => "scei", + .amdhsa, + .amdpal, + => "amd", + .cuda, + .nvcl, + => "nvidia", + .mesa3d, + => "mesa", + else => "unknown", }); + try llvm_triple.append('-'); const llvm_os = switch (target.os.tag) { .freestanding => "unknown", From c5395f7cd948f02ada095515b9d6824cbbac4f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 30 Oct 2024 11:05:18 +0100 Subject: [PATCH 6/7] llvm: Set OS min version and libc version in ~all cases. Except Windows, because that just doesn't really fit into LLVM's target triple format currently. --- src/codegen/llvm.zig | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 682b96d31a34..2dcb1c390790 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -239,13 +239,20 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { }; try llvm_triple.appendSlice(llvm_os); - if (target.os.tag.isDarwin()) { - const min_version = target.os.version_range.semver.min; - try llvm_triple.writer().print("{d}.{d}.{d}", .{ - min_version.major, - min_version.minor, - min_version.patch, - }); + switch (target.os.versionRange()) { + .none, + .windows, + => {}, + .semver => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{ + ver.min.major, + ver.min.minor, + ver.min.patch, + }), + .linux => |ver| try llvm_triple.writer().print("{d}.{d}.{d}", .{ + ver.range.min.major, + ver.range.min.minor, + ver.range.min.patch, + }), } try llvm_triple.append('-'); @@ -279,6 +286,19 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { }; try llvm_triple.appendSlice(llvm_abi); + // This should eventually handle the Android API level too. + switch (target.os.versionRange()) { + .none, + .semver, + .windows, + => {}, + .linux => |ver| if (target.abi.isGnu()) try llvm_triple.writer().print("{d}.{d}.{d}", .{ + ver.glibc.major, + ver.glibc.minor, + ver.glibc.patch, + }), + } + return llvm_triple.toOwnedSlice(); } From 3c1ccbdf3990b6d802cdc8a0db7c11eaac0960e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 30 Oct 2024 21:57:44 +0100 Subject: [PATCH 7/7] std.Target: Add support for specifying Android API level. --- lib/std/Build/Cache.zig | 1 + lib/std/Target.zig | 3 ++ lib/std/Target/Query.zig | 59 +++++++++++++++++++++++++++++++++++----- lib/std/c.zig | 18 +++++++----- lib/std/zig/system.zig | 4 +++ src/Builtin.zig | 3 ++ src/codegen/llvm.zig | 3 +- 7 files changed, 75 insertions(+), 16 deletions(-) diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index 7f8a6d3159bc..16ecf3c0b0e5 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -221,6 +221,7 @@ pub const HashHelper = struct { hh.add(linux.range.min); hh.add(linux.range.max); hh.add(linux.glibc); + hh.add(linux.android); }, .windows => |windows| { hh.add(windows.min); diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 5840f55c9e98..470009592e94 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -359,6 +359,8 @@ pub const Os = struct { pub const LinuxVersionRange = struct { range: std.SemanticVersion.Range, glibc: std.SemanticVersion, + /// Android API level. + android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated. pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool { return range.range.includesVersion(ver); @@ -480,6 +482,7 @@ pub const Os = struct { break :blk default_min; }, + .android = 14, }, }, .rtems => .{ diff --git a/lib/std/Target/Query.zig b/lib/std/Target/Query.zig index 26001f140860..e50759a347c3 100644 --- a/lib/std/Target/Query.zig +++ b/lib/std/Target/Query.zig @@ -25,10 +25,14 @@ os_version_min: ?OsVersion = null, /// When `os_tag` is native, `null` means equal to the native OS version. os_version_max: ?OsVersion = null, -/// `null` means default when cross compiling, or native when os_tag is native. +/// `null` means default when cross compiling, or native when `os_tag` is native. /// If `isGnuLibC()` is `false`, this must be `null` and is ignored. glibc_version: ?SemanticVersion = null, +/// `null` means default when cross compiling, or native when `os_tag` is native. +/// If `isAndroid()` is `false`, this must be `null` and is ignored. +android_api_level: ?u32 = null, + /// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI. abi: ?Target.Abi = null, @@ -98,10 +102,8 @@ pub fn fromTarget(target: Target) Query { .os_version_min = undefined, .os_version_max = undefined, .abi = target.abi, - .glibc_version = if (target.isGnuLibC()) - target.os.version_range.linux.glibc - else - null, + .glibc_version = if (target.isGnuLibC()) target.os.version_range.linux.glibc else null, + .android_api_level = if (target.abi.isAndroid()) target.os.version_range.linux.android else null, }; result.updateOsVersionRange(target.os); @@ -147,7 +149,7 @@ pub const ParseOptions = struct { /// The fields are, respectively: /// * CPU Architecture /// * Operating System (and optional version range) - /// * C ABI (optional, with optional glibc version) + /// * C ABI (optional, with optional glibc version or Android API level) /// The string "native" can be used for CPU architecture as well as Operating System. /// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted. arch_os_abi: []const u8 = "native", @@ -234,6 +236,11 @@ pub fn parse(args: ParseOptions) !Query { error.Overflow => return error.InvalidAbiVersion, error.InvalidVersion => return error.InvalidAbiVersion, }; + } else if (abi.isAndroid()) { + result.android_api_level = std.fmt.parseUnsigned(u32, abi_ver_text, 10) catch |err| switch (err) { + error.InvalidCharacter => return error.InvalidVersion, + error.Overflow => return error.Overflow, + }; } else { return error.InvalidAbiVersion; } @@ -355,7 +362,7 @@ pub fn isNativeCpu(self: Query) bool { pub fn isNativeOs(self: Query) bool { return self.os_tag == null and self.os_version_min == null and self.os_version_max == null and - self.dynamic_linker.get() == null and self.glibc_version == null; + self.dynamic_linker.get() == null and self.glibc_version == null and self.android_api_level == null; } pub fn isNativeAbi(self: Query) bool { @@ -439,6 +446,13 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { result.appendSliceAssumeCapacity(name); result.appendAssumeCapacity('.'); try formatVersion(v, result.writer()); + } else if (self.android_api_level) |lvl| { + const name = if (self.abi) |abi| @tagName(abi) else "android"; + try result.ensureUnusedCapacity(name.len + 2); + result.appendAssumeCapacity('-'); + result.appendSliceAssumeCapacity(name); + result.appendAssumeCapacity('.'); + try result.writer().print("{d}", .{lvl}); } else if (self.abi) |abi| { const name = @tagName(abi); try result.ensureUnusedCapacity(name.len + 1); @@ -561,6 +575,7 @@ pub fn eql(a: Query, b: Query) bool { if (!OsVersion.eqlOpt(a.os_version_min, b.os_version_min)) return false; if (!OsVersion.eqlOpt(a.os_version_max, b.os_version_max)) return false; if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false; + if (a.android_api_level != b.android_api_level) return false; if (a.abi != b.abi) return false; if (!a.dynamic_linker.eql(b.dynamic_linker)) return false; if (a.ofmt != b.ofmt) return false; @@ -592,6 +607,15 @@ test parse { try std.testing.expectEqualSlices(u8, "native-native-gnu.2.1.1", text); } + if (builtin.target.abi.isAndroid()) { + var query = try Query.parse(.{}); + query.android_api_level = 30; + + const text = try query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + + try std.testing.expectEqualSlices(u8, "native-native-android.30", text); + } { const query = try Query.parse(.{ .arch_os_abi = "aarch64-linux", @@ -677,4 +701,25 @@ test parse { defer std.testing.allocator.free(text); try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text); } + { + const query = try Query.parse(.{ + .arch_os_abi = "aarch64-linux.3.10...4.4.1-android.30", + }); + const target = try std.zig.system.resolveTargetQuery(query); + + try std.testing.expect(target.cpu.arch == .aarch64); + try std.testing.expect(target.os.tag == .linux); + try std.testing.expect(target.os.version_range.linux.range.min.major == 3); + try std.testing.expect(target.os.version_range.linux.range.min.minor == 10); + try std.testing.expect(target.os.version_range.linux.range.min.patch == 0); + try std.testing.expect(target.os.version_range.linux.range.max.major == 4); + try std.testing.expect(target.os.version_range.linux.range.max.minor == 4); + try std.testing.expect(target.os.version_range.linux.range.max.patch == 1); + try std.testing.expect(target.os.version_range.linux.android == 30); + try std.testing.expect(target.abi == .android); + + const text = try query.zigTriple(std.testing.allocator); + defer std.testing.allocator.free(text); + try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-android.30", text); + } } diff --git a/lib/std/c.zig b/lib/std/c.zig index d28f5b0ac4b8..3d638487cbc6 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -44,22 +44,26 @@ comptime { } } -/// If not linking libc, returns false. -/// If linking musl libc, returns true. -/// If linking gnu libc (glibc), returns true if the target version is greater -/// than or equal to `glibc_version`. -/// If linking a libc other than these, returns `false`. -pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool { +/// * If not linking libc, returns `false`. +/// * If linking musl libc, returns `true`. +/// * If linking GNU libc (glibc), returns `true` if the target version is greater than or equal to +/// `version`. +/// * If linking Android libc (bionic), returns `true` if the target API level is greater than or +/// equal to `version.major`, ignoring other components. +/// * If linking a libc other than these, returns `false`. +pub inline fn versionCheck(comptime version: std.SemanticVersion) bool { return comptime blk: { if (!builtin.link_libc) break :blk false; if (native_abi.isMusl()) break :blk true; if (builtin.target.isGnuLibC()) { const ver = builtin.os.version_range.linux.glibc; - const order = ver.order(glibc_version); + const order = ver.order(version); break :blk switch (order) { .gt, .eq => true, .lt => false, }; + } else if (builtin.abi.isAndroid()) { + break :blk builtin.os.version_range.linux.android >= version.major; } else { break :blk false; } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index d1967877b377..448699a76fc7 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -331,6 +331,10 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { os.version_range.linux.glibc = glibc; } + if (query.android_api_level) |android| { + os.version_range.linux.android = android; + } + // Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the // native CPU architecture as being different than the current target), we use this: const cpu_arch = query.cpu_arch orelse builtin.cpu.arch; diff --git a/src/Builtin.zig b/src/Builtin.zig index 34b73f0e42eb..f3018d30235f 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -124,6 +124,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { \\ .minor = {}, \\ .patch = {}, \\ }}, + \\ .android = {}, \\ }}}}, \\ , .{ @@ -138,6 +139,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void { linux.glibc.major, linux.glibc.minor, linux.glibc.patch, + + linux.android, }), .windows => |windows| try buffer.writer().print( \\ .windows = .{{ diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2dcb1c390790..c5bfe6f0a995 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -286,7 +286,6 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { }; try llvm_triple.appendSlice(llvm_abi); - // This should eventually handle the Android API level too. switch (target.os.versionRange()) { .none, .semver, @@ -296,7 +295,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { ver.glibc.major, ver.glibc.minor, ver.glibc.patch, - }), + }) else if (target.abi.isAndroid()) try llvm_triple.writer().print("{d}", .{ver.android}), } return llvm_triple.toOwnedSlice();