╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ link.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
4 5 if (ctx.includeTest("static-lib")) |case| { 6 const obj1 = case.addObject(.{ 7 .name = "obj1", 8 .name_prefix = false, 9 .name_target = false, 10 .use_llvm = true, 11 .use_lld = true, 12 .c_source_bytes = 13 \\int foo1 = 1; 14 \\int foo2 = 2; 15 \\unsigned int fooBar() { 16 \\ return foo1 + foo2; 17 \\} 18 , 19 }); 20 const obj2 = case.addObject(.{ 21 .name = "this_is_a_long_name", 22 .name_prefix = false, 23 .name_target = false, 24 .zig_source_bytes = 25 \\fn fooWeak() callconv(.c) usize { 26 \\ return 0xaabbccddaabbccdd; 27 \\} 28 \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd }; 29 \\export var foo_strong: usize = 0x1122334411223344; 30 \\comptime { 31 \\ @export(&fooWeak, .{ .name = "fooWeak", .linkage = .weak }); 32 \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong }); 33 \\} 34 , 35 }); 36 37 const lib = case.addLibrary(.static, .{ 38 .name = "lib", 39 .name_prefix = false, 40 .name_target = false, 41 }); 42 lib.root_module.addObject(obj1); 43 lib.root_module.addObject(obj2); 44 45 case.verifyObjdump(lib.getEmittedBin(), &.{ 46 "-s", 47 "--elements=file-type", 48 "--symbols", 49 "--only-symbol=foo", 50 }, .{ .use_llvm = true }); 51 52 const exe = case.addExecutable(.{ 53 .name = "test", 54 .zig_source_bytes = 55 \\extern fn fooBar() c_uint; 56 \\extern fn fooWeak() usize; 57 \\extern var foo_array: [2]u16; 58 \\extern var foo_strong: usize; 59 \\extern var foo_strong_alias: usize; 60 \\pub fn main() !u8 { 61 \\ return @intFromBool(0xcd003365cd00df35 != fooBar() + 62 \\ fooWeak() + 63 \\ foo_array[1] + 64 \\ foo_strong + 65 \\ foo_strong_alias); 66 \\} 67 , 68 }); 69 exe.root_module.linkLibrary(lib); 70 71 const run = case.addRunArtifact(exe); 72 run.addCheck(.{ .expect_term = .{ .exited = 0 } }); 73 } 74 75 if (ctx.includeTest("tls")) |case| { 76 const obj = case.addObject(.{ 77 .name = "obj", 78 .zig_source_bytes = 79 \\threadlocal var threadlocal_var: u32 = 1234; 80 \\threadlocal var threadlocal_arr: [4]u16 = .{ 0x1111, 0x2222, 0x3333, 0x4444, }; 81 \\export fn threadlocal_read(a: *u32, b: *u16) void { 82 \\ a.* = threadlocal_var; 83 \\ b.* = threadlocal_arr[3]; 84 \\} 85 \\export fn threadlocal_write(a: u32, b: u16) void { 86 \\ threadlocal_var = a; 87 \\ threadlocal_arr[3] = b; 88 \\} 89 , 90 }); 91 92 case.verifyObjdump(obj.getEmittedBin(), &.{ 93 "-s", 94 "--symbols", 95 "--only-symbol=threadlocal", 96 "--only-symbol=tls", 97 }, .{ .use_llvm = true }); 98 99 const exe = case.addExecutable(.{ 100 .name = "test", 101 .zig_source_bytes = 102 \\extern fn threadlocal_read(a: *u32, b: *u16) void; 103 \\extern fn threadlocal_write(a: u32, b: u16) void; 104 \\threadlocal var threadlocal_foo: u64 = 0xcafecafecafecafe; 105 \\pub fn main() !u8 { 106 \\ var a: u32 = undefined; 107 \\ var b: u16 = undefined; 108 \\ threadlocal_read(&a, &b); 109 \\ if (a != 1234 or b != 0x4444) return 1; 110 \\ if (threadlocal_foo != 0xcafecafecafecafe) return 2; 111 \\ threadlocal_write(0xabcdabcd, 0x5555); 112 \\ threadlocal_foo = 1; 113 \\ threadlocal_read(&a, &b); 114 \\ if (a != 0xabcdabcd or b != 0x5555) return 3; 115 \\ if (threadlocal_foo != 1) return 4; 116 \\ return 0; 117 \\} 118 , 119 }); 120 exe.root_module.addObject(obj); 121 122 const run = case.addRunArtifact(exe); 123 run.addCheck(.{ .expect_term = .{ .exited = 0 } }); 124 } 125 126 if (ctx.includeTest("dynamic-lib-code")) |case| { 127 const lib = case.addLibrary(.dynamic, .{ 128 .name = "lib", 129 .name_target = false, 130 .zig_source_bytes = 131 \\export fn foo1() callconv(.c) u64 { 132 \\ return 0x1122334411223344; 133 \\} 134 \\export fn foo2() callconv(.c) u64 { 135 \\ return 0xaabbccddaabbccdd; 136 \\} 137 , 138 }); 139 140 case.verifyObjdump(lib.getEmittedBin(), &.{ 141 "-s", 142 "--exports", 143 "--only-symbol=foo", 144 }, .{ .os = true }); 145 146 if (ctx.target.result.os.tag == .windows) { 147 case.verifyObjdump(lib.getEmittedImplib(), &.{ 148 "-s", 149 "--exports=sort", 150 "--only-symbol=foo", 151 }, .{ .sub_name = "implib", .os = true, .arch = true }); 152 } 153 154 const exe = case.addExecutable(.{ 155 .name = "test", 156 .zig_source_bytes = 157 \\extern fn foo1() u64; 158 \\pub fn main() !u8 { 159 \\ const foo2 = @extern( 160 \\ *const fn () callconv(.c) u64, 161 \\ .{ .name = "foo2", .is_dll_import = true }, 162 \\ ); 163 \\ return @intFromBool(0xbbde0021bbde0021 != foo1() + foo2()); 164 \\} 165 , 166 }); 167 exe.root_module.linkLibrary(lib); 168 169 const run = case.addRunArtifact(exe); 170 run.addCheck(.{ .expect_term = .{ .exited = 0 } }); 171 } 172 173 if (ctx.includeTest("dynamic-lib-data")) |case| { 174 const lib = case.addLibrary(.dynamic, .{ 175 .name = "lib", 176 .name_target = false, 177 .zig_source_bytes = 178 \\export var foo_array: [2]u16 = .{ 0xffff, 0xabcd }; 179 \\export var foo_strong: usize = 0x1122334411223344; 180 \\comptime { 181 \\ @export(&foo_strong, .{ .name = "foo_strong_alias", .linkage = .strong }); 182 \\} 183 , 184 }); 185 186 case.verifyObjdump(lib.getEmittedBin(), &.{ 187 "-s", 188 "--exports", 189 "--only-symbol=foo", 190 }, .{}); 191 192 if (ctx.target.result.os.tag == .windows) { 193 case.verifyObjdump(lib.getEmittedImplib(), &.{ 194 "-s", 195 "--exports=sort", 196 "--only-symbol=foo", 197 }, .{ .sub_name = "implib", .os = true, .arch = true }); 198 } 199 200 const exe = case.addExecutable(.{ 201 .name = "test", 202 .zig_source_bytes = 203 \\pub fn main() !u8 { 204 \\ const foo_array = @extern(*[2]u16, .{ .name = "foo_array", .is_dll_import = true }); 205 \\ const foo_strong = @extern(*usize, .{ .name = "foo_strong", .is_dll_import = true }); 206 \\ const foo_strong_alias = @extern(*usize, .{ .name = "foo_strong_alias", .is_dll_import = true }); 207 \\ return @intFromBool(0x2244668822451255 != 208 \\ foo_array[1] + 209 \\ foo_strong.* + 210 \\ foo_strong_alias.*); 211 \\} 212 , 213 }); 214 exe.root_module.linkLibrary(lib); 215 216 const run = case.addRunArtifact(exe); 217 run.addCheck(.{ .expect_term = .{ .exited = 0 } }); 218 } 219 220 if (ctx.includeTest("abs-symbol")) |case| { 221 const abs = case.addObject(.{ 222 .name = "abs", 223 .use_llvm = true, // TODO: .globl not supported on self-hosted 224 .use_lld = true, 225 .asm_source_bytes = 226 \\.globl foo 227 \\foo = 0xcafecafe 228 \\ 229 , 230 }); 231 232 const abs_reloc = case.addObject(.{ 233 .name = "abs_reloc", 234 .use_llvm = true, // TODO: .globl not supported on self-hosted 235 .use_lld = true, 236 .asm_source_bytes = 237 \\.data 238 \\.globl foo_copy 239 \\foo_copy: 240 \\.long foo 241 , 242 }); 243 244 case.verifyObjdump(abs_reloc.getEmittedBin(), &.{ 245 "-s", 246 "--relocs", 247 }, .{ .arch = true }); 248 249 const exe = case.addExecutable(.{ 250 .name = "test", 251 .zig_source_bytes = 252 \\extern var foo_copy: u32; 253 \\pub fn main() !u8 { 254 \\ return @intFromBool(foo_copy != 0xcafecafe); 255 \\} 256 , 257 }); 258 exe.root_module.addObject(abs); 259 exe.root_module.addObject(abs_reloc); 260 261 const run = case.addRunArtifact(exe); 262 run.addCheck(.{ .expect_term = .{ .exited = 0 } }); 263 264 if (!ctx.use_llvm) { 265 const exe_reloc_err = case.addExecutable(.{ 266 .name = "test-reloc-err", 267 .zig_source_bytes = 268 \\extern const foo: u32; 269 \\pub fn main() !u8 { 270 \\ return @intFromBool(foo != 0xcafecafe); 271 \\} 272 , 273 }); 274 exe_reloc_err.root_module.addObject(abs); 275 case.expectLinkErrors(exe_reloc_err, .{ 276 .contains = "error: absolute symbol 'foo' targeted by invalid relocation type: /?/", 277 }); 278 } 279 } 280 281 if (ctx.includeTest("explicit-extern-lib-name")) |case| { 282 // TODO: Lld.zig does not look at explicit inputs to resolve explicit extern lib names 283 if (ctx.use_llvm) return; 284 285 const lib1 = case.addLibrary(.dynamic, .{ 286 .name = "lib1", 287 .name_target = false, 288 .zig_source_bytes = 289 \\export fn foo() u8 { 290 \\ return 43; 291 \\} 292 , 293 }); 294 295 const lib2 = case.addLibrary(.dynamic, .{ 296 .name = "lib2", 297 .name_target = false, 298 .zig_source_bytes = 299 \\export fn foo() u8 { 300 \\ return 42; 301 \\} 302 , 303 }); 304 305 const lib3 = case.addLibrary(.static, .{ 306 .name = "lib3", 307 .zig_source_bytes = 308 \\extern fn foo() u8; 309 \\export fn callFoo() u8 { 310 \\ return foo(); 311 \\} 312 , 313 }); 314 315 const exe = case.addExecutable(.{ 316 .name = "test", 317 .zig_source_bytes = 318 \\extern "explicit-extern-lib-name-lib2" fn foo() u8; 319 \\extern fn callFoo() u8; 320 \\pub fn main() !u8 { 321 \\ return foo() + callFoo(); 322 \\} 323 , 324 }); 325 exe.root_module.linkLibrary(lib1); 326 exe.root_module.linkLibrary(lib2); 327 // exe.root_module.addLibraryPath(.{ 328 // .generated = .{ 329 // .index = lib2.getEmittedBin().generated.index, 330 // .up = 1, 331 // }, 332 // }); 333 exe.root_module.linkLibrary(lib3); 334 335 const run = case.addRunArtifact(exe); 336 run.addCheck(.{ .expect_term = .{ .exited = 84 } }); 337 } 338 } 339 340 const LinkContext = @import("tests.zig").LinkContext; 341 const std = @import("std"); 342