From 3e2f8233a86bf4a2787eb6d37a54b9c8eae8a985 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 10 Nov 2021 07:40:52 -0800 Subject: [PATCH] Make Rosetta a new variant in ExternalExecutor enum When running, check if Rosetta is available, otherwise, pass the tests. --- lib/std/build.zig | 2 +- lib/std/zig/CrossTarget.zig | 9 ++++++--- lib/std/zig/cross_target.zig | 10 +++++++--- src/test.zig | 23 +++++++++++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index ea6a0e05f1..6c91303c14 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -2529,7 +2529,7 @@ pub const LibExeObjStep = struct { } } } else switch (self.target.getExternalExecutor()) { - .native, .unavailable => {}, + .native, .rosetta, .unavailable => {}, .qemu => |bin_name| if (self.enable_qemu) qemu: { const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc; const glibc_dir_arg = if (need_cross_glibc) diff --git a/lib/std/zig/CrossTarget.zig b/lib/std/zig/CrossTarget.zig index 6024c893fb..96213b1471 100644 --- a/lib/std/zig/CrossTarget.zig +++ b/lib/std/zig/CrossTarget.zig @@ -643,10 +643,13 @@ pub fn getExternalExecutor(self: CrossTarget) Executor { return .native; } } - // If the OS match and OS is macOS and CPU is arm64, treat always as native - // since we'll be running the foreign architecture tests using Rosetta2. + // If the OS match and OS is macOS and CPU is arm64, we can use Rosetta 2 + // to emulate the foreign architecture. if (os_match and os_tag == .macos and builtin.cpu.arch == .aarch64) { - return .native; + return switch (cpu_arch) { + .x86_64 => .rosetta, + else => .unavailable, + }; } // If the OS matches, we can use QEMU to emulate a foreign architecture. diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig index 8e3725c623..9134b6ad5c 100644 --- a/lib/std/zig/cross_target.zig +++ b/lib/std/zig/cross_target.zig @@ -596,6 +596,7 @@ pub const CrossTarget = struct { pub const Executor = union(enum) { native, + rosetta, qemu: []const u8, wine: []const u8, wasmtime: []const u8, @@ -626,10 +627,13 @@ pub const CrossTarget = struct { return .native; } } - // If the OS match and OS is macOS and CPU is arm64, treat always as native - // since we'll be running the foreign architecture tests using Rosetta2. + // If the OS match and OS is macOS and CPU is arm64, we can use Rosetta 2 + // to emulate the foreign architecture. if (os_match and os_tag == .macos and builtin.cpu.arch == .aarch64) { - return .native; + return switch (cpu_arch) { + .x86_64 => .rosetta, + else => .unavailable, + }; } // If the OS matches, we can use QEMU to emulate a foreign architecture. diff --git a/src/test.zig b/src/test.zig index 44faea0ed9..a0bf9c2c03 100644 --- a/src/test.zig +++ b/src/test.zig @@ -1132,6 +1132,29 @@ pub const TestContext = struct { .native => try argv.append(exe_path), .unavailable => return, // Pass test. + .rosetta => if (builtin.os.tag == .macos) { + // Check based on official Apple docs. + // If sysctlbyname returns errno.ENOENT, then we are running a native process. + // Otherwise, if an error occurs then we are not native and there is no Rosetta available. + // Finally if OK, we are running a translated process via Rosetta. + // https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment + var ret: c_int = 0; + var size: usize = @sizeOf(c_int); + std.os.sysctlbynameZ( + "sysctl.proc_translated", + &ret, + &size, + null, + 0, + ) catch |err| switch (err) { + error.UnknownName => unreachable, // Native process, we should never trigger it as .rosetta. + else => return, // No Rosetta available, pass test. + }; + try argv.append(exe_path); + } else { + return; // Rosetta not available, pass test. + }, + .qemu => |qemu_bin_name| if (enable_qemu) { // TODO Ability for test cases to specify whether to link libc. const need_cross_glibc = false; // target.isGnuLibC() and self.is_linking_libc;