diff --git a/build.zig b/build.zig index 5887d2a932..28d1486ad0 100644 --- a/build.zig +++ b/build.zig @@ -300,6 +300,7 @@ pub fn build(b: *Builder) !void { const is_qemu_enabled = b.option(bool, "enable-qemu", "Use QEMU to run cross compiled foreign architecture tests") orelse false; const is_wasmtime_enabled = b.option(bool, "enable-wasmtime", "Use Wasmtime to enable and run WASI libstd tests") orelse false; const is_darling_enabled = b.option(bool, "enable-darling", "[Experimental] Use Darling to run cross compiled macOS tests") orelse false; + const is_rosetta_enabled = b.option(bool, "enable-rosetta", "(Darwin) Use Rosetta to run x86_64 macOS tests on arm64 macOS") orelse false; const glibc_multi_dir = b.option([]const u8, "enable-foreign-glibc", "Provide directory with glibc installations to run cross compiled tests that link glibc"); const test_stage2_options = b.addOptions(); @@ -319,6 +320,7 @@ pub fn build(b: *Builder) !void { test_stage2_options.addOption(bool, "enable_qemu", is_qemu_enabled); test_stage2_options.addOption(bool, "enable_wine", is_wine_enabled); test_stage2_options.addOption(bool, "enable_wasmtime", is_wasmtime_enabled); + test_stage2_options.addOption(bool, "enable_rosetta", is_rosetta_enabled); test_stage2_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2); test_stage2_options.addOption(bool, "enable_darling", is_darling_enabled); test_stage2_options.addOption(?[]const u8, "glibc_multi_install_dir", glibc_multi_dir); @@ -370,6 +372,7 @@ pub fn build(b: *Builder) !void { is_qemu_enabled, is_wasmtime_enabled, is_darling_enabled, + is_rosetta_enabled, glibc_multi_dir, )); @@ -387,6 +390,7 @@ pub fn build(b: *Builder) !void { is_qemu_enabled, is_wasmtime_enabled, is_darling_enabled, + is_rosetta_enabled, glibc_multi_dir, )); @@ -404,6 +408,7 @@ pub fn build(b: *Builder) !void { is_qemu_enabled, is_wasmtime_enabled, is_darling_enabled, + is_rosetta_enabled, glibc_multi_dir, )); @@ -434,6 +439,7 @@ pub fn build(b: *Builder) !void { is_qemu_enabled, is_wasmtime_enabled, is_darling_enabled, + is_rosetta_enabled, glibc_multi_dir, ); diff --git a/lib/std/build.zig b/lib/std/build.zig index ea6a0e05f1..600fb691ae 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1516,6 +1516,9 @@ pub const LibExeObjStep = struct { /// Experimental. Uses system Darling installation to run cross compiled macOS build artifacts. enable_darling: bool = false, + /// Darwin. Uses Rosetta to run x86_64 macOS build artifacts on arm64 macOS. + enable_rosetta: bool = false, + /// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc, /// this will be the directory $glibc-build-dir/install/glibcs /// Given the example of the aarch64 target, this is the directory @@ -2530,6 +2533,9 @@ pub const LibExeObjStep = struct { } } else switch (self.target.getExternalExecutor()) { .native, .unavailable => {}, + .rosetta => if (self.enable_rosetta) { + try zig_args.append("--test-cmd-bin"); + }, .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 03bb6bc5ff..96213b1471 100644 --- a/lib/std/zig/CrossTarget.zig +++ b/lib/std/zig/CrossTarget.zig @@ -612,6 +612,7 @@ pub fn vcpkgTriplet(self: CrossTarget, allocator: mem.Allocator, linkage: VcpkgL pub const Executor = union(enum) { native, + rosetta, qemu: []const u8, wine: []const u8, wasmtime: []const u8, @@ -642,6 +643,14 @@ pub fn getExternalExecutor(self: CrossTarget) Executor { return .native; } } + // 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 switch (cpu_arch) { + .x86_64 => .rosetta, + else => .unavailable, + }; + } // If the OS matches, we can use QEMU to emulate a foreign architecture. if (os_match) { diff --git a/src/test.zig b/src/test.zig index 44faea0ed9..69d2d31a08 100644 --- a/src/test.zig +++ b/src/test.zig @@ -10,6 +10,7 @@ const enable_qemu: bool = build_options.enable_qemu; const enable_wine: bool = build_options.enable_wine; const enable_wasmtime: bool = build_options.enable_wasmtime; const enable_darling: bool = build_options.enable_darling; +const enable_rosetta: bool = build_options.enable_rosetta; const glibc_multi_install_dir: ?[]const u8 = build_options.glibc_multi_install_dir; const skip_compile_errors = build_options.skip_compile_errors; const ThreadPool = @import("ThreadPool.zig"); @@ -1132,6 +1133,12 @@ pub const TestContext = struct { .native => try argv.append(exe_path), .unavailable => return, // Pass test. + .rosetta => if (enable_rosetta) { + 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; diff --git a/test/behavior/muladd.zig b/test/behavior/muladd.zig index eaa30324df..cff7b5e2ad 100644 --- a/test/behavior/muladd.zig +++ b/test/behavior/muladd.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const expect = @import("std").testing.expect; test "@mulAdd" { @@ -24,6 +25,10 @@ fn testMulAdd() !void { var c: f64 = 6.25; try expect(@mulAdd(f64, a, b, c) == 20); } + if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) { + // https://github.com/ziglang/zig/issues/9900 + return error.SkipZigTest; + } { var a: f16 = 5.5; var b: f128 = 2.5; diff --git a/test/tests.zig b/test/tests.zig index 267830bbdc..511d8bc6f2 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -270,8 +270,14 @@ const test_targets = blk: { .os_tag = .macos, .abi = .gnu, }, - // https://github.com/ziglang/zig/issues/3295 - .disable_native = true, + }, + + TestTarget{ + .target = .{ + .cpu_arch = .aarch64, + .os_tag = .macos, + .abi = .gnu, + }, }, TestTarget{ @@ -511,6 +517,7 @@ pub fn addPkgTests( is_qemu_enabled: bool, is_wasmtime_enabled: bool, is_darling_enabled: bool, + is_rosetta_enabled: bool, glibc_dir: ?[]const u8, ) *build.Step { const step = b.step(b.fmt("test-{s}", .{name}), desc); @@ -572,6 +579,7 @@ pub fn addPkgTests( these_tests.enable_qemu = is_qemu_enabled; these_tests.enable_wasmtime = is_wasmtime_enabled; these_tests.enable_darling = is_darling_enabled; + these_tests.enable_rosetta = is_rosetta_enabled; these_tests.glibc_multi_install_dir = glibc_dir; these_tests.addIncludeDir("test");