aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-12-02 21:51:14 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-12-02 21:51:14 -0700
commitf3edff439e2dd8e4055d21507b352141cd5b1718 (patch)
tree160b6397c84011c008c0a5671bbdbbcf41c4b5fd /src
parent0cd87102221233c2885faccfcaaac297b8d3b656 (diff)
downloadzig-f3edff439e2dd8e4055d21507b352141cd5b1718.tar.gz
zig-f3edff439e2dd8e4055d21507b352141cd5b1718.zip
improve detection of how to execute binaries on the host
`getExternalExecutor` is moved from `std.zig.CrossTarget` to `std.zig.system.NativeTargetInfo.getExternalExecutor`. The function also now communicates a bit more information about *why* the host is unable to execute a binary. The CLI is updated to report this information in a useful manner. `getExternalExecutor` is also improved to detect such patterns as: * x86_64 is able to execute x86 binaries * aarch64 is able to execute arm binaries * etc. Added qemu-hexagon support to `getExternalExecutor`. `std.Target.canExecBinaries` of is removed; callers should use the more powerful `getExternalExecutor` instead. Now that `zig test` tries to run the resulting binary no matter what, this commit has a follow-up change to the build system and docgen to utilize the `getExternalExecutor` function and pass `--test-no-exec` in some cases to avoid getting the error. Additionally: * refactor: extract NativePaths and NativeTargetInfo into their own files named after the structs. * small improvement to langref to reduce the complexity of the `callconv` expression in a couple examples.
Diffstat (limited to 'src')
-rw-r--r--src/main.zig120
-rw-r--r--src/test.zig13
2 files changed, 108 insertions, 25 deletions
diff --git a/src/main.zig b/src/main.zig
index 3b5f10685f..54adf80fa6 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2539,6 +2539,7 @@ fn buildOutputType(
&comp_destroyed,
all_args,
runtime_args_start,
+ link_libc,
);
}
@@ -2611,6 +2612,7 @@ fn buildOutputType(
&comp_destroyed,
all_args,
runtime_args_start,
+ link_libc,
);
},
.update_and_run => {
@@ -2636,6 +2638,7 @@ fn buildOutputType(
&comp_destroyed,
all_args,
runtime_args_start,
+ link_libc,
);
},
}
@@ -2700,6 +2703,7 @@ fn runOrTest(
comp_destroyed: *bool,
all_args: []const []const u8,
runtime_args_start: ?usize,
+ link_libc: bool,
) !void {
const exe_loc = emit_bin_loc orelse return;
const exe_directory = exe_loc.directory orelse comp.bin_file.options.emit.?.directory;
@@ -2740,7 +2744,7 @@ fn runOrTest(
if (std.process.can_execv and arg_mode == .run and !watch) {
// execv releases the locks; no need to destroy the Compilation here.
const err = std.process.execv(gpa, argv.items);
- try warnAboutForeignBinaries(gpa, arena, arg_mode, target_info);
+ try warnAboutForeignBinaries(gpa, arena, arg_mode, target_info, link_libc);
const cmd = try argvCmd(arena, argv.items);
fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd });
} else {
@@ -2759,7 +2763,7 @@ fn runOrTest(
}
const term = child.spawnAndWait() catch |err| {
- try warnAboutForeignBinaries(gpa, arena, arg_mode, target_info);
+ try warnAboutForeignBinaries(gpa, arena, arg_mode, target_info, link_libc);
const cmd = try argvCmd(arena, argv.items);
fatal("the following command failed with '{s}':\n{s}", .{ @errorName(err), cmd });
};
@@ -4662,34 +4666,108 @@ fn warnAboutForeignBinaries(
arena: Allocator,
arg_mode: ArgMode,
target_info: std.zig.system.NativeTargetInfo,
+ link_libc: bool,
) !void {
const host_cross_target: std.zig.CrossTarget = .{};
const host_target_info = try detectNativeTargetInfo(gpa, host_cross_target);
- if (!host_target_info.target.canExecBinariesOf(target_info.target)) {
- const host_name = try host_target_info.target.zigTriple(arena);
- const foreign_name = try target_info.target.zigTriple(arena);
- const tip_suffix = switch (arg_mode) {
- .zig_test => ". Consider using --test-no-exec or --test-cmd",
- else => "",
- };
- warn("the host system ({s}) does not appear to be capable of executing binaries from the target ({s}){s}", .{
- host_name, foreign_name, tip_suffix,
- });
- return;
- }
-
- if (target_info.dynamic_linker.get()) |foreign_dl| {
- std.fs.cwd().access(foreign_dl, .{}) catch {
+ switch (host_target_info.getExternalExecutor(target_info, .{ .link_libc = link_libc })) {
+ .native => return,
+ .rosetta => {
+ const host_name = try host_target_info.target.zigTriple(arena);
+ const foreign_name = try target_info.target.zigTriple(arena);
+ warn("the host system ({s}) does not appear to be capable of executing binaries from the target ({s}). Consider installing Rosetta.", .{
+ host_name, foreign_name,
+ });
+ },
+ .qemu => |qemu| {
+ const host_name = try host_target_info.target.zigTriple(arena);
+ const foreign_name = try target_info.target.zigTriple(arena);
+ switch (arg_mode) {
+ .zig_test => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '--test-cmd {s} --test-cmd-bin' " ++
+ "to run the tests",
+ .{ host_name, foreign_name, qemu },
+ ),
+ else => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '{s}' to run the binary",
+ .{ host_name, foreign_name, qemu },
+ ),
+ }
+ },
+ .wine => |wine| {
+ const host_name = try host_target_info.target.zigTriple(arena);
+ const foreign_name = try target_info.target.zigTriple(arena);
+ switch (arg_mode) {
+ .zig_test => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '--test-cmd {s} --test-cmd-bin' " ++
+ "to run the tests",
+ .{ host_name, foreign_name, wine },
+ ),
+ else => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '{s}' to run the binary",
+ .{ host_name, foreign_name, wine },
+ ),
+ }
+ },
+ .wasmtime => |wasmtime| {
+ const host_name = try host_target_info.target.zigTriple(arena);
+ const foreign_name = try target_info.target.zigTriple(arena);
+ switch (arg_mode) {
+ .zig_test => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '--test-cmd {s} --test-cmd-bin' " ++
+ "to run the tests",
+ .{ host_name, foreign_name, wasmtime },
+ ),
+ else => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '{s}' to run the binary",
+ .{ host_name, foreign_name, wasmtime },
+ ),
+ }
+ },
+ .darling => |darling| {
+ const host_name = try host_target_info.target.zigTriple(arena);
+ const foreign_name = try target_info.target.zigTriple(arena);
+ switch (arg_mode) {
+ .zig_test => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '--test-cmd {s} --test-cmd-bin' " ++
+ "to run the tests",
+ .{ host_name, foreign_name, darling },
+ ),
+ else => warn(
+ "the host system ({s}) does not appear to be capable of executing binaries " ++
+ "from the target ({s}). Consider using '{s}' to run the binary",
+ .{ host_name, foreign_name, darling },
+ ),
+ }
+ },
+ .bad_dl => |foreign_dl| {
const host_dl = host_target_info.dynamic_linker.get() orelse "(none)";
const tip_suffix = switch (arg_mode) {
- .zig_test => ", --test-no-exec, or --test-cmd",
+ .zig_test => ", '--test-no-exec', or '--test-cmd'",
else => "",
};
- warn("the host system does not appear to be capable of executing binaries from the target because the host dynamic linker is located at '{s}', while the target dynamic linker path is '{s}'. Consider using --dynamic-linker{s}", .{
+ warn("the host system does not appear to be capable of executing binaries from the target because the host dynamic linker is '{s}', while the target dynamic linker is '{s}'. Consider using '--dynamic-linker'{s}", .{
host_dl, foreign_dl, tip_suffix,
});
- return;
- };
+ },
+ .bad_os_or_cpu => {
+ const host_name = try host_target_info.target.zigTriple(arena);
+ const foreign_name = try target_info.target.zigTriple(arena);
+ const tip_suffix = switch (arg_mode) {
+ .zig_test => ". Consider using '--test-no-exec' or '--test-cmd'",
+ else => "",
+ };
+ warn("the host system ({s}) does not appear to be capable of executing binaries from the target ({s}){s}", .{
+ host_name, foreign_name, tip_suffix,
+ });
+ },
}
}
diff --git a/src/test.zig b/src/test.zig
index 08c33b419d..af0dbec24b 100644
--- a/src/test.zig
+++ b/src/test.zig
@@ -611,6 +611,8 @@ pub const TestContext = struct {
}
fn run(self: *TestContext) !void {
+ const host = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, .{});
+
var progress = std.Progress{};
const root_node = try progress.start("compiler", self.cases.items.len);
defer root_node.end();
@@ -669,6 +671,7 @@ pub const TestContext = struct {
zig_lib_directory,
&thread_pool,
global_cache_directory,
+ host,
) catch |err| {
fail_count += 1;
print("test '{s}' failed: {s}\n\n", .{ case.name, @errorName(err) });
@@ -687,6 +690,7 @@ pub const TestContext = struct {
zig_lib_directory: Compilation.Directory,
thread_pool: *ThreadPool,
global_cache_directory: Compilation.Directory,
+ host: std.zig.system.NativeTargetInfo,
) !void {
const target_info = try std.zig.system.NativeTargetInfo.detect(allocator, case.target);
const target = target_info.target;
@@ -882,6 +886,7 @@ pub const TestContext = struct {
.stage1 => true,
else => null,
};
+ const link_libc = case.backend == .llvm;
const comp = try Compilation.create(allocator, .{
.local_cache_directory = zig_cache_directory,
.global_cache_directory = global_cache_directory,
@@ -903,7 +908,7 @@ pub const TestContext = struct {
.is_native_os = case.target.isNativeOs(),
.is_native_abi = case.target.isNativeAbi(),
.dynamic_linker = target_info.dynamic_linker.get(),
- .link_libc = case.backend == .llvm,
+ .link_libc = link_libc,
.use_llvm = use_llvm,
.use_stage1 = use_stage1,
.self_exe_path = std.testing.zig_exe_path,
@@ -1113,7 +1118,7 @@ pub const TestContext = struct {
// child process.
const exe_path = try std.fmt.allocPrint(arena, "." ++ std.fs.path.sep_str ++ "{s}", .{bin_name});
if (case.object_format != null and case.object_format.? == .c) {
- if (case.target.getExternalExecutor() != .native) {
+ if (host.getExternalExecutor(target_info, .{ .link_libc = true }) != .native) {
// We wouldn't be able to run the compiled C code.
return; // Pass test.
}
@@ -1129,9 +1134,9 @@ pub const TestContext = struct {
"-lc",
exe_path,
});
- } else switch (case.target.getExternalExecutor()) {
+ } else switch (host.getExternalExecutor(target_info, .{ .link_libc = link_libc })) {
.native => try argv.append(exe_path),
- .unavailable => return, // Pass test.
+ .bad_dl, .bad_os_or_cpu => return, // Pass test.
.rosetta => if (enable_rosetta) {
try argv.append(exe_path);