Commit 03b33b0f01
Changed files (21)
test/link/macho/bugs/13056/build.zig
@@ -1,38 +0,0 @@
-const std = @import("std");
-
-pub const requires_macos_sdk = true;
-pub const requires_symlinks = true;
-
-pub fn build(b: *std.Build) void {
- const test_step = b.step("test", "Test it");
- b.default_step = test_step;
-
- add(b, test_step, .Debug);
- add(b, test_step, .ReleaseFast);
- add(b, test_step, .ReleaseSmall);
- add(b, test_step, .ReleaseSafe);
-}
-
-fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
- const target = b.resolveTargetQuery(.{ .os_tag = .macos });
- const sdk = std.zig.system.darwin.getSdk(b.allocator, target.result) orelse
- @panic("macOS SDK is required to run the test");
-
- const exe = b.addExecutable(.{
- .name = "test",
- .optimize = optimize,
- .target = b.host,
- });
- exe.addSystemIncludePath(.{ .path = b.pathJoin(&.{ sdk, "/usr/include" }) });
- exe.addIncludePath(.{ .path = b.pathJoin(&.{ sdk, "/usr/include/c++/v1" }) });
- exe.addCSourceFile(.{ .file = .{ .path = "test.cpp" }, .flags = &.{
- "-nostdlib++",
- "-nostdinc++",
- } });
- exe.addObjectFile(.{ .path = b.pathJoin(&.{ sdk, "/usr/lib/libc++.tbd" }) });
-
- const run_cmd = b.addRunArtifact(exe);
- run_cmd.expectStdErrEqual("x: 5\n");
-
- test_step.dependOn(&run_cmd.step);
-}
test/link/macho/bugs/13056/test.cpp
@@ -1,10 +0,0 @@
-// test.cpp
-#include <new>
-#include <cstdio>
-
-int main() {
- int *x = new int;
- *x = 5;
- fprintf(stderr, "x: %d\n", *x);
- delete x;
-}
test/link/macho/bugs/13457/build.zig
@@ -1,30 +0,0 @@
-const std = @import("std");
-
-pub const requires_symlinks = true;
-
-pub fn build(b: *std.Build) void {
- const test_step = b.step("test", "Test it");
- b.default_step = test_step;
-
- add(b, test_step, .Debug);
- add(b, test_step, .ReleaseFast);
- add(b, test_step, .ReleaseSmall);
- add(b, test_step, .ReleaseSafe);
-}
-
-fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
- const target = b.resolveTargetQuery(.{ .os_tag = .macos });
-
- const exe = b.addExecutable(.{
- .name = "test",
- .root_source_file = .{ .path = "main.zig" },
- .optimize = optimize,
- .target = target,
- });
-
- const run = b.addRunArtifact(exe);
- run.skip_foreign_checks = true;
- run.expectStdOutEqual("");
-
- test_step.dependOn(&run.step);
-}
test/link/macho/bugs/13457/main.zig
@@ -1,1 +0,0 @@
-pub fn main() void {}
test/link/macho/bugs/16308/build.zig
@@ -1,23 +0,0 @@
-const std = @import("std");
-
-pub const requires_symlinks = true;
-
-pub fn build(b: *std.Build) void {
- const test_step = b.step("test", "Test it");
- b.default_step = test_step;
-
- const target = b.resolveTargetQuery(.{ .os_tag = .macos });
-
- const lib = b.addSharedLibrary(.{
- .name = "a",
- .root_source_file = .{ .path = "main.zig" },
- .optimize = .Debug,
- .target = target,
- });
-
- const check = lib.checkObject();
- check.checkInSymtab();
- check.checkNotPresent("external _abc");
-
- test_step.dependOn(&check.step);
-}
test/link/macho/bugs/16308/main.zig
@@ -1,1 +0,0 @@
-fn abc() void {}
test/link/macho/bugs/16628/a_arm64.s
@@ -1,37 +0,0 @@
-.globl _foo
-.align 4
-_foo:
- .cfi_startproc
- stp x29, x30, [sp, #-32]!
- .cfi_def_cfa_offset 32
- .cfi_offset w30, -24
- .cfi_offset w29, -32
- mov x29, sp
- .cfi_def_cfa w29, 32
- bl _bar
- ldp x29, x30, [sp], #32
- .cfi_restore w29
- .cfi_restore w30
- .cfi_def_cfa_offset 0
- ret
- .cfi_endproc
-
-.globl _bar
-.align 4
-_bar:
- .cfi_startproc
- sub sp, sp, #32
- .cfi_def_cfa_offset -32
- stp x29, x30, [sp, #16]
- .cfi_offset w30, -24
- .cfi_offset w29, -32
- mov x29, sp
- .cfi_def_cfa w29, 32
- mov w0, #4
- ldp x29, x30, [sp, #16]
- .cfi_restore w29
- .cfi_restore w30
- add sp, sp, #32
- .cfi_def_cfa_offset 0
- ret
- .cfi_endproc
test/link/macho/bugs/16628/a_x64.s
@@ -1,29 +0,0 @@
-.globl _foo
-_foo:
- .cfi_startproc
- push %rbp
- .cfi_def_cfa_offset 8
- .cfi_offset %rbp, -8
- mov %rsp, %rbp
- .cfi_def_cfa_register %rbp
- call _bar
- pop %rbp
- .cfi_restore %rbp
- .cfi_def_cfa_offset 0
- ret
- .cfi_endproc
-
-.globl _bar
-_bar:
- .cfi_startproc
- push %rbp
- .cfi_def_cfa_offset 8
- .cfi_offset %rbp, -8
- mov %rsp, %rbp
- .cfi_def_cfa_register %rbp
- mov $4, %rax
- pop %rbp
- .cfi_restore %rbp
- .cfi_def_cfa_offset 0
- ret
- .cfi_endproc
test/link/macho/bugs/16628/build.zig
@@ -1,42 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-
-pub const requires_symlinks = true;
-pub const requires_macos_sdk = false;
-
-pub fn build(b: *std.Build) void {
- const test_step = b.step("test", "Test it");
- b.default_step = test_step;
-
- add(b, test_step, .Debug);
- add(b, test_step, .ReleaseFast);
- add(b, test_step, .ReleaseSmall);
- add(b, test_step, .ReleaseSafe);
-}
-
-fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
- const target = b.resolveTargetQuery(.{ .os_tag = .macos });
-
- const exe = b.addExecutable(.{
- .name = "test",
- .optimize = optimize,
- .target = target,
- });
- exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} });
- switch (builtin.cpu.arch) {
- .aarch64 => {
- exe.addCSourceFile(.{ .file = .{ .path = "a_arm64.s" }, .flags = &[0][]const u8{} });
- },
- .x86_64 => {
- exe.addCSourceFile(.{ .file = .{ .path = "a_x64.s" }, .flags = &[0][]const u8{} });
- },
- else => unreachable,
- }
- exe.linkLibC();
-
- const run = b.addRunArtifact(exe);
- run.skip_foreign_checks = true;
- run.expectStdOutEqual("4\n");
-
- test_step.dependOn(&run.step);
-}
test/link/macho/bugs/16628/main.c
@@ -1,8 +0,0 @@
-#include <stdio.h>
-
-int foo();
-
-int main() {
- printf("%d\n", foo());
- return 0;
-}
test/link/macho/dead_strip_dylibs/build.zig
@@ -1,61 +0,0 @@
-const std = @import("std");
-
-pub const requires_macos_sdk = true;
-pub const requires_symlinks = true;
-
-pub fn build(b: *std.Build) void {
- const test_step = b.step("test", "Test it");
- b.default_step = test_step;
-
- add(b, test_step, .Debug);
- add(b, test_step, .ReleaseFast);
- add(b, test_step, .ReleaseSmall);
- add(b, test_step, .ReleaseSafe);
-}
-
-fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
- {
- // Without -dead_strip_dylibs we expect `-la` to include liba.dylib in the final executable
- const exe = createScenario(b, optimize, "no-dead-strip");
-
- const check = exe.checkObject();
- check.checkInHeaders();
- check.checkExact("cmd LOAD_DYLIB");
- check.checkContains("Cocoa");
-
- check.checkInHeaders();
- check.checkExact("cmd LOAD_DYLIB");
- check.checkContains("libobjc");
-
- test_step.dependOn(&check.step);
-
- const run_cmd = b.addRunArtifact(exe);
- test_step.dependOn(&run_cmd.step);
- }
-
- {
- // With -dead_strip_dylibs, we should include liba.dylib as it's unreachable
- const exe = createScenario(b, optimize, "yes-dead-strip");
- exe.dead_strip_dylibs = true;
-
- const run_cmd = b.addRunArtifact(exe);
- run_cmd.expectExitCode(@as(u8, @bitCast(@as(i8, -2)))); // should fail
- test_step.dependOn(&run_cmd.step);
- }
-}
-
-fn createScenario(
- b: *std.Build,
- optimize: std.builtin.OptimizeMode,
- name: []const u8,
-) *std.Build.Step.Compile {
- const exe = b.addExecutable(.{
- .name = name,
- .optimize = optimize,
- .target = b.host,
- });
- exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} });
- exe.linkLibC();
- exe.linkFramework("Cocoa");
- return exe;
-}
test/link/macho/dead_strip_dylibs/main.c
@@ -1,11 +0,0 @@
-#include <objc/runtime.h>
-
-int main(int argc, char* argv[]) {
- if (objc_getClass("NSObject") == 0) {
- return -1;
- }
- if (objc_getClass("NSApplication") == 0) {
- return -2;
- }
- return 0;
-}
test/link/macho/linksection/build.zig
@@ -1,39 +0,0 @@
-const std = @import("std");
-
-pub const requires_symlinks = true;
-
-pub fn build(b: *std.Build) void {
- const test_step = b.step("test", "Test it");
- b.default_step = test_step;
-
- add(b, test_step, .Debug);
- add(b, test_step, .ReleaseFast);
- add(b, test_step, .ReleaseSmall);
- add(b, test_step, .ReleaseSafe);
-}
-
-fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
- const target = b.resolveTargetQuery(.{ .os_tag = .macos });
-
- const obj = b.addObject(.{
- .name = "test",
- .root_source_file = .{ .path = "main.zig" },
- .optimize = optimize,
- .target = target,
- });
-
- const check = obj.checkObject();
-
- check.checkInSymtab();
- check.checkContains("(__DATA,__TestGlobal) external _test_global");
-
- check.checkInSymtab();
- check.checkContains("(__TEXT,__TestFn) external _testFn");
-
- if (optimize == .Debug) {
- check.checkInSymtab();
- check.checkContains("(__TEXT,__TestGenFnA) _main.testGenericFn__anon_");
- }
-
- test_step.dependOn(&check.step);
-}
test/link/macho/linksection/main.zig
@@ -1,5 +0,0 @@
-export var test_global: u32 linksection("__DATA,__TestGlobal") = undefined;
-export fn testFn() linksection("__TEXT,__TestFn") callconv(.C) void {
- testGenericFn("A");
-}
-fn testGenericFn(comptime suffix: []const u8) linksection("__TEXT,__TestGenFn" ++ suffix) void {}
test/link/macho/objcpp/build.zig
@@ -1,35 +0,0 @@
-const std = @import("std");
-
-pub const requires_symlinks = true;
-pub const requires_macos_sdk = true;
-
-pub fn build(b: *std.Build) void {
- const test_step = b.step("test", "Test it");
- b.default_step = test_step;
-
- add(b, test_step, .Debug);
- add(b, test_step, .ReleaseFast);
- add(b, test_step, .ReleaseSmall);
- add(b, test_step, .ReleaseSafe);
-}
-
-fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
- const exe = b.addExecutable(.{
- .name = "test",
- .optimize = optimize,
- .target = b.host,
- });
- b.default_step.dependOn(&exe.step);
- exe.addIncludePath(.{ .path = "." });
- exe.addCSourceFile(.{ .file = .{ .path = "Foo.mm" }, .flags = &[0][]const u8{} });
- exe.addCSourceFile(.{ .file = .{ .path = "test.mm" }, .flags = &[0][]const u8{} });
- exe.linkLibCpp();
- // TODO when we figure out how to ship framework stubs for cross-compilation,
- // populate paths to the sysroot here.
- exe.linkFramework("Foundation");
-
- const run_cmd = b.addRunArtifact(exe);
- run_cmd.expectStdOutEqual("Hello from C++ and Zig");
-
- test_step.dependOn(&run_cmd.step);
-}
test/link/macho/objcpp/Foo.h
@@ -1,7 +0,0 @@
-#import <Foundation/Foundation.h>
-
-@interface Foo : NSObject
-
-- (NSString *)name;
-
-@end
test/link/macho/objcpp/Foo.mm
@@ -1,11 +0,0 @@
-#import "Foo.h"
-
-@implementation Foo
-
-- (NSString *)name
-{
- NSString *str = [[NSString alloc] initWithFormat:@"Zig"];
- return str;
-}
-
-@end
test/link/macho/objcpp/test.mm
@@ -1,14 +0,0 @@
-#import "Foo.h"
-#import <assert.h>
-#include <iostream>
-
-int main(int argc, char *argv[])
-{
- @autoreleasepool {
- Foo *foo = [[Foo alloc] init];
- NSString *result = [foo name];
- std::cout << "Hello from C++ and " << [result UTF8String];
- assert([result isEqualToString:@"Zig"]);
- return 0;
- }
-}
test/link/link.zig
@@ -48,6 +48,8 @@ const OverlayOptions = struct {
cpp_source_flags: []const []const u8 = &.{},
objc_source_bytes: ?[]const u8 = null,
objc_source_flags: []const []const u8 = &.{},
+ objcpp_source_bytes: ?[]const u8 = null,
+ objcpp_source_flags: []const []const u8 = &.{},
zig_source_bytes: ?[]const u8 = null,
pic: ?bool = null,
strip: ?bool = null,
@@ -100,6 +102,12 @@ fn addCompileStep(
.static_lib => .static,
},
});
+ if (overlay.objcpp_source_bytes) |bytes| {
+ compile_step.addCSourceFile(.{
+ .file = b.addWriteFiles().add("a.mm", bytes),
+ .flags = overlay.objcpp_source_flags,
+ });
+ }
if (overlay.objc_source_bytes) |bytes| {
compile_step.addCSourceFile(.{
.file = b.addWriteFiles().add("a.m", bytes),
test/link/macho.zig
@@ -1,5 +1,4 @@
//! Here we test our MachO linker for correctness and functionality.
-//! TODO migrate standalone tests from test/link/macho/* to here.
pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
const macho_step = b.step("test-macho", "Run MachO tests");
@@ -18,12 +17,14 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
macho_step.dependOn(testDeadStrip(b, .{ .target = default_target }));
macho_step.dependOn(testEmptyObject(b, .{ .target = default_target }));
+ macho_step.dependOn(testEmptyZig(b, .{ .target = default_target }));
macho_step.dependOn(testEntryPoint(b, .{ .target = default_target }));
macho_step.dependOn(testHeaderWeakFlags(b, .{ .target = default_target }));
macho_step.dependOn(testHelloC(b, .{ .target = default_target }));
macho_step.dependOn(testHelloZig(b, .{ .target = default_target }));
macho_step.dependOn(testLargeBss(b, .{ .target = default_target }));
macho_step.dependOn(testLayout(b, .{ .target = default_target }));
+ macho_step.dependOn(testLinksection(b, .{ .target = default_target }));
macho_step.dependOn(testMhExecuteHeader(b, .{ .target = default_target }));
macho_step.dependOn(testNoDeadStrip(b, .{ .target = default_target }));
macho_step.dependOn(testNoExportsDylib(b, .{ .target = default_target }));
@@ -59,8 +60,10 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
if (build_opts.has_macos_sdk) {
macho_step.dependOn(testDeadStripDylibs(b, .{ .target = b.host }));
macho_step.dependOn(testHeaderpad(b, .{ .target = b.host }));
+ macho_step.dependOn(testLinkDirectlyCppTbd(b, .{ .target = b.host }));
macho_step.dependOn(testNeededFramework(b, .{ .target = b.host }));
macho_step.dependOn(testObjc(b, .{ .target = b.host }));
+ macho_step.dependOn(testObjcpp(b, .{ .target = b.host }));
macho_step.dependOn(testWeakFramework(b, .{ .target = b.host }));
}
}
@@ -255,6 +258,18 @@ fn testEmptyObject(b: *Build, opts: Options) *Step {
return test_step;
}
+fn testEmptyZig(b: *Build, opts: Options) *Step {
+ const test_step = addTestStep(b, "macho-empty-zig", opts);
+
+ const exe = addExecutable(b, opts, .{ .name = "empty", .zig_source_bytes = "pub fn main() void {}" });
+
+ const run = addRunArtifact(exe);
+ run.expectExitCode(0);
+ test_step.dependOn(&run.step);
+
+ return test_step;
+}
+
fn testEntryPoint(b: *Build, opts: Options) *Step {
const test_step = addTestStep(b, "macho-entry-point", opts);
@@ -745,6 +760,65 @@ fn testLayout(b: *Build, opts: Options) *Step {
return test_step;
}
+fn testLinkDirectlyCppTbd(b: *Build, opts: Options) *Step {
+ const test_step = addTestStep(b, "macho-link-directly-cpp-tbd", opts);
+
+ const sdk = std.zig.system.darwin.getSdk(b.allocator, opts.target.result) orelse
+ @panic("macOS SDK is required to run the test");
+
+ const exe = addExecutable(b, opts, .{
+ .name = "main",
+ .cpp_source_bytes =
+ \\#include <new>
+ \\#include <cstdio>
+ \\int main() {
+ \\ int *x = new int;
+ \\ *x = 5;
+ \\ fprintf(stderr, "x: %d\n", *x);
+ \\ delete x;
+ \\}
+ ,
+ .cpp_source_flags = &.{ "-nostdlib++", "-nostdinc++" },
+ });
+ exe.root_module.addSystemIncludePath(.{ .path = b.pathJoin(&.{ sdk, "/usr/include" }) });
+ exe.root_module.addIncludePath(.{ .path = b.pathJoin(&.{ sdk, "/usr/include/c++/v1" }) });
+ exe.root_module.addObjectFile(.{ .path = b.pathJoin(&.{ sdk, "/usr/lib/libc++.tbd" }) });
+
+ const check = exe.checkObject();
+ check.checkInSymtab();
+ check.checkContains("[referenced dynamically] external __mh_execute_header");
+ test_step.dependOn(&check.step);
+
+ return test_step;
+}
+
+fn testLinksection(b: *Build, opts: Options) *Step {
+ const test_step = addTestStep(b, "macho-linksection", opts);
+
+ const obj = addObject(b, opts, .{ .name = "main", .zig_source_bytes =
+ \\export var test_global: u32 linksection("__DATA,__TestGlobal") = undefined;
+ \\export fn testFn() linksection("__TEXT,__TestFn") callconv(.C) void {
+ \\ testGenericFn("A");
+ \\}
+ \\fn testGenericFn(comptime suffix: []const u8) linksection("__TEXT,__TestGenFn" ++ suffix) void {}
+ });
+
+ const check = obj.checkObject();
+ check.checkInSymtab();
+ check.checkContains("(__DATA,__TestGlobal) external _test_global");
+ check.checkInSymtab();
+ check.checkContains("(__TEXT,__TestFn) external _testFn");
+
+ if (opts.optimize == .Debug) {
+ check.checkInSymtab();
+ check.checkContains("(__TEXT,__TestGenFnA) _a.testGenericFn__anon_");
+ }
+
+ test_step.dependOn(&check.step);
+
+ return test_step;
+}
+
fn testMhExecuteHeader(b: *Build, opts: Options) *Step {
const test_step = addTestStep(b, "macho-mh-execute-header", opts);
@@ -870,6 +944,59 @@ fn testObjc(b: *Build, opts: Options) *Step {
return test_step;
}
+fn testObjcpp(b: *Build, opts: Options) *Step {
+ const test_step = addTestStep(b, "macho-objcpp", opts);
+
+ const foo_h = foo_h: {
+ const wf = WriteFile.create(b);
+ break :foo_h wf.add("Foo.h",
+ \\#import <Foundation/Foundation.h>
+ \\@interface Foo : NSObject
+ \\- (NSString *)name;
+ \\@end
+ );
+ };
+
+ const foo_o = addObject(b, opts, .{ .name = "foo", .objcpp_source_bytes =
+ \\#import "Foo.h"
+ \\@implementation Foo
+ \\- (NSString *)name
+ \\{
+ \\ NSString *str = [[NSString alloc] initWithFormat:@"Zig"];
+ \\ return str;
+ \\}
+ \\@end
+ });
+ foo_o.root_module.addIncludePath(foo_h.dirname());
+ foo_o.linkLibCpp();
+
+ const exe = addExecutable(b, opts, .{ .name = "main", .objcpp_source_bytes =
+ \\#import "Foo.h"
+ \\#import <assert.h>
+ \\#include <iostream>
+ \\int main(int argc, char *argv[])
+ \\{
+ \\ @autoreleasepool {
+ \\ Foo *foo = [[Foo alloc] init];
+ \\ NSString *result = [foo name];
+ \\ std::cout << "Hello from C++ and " << [result UTF8String];
+ \\ assert([result isEqualToString:@"Zig"]);
+ \\ return 0;
+ \\ }
+ \\}
+ });
+ exe.root_module.addIncludePath(foo_h.dirname());
+ exe.addObject(foo_o);
+ exe.linkLibCpp();
+ exe.root_module.linkFramework("Foundation", .{});
+
+ const run = addRunArtifact(exe);
+ run.expectStdOutEqual("Hello from C++ and Zig");
+ test_step.dependOn(&run.step);
+
+ return test_step;
+}
+
fn testPagezeroSize(b: *Build, opts: Options) *Step {
const test_step = addTestStep(b, "macho-pagezero-size", opts);
test/link.zig
@@ -89,30 +89,4 @@ pub const cases = [_]Case{
.build_root = "test/link/wasm/type",
.import = @import("link/wasm/type/build.zig"),
},
-
- // Mach-O Cases
- .{
- .build_root = "test/link/macho/bugs/13056",
- .import = @import("link/macho/bugs/13056/build.zig"),
- },
- .{
- .build_root = "test/link/macho/bugs/13457",
- .import = @import("link/macho/bugs/13457/build.zig"),
- },
- .{
- .build_root = "test/link/macho/bugs/16308",
- .import = @import("link/macho/bugs/16308/build.zig"),
- },
- .{
- .build_root = "test/link/macho/bugs/16628",
- .import = @import("link/macho/bugs/16628/build.zig"),
- },
- .{
- .build_root = "test/link/macho/linksection",
- .import = @import("link/macho/linksection/build.zig"),
- },
- .{
- .build_root = "test/link/macho/objcpp",
- .import = @import("link/macho/objcpp/build.zig"),
- },
};