Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/compiler/aro/aro/Driver.zig
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ pub fn parseArgs(
try d.comp.addDiagnostic(.{ .tag = .cli_invalid_target, .extra = .{ .str = arg } }, &.{});
continue;
};
const target = std.zig.system.resolveTargetQuery(query) catch |e| {
const target = std.zig.system.resolveTargetQuery(query, d.comp.gpa) catch |e| {
return d.fatal("unable to resolve target: {s}", .{errorDescription(e)});
};
d.comp.target = target;
Expand Down
4 changes: 2 additions & 2 deletions lib/compiler/aro/aro/Value.zig
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ test "minUnsignedBits" {
var comp = Compilation.init(std.testing.allocator, std.fs.cwd());
defer comp.deinit();
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
comp.target = try std.zig.system.resolveTargetQuery(target_query);
comp.target = try std.zig.system.resolveTargetQuery(target_query, comp.gpa);

try Test.checkIntBits(&comp, 0, 0);
try Test.checkIntBits(&comp, 1, 1);
Expand Down Expand Up @@ -106,7 +106,7 @@ test "minSignedBits" {
var comp = Compilation.init(std.testing.allocator, std.fs.cwd());
defer comp.deinit();
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = "x86_64-linux-gnu" });
comp.target = try std.zig.system.resolveTargetQuery(target_query);
comp.target = try std.zig.system.resolveTargetQuery(target_query, comp.gpa);

try Test.checkIntBits(&comp, -1, 1);
try Test.checkIntBits(&comp, -2, 2);
Expand Down
2 changes: 1 addition & 1 deletion lib/compiler/aro/aro/toolchains/Linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ test Linux {

const raw_triple = "x86_64-linux-gnu";
const target_query = try std.Target.Query.parse(.{ .arch_os_abi = raw_triple });
comp.target = try std.zig.system.resolveTargetQuery(target_query);
comp.target = try std.zig.system.resolveTargetQuery(target_query, arena);
comp.langopts.setEmulatedCompiler(.gcc);

var driver: Driver = .{ .comp = &comp };
Expand Down
2 changes: 1 addition & 1 deletion lib/compiler/build_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub fn main() !void {
.zig_lib_directory = zig_lib_directory,
.host = .{
.query = .{},
.result = try std.zig.system.resolveTargetQuery(.{}),
.result = try std.zig.system.resolveTargetQuery(.{}, arena),
},
.time_report = false,
};
Expand Down
2 changes: 1 addition & 1 deletion lib/compiler/libc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub fn main() !void {
const target_query = std.zig.parseTargetQueryOrReportFatalError(gpa, .{
.arch_os_abi = target_arch_os_abi,
});
const target = std.zig.resolveTargetQueryOrFatal(target_query);
const target = std.zig.resolveTargetQueryOrFatal(target_query, gpa);

if (print_includes) {
const libc_installation: ?*LibCInstallation = libc: {
Expand Down
4 changes: 2 additions & 2 deletions lib/compiler/resinator/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.A
.cpu_arch = includes_arch,
.abi = .msvc,
};
const target = std.zig.resolveTargetQueryOrFatal(target_query);
const target = std.zig.resolveTargetQueryOrFatal(target_query, arena);
const is_native_abi = target_query.isNativeAbi();
const detected_libc = std.zig.LibCDirs.detect(arena, zig_lib_dir, &target, is_native_abi, true, null) catch {
if (includes == .any) {
Expand All @@ -608,7 +608,7 @@ fn getIncludePaths(arena: std.mem.Allocator, auto_includes_option: cli.Options.A
.cpu_arch = includes_arch,
.abi = .gnu,
};
const target = std.zig.resolveTargetQueryOrFatal(target_query);
const target = std.zig.resolveTargetQueryOrFatal(target_query, arena);
const is_native_abi = target_query.isNativeAbi();
const detected_libc = std.zig.LibCDirs.detect(arena, zig_lib_dir, &target, is_native_abi, true, null) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
Expand Down
5 changes: 4 additions & 1 deletion lib/compiler/std-docs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,10 @@ fn serveWasm(
.target = &(std.zig.system.resolveTargetQuery(std.Build.parseTargetQuery(.{
.arch_os_abi = autodoc_arch_os_abi,
.cpu_features = autodoc_cpu_features,
}) catch unreachable) catch unreachable),
}) catch unreachable, gpa) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => unreachable,
}),
.output_mode = .Exe,
});
// std.http.Server does not have a sendfile API yet.
Expand Down
2 changes: 1 addition & 1 deletion lib/std/Build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2650,7 +2650,7 @@ pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget {
}
return .{
.query = query,
.result = std.zig.system.resolveTargetQuery(query) catch
.result = std.zig.system.resolveTargetQuery(query, b.allocator) catch
@panic("unable to resolve target query"),
};
}
Expand Down
2 changes: 1 addition & 1 deletion lib/std/Build/Step/Options.zig
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ test Options {
.global_cache_root = .{ .path = "test", .handle = std.fs.cwd() },
.host = .{
.query = .{},
.result = try std.zig.system.resolveTargetQuery(.{}),
.result = try std.zig.system.resolveTargetQuery(.{}, arena.allocator()),
},
.zig_lib_directory = std.Build.Cache.Directory.cwd(),
.time_report = false,
Expand Down
5 changes: 4 additions & 1 deletion lib/std/Build/WebServer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,10 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim
.target = &(std.zig.system.resolveTargetQuery(std.Build.parseTargetQuery(.{
.arch_os_abi = arch_os_abi,
.cpu_features = cpu_features,
}) catch unreachable) catch unreachable),
}) catch unreachable, ws.gpa) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => unreachable,
}),
.output_mode = .Exe,
});
return base_path.join(arena, bin_name);
Expand Down
4 changes: 4 additions & 0 deletions lib/std/Target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2045,6 +2045,10 @@ pub inline fn isMuslLibC(target: *const Target) bool {
return target.os.tag == .linux and target.abi.isMusl();
}

pub inline fn isBionicLibC(target: *const Target) bool {
return target.os.tag == .linux and target.abi.isAndroid();
}

pub inline fn isDarwinLibC(target: *const Target) bool {
return switch (target.abi) {
.none, .macabi, .simulator => target.os.tag.isDarwin(),
Expand Down
10 changes: 5 additions & 5 deletions lib/std/Target/Query.zig
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ test parse {
.arch_os_abi = "x86_64-linux-gnu",
.cpu_features = "x86_64-sse-sse2-avx-cx8",
});
const target = try std.zig.system.resolveTargetQuery(query);
const target = try std.zig.system.resolveTargetQuery(query, std.testing.allocator);

try std.testing.expect(target.os.tag == .linux);
try std.testing.expect(target.abi == .gnu);
Expand All @@ -673,7 +673,7 @@ test parse {
.arch_os_abi = "arm-linux-musleabihf",
.cpu_features = "generic+v8a",
});
const target = try std.zig.system.resolveTargetQuery(query);
const target = try std.zig.system.resolveTargetQuery(query, std.testing.allocator);

try std.testing.expect(target.os.tag == .linux);
try std.testing.expect(target.abi == .musleabihf);
Expand All @@ -690,7 +690,7 @@ test parse {
.arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27",
.cpu_features = "generic+v8a",
});
const target = try std.zig.system.resolveTargetQuery(query);
const target = try std.zig.system.resolveTargetQuery(query, std.testing.allocator);

try std.testing.expect(target.cpu.arch == .aarch64);
try std.testing.expect(target.os.tag == .linux);
Expand All @@ -713,7 +713,7 @@ test parse {
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);
const target = try std.zig.system.resolveTargetQuery(query, std.testing.allocator);

try std.testing.expect(target.cpu.arch == .aarch64);
try std.testing.expect(target.os.tag == .linux);
Expand All @@ -734,7 +734,7 @@ test parse {
const query = try Query.parse(.{
.arch_os_abi = "x86-windows.xp...win8-msvc",
});
const target = try std.zig.system.resolveTargetQuery(query);
const target = try std.zig.system.resolveTargetQuery(query, std.testing.allocator);

try std.testing.expect(target.cpu.arch == .x86);
try std.testing.expect(target.os.tag == .windows);
Expand Down
4 changes: 2 additions & 2 deletions lib/std/zig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,8 @@ pub fn putAstErrorsIntoBundle(
try wip_errors.addZirErrorMessages(zir, tree, tree.source, path);
}

pub fn resolveTargetQueryOrFatal(target_query: std.Target.Query) std.Target {
return std.zig.system.resolveTargetQuery(target_query) catch |err|
pub fn resolveTargetQueryOrFatal(target_query: std.Target.Query, gpa: Allocator) std.Target {
return std.zig.system.resolveTargetQuery(target_query, gpa) catch |err|
std.process.fatal("unable to resolve target: {s}", .{@errorName(err)});
}

Expand Down
69 changes: 68 additions & 1 deletion lib/std/zig/system.zig
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pub fn getExternalExecutor(
}

pub const DetectError = error{
OutOfMemory,
FileSystem,
SystemResources,
SymLinkLoop,
Expand All @@ -172,14 +173,16 @@ pub const DetectError = error{
OSVersionDetectionFail,
Unexpected,
ProcessNotFound,
/// Android-only. Querying API level through `getprop` failed.
ApiLevelQueryFailed,
};

/// Given a `Target.Query`, which specifies in detail which parts of the
/// target should be detected natively, which should be standard or default,
/// and which are provided explicitly, this function resolves the native
/// components by detecting the native system, and then resolves
/// standard/default parts relative to that.
pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
pub fn resolveTargetQuery(query: Target.Query, gpa: Allocator) DetectError!Target {
// 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 query_cpu_arch = query.cpu_arch orelse builtin.cpu.arch;
Expand Down Expand Up @@ -448,6 +451,30 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
}
}

if (builtin.os.tag == .linux and result.isBionicLibC() and query.os_tag == null and query.android_api_level == null) {
result.os.version_range.linux.android = detectAndroidApiLevel(gpa) catch |err| return switch (err) {
error.InvalidWtf8,
error.CurrentWorkingDirectoryUnlinked,
error.InvalidBatchScriptArg,
error.InvalidHandle,
=> unreachable, // Windows-only
error.ApiLevelQueryFailed => |e| e,
else => blk: {
std.log.err("spawning or reading from getprop failed ({s})", .{@errorName(err)});
switch (err) {
error.OutOfMemory,
error.SystemResources,
error.FileSystem,
error.ProcessFdQuotaExceeded,
error.SystemFdQuotaExceeded,
error.SymLinkLoop,
=> |e| break :blk e,
else => break :blk error.ApiLevelQueryFailed,
}
},
};
}

return result;
}

Expand Down Expand Up @@ -1146,6 +1173,11 @@ fn detectAbiAndDynamicLinker(
error.FileTooBig,
error.Unexpected,
=> |e| {
if (e == error.FileNotFound and os.tag == .linux and mem.eql(u8, file_name, "/usr/bin/env")) {
// Android does not have a /usr directory, so try again
file_name = "/system/bin/env";
continue;
}
std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.", .{@errorName(e)});
return defaultAbiAndDynamicLinker(cpu, os, query);
},
Expand Down Expand Up @@ -1293,9 +1325,44 @@ fn elfInt(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @Type
}
}

fn detectAndroidApiLevel(gpa: Allocator) !u32 {
comptime if (builtin.os.tag != .linux) unreachable;

var child = std.process.Child.init(&.{ "/system/bin/getprop", "ro.build.version.sdk" }, gpa);
// pass empty EnvMap, no allocator and deinit() required
child.env_map = &std.process.EnvMap.init(undefined);
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Ignore;

try child.spawn();
Comment thread
lunagl marked this conversation as resolved.
errdefer _ = child.kill() catch {};

// PROP_VALUE_MAX is 92, output is value + newline.
// Currently API levels are two-digit numbers, but we want to make sure we never read a partial value.
var stdout_buf: [92 + 1]u8 = undefined;
var reader = child.stdout.?.readerStreaming(&.{});
const n = try reader.interface.readSliceShort(&stdout_buf);
const api_level = std.fmt.parseInt(u32, stdout_buf[0 .. n - 1], 10) catch |e| {
std.log.err(
"Could not parse API level, unexpected getprop output '{s}' ({s})",
.{ stdout_buf[0 .. n - 1], @errorName(e) },
);
return error.ApiLevelQueryFailed;
};

const term = try child.wait();
if (term != .Exited or term.Exited != 0) {
std.log.err("getprop terminated abnormally: {}", .{term});
return error.ApiLevelQueryFailed;
}
return api_level;
}

const builtin = @import("builtin");
const std = @import("../std.zig");
const mem = std.mem;
const Allocator = mem.Allocator;
const elf = std.elf;
const fs = std.fs;
const assert = std.debug.assert;
Expand Down
5 changes: 4 additions & 1 deletion src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5369,7 +5369,10 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU
//.simd128,
// .tail_call, not supported by Safari
}),
}) catch unreachable,
}, gpa) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => unreachable,
},

.is_native_os = false,
.is_native_abi = false,
Expand Down
Loading
Loading