authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-05 01:55:37-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2026-06-23 00:27:17-04:00
log72bc140ad16a4a2dbe632129ea9068630e019277
treeaeef79d6067addbf4d08c4be1a4fb12c8d6bbc09
parent7f0b5787fb1db871501bc4b03629d68dc378e038

test/link: separate out shared lib tests

- Fixup snapshot naming - Fixup verifyObjdumps so we can dump other artifacts - Add llvm link_targets for comparison

10 files changed, 218 insertions(+), 85 deletions(-)

lib/compiler/objdump.zig+7-6
......@@ -401,12 +401,13 @@ const coff = struct {
401401 , .{ expected_kind, num_symbols });
402402
403403 if (d.opts.linker_member == .first_linker) {
404 try w.writeAll(
405 \\
406 \\Archive symbols:
407 \\& Member Symbol
408 \\
409 );
404 if (d.element(.@"table-header"))
405 try w.writeAll(
406 \\
407 \\Archive symbols:
408 \\& Member Symbol
409 \\
410 );
410411
411412 const offsets = try r.readAlloc(gpa, num_symbols * 4);
412413 defer gpa.free(offsets);
test/link.zig+96-36
......@@ -1,29 +1,5 @@
11pub fn addCases(ctx: *LinkContext) void {
2 if (ctx.includeTest("exports-static")) |case| {
3 const lib = case.addLibrary(.static, .{
4 .name = "lib",
5 .zig_source_file = ctx.sourcePath("exports.zig"),
6 });
7 case.verifyObjdump(lib, &.{
8 "-s",
9 "--symbols",
10 "--only-symbol=foo",
11 }, .{});
12 }
13
14 if (ctx.includeTest("exports-dynamic")) |case| {
15 const lib = case.addLibrary(.dynamic, .{
16 .name = "lib",
17 .zig_source_file = ctx.sourcePath("exports.zig"),
18 });
19 case.verifyObjdump(lib, &.{
20 "-s",
21 "--exports",
22 "--only-symbol=foo",
23 }, .{});
24 }
25
26 if (ctx.includeTest("emit-static-lib")) |case| {
2 if (ctx.includeTest("static-lib")) |case| {
273 const obj1 = case.addObject(.{
284 .name = "obj1",
295 .name_prefix = false,
......@@ -43,14 +19,14 @@ pub fn addCases(ctx: *LinkContext) void {
4319 .name_prefix = false,
4420 .name_target = false,
4521 .zig_source_bytes =
46 \\fn weakFoo() callconv(.c) usize {
22 \\fn fooWeak() callconv(.c) usize {
4723 \\ return 0xaabbccddaabbccdd;
4824 \\}
49 \\export var array_foo: [2]u16 = .{ 0xffff, 0xabcd };
50 \\export var strong_foo: usize = 0x1122334411223344;
25 \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd };
26 \\export var foo_strong: usize = 0x1122334411223344;
5127 \\comptime {
52 \\ @export(&weakFoo, .{ .name = "weakFoo", .linkage = .weak });
53 \\ @export(&strong_foo, .{ .name = "strong_foo_alias", .linkage = .strong });
28 \\ @export(&fooWeak, .{ .name = "fooWeak", .linkage = .weak });
29 \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong });
5430 \\}
5531 ,
5632 });
......@@ -63,25 +39,109 @@ pub fn addCases(ctx: *LinkContext) void {
6339 lib.root_module.addObject(obj1);
6440 lib.root_module.addObject(obj2);
6541
66 case.verifyObjdump(lib, &.{
42 case.verifyObjdump(lib.getEmittedBin(), &.{
6743 "-s",
6844 "--elements=file-type",
6945 "--symbols",
7046 "--only-symbol=foo",
71 "--only-symbol=Foo",
7247 }, .{});
7348
7449 const exe = case.addExecutable(.{
7550 .name = "test",
7651 .zig_source_bytes =
7752 \\extern fn fooBar() c_uint;
78 \\extern fn weakFoo() usize;
53 \\extern fn fooWeak() usize;
54 \\extern var foo_array: [2]u16;
55 \\extern var foo_strong: usize;
56 \\extern var foo_strong_alias: usize;
57 \\pub fn main() !u8 {
58 \\ return @intFromBool(0xcd003365cd00df35 != fooBar() +
59 \\ fooWeak() +
60 \\ foo_array[1] +
61 \\ foo_strong +
62 \\ foo_strong_alias);
63 \\}
64 ,
65 });
66 exe.root_module.linkLibrary(lib);
67
68 const run = case.addRunArtifact(exe);
69 run.addCheck(.{ .expect_term = .{ .exited = 0 } });
70 }
71
72 if (ctx.includeTest("dynamic-lib-code")) |case| {
73 const lib = case.addLibrary(.dynamic, .{
74 .name = "lib",
75 .zig_source_bytes =
76 \\export fn foo1() callconv(.c) u64 {
77 \\ return 0x1122334411223344;
78 \\}
79 \\export fn foo2() callconv(.c) u64 {
80 \\ return 0xaabbccddaabbccdd;
81 \\}
82 ,
83 });
84
85 case.verifyObjdump(lib.getEmittedBin(), &.{
86 "-s",
87 "--exports",
88 "--only-symbol=foo",
89 }, .{ .os = true });
90
91 if (ctx.target.result.os.tag == .windows) {
92 case.verifyObjdump(lib.getEmittedImplib(), &.{
93 "-s",
94 "--exports",
95 "--only-symbol=foo",
96 }, .{ .sub_name = "implib", .os = true });
97 }
98
99 const exe = case.addExecutable(.{
100 .name = "test",
101 .zig_source_bytes =
102 \\extern fn foo1() u64;
103 \\pub fn main() !u8 {
104 \\ const foo2 = @extern(
105 \\ *const fn () callconv(.c) u64,
106 \\ .{ .name = "foo2", .is_dll_import = true },
107 \\ );
108 \\ return @intFromBool(0xbbde0021bbde0021 != foo1() + foo2());
109 \\}
110 ,
111 });
112 exe.root_module.linkLibrary(lib);
113
114 const run = case.addRunArtifact(exe);
115 run.addCheck(.{ .expect_term = .{ .exited = 0 } });
116 }
117
118 if (ctx.includeTest("dynamic-lib-data")) |case| {
119 const lib = case.addLibrary(.dynamic, .{
120 .name = "lib",
121 .zig_source_bytes =
122 \\export var array_foo: [2]u16 = .{ 0xffff, 0xabcd };
123 \\export var strong_foo: usize = 0x1122334411223344;
124 ,
125 });
126
127 case.verifyObjdump(lib.getEmittedBin(), &.{
128 "-s",
129 "--exports",
130 "--only-symbol=foo",
131 }, .{});
132
133 if (ctx.target.result.os.tag == .windows) {
134 // TODO: objdump implib on windows
135 }
136
137 const exe = case.addExecutable(.{
138 .name = "test",
139 .zig_source_bytes =
79140 \\extern var array_foo: [2]u16;
80141 \\extern var strong_foo: usize;
81142 \\extern var strong_foo_alias: usize;
82143 \\pub fn main() !u8 {
83 \\ return @intFromBool(0xcd003365cd00df35 != fooBar() +
84 \\ weakFoo() +
144 \\ return @intFromBool(0x2244668822451255 !=
85145 \\ array_foo[1] +
86146 \\ strong_foo +
87147 \\ strong_foo_alias);
......@@ -118,7 +178,7 @@ pub fn addCases(ctx: *LinkContext) void {
118178 ,
119179 });
120180
121 case.verifyObjdump(abs_reloc, &.{
181 case.verifyObjdump(abs_reloc.getEmittedBin(), &.{
122182 "-s",
123183 "--relocs",
124184 }, .{ .arch = true });
test/link/snapshots/abs-symbol-x86_64.dmp deleted-1
......@@ -1 +0,0 @@
1xxxxxxxx ADDR32 xxxxxxxx UNDEF | foo
test/link/snapshots/dynamic-lib-code.implib-windows.dmp created+32
......@@ -0,0 +1,32 @@
1 0 date
2 0 user_id
3 0 group_id
4 0 file_mode
5xxxxxxxxxxxxxxxx size
6 second_linker type
7 | 7 symbols
8 | 5 members
9xxxxxxxx __imp_foo1
10xxxxxxxx __imp_foo2
11xxxxxxxx foo1
12xxxxxxxx foo2
13 0 version
14 8664 machine (AMD64)
15 0 time_date_stamp
16xxxxxxxxxxxxxxxx size_of_data
17 0 hint
18 CODE import_type
19 NAME name_type
20 symbol name | foo1
21 import name | foo1
22 dll | dynamic-lib-code-lib-x86_64-windows.win10...win11_dt-msvc-Debug-llvm-lld-libc.dll
23 0 version
24 8664 machine (AMD64)
25 0 time_date_stamp
26xxxxxxxxxxxxxxxx size_of_data
27 0 hint
28 CODE import_type
29 NAME name_type
30 symbol name | foo2
31 import name | foo2
32 dll | dynamic-lib-code-lib-x86_64-windows.win10...win11_dt-msvc-Debug-llvm-lld-libc.dll
test/link/snapshots/dynamic-lib-code.windows.dmp created+13
......@@ -0,0 +1,13 @@
1Export directory:
2 0 flags
3 0 time_date_stamp
4 0.00 version
5xxxxxxxxxxxxxxxx name_rva
6 1 ordinal_base
7xxxxxxxxxxxxxxxx number_of_entries
8xxxxxxxxxxxxxxxx number_of_names
9xxxxxxxxxxxxxxxx export_address_table_rva
10xxxxxxxxxxxxxxxx name_pointer_table_rva
11xxxxxxxxxxxxxxxx ordinal_table_rva
12xxxx xxxx xxxxxxxx | foo1
13xxxx xxxx xxxxxxxx | foo2
test/link/snapshots/emit-static-lib.dmp deleted-10
......@@ -1,10 +0,0 @@
1lib.lib: COFF archive
2lib.lib(obj1.obj): COFF object
3xxxx 00000000 1 NULL() EXTERNAL | fooBar
4xxxx 00000000 2 NULL EXTERNAL | foo1
5xxxx 00000004 2 NULL EXTERNAL | foo2
6lib.lib(this_is_a_long_name.obj): COFF object
7xxxx 00000000 4 NULL() EXTERNAL | weakFoo
8xxxx 00000010 2 NULL EXTERNAL | array_foo
9xxxx 00000000 2 NULL EXTERNAL | strong_foo_alias
10xxxx 00000000 2 NULL EXTERNAL | strong_foo
test/link/snapshots/exports-dynamic.dmp deleted-14
......@@ -1,14 +0,0 @@
1Export directory:
2 0 flags
3 0 time_date_stamp
4 0.00 version
5xxxxxxxxxxxxxxxx name_rva
6 1 ordinal_base
7xxxxxxxxxxxxxxxx number_of_entries
8xxxxxxxxxxxxxxxx number_of_names
9xxxxxxxxxxxxxxxx export_address_table_rva
10xxxxxxxxxxxxxxxx name_pointer_table_rva
11xxxxxxxxxxxxxxxx ordinal_table_rva
12xxxx xxxx xxxxxxxx | foo_const
13xxxx xxxx xxxxxxxx | foo_fn
14xxxx xxxx xxxxxxxx | foo_var
test/link/snapshots/exports-static.dmp deleted-3
......@@ -1,3 +0,0 @@
1xxxx 00000000 4 NULL() EXTERNAL | foo_fn
2xxxx 00000000 2 NULL EXTERNAL | foo_var
3xxxx 00000008 3 NULL EXTERNAL | foo_const
test/src/Link.zig+32-15
......@@ -101,7 +101,7 @@ pub const Case = struct {
101101 }
102102
103103 const SnapshotScope = struct {
104 /// If a test case has multiple verifyObjdump calls, `opt_sub_name` can
104 /// If a test case has multiple verifyObjdump calls, `opt_sub_name` should
105105 /// be used to differentiate them.
106106 sub_name: ?[]const u8 = null,
107107 arch: bool = false,
......@@ -120,7 +120,7 @@ pub const Case = struct {
120120 ///
121121 pub fn verifyObjdump(
122122 self: *const Case,
123 compile: *Step.Compile,
123 file: Build.LazyPath,
124124 args: []const []const u8,
125125 scope: SnapshotScope,
126126 ) void {
......@@ -140,7 +140,7 @@ pub const Case = struct {
140140 .{ snapshot_name, ctx.target_desc },
141141 ));
142142 run_step.addArgs(&.{ ctx.b.graph.zig_exe, "objdump" });
143 run_step.addArtifactArg(compile);
143 run_step.addFileArg(file);
144144 run_step.addArgs(args);
145145 run_step.addCheck(.{ .expect_term = .{ .exited = 0 } });
146146
......@@ -166,22 +166,39 @@ pub const Case = struct {
166166 const w = &snapshot_name.writer;
167167
168168 try w.writeAll(self.prefix);
169 if (scope.sub_name) |sub_name| {
170 try w.writeByte('.');
171 try w.writeAll(sub_name);
172 }
169 var sep: u8 = '.';
170
171 if (try snapshotNameInner(w, scope.sub_name != null, &sep))
172 try w.writeAll(scope.sub_name.?);
173 if (try snapshotNameInner(w, scope.arch, &sep))
174 try w.print("{t}", .{ctx.target.result.cpu.arch});
175 if (try snapshotNameInner(w, scope.os, &sep))
176 try w.print("{t}", .{ctx.target.result.os.tag});
177 if (try snapshotNameInner(w, scope.abi, &sep))
178 try w.print("{t}", .{ctx.target.result.abi});
179 if (try snapshotNameInner(w, scope.optimize, &sep))
180 try w.print("{t}", .{ctx.optimize});
181 if (try snapshotNameInner(w, scope.use_llvm, &sep))
182 try w.writeAll(if (ctx.use_llvm) "llvm" else "no-llvm");
183 if (try snapshotNameInner(w, scope.use_lld, &sep))
184 try w.writeAll(if (ctx.use_lld) "lld" else "no-lld");
185 if (try snapshotNameInner(w, scope.link_libc, &sep))
186 try w.writeAll(if (ctx.link_libc) "libc" else "no-libc");
173187
174 if (scope.arch) try w.print("-{t}", .{ctx.target.result.cpu.arch});
175 if (scope.os) try w.print("-{t}", .{ctx.target.result.os.tag});
176 if (scope.abi) try w.print("-{t}", .{ctx.target.result.abi});
177 if (scope.optimize) try w.print("-{t}", .{ctx.optimize});
178 if (scope.use_llvm) try w.writeAll(if (ctx.use_llvm) "-llvm" else "-no-llvm");
179 if (scope.use_lld) try w.writeAll(if (ctx.use_lld) "-lld" else "-no-lld");
180 if (scope.link_libc) try w.writeAll(if (ctx.link_libc) "-libc" else "-no-libc");
181 try w.writeAll(".dmp");
188 if (sep == '-') try w.writeByte('.');
189 try w.writeAll("dmp");
182190
183191 return try snapshot_name.toOwnedSlice();
184192 }
193
194 fn snapshotNameInner(w: *std.Io.Writer, cond: bool, sep: *u8) !bool {
195 if (cond) {
196 try w.writeByte(sep.*);
197 sep.* = '-';
198 }
199
200 return cond;
201 }
185202};
186203
187204fn createModule(self: *const Link, overlay: OverlayOptions) *Build.Module {
test/tests.zig+38
......@@ -2094,6 +2094,25 @@ const link_targets = blk: {
20942094 },
20952095 .link_libc = true,
20962096 },
2097 .{
2098 .target = .{
2099 .cpu_arch = .x86_64,
2100 .os_tag = .windows,
2101 .abi = .gnu,
2102 },
2103 .use_llvm = true,
2104 .use_lld = true,
2105 },
2106 .{
2107 .target = .{
2108 .cpu_arch = .x86_64,
2109 .os_tag = .windows,
2110 .abi = .gnu,
2111 },
2112 .link_libc = true,
2113 .use_llvm = true,
2114 .use_lld = true,
2115 },
20972116 .{
20982117 .target = .{
20992118 .cpu_arch = .x86_64,
......@@ -2109,6 +2128,25 @@ const link_targets = blk: {
21092128 },
21102129 .link_libc = true,
21112130 },
2131 .{
2132 .target = .{
2133 .cpu_arch = .x86_64,
2134 .os_tag = .windows,
2135 .abi = .msvc,
2136 },
2137 .use_llvm = true,
2138 .use_lld = true,
2139 },
2140 .{
2141 .target = .{
2142 .cpu_arch = .x86_64,
2143 .os_tag = .windows,
2144 .abi = .msvc,
2145 },
2146 .link_libc = true,
2147 .use_llvm = true,
2148 .use_lld = true,
2149 },
21122150 };
21132151};
21142152