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 /doc | |
| 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 'doc')
| -rw-r--r-- | doc/docgen.zig | 33 | ||||
| -rw-r--r-- | doc/langref.html.in | 18 |
2 files changed, 41 insertions, 10 deletions
diff --git a/doc/docgen.zig b/doc/docgen.zig index 08502f0b79..29cb8bda5f 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -1202,6 +1202,7 @@ fn genHtml( var env_map = try process.getEnvMap(allocator); try env_map.put("ZIG_DEBUG_COLOR", "1"); + const host = try std.zig.system.NativeTargetInfo.detect(allocator, .{}); const builtin_code = try getBuiltinCode(allocator, &env_map, zig_exe); for (toc.nodes) |node| { @@ -1424,13 +1425,17 @@ fn genHtml( var test_args = std.ArrayList([]const u8).init(allocator); defer test_args.deinit(); - try test_args.appendSlice(&[_][]const u8{ zig_exe, "test", tmp_source_file_name }); + try test_args.appendSlice(&[_][]const u8{ + zig_exe, "test", tmp_source_file_name, + }); try shell_out.print("$ zig test {s}.zig ", .{code.name}); switch (code.mode) { .Debug => {}, else => { - try test_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) }); + try test_args.appendSlice(&[_][]const u8{ + "-O", @tagName(code.mode), + }); try shell_out.print("-O {s} ", .{@tagName(code.mode)}); }, } @@ -1441,8 +1446,26 @@ fn genHtml( if (code.target_str) |triple| { try test_args.appendSlice(&[_][]const u8{ "-target", triple }); try shell_out.print("-target {s} ", .{triple}); + + const cross_target = try std.zig.CrossTarget.parse(.{ + .arch_os_abi = triple, + }); + const target_info = try std.zig.system.NativeTargetInfo.detect( + allocator, + cross_target, + ); + switch (host.getExternalExecutor(target_info, .{ + .link_libc = code.link_libc, + })) { + .native => {}, + else => { + try test_args.appendSlice(&[_][]const u8{"--test-no-exec"}); + try shell_out.writeAll("--test-no-exec"); + }, + } } - const result = exec(allocator, &env_map, test_args.items) catch return parseError(tokenizer, code.source_token, "test failed", .{}); + const result = exec(allocator, &env_map, test_args.items) catch + return parseError(tokenizer, code.source_token, "test failed", .{}); const escaped_stderr = try escapeHtml(allocator, result.stderr); const escaped_stdout = try escapeHtml(allocator, result.stdout); try shell_out.print("\n{s}{s}\n", .{ escaped_stderr, escaped_stdout }); @@ -1504,9 +1527,7 @@ fn genHtml( defer test_args.deinit(); try test_args.appendSlice(&[_][]const u8{ - zig_exe, - "test", - tmp_source_file_name, + zig_exe, "test", tmp_source_file_name, }); var mode_arg: []const u8 = ""; switch (code.mode) { diff --git a/doc/langref.html.in b/doc/langref.html.in index 117c533f40..db68f8eb08 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -4763,7 +4763,13 @@ test "noreturn" { <p>Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:</p> {#code_begin|test|noreturn_from_exit#} {#target_windows#} -pub extern "kernel32" fn ExitProcess(exit_code: c_uint) callconv(if (@import("builtin").target.cpu.arch == .i386) .Stdcall else .C) noreturn; +const std = @import("std"); +const builtin = @import("builtin"); +const native_arch = builtin.cpu.arch; +const expect = std.testing.expect; + +const WINAPI: std.builtin.CallingConvention = if (native_arch == .i386) .Stdcall else .C; +extern "kernel32" fn ExitProcess(exit_code: c_uint) callconv(WINAPI) noreturn; test "foo" { const value = bar() catch ExitProcess(1); @@ -4774,12 +4780,15 @@ fn bar() anyerror!u32 { return 1234; } -const expect = @import("std").testing.expect; {#code_end#} {#header_close#} + {#header_open|Functions#} {#code_begin|test|functions#} -const expect = @import("std").testing.expect; +const std = @import("std"); +const builtin = @import("builtin"); +const native_arch = builtin.cpu.arch; +const expect = std.testing.expect; // Functions are declared like this fn add(a: i8, b: i8) i8 { @@ -4798,7 +4807,8 @@ export fn sub(a: i8, b: i8) i8 { return a - b; } // at link time, when linking statically, or at runtime, when linking // dynamically. // The callconv specifier changes the calling convention of the function. -extern "kernel32" fn ExitProcess(exit_code: u32) callconv(if (@import("builtin").target.cpu.arch == .i386) .Stdcall else .C) noreturn; +const WINAPI: std.builtin.CallingConvention = if (native_arch == .i386) .Stdcall else .C; +extern "kernel32" fn ExitProcess(exit_code: u32) callconv(WINAPI) noreturn; extern "c" fn atan2(a: f64, b: f64) f64; // The @setCold builtin tells the optimizer that a function is rarely called. |
