authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-30 21:57:44+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-11-01 06:23:59+01:00
log3c1ccbdf3990b6d802cdc8a0db7c11eaac0960e8
tree4c68b538c30b3df1362fd03fa3947958cce6d744
parentc5395f7cd948f02ada095515b9d6824cbbac4f22
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.Target: Add support for specifying Android API level.


7 files changed, 75 insertions(+), 16 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+3
...@@ -359,6 +359,8 @@ pub const Os = struct {...@@ -359,6 +359,8 @@ pub const Os = struct {
359 pub const LinuxVersionRange = struct {359 pub const LinuxVersionRange = struct {
360 range: std.SemanticVersion.Range,360 range: std.SemanticVersion.Range,
361 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.
362364
363 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {365 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
364 return range.range.includesVersion(ver);366 return range.range.includesVersion(ver);
...@@ -480,6 +482,7 @@ pub const Os = struct {...@@ -480,6 +482,7 @@ pub const Os = struct {
480482
481 break :blk default_min;483 break :blk default_min;
482 },484 },
485 .android = 14,
483 },486 },
484 },487 },
485 .rtems => .{488 .rtems => .{
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+1-2
...@@ -286,7 +286,6 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {...@@ -286,7 +286,6 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
286 };286 };
287 try llvm_triple.appendSlice(llvm_abi);287 try llvm_triple.appendSlice(llvm_abi);
288288
289 // This should eventually handle the Android API level too.
290 switch (target.os.versionRange()) {289 switch (target.os.versionRange()) {
291 .none,290 .none,
292 .semver,291 .semver,
...@@ -296,7 +295,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {...@@ -296,7 +295,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
296 ver.glibc.major,295 ver.glibc.major,
297 ver.glibc.minor,296 ver.glibc.minor,
298 ver.glibc.patch,297 ver.glibc.patch,
299 }),298 }) else if (target.abi.isAndroid()) try llvm_triple.writer().print("{d}", .{ver.android}),
300 }299 }
301300
302 return llvm_triple.toOwnedSlice();301 return llvm_triple.toOwnedSlice();