Zig 0.12.0 fails to link against dynamic library on MacOS
Zig Version
0.12.0
Steps to Reproduce and Observed Behavior
Zig fails to link against a dynamic library when it is passed by filename on the command-line, i.e. a command like
$ zig build-lib some-dir/libadd.dylib main.zig
fails with an error of the form
error: unknown file type for an object file
note: while parsing some-dir/libadd.dylib
However, it succeeds when instead using -L and -l flags as follows
$ zig build-lib -Lsome-dir -ladd main.zig
See https://github.com/aherrmann/rules_zig/issues/274 for further details.
Note, this used to work with Zig 0.11.0. So, this is a regression.
Expected Behavior
The linking should succeed with both types of commands. For reference zig build-lib --help states:
Supported file types:
.zig Zig source code
...
.dylib Mach-O (macOS) dynamic library
...
You need to specify -dynamic to generate dynamic library files.
Although in 0.11.0 you can generate libmain.a by zig build-lib libadd.dylib main.zig, it is an incorrect archive file. If you check its contents by ar t libmain.a, you will find that libadd.dylib is packaged together, and this file cannot be compiled into an executable file by clang.
$ zig version
0.11.0
$ cat add.c
int add(int a, int b) {
return a + b;
}
$ cat main.zig
const std = @import("std");
const print = std.debug.print;
export fn greet() void {
const sum = add(1, 2);
print("{}\n", .{sum});
}
extern fn add(a: c_int, b: c_int) callconv(.C) c_int;
$ clang add.c -shared -o libadd.dylib
$ zig build-lib libadd.dylib main.zig
$ ar t libmain.a
__.SYMDEF
libadd.dylib
./libmain.a.o
$ cat entry.c
void greet();
int main() {
greet();
}
$ clang libmain.a entry.c
ld: warning: archive member is not an object file
ld: warning: object file (libmain.a[3](./libmain.a.o)) was built for newer 'macOS' version (14.4.1) than being linked (14.0)
Undefined symbols for architecture arm64:
"_add", referenced from:
_greet in libmain.a.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I can't decide whether to set the output mode to dynamic library when compiling with dynamic library files in Zig to avoid generating invalid files.
Thanks for clarifying! I misunderstood what Zig's behavior should be in this case. In the dynamic library case
zig build-lib -dynamic libadd.dylib main.zig
will generate libmain.dylib such that it links dynamically against libadd.dylib.
$ otool -l libmain.dylib | grep libadd
name libadd.dylib (offset 24)
I assumed that in the static case it would also not attempt to include libadd.dylib into the archive. But, it seems it does.
It looks like if the intent is to maintain libadd.dylib as a dynamic dependency then the correct build-lib command omits libadd.dylib altogether.
zig build-lib main.zig