When you call addPackagePath
, it does not know anything about the lib
you created earlier - they use the same source code, but are aware of independent metadata. Calling addStaticLibrary
creates a library that can be linked, which, like in C, requires you to declare symbols for the linker to link.
Essentially, addStaticLibrary
, addExecutable
and addPackage[Path]
are all referring to independent entities.
E.g., if you were to do
const lib = b.addStaticLibrary("demo", "src/main.zig");
lib.addOptions("build_options", options);
const exe = b.addExecutable("caller", "caller.zig");
exe.linkLibrary(lib);
exe.install();
it would link any symbols export
ed by src/main.zig
(either directly or transitively), although it doesn’t in this example.
If all you want to do is create a source library, you needn’t make any call to addStaticLibrary
, thus your build.zig code can simply be:
const options = b.addOptions();
options.addOption(usize, "digits", 50);
const demo_pkg: std.build.Pkg = .{
.name = "demo",
.source = comptime .{ .path = std.fs.path.dirname(@src().file).? ++ std.fs.path.sep_str ++ "src/main.zig" },
.dependencies = &[_]std.build.Pkg{
.{ .name = "build_options", .source = options.getSource() },
},
};
const exe = b.addExecutable("caller", "caller.zig");
exe.addPackage(demo_pkg);
Often this is preferable if you’re only working with zig, as it allows you to leverage all the advantages of compiling zig (dead code elimination, comptime, root declaration awareness, async, etc).
If you need to interact with the ABI layer at all, that is when you may want to consider export
ing your functions, and/or linking functions as extern
:
// build.zig:build
const lib = b.addStaticLibrary("foo", "foo.zig");
const exe = b.addExecutable("bar", "bar.zig");
exe.linkLibrary(lib);
exe.install();
// foo.zig
export fn add(a: u32, b: u32) u32 {
return a +% b;
}
// bar.zig
const std = @import("std");
extern fn add(a: u32, b: u32) u32;
pub fn main() void {
std.debug.print("{}\n", .{add(1, 2)}); // should print 3
}
Also, I would recommend against exe.addObjectFile("./zig-out/lib/libdemo.a")
at all, as you end up relying on details that are opaque to the build system.