I’m trying to create a simple lib in a “standard” Zig way, with build.zig and zon files. I read the official build system guide but unfortunately it didn’t help because I couldn’t learn the underlying concepts like what the steps and modules are, how the tree is built, etc. Reading sources made some hints but I don’t see a picture yet. Also, I read a related topic but it doesn’t cover some of my cases.
For clarity, suppose there is a simple “testlib” folder with a single src/lib.zig
file and a function add()
inside (generated by zig init
). This lib I’m importing from within “testapp” folder, src/main.zig
file:
~/testapp $ ls
src
build.zib
build.zig.zon
~/testapp $ cat src/main.zig
const std = @import("std");
const testlib = @import("testlib");
pub fn main() !void {
if (testlib.add(1, 3) != 4) return error.Error;
}
~/testapp $ cat build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "testapp",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// This actually works, so I guess the third item in the questionnaire is resolved.
const lib_mod = b.addModule("testlib", .{
.root_source_file = .{ .path = "../testlib/src/lib.zig" },
});
exe.root_module.addImport("testlib", lib_mod);
b.installArtifact(exe);
// (addon 1) I saw it somewhere but didn't find any documentation on how to use it:
// const lib_mod = b.dependency("testlib", .{ .target = target }).module("testlib");
// (addon 2) Even though, I know it would be a bad practice, I would like to
// run the exe right after it was installed with `zig build`
// I tried it with this:
// const run_cmd = b.addRunArtifact(exe);
// run_cmd.step.dependOn(b.getInstallStep());
// exe.step.dependOn(run_cmd.step);
// But got failed with that:
// dependency loop detected:
// zig build-exe out Debug native
// run out
// zig build-exe out Debug native
// install out
// install
}
~/testapp $ cat build.zig.zon
.{
.name = "testapp",
.version = "0.1.0",
.dependencies = .{
.testlib = .{
.url = "../testlib",
.hash = "122044d7646b9f7171bbd07e4a7d749b09be2f2754552d5dc7ba64e92330063feb09",
},
},
.paths = .{"src"},
}
~/testlib $ ls
src
build.zib
build.zig.zon
~/testlib $ cat src/lib.zig
const std = @import("std");
const testing = std.testing;
pub export fn add(a: i32, b: i32) i32 {
return a + b;
}
test "basic add functionality" {
try testing.expect(add(3, 7) == 10);
}
~/testlib $ cat build.zig.zon
.{
.name = "testlib",
.version = "0.1.0",
.paths = .{
"build.zig",
"build.zig.zon",
"src",
//"LICENSE",
//"README.md",
},
}
The error I get sometimes while importing testlib
namespace but not actually providing it is:
error: no module named 'testlib' available within module root
So, what I would love to understand is how to import and compile an external library for the testapp in three different ways:
Importing directly a source file(that is clear)- Importing with CLI, i.e.
zig run main.zig --flag [options] testlib
- Importing with
zig fetch --save
into build.zig.zon and setting up build.zig - Importing with just build.zig, without relying on lib’s or app’s zon files
Also, commenting on the addons above would be very helpful as well as any conceptual breakdowns.