diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-12-02 21:51:14 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-12-02 21:51:14 -0700 |
| commit | f3edff439e2dd8e4055d21507b352141cd5b1718 (patch) | |
| tree | 160b6397c84011c008c0a5671bbdbbcf41c4b5fd /src | |
| parent | 0cd87102221233c2885faccfcaaac297b8d3b656 (diff) | |
| download | zig-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.zig | 120 | ||||
| -rw-r--r-- | src/test.zig | 13 |
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); |
