Skip to content

Commit 73b70d4

Browse files
committed
std.Target: Add support for specifying Android API level.
1 parent 5a6f00d commit 73b70d4

File tree

7 files changed

+75
-16
lines changed

7 files changed

+75
-16
lines changed

lib/std/Build/Cache.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ pub const HashHelper = struct {
221221
hh.add(linux.range.min);
222222
hh.add(linux.range.max);
223223
hh.add(linux.glibc);
224+
hh.add(linux.android);
224225
},
225226
.windows => |windows| {
226227
hh.add(windows.min);

lib/std/Target.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ pub const Os = struct {
359359
pub const LinuxVersionRange = struct {
360360
range: std.SemanticVersion.Range,
361361
glibc: std.SemanticVersion,
362+
/// Android API level.
363+
android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated.
362364

363365
pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
364366
return range.range.includesVersion(ver);
@@ -480,6 +482,7 @@ pub const Os = struct {
480482

481483
break :blk default_min;
482484
},
485+
.android = 14,
483486
},
484487
},
485488
.rtems => .{

lib/std/Target/Query.zig

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@ os_version_min: ?OsVersion = null,
2525
/// When `os_tag` is native, `null` means equal to the native OS version.
2626
os_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.
2929
/// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
3030
glibc_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.
34+
android_api_level: ?u32 = null,
35+
3236
/// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
3337
abi: ?Target.Abi = null,
3438

@@ -98,10 +102,8 @@ pub fn fromTarget(target: Target) Query {
98102
.os_version_min = undefined,
99103
.os_version_max = undefined,
100104
.abi = target.abi,
101-
.glibc_version = if (target.isGnuLibC())
102-
target.os.version_range.linux.glibc
103-
else
104-
null,
105+
.glibc_version = if (target.isGnuLibC()) target.os.version_range.linux.glibc else null,
106+
.android_api_level = if (target.abi.isAndroid()) target.os.version_range.linux.android else null,
105107
};
106108
result.updateOsVersionRange(target.os);
107109

@@ -147,7 +149,7 @@ pub const ParseOptions = struct {
147149
/// The fields are, respectively:
148150
/// * CPU Architecture
149151
/// * 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)
151153
/// The string "native" can be used for CPU architecture as well as Operating System.
152154
/// If the CPU Architecture is specified as "native", then the Operating System and C ABI may be omitted.
153155
arch_os_abi: []const u8 = "native",
@@ -234,6 +236,11 @@ pub fn parse(args: ParseOptions) !Query {
234236
error.Overflow => return error.InvalidAbiVersion,
235237
error.InvalidVersion => return error.InvalidAbiVersion,
236238
};
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+
};
237244
} else {
238245
return error.InvalidAbiVersion;
239246
}
@@ -355,7 +362,7 @@ pub fn isNativeCpu(self: Query) bool {
355362

356363
pub fn isNativeOs(self: Query) bool {
357364
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;
359366
}
360367

361368
pub fn isNativeAbi(self: Query) bool {
@@ -439,6 +446,13 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
439446
result.appendSliceAssumeCapacity(name);
440447
result.appendAssumeCapacity('.');
441448
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});
442456
} else if (self.abi) |abi| {
443457
const name = @tagName(abi);
444458
try result.ensureUnusedCapacity(name.len + 1);
@@ -561,6 +575,7 @@ pub fn eql(a: Query, b: Query) bool {
561575
if (!OsVersion.eqlOpt(a.os_version_min, b.os_version_min)) return false;
562576
if (!OsVersion.eqlOpt(a.os_version_max, b.os_version_max)) return false;
563577
if (!versionEqualOpt(a.glibc_version, b.glibc_version)) return false;
578+
if (a.android_api_level != b.android_api_level) return false;
564579
if (a.abi != b.abi) return false;
565580
if (!a.dynamic_linker.eql(b.dynamic_linker)) return false;
566581
if (a.ofmt != b.ofmt) return false;
@@ -592,6 +607,15 @@ test parse {
592607

593608
try std.testing.expectEqualSlices(u8, "native-native-gnu.2.1.1", text);
594609
}
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+
}
595619
{
596620
const query = try Query.parse(.{
597621
.arch_os_abi = "aarch64-linux",
@@ -677,4 +701,25 @@ test parse {
677701
defer std.testing.allocator.free(text);
678702
try std.testing.expectEqualSlices(u8, "aarch64-linux.3.10...4.4.1-gnu.2.27", text);
679703
}
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+
}
680725
}

lib/std/c.zig

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,26 @@ comptime {
4444
}
4545
}
4646

47-
/// If not linking libc, returns false.
48-
/// If linking musl libc, returns true.
49-
/// If linking gnu libc (glibc), returns true if the target version is greater
50-
/// than or equal to `glibc_version`.
51-
/// If linking a libc other than these, returns `false`.
52-
pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool {
47+
/// * If not linking libc, returns `false`.
48+
/// * If linking musl libc, returns `true`.
49+
/// * If linking GNU libc (glibc), returns `true` if the target version is greater than or equal to
50+
/// `version`.
51+
/// * If linking Android libc (bionic), returns `true` if the target API level is greater than or
52+
/// equal to `version.major`, ignoring other components.
53+
/// * If linking a libc other than these, returns `false`.
54+
pub inline fn versionCheck(comptime version: std.SemanticVersion) bool {
5355
return comptime blk: {
5456
if (!builtin.link_libc) break :blk false;
5557
if (native_abi.isMusl()) break :blk true;
5658
if (builtin.target.isGnuLibC()) {
5759
const ver = builtin.os.version_range.linux.glibc;
58-
const order = ver.order(glibc_version);
60+
const order = ver.order(version);
5961
break :blk switch (order) {
6062
.gt, .eq => true,
6163
.lt => false,
6264
};
65+
} else if (builtin.abi.isAndroid()) {
66+
break :blk builtin.os.version_range.linux.android >= version.major;
6367
} else {
6468
break :blk false;
6569
}

lib/std/zig/system.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
331331
os.version_range.linux.glibc = glibc;
332332
}
333333

334+
if (query.android_api_level) |android| {
335+
os.version_range.linux.android = android;
336+
}
337+
334338
// Until https://github.com/ziglang/zig/issues/4592 is implemented (support detecting the
335339
// native CPU architecture as being different than the current target), we use this:
336340
const cpu_arch = query.cpu_arch orelse builtin.cpu.arch;

src/Builtin.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
124124
\\ .minor = {},
125125
\\ .patch = {},
126126
\\ }},
127+
\\ .android = {},
127128
\\ }}}},
128129
\\
129130
, .{
@@ -138,6 +139,8 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
138139
linux.glibc.major,
139140
linux.glibc.minor,
140141
linux.glibc.patch,
142+
143+
linux.android,
141144
}),
142145
.windows => |windows| try buffer.writer().print(
143146
\\ .windows = .{{

src/codegen/llvm.zig

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,6 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
286286
};
287287
try llvm_triple.appendSlice(llvm_abi);
288288

289-
// This should eventually handle the Android API level too.
290289
switch (target.os.versionRange()) {
291290
.none,
292291
.semver,
@@ -296,7 +295,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
296295
ver.glibc.major,
297296
ver.glibc.minor,
298297
ver.glibc.patch,
299-
}),
298+
}) else if (target.abi.isAndroid()) try llvm_triple.writer().print("{d}", .{ver.android}),
300299
}
301300

302301
return llvm_triple.toOwnedSlice();

0 commit comments

Comments
 (0)