commit 72bc140ad16a4a2dbe632129ea9068630e019277 (tree)
parent 7f0b5787fb1db871501bc4b03629d68dc378e038
Author: kcbanner <kcbanner@gmail.com>
Date: Fri, 5 Jun 2026 01:55:37 -0400
test/link: separate out shared lib tests
- Fixup snapshot naming
- Fixup verifyObjdumps so we can dump other artifacts
- Add llvm link_targets for comparison
Diffstat:
10 files changed, 218 insertions(+), 85 deletions(-)
diff --git a/lib/compiler/objdump.zig b/lib/compiler/objdump.zig
@@ -401,12 +401,13 @@ const coff = struct {
, .{ expected_kind, num_symbols });
if (d.opts.linker_member == .first_linker) {
- try w.writeAll(
- \\
- \\Archive symbols:
- \\& Member Symbol
- \\
- );
+ if (d.element(.@"table-header"))
+ try w.writeAll(
+ \\
+ \\Archive symbols:
+ \\& Member Symbol
+ \\
+ );
const offsets = try r.readAlloc(gpa, num_symbols * 4);
defer gpa.free(offsets);
diff --git a/test/link.zig b/test/link.zig
@@ -1,29 +1,5 @@
pub fn addCases(ctx: *LinkContext) void {
- if (ctx.includeTest("exports-static")) |case| {
- const lib = case.addLibrary(.static, .{
- .name = "lib",
- .zig_source_file = ctx.sourcePath("exports.zig"),
- });
- case.verifyObjdump(lib, &.{
- "-s",
- "--symbols",
- "--only-symbol=foo",
- }, .{});
- }
-
- if (ctx.includeTest("exports-dynamic")) |case| {
- const lib = case.addLibrary(.dynamic, .{
- .name = "lib",
- .zig_source_file = ctx.sourcePath("exports.zig"),
- });
- case.verifyObjdump(lib, &.{
- "-s",
- "--exports",
- "--only-symbol=foo",
- }, .{});
- }
-
- if (ctx.includeTest("emit-static-lib")) |case| {
+ if (ctx.includeTest("static-lib")) |case| {
const obj1 = case.addObject(.{
.name = "obj1",
.name_prefix = false,
@@ -43,14 +19,14 @@ pub fn addCases(ctx: *LinkContext) void {
.name_prefix = false,
.name_target = false,
.zig_source_bytes =
- \\fn weakFoo() callconv(.c) usize {
+ \\fn fooWeak() callconv(.c) usize {
\\ return 0xaabbccddaabbccdd;
\\}
- \\export var array_foo: [2]u16 = .{ 0xffff, 0xabcd };
- \\export var strong_foo: usize = 0x1122334411223344;
+ \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd };
+ \\export var foo_strong: usize = 0x1122334411223344;
\\comptime {
- \\ @export(&weakFoo, .{ .name = "weakFoo", .linkage = .weak });
- \\ @export(&strong_foo, .{ .name = "strong_foo_alias", .linkage = .strong });
+ \\ @export(&fooWeak, .{ .name = "fooWeak", .linkage = .weak });
+ \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong });
\\}
,
});
@@ -63,25 +39,109 @@ pub fn addCases(ctx: *LinkContext) void {
lib.root_module.addObject(obj1);
lib.root_module.addObject(obj2);
- case.verifyObjdump(lib, &.{
+ case.verifyObjdump(lib.getEmittedBin(), &.{
"-s",
"--elements=file-type",
"--symbols",
"--only-symbol=foo",
- "--only-symbol=Foo",
}, .{});
const exe = case.addExecutable(.{
.name = "test",
.zig_source_bytes =
\\extern fn fooBar() c_uint;
- \\extern fn weakFoo() usize;
+ \\extern fn fooWeak() usize;
+ \\extern var foo_array: [2]u16;
+ \\extern var foo_strong: usize;
+ \\extern var foo_strong_alias: usize;
+ \\pub fn main() !u8 {
+ \\ return @intFromBool(0xcd003365cd00df35 != fooBar() +
+ \\ fooWeak() +
+ \\ foo_array[1] +
+ \\ foo_strong +
+ \\ foo_strong_alias);
+ \\}
+ ,
+ });
+ exe.root_module.linkLibrary(lib);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 0 } });
+ }
+
+ if (ctx.includeTest("dynamic-lib-code")) |case| {
+ const lib = case.addLibrary(.dynamic, .{
+ .name = "lib",
+ .zig_source_bytes =
+ \\export fn foo1() callconv(.c) u64 {
+ \\ return 0x1122334411223344;
+ \\}
+ \\export fn foo2() callconv(.c) u64 {
+ \\ return 0xaabbccddaabbccdd;
+ \\}
+ ,
+ });
+
+ case.verifyObjdump(lib.getEmittedBin(), &.{
+ "-s",
+ "--exports",
+ "--only-symbol=foo",
+ }, .{ .os = true });
+
+ if (ctx.target.result.os.tag == .windows) {
+ case.verifyObjdump(lib.getEmittedImplib(), &.{
+ "-s",
+ "--exports",
+ "--only-symbol=foo",
+ }, .{ .sub_name = "implib", .os = true });
+ }
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
+ \\extern fn foo1() u64;
+ \\pub fn main() !u8 {
+ \\ const foo2 = @extern(
+ \\ *const fn () callconv(.c) u64,
+ \\ .{ .name = "foo2", .is_dll_import = true },
+ \\ );
+ \\ return @intFromBool(0xbbde0021bbde0021 != foo1() + foo2());
+ \\}
+ ,
+ });
+ exe.root_module.linkLibrary(lib);
+
+ const run = case.addRunArtifact(exe);
+ run.addCheck(.{ .expect_term = .{ .exited = 0 } });
+ }
+
+ if (ctx.includeTest("dynamic-lib-data")) |case| {
+ const lib = case.addLibrary(.dynamic, .{
+ .name = "lib",
+ .zig_source_bytes =
+ \\export var array_foo: [2]u16 = .{ 0xffff, 0xabcd };
+ \\export var strong_foo: usize = 0x1122334411223344;
+ ,
+ });
+
+ case.verifyObjdump(lib.getEmittedBin(), &.{
+ "-s",
+ "--exports",
+ "--only-symbol=foo",
+ }, .{});
+
+ if (ctx.target.result.os.tag == .windows) {
+ // TODO: objdump implib on windows
+ }
+
+ const exe = case.addExecutable(.{
+ .name = "test",
+ .zig_source_bytes =
\\extern var array_foo: [2]u16;
\\extern var strong_foo: usize;
\\extern var strong_foo_alias: usize;
\\pub fn main() !u8 {
- \\ return @intFromBool(0xcd003365cd00df35 != fooBar() +
- \\ weakFoo() +
+ \\ return @intFromBool(0x2244668822451255 !=
\\ array_foo[1] +
\\ strong_foo +
\\ strong_foo_alias);
@@ -118,7 +178,7 @@ pub fn addCases(ctx: *LinkContext) void {
,
});
- case.verifyObjdump(abs_reloc, &.{
+ case.verifyObjdump(abs_reloc.getEmittedBin(), &.{
"-s",
"--relocs",
}, .{ .arch = true });
diff --git a/test/link/snapshots/abs-symbol-x86_64.dmp b/test/link/snapshots/abs-symbol-x86_64.dmp
@@ -1 +0,0 @@
-xxxxxxxx ADDR32 xxxxxxxx UNDEF | foo
diff --git a/test/link/snapshots/dynamic-lib-code.implib-windows.dmp b/test/link/snapshots/dynamic-lib-code.implib-windows.dmp
@@ -0,0 +1,32 @@
+ 0 date
+ 0 user_id
+ 0 group_id
+ 0 file_mode
+xxxxxxxxxxxxxxxx size
+ second_linker type
+ | 7 symbols
+ | 5 members
+xxxxxxxx __imp_foo1
+xxxxxxxx __imp_foo2
+xxxxxxxx foo1
+xxxxxxxx foo2
+ 0 version
+ 8664 machine (AMD64)
+ 0 time_date_stamp
+xxxxxxxxxxxxxxxx size_of_data
+ 0 hint
+ CODE import_type
+ NAME name_type
+ symbol name | foo1
+ import name | foo1
+ dll | dynamic-lib-code-lib-x86_64-windows.win10...win11_dt-msvc-Debug-llvm-lld-libc.dll
+ 0 version
+ 8664 machine (AMD64)
+ 0 time_date_stamp
+xxxxxxxxxxxxxxxx size_of_data
+ 0 hint
+ CODE import_type
+ NAME name_type
+ symbol name | foo2
+ import name | foo2
+ dll | dynamic-lib-code-lib-x86_64-windows.win10...win11_dt-msvc-Debug-llvm-lld-libc.dll
diff --git a/test/link/snapshots/dynamic-lib-code.windows.dmp b/test/link/snapshots/dynamic-lib-code.windows.dmp
@@ -0,0 +1,13 @@
+Export directory:
+ 0 flags
+ 0 time_date_stamp
+ 0.00 version
+xxxxxxxxxxxxxxxx name_rva
+ 1 ordinal_base
+xxxxxxxxxxxxxxxx number_of_entries
+xxxxxxxxxxxxxxxx number_of_names
+xxxxxxxxxxxxxxxx export_address_table_rva
+xxxxxxxxxxxxxxxx name_pointer_table_rva
+xxxxxxxxxxxxxxxx ordinal_table_rva
+xxxx xxxx xxxxxxxx | foo1
+xxxx xxxx xxxxxxxx | foo2
diff --git a/test/link/snapshots/emit-static-lib.dmp b/test/link/snapshots/emit-static-lib.dmp
@@ -1,10 +0,0 @@
-lib.lib: COFF archive
-lib.lib(obj1.obj): COFF object
-xxxx 00000000 1 NULL() EXTERNAL | fooBar
-xxxx 00000000 2 NULL EXTERNAL | foo1
-xxxx 00000004 2 NULL EXTERNAL | foo2
-lib.lib(this_is_a_long_name.obj): COFF object
-xxxx 00000000 4 NULL() EXTERNAL | weakFoo
-xxxx 00000010 2 NULL EXTERNAL | array_foo
-xxxx 00000000 2 NULL EXTERNAL | strong_foo_alias
-xxxx 00000000 2 NULL EXTERNAL | strong_foo
diff --git a/test/link/snapshots/exports-dynamic.dmp b/test/link/snapshots/exports-dynamic.dmp
@@ -1,14 +0,0 @@
-Export directory:
- 0 flags
- 0 time_date_stamp
- 0.00 version
-xxxxxxxxxxxxxxxx name_rva
- 1 ordinal_base
-xxxxxxxxxxxxxxxx number_of_entries
-xxxxxxxxxxxxxxxx number_of_names
-xxxxxxxxxxxxxxxx export_address_table_rva
-xxxxxxxxxxxxxxxx name_pointer_table_rva
-xxxxxxxxxxxxxxxx ordinal_table_rva
-xxxx xxxx xxxxxxxx | foo_const
-xxxx xxxx xxxxxxxx | foo_fn
-xxxx xxxx xxxxxxxx | foo_var
diff --git a/test/link/snapshots/exports-static.dmp b/test/link/snapshots/exports-static.dmp
@@ -1,3 +0,0 @@
-xxxx 00000000 4 NULL() EXTERNAL | foo_fn
-xxxx 00000000 2 NULL EXTERNAL | foo_var
-xxxx 00000008 3 NULL EXTERNAL | foo_const
diff --git a/test/src/Link.zig b/test/src/Link.zig
@@ -101,7 +101,7 @@ pub const Case = struct {
}
const SnapshotScope = struct {
- /// If a test case has multiple verifyObjdump calls, `opt_sub_name` can
+ /// If a test case has multiple verifyObjdump calls, `opt_sub_name` should
/// be used to differentiate them.
sub_name: ?[]const u8 = null,
arch: bool = false,
@@ -120,7 +120,7 @@ pub const Case = struct {
///
pub fn verifyObjdump(
self: *const Case,
- compile: *Step.Compile,
+ file: Build.LazyPath,
args: []const []const u8,
scope: SnapshotScope,
) void {
@@ -140,7 +140,7 @@ pub const Case = struct {
.{ snapshot_name, ctx.target_desc },
));
run_step.addArgs(&.{ ctx.b.graph.zig_exe, "objdump" });
- run_step.addArtifactArg(compile);
+ run_step.addFileArg(file);
run_step.addArgs(args);
run_step.addCheck(.{ .expect_term = .{ .exited = 0 } });
@@ -166,22 +166,39 @@ pub const Case = struct {
const w = &snapshot_name.writer;
try w.writeAll(self.prefix);
- if (scope.sub_name) |sub_name| {
- try w.writeByte('.');
- try w.writeAll(sub_name);
- }
+ var sep: u8 = '.';
+
+ if (try snapshotNameInner(w, scope.sub_name != null, &sep))
+ try w.writeAll(scope.sub_name.?);
+ if (try snapshotNameInner(w, scope.arch, &sep))
+ try w.print("{t}", .{ctx.target.result.cpu.arch});
+ if (try snapshotNameInner(w, scope.os, &sep))
+ try w.print("{t}", .{ctx.target.result.os.tag});
+ if (try snapshotNameInner(w, scope.abi, &sep))
+ try w.print("{t}", .{ctx.target.result.abi});
+ if (try snapshotNameInner(w, scope.optimize, &sep))
+ try w.print("{t}", .{ctx.optimize});
+ if (try snapshotNameInner(w, scope.use_llvm, &sep))
+ try w.writeAll(if (ctx.use_llvm) "llvm" else "no-llvm");
+ if (try snapshotNameInner(w, scope.use_lld, &sep))
+ try w.writeAll(if (ctx.use_lld) "lld" else "no-lld");
+ if (try snapshotNameInner(w, scope.link_libc, &sep))
+ try w.writeAll(if (ctx.link_libc) "libc" else "no-libc");
- if (scope.arch) try w.print("-{t}", .{ctx.target.result.cpu.arch});
- if (scope.os) try w.print("-{t}", .{ctx.target.result.os.tag});
- if (scope.abi) try w.print("-{t}", .{ctx.target.result.abi});
- if (scope.optimize) try w.print("-{t}", .{ctx.optimize});
- if (scope.use_llvm) try w.writeAll(if (ctx.use_llvm) "-llvm" else "-no-llvm");
- if (scope.use_lld) try w.writeAll(if (ctx.use_lld) "-lld" else "-no-lld");
- if (scope.link_libc) try w.writeAll(if (ctx.link_libc) "-libc" else "-no-libc");
- try w.writeAll(".dmp");
+ if (sep == '-') try w.writeByte('.');
+ try w.writeAll("dmp");
return try snapshot_name.toOwnedSlice();
}
+
+ fn snapshotNameInner(w: *std.Io.Writer, cond: bool, sep: *u8) !bool {
+ if (cond) {
+ try w.writeByte(sep.*);
+ sep.* = '-';
+ }
+
+ return cond;
+ }
};
fn createModule(self: *const Link, overlay: OverlayOptions) *Build.Module {
diff --git a/test/tests.zig b/test/tests.zig
@@ -2098,6 +2098,25 @@ const link_targets = blk: {
.target = .{
.cpu_arch = .x86_64,
.os_tag = .windows,
+ .abi = .gnu,
+ },
+ .use_llvm = true,
+ .use_lld = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
+ },
+ .link_libc = true,
+ .use_llvm = true,
+ .use_lld = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
.abi = .msvc,
},
},
@@ -2109,6 +2128,25 @@ const link_targets = blk: {
},
.link_libc = true,
},
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .msvc,
+ },
+ .use_llvm = true,
+ .use_lld = true,
+ },
+ .{
+ .target = .{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .msvc,
+ },
+ .link_libc = true,
+ .use_llvm = true,
+ .use_lld = true,
+ },
};
};