Tests building fails due to lack of C library linking

My build.zig (fragment):

const exe_tests = b.addTest("src/tests.zig");
exe_tests.addLibraryPath("/path/to/lua/libs");
exe_tests.linkLibC();
exe_tests.linkSystemLibrary("lua");
exe_tests.setTarget(target);
exe_tests.setBuildMode(mode);

The src/tests.zig file:

test {
  _ = @import("lua_test.zig");
}

lua_test.zig:

const std = @import("std");
const testing = std.testing;
const expect = testing.expect;

const lua = @import("lua.zig");

// and then the tests...

lua.zig:

extern "c" fn luaL_newstate() ?*Lua;
extern "c" fn luaL_openlibs(lua: *Lua) void;
extern "c" fn lua_close(lua: *Lua) void;

// ...and so on...

When I try the command:

$ zig test src/tests.zig -lc -llua -L/path/to/lua/libs

everything works fine.

The following command, though (without the flags):

$ zig test src/tests.zig

fails miserably with message:

src/lua.zig:10:8: error: dependency on libc must be explicitly specified in the build command
extern "c" fn lua_close(lua: *Lua) void;
       ^~~

lua_close is the first/only C function called in the tests (I suppose).

Why? What am I doing wrong?

In general, it’s not a big problem to provide the build flags, yet it would be more convenient to have fully working build.zig file.

Does it make a difference if you drop the "c", like below?

extern fn lua_close(lua: *Lua) void;

EDIT: uhh, scratch that. I thought “c” is not required but looks like it indeed is used in the Zig docs.

Could it be that something in the lua C library depends on C run-time and when the linker detects that, you get this error message?

I’m not sure I understand your comment.

I have no problem linking both the C library and lua (static library) with flags, passed to the zig test command. Everything works.

My question is rather why those flags have to be passed at all? In my build.zig file I have specified both dependencies for the test:

exe_tests.addLibraryPath("/path/to/lua/libs");
exe_tests.linkLibC();
exe_tests.linkSystemLibrary("lua");

Did I do it wrong? Why, having those dependencies stated in build.zig file, it is still needed to pass those flags to the zig test command?

BTW, I have also specified the same dependencies for my executable app, and it works as intented, by the zig build command, without passing any flags. That’s why I don’t understand, why those flags are needed for the zig test command.

It’s been my experience that running zig test some-source.zig bypasses the build.zig file entirely. That’d be my guess why you have to specify those options when you run zig test. I run my tests through zig build test which uses build.zig to build the test executable.

zig build test - that was it.

Silly me.

Thanx!

1 Like