From 0e1afee732c1007280b8afdab51aef3ceb860432 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 12 Oct 2020 17:28:02 +0200 Subject: [PATCH 1/2] Enable stage2 end-to-end tests on macOS run natively This commit enables stage2 end-to-end tests to run natively on macOS (where and when applicable). Since QEMU on macOS doesn't support the same type of architecture emulation as it does on linux (i.e., there is no `qemu-x86_64` for instance), this commit ensures that we specify a path to dynamic linker on macOS (`/usr/lib/dyld`) which is then checked for existence in `std.CrossTarget.getExternalExecutor()` function, and if exists, we can run the test natively. Signed-off-by: Jakub Konka --- lib/std/zig/cross_target.zig | 7 ++++++- test/stage2/test.zig | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig index 3d39c8338b72217c6e65adc2af3f5e304ce1784b..77c7f12728bfe293ab09cd6f5ae7d01ab6f2c393 100644 --- a/lib/std/zig/cross_target.zig +++ b/lib/std/zig/cross_target.zig @@ -608,10 +608,15 @@ pub const CrossTarget = struct { // If the OS and CPU arch match, the binary can be considered native. if (os_match and cpu_arch == Target.current.cpu.arch) { // However, we also need to verify that the dynamic linker path is valid. - // TODO Until that is implemented, we prevent returning `.native` when the OS is non-native. if (self.os_tag == null) { return .native; } + if (self.dynamic_linker.max_byte) |len| blk: { + std.fs.cwd().access(self.dynamic_linker.buffer[0..len + 1], .{}) catch { + break :blk; + }; + return .native; + } } // If the OS matches, we can use QEMU to emulate a foreign architecture. diff --git a/test/stage2/test.zig b/test/stage2/test.zig index 183555e3310740f6e9240387a5fb3a699c821913..2090c9493e7f99e745e1d3579f048c4e3b3f6660 100644 --- a/test/stage2/test.zig +++ b/test/stage2/test.zig @@ -14,6 +14,7 @@ const linux_x64 = std.zig.CrossTarget{ const macosx_x64 = std.zig.CrossTarget{ .cpu_arch = .x86_64, .os_tag = .macos, + .dynamic_linker = std.zig.CrossTarget.DynamicLinker.init("/usr/lib/dyld"), }; const linux_riscv64 = std.zig.CrossTarget{ @@ -145,7 +146,7 @@ pub fn addCases(ctx: *TestContext) !void { } { - var case = ctx.exe("hello world", macosx_x64); + var case = ctx.exe("hello world with updates", macosx_x64); case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); // Incorrect return type -- 2.54.0 From d91e75f5cacebd80f574993160839f8af21a5984 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 15 Oct 2020 16:44:16 -0700 Subject: [PATCH 2/2] getExternalExecutor fixups regarding dynamic linker * std.Target.standardDynamicLinkerPath: macOS has a dynamic linker * no need to override the default dynamic linker in the macos CrossTarget initialization in the tests * in getExternalExecutor, when validating the dynamic linker path, take into account the standard dynamic linker path. --- lib/std/target.zig | 36 +++++++++++++++++++++--------------- lib/std/zig/cross_target.zig | 11 +++++++---- test/stage2/test.zig | 5 ++--- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 86aabf4282723d1fdf7d46e68785573947699e91..1b93c82a76f1a7063e9d804ab90a3f1de8465656 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -483,6 +483,16 @@ pub const Target = struct { else => false, }; } + + pub fn floatAbi(abi: Abi) FloatAbi { + return switch (abi) { + .gnueabihf, + .eabihf, + .musleabihf, + => .hard, + else => .soft, + }; + } }; pub const ObjectFormat = enum { @@ -1259,13 +1269,7 @@ pub const Target = struct { }; pub fn getFloatAbi(self: Target) FloatAbi { - return switch (self.abi) { - .gnueabihf, - .eabihf, - .musleabihf, - => .hard, - else => .soft, - }; + return self.abi.floatAbi(); } pub fn hasDynamicLinker(self: Target) bool { @@ -1336,12 +1340,12 @@ pub const Target = struct { const print = S.print; const copy = S.copy; - if (self.isAndroid()) { + if (self.abi == .android) { const suffix = if (self.cpu.arch.ptrBitWidth() == 64) "64" else ""; return print(&result, "/system/bin/linker{}", .{suffix}); } - if (self.isMusl()) { + if (self.abi.isMusl()) { const is_arm = switch (self.cpu.arch) { .arm, .armeb, .thumb, .thumbeb => true, else => false, @@ -1351,7 +1355,7 @@ pub const Target = struct { .armeb, .thumbeb => "armeb", else => |arch| @tagName(arch), }; - const arch_suffix = if (is_arm and self.getFloatAbi() == .hard) "hf" else ""; + const arch_suffix = if (is_arm and self.abi.floatAbi() == .hard) "hf" else ""; return print(&result, "/lib/ld-musl-{}{}.so.1", .{ arch_part, arch_suffix }); } @@ -1373,7 +1377,7 @@ pub const Target = struct { .armeb, .thumb, .thumbeb, - => return copy(&result, switch (self.getFloatAbi()) { + => return copy(&result, switch (self.abi.floatAbi()) { .hard => "/lib/ld-linux-armhf.so.3", else => "/lib/ld-linux.so.3", }), @@ -1444,13 +1448,15 @@ pub const Target = struct { => return result, }, + .ios, + .tvos, + .watchos, + .macos, + => return copy(&result, "/usr/lib/dyld"), + // Operating systems in this list have been verified as not having a standard // dynamic linker path. .freestanding, - .ios, - .tvos, - .watchos, - .macos, .uefi, .windows, .emscripten, diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig index 77c7f12728bfe293ab09cd6f5ae7d01ab6f2c393..2f9446982d377fbfab098461845dea402a60fa5e 100644 --- a/lib/std/zig/cross_target.zig +++ b/lib/std/zig/cross_target.zig @@ -606,15 +606,18 @@ pub const CrossTarget = struct { const os_match = os_tag == Target.current.os.tag; // If the OS and CPU arch match, the binary can be considered native. + // TODO additionally match the CPU features. This `getExternalExecutor` function should + // be moved to std.Target and match any chosen target against the native target. if (os_match and cpu_arch == Target.current.cpu.arch) { // However, we also need to verify that the dynamic linker path is valid. if (self.os_tag == null) { return .native; } - if (self.dynamic_linker.max_byte) |len| blk: { - std.fs.cwd().access(self.dynamic_linker.buffer[0..len + 1], .{}) catch { - break :blk; - }; + // TODO here we call toTarget, a deprecated function, because of the above TODO about moving + // this code to std.Target. + const opt_dl = self.dynamic_linker.get() orelse self.toTarget().standardDynamicLinkerPath().get(); + if (opt_dl) |dl| blk: { + std.fs.cwd().access(dl, .{}) catch break :blk; return .native; } } diff --git a/test/stage2/test.zig b/test/stage2/test.zig index 2090c9493e7f99e745e1d3579f048c4e3b3f6660..7e1de126b6c2deeeb19a1314d17e8dd1510ec410 100644 --- a/test/stage2/test.zig +++ b/test/stage2/test.zig @@ -14,7 +14,6 @@ const linux_x64 = std.zig.CrossTarget{ const macosx_x64 = std.zig.CrossTarget{ .cpu_arch = .x86_64, .os_tag = .macos, - .dynamic_linker = std.zig.CrossTarget.DynamicLinker.init("/usr/lib/dyld"), }; const linux_riscv64 = std.zig.CrossTarget{ @@ -184,7 +183,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ ); \\ unreachable; \\} - , + , "Hello, World!\n", ); // Now change the message only @@ -994,7 +993,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ ); \\ unreachable; \\} - , + , "Hello, World!\n", ); try case.files.append(.{ -- 2.54.0