Skip to content

Commit

Permalink
macho: fix invalid default dylib link behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
kubkon committed Jul 3, 2023
1 parent 179a8b7 commit 3701c16
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 18 deletions.
12 changes: 6 additions & 6 deletions src/MachO/Options.zig
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ pub fn parse(arena: Allocator, args: []const []const u8, ctx: anytype) !Options
search_strategy = .paths_first;
} else if (mem.eql(u8, arg, "-search_dylib_first")) {
search_strategy = .dylibs_first;
} else if (mem.eql(u8, arg, "-framework") or mem.eql(u8, arg, "-weak_framework")) {
try frameworks.put(it.nextOrFatal(ctx), .{});
} else if (mem.eql(u8, arg, "-framework")) {
try frameworks.put(it.nextOrFatal(ctx), .{ .needed = false });
} else if (mem.startsWith(u8, arg, "-F")) {
try framework_dirs.append(arg[2..]);
} else if (mem.startsWith(u8, arg, "-needed-l")) {
Expand All @@ -231,11 +231,11 @@ pub fn parse(arena: Allocator, args: []const []const u8, ctx: anytype) !Options
} else if (mem.eql(u8, arg, "-needed_framework")) {
try frameworks.put(it.nextOrFatal(ctx), .{ .needed = true });
} else if (mem.startsWith(u8, arg, "-weak-l")) {
try libs.put(arg["-weak-l".len..], .{ .weak = true });
try libs.put(arg["-weak-l".len..], .{ .needed = false, .weak = true });
} else if (mem.eql(u8, arg, "-weak_library")) {
try libs.put(it.nextOrFatal(ctx), .{ .weak = true });
try libs.put(it.nextOrFatal(ctx), .{ .needed = false, .weak = true });
} else if (mem.eql(u8, arg, "-weak_framework")) {
try frameworks.put(it.nextOrFatal(ctx), .{ .weak = true });
try frameworks.put(it.nextOrFatal(ctx), .{ .needed = false, .weak = true });
} else if (mem.eql(u8, arg, "-o")) {
out_path = it.nextOrFatal(ctx);
} else if (mem.eql(u8, arg, "-stack_size")) {
Expand Down Expand Up @@ -403,7 +403,7 @@ pub fn parse(arena: Allocator, args: []const []const u8, ctx: anytype) !Options
} else if (mem.eql(u8, arg, "-demangle")) {
std.log.debug("TODO unimplemented -demangle option", .{});
} else if (mem.startsWith(u8, arg, "-l")) {
try libs.put(arg[2..], .{});
try libs.put(arg[2..], .{ .needed = false });
} else if (mem.startsWith(u8, arg, "-L")) {
try lib_dirs.append(arg[2..]);
} else if (mem.eql(u8, arg, "-no_deduplicate")) {
Expand Down
4 changes: 4 additions & 0 deletions test/macho.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ pub const cases = [_]Case{
.build_root = "test/macho/dead-strip",
.import = @import("macho/dead-strip/build.zig"),
},
.{
.build_root = "test/macho/dead-strip-dylibs",
.import = @import("macho/dead-strip-dylibs/build.zig"),
},
.{
.build_root = "test/macho/dylib",
.import = @import("macho/dylib/build.zig"),
Expand Down
54 changes: 54 additions & 0 deletions test/macho/dead-strip-dylibs/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const std = @import("std");

pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test it");
b.default_step = test_step;

{
const exe = b.addSystemCommand(&.{
"cc",
"-fno-lto",
"main.c",
"-framework",
"Cocoa",
"-B../../../zig-out/bin/",
"-o",
"a1.out",
});
test_step.dependOn(&exe.step);

const check = std.Build.Step.CheckObject.create(b, .{ .path = b.pathFromRoot("a1.out") }, .macho);
check.checkStart("cmd LOAD_DYLIB");
check.checkNext("name {*}Cocoa");
check.checkStart("cmd LOAD_DYLIB");
check.checkNext("name {*}libobjc{*}.dylib");
check.step.dependOn(&exe.step);
test_step.dependOn(&check.step);

const run = b.addSystemCommand(&.{"./a1.out"});
run.has_side_effects = true;
run.step.dependOn(&exe.step);
test_step.dependOn(&run.step);
}

{
const exe = b.addSystemCommand(&.{
"cc",
"-fno-lto",
"main.c",
"-Wl,-dead_strip_dylibs",
"-framework",
"Cocoa",
"-B../../../zig-out/bin/",
"-o",
"a2.out",
});
test_step.dependOn(&exe.step);

const run = b.addSystemCommand(&.{"./a2.out"});
run.has_side_effects = true;
run.expectExitCode(@as(u8, @bitCast(@as(i8, -2))));
run.step.dependOn(&exe.step);
test_step.dependOn(&run.step);
}
}
11 changes: 11 additions & 0 deletions test/macho/dead-strip-dylibs/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#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;
}
24 changes: 12 additions & 12 deletions test/macho/dead-strip/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test it");
b.default_step = test_step;

const exe_step = b.addSystemCommand(&.{
const exe = b.addSystemCommand(&.{
"cc",
"-fno-lto",
"-dead_strip",
"main.c",
"-B../../../zig-out/bin/",
});
test_step.dependOn(&exe_step.step);
test_step.dependOn(&exe.step);

const run_step = b.addSystemCommand(&.{"./a.out"});
run_step.has_side_effects = true;
run_step.expectStdOutEqual("Hello!\n");
run_step.step.dependOn(&exe_step.step);
test_step.dependOn(&run_step.step);
const run = b.addSystemCommand(&.{"./a.out"});
run.has_side_effects = true;
run.expectStdOutEqual("Hello!\n");
run.step.dependOn(&exe.step);
test_step.dependOn(&run.step);

const check_step = std.Build.Step.CheckObject.create(b, .{ .path = b.pathFromRoot("a.out") }, .macho);
check_step.checkInSymtab();
check_step.checkNotPresent("{*} (__TEXT,__text) external _iAmUnused");
check_step.step.dependOn(&exe_step.step);
test_step.dependOn(&check_step.step);
const check = std.Build.Step.CheckObject.create(b, .{ .path = b.pathFromRoot("a.out") }, .macho);
check.checkInSymtab();
check.checkNotPresent("{*} (__TEXT,__text) external _iAmUnused");
check.step.dependOn(&exe.step);
test_step.dependOn(&check.step);
}

0 comments on commit 3701c16

Please sign in to comment.