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 {...@@ -401,12 +401,13 @@ const coff = struct {
401 , .{ expected_kind, num_symbols });401 , .{ expected_kind, num_symbols });
402402
403 if (d.opts.linker_member == .first_linker) {403 if (d.opts.linker_member == .first_linker) {
404 try w.writeAll(404 if (d.element(.@"table-header"))
405 \\405 try w.writeAll(
406 \\Archive symbols:406 \\
407 \\& Member Symbol407 \\Archive symbols:
408 \\408 \\& Member Symbol
409 );409 \\
410 );
410411
411 const offsets = try r.readAlloc(gpa, num_symbols * 4);412 const offsets = try r.readAlloc(gpa, num_symbols * 4);
412 defer gpa.free(offsets);413 defer gpa.free(offsets);
test/link.zig+96-36
...@@ -1,29 +1,5 @@...@@ -1,29 +1,5 @@
1pub fn addCases(ctx: *LinkContext) void {1pub fn addCases(ctx: *LinkContext) void {
2 if (ctx.includeTest("exports-static")) |case| {2 if (ctx.includeTest("static-lib")) |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| {
27 const obj1 = case.addObject(.{3 const obj1 = case.addObject(.{
28 .name = "obj1",4 .name = "obj1",
29 .name_prefix = false,5 .name_prefix = false,
...@@ -43,14 +19,14 @@ pub fn addCases(ctx: *LinkContext) void {...@@ -43,14 +19,14 @@ pub fn addCases(ctx: *LinkContext) void {
43 .name_prefix = false,19 .name_prefix = false,
44 .name_target = false,20 .name_target = false,
45 .zig_source_bytes =21 .zig_source_bytes =
46 \\fn weakFoo() callconv(.c) usize {22 \\fn fooWeak() callconv(.c) usize {
47 \\ return 0xaabbccddaabbccdd;23 \\ return 0xaabbccddaabbccdd;
48 \\}24 \\}
49 \\export var array_foo: [2]u16 = .{ 0xffff, 0xabcd };25 \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd };
50 \\export var strong_foo: usize = 0x1122334411223344;26 \\export var foo_strong: usize = 0x1122334411223344;
51 \\comptime {27 \\comptime {
52 \\ @export(&weakFoo, .{ .name = "weakFoo", .linkage = .weak });28 \\ @export(&fooWeak, .{ .name = "fooWeak", .linkage = .weak });
53 \\ @export(&strong_foo, .{ .name = "strong_foo_alias", .linkage = .strong });29 \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong });
54 \\}30 \\}
55 ,31 ,
56 });32 });
...@@ -63,25 +39,109 @@ pub fn addCases(ctx: *LinkContext) void {...@@ -63,25 +39,109 @@ pub fn addCases(ctx: *LinkContext) void {
63 lib.root_module.addObject(obj1);39 lib.root_module.addObject(obj1);
64 lib.root_module.addObject(obj2);40 lib.root_module.addObject(obj2);
6541
66 case.verifyObjdump(lib, &.{42 case.verifyObjdump(lib.getEmittedBin(), &.{
67 "-s",43 "-s",
68 "--elements=file-type",44 "--elements=file-type",
69 "--symbols",45 "--symbols",
70 "--only-symbol=foo",46 "--only-symbol=foo",
71 "--only-symbol=Foo",
72 }, .{});47 }, .{});
7348
74 const exe = case.addExecutable(.{49 const exe = case.addExecutable(.{
75 .name = "test",50 .name = "test",
76 .zig_source_bytes =51 .zig_source_bytes =
77 \\extern fn fooBar() c_uint;52 \\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 =
79 \\extern var array_foo: [2]u16;140 \\extern var array_foo: [2]u16;
80 \\extern var strong_foo: usize;141 \\extern var strong_foo: usize;
81 \\extern var strong_foo_alias: usize;142 \\extern var strong_foo_alias: usize;
82 \\pub fn main() !u8 {143 \\pub fn main() !u8 {
83 \\ return @intFromBool(0xcd003365cd00df35 != fooBar() +144 \\ return @intFromBool(0x2244668822451255 !=
84 \\ weakFoo() +
85 \\ array_foo[1] +145 \\ array_foo[1] +
86 \\ strong_foo +146 \\ strong_foo +
87 \\ strong_foo_alias);147 \\ strong_foo_alias);
...@@ -118,7 +178,7 @@ pub fn addCases(ctx: *LinkContext) void {...@@ -118,7 +178,7 @@ pub fn addCases(ctx: *LinkContext) void {
118 ,178 ,
119 });179 });
120180
121 case.verifyObjdump(abs_reloc, &.{181 case.verifyObjdump(abs_reloc.getEmittedBin(), &.{
122 "-s",182 "-s",
123 "--relocs",183 "--relocs",
124 }, .{ .arch = true });184 }, .{ .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 {...@@ -101,7 +101,7 @@ pub const Case = struct {
101 }101 }
102102
103 const SnapshotScope = struct {103 const SnapshotScope = struct {
104 /// If a test case has multiple verifyObjdump calls, `opt_sub_name` can104 /// If a test case has multiple verifyObjdump calls, `opt_sub_name` should
105 /// be used to differentiate them.105 /// be used to differentiate them.
106 sub_name: ?[]const u8 = null,106 sub_name: ?[]const u8 = null,
107 arch: bool = false,107 arch: bool = false,
...@@ -120,7 +120,7 @@ pub const Case = struct {...@@ -120,7 +120,7 @@ pub const Case = struct {
120 ///120 ///
121 pub fn verifyObjdump(121 pub fn verifyObjdump(
122 self: *const Case,122 self: *const Case,
123 compile: *Step.Compile,123 file: Build.LazyPath,
124 args: []const []const u8,124 args: []const []const u8,
125 scope: SnapshotScope,125 scope: SnapshotScope,
126 ) void {126 ) void {
...@@ -140,7 +140,7 @@ pub const Case = struct {...@@ -140,7 +140,7 @@ pub const Case = struct {
140 .{ snapshot_name, ctx.target_desc },140 .{ snapshot_name, ctx.target_desc },
141 ));141 ));
142 run_step.addArgs(&.{ ctx.b.graph.zig_exe, "objdump" });142 run_step.addArgs(&.{ ctx.b.graph.zig_exe, "objdump" });
143 run_step.addArtifactArg(compile);143 run_step.addFileArg(file);
144 run_step.addArgs(args);144 run_step.addArgs(args);
145 run_step.addCheck(.{ .expect_term = .{ .exited = 0 } });145 run_step.addCheck(.{ .expect_term = .{ .exited = 0 } });
146146
...@@ -166,22 +166,39 @@ pub const Case = struct {...@@ -166,22 +166,39 @@ pub const Case = struct {
166 const w = &snapshot_name.writer;166 const w = &snapshot_name.writer;
167167
168 try w.writeAll(self.prefix);168 try w.writeAll(self.prefix);
169 if (scope.sub_name) |sub_name| {169 var sep: u8 = '.';
170 try w.writeByte('.');170
171 try w.writeAll(sub_name);171 if (try snapshotNameInner(w, scope.sub_name != null, &sep))
172 }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});188 if (sep == '-') try w.writeByte('.');
175 if (scope.os) try w.print("-{t}", .{ctx.target.result.os.tag});189 try w.writeAll("dmp");
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");
182190
183 return try snapshot_name.toOwnedSlice();191 return try snapshot_name.toOwnedSlice();
184 }192 }
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 }
185};202};
186203
187fn createModule(self: *const Link, overlay: OverlayOptions) *Build.Module {204fn createModule(self: *const Link, overlay: OverlayOptions) *Build.Module {
test/tests.zig+38
...@@ -2094,6 +2094,25 @@ const link_targets = blk: {...@@ -2094,6 +2094,25 @@ const link_targets = blk: {
2094 },2094 },
2095 .link_libc = true,2095 .link_libc = true,
2096 },2096 },
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 },
2097 .{2116 .{
2098 .target = .{2117 .target = .{
2099 .cpu_arch = .x86_64,2118 .cpu_arch = .x86_64,
...@@ -2109,6 +2128,25 @@ const link_targets = blk: {...@@ -2109,6 +2128,25 @@ const link_targets = blk: {
2109 },2128 },
2110 .link_libc = true,2129 .link_libc = true,
2111 },2130 },
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 },
2112 };2150 };
2113};2151};
21142152