Assuming following folder structure:
src/
lib.zig
module_a/
file_a.zig
file_a_test.zig
module_b/
file_b.zig
file_b_test.zig
tools/
tools.zig
tools_test.zig
How should I structure my build.zig
in order to be somehow able to use:
const tools = @import("tools")
in my two other modules: module_a
and module_b
?
I also want to be able to run the tests somehow, so they don't break, for example in this fassion:
zig test src/module_a/file_a_test.zig
This is NOT an application, I don't have a main.zig
file.
I can have a lib.zig
file though somewhere under src
directory if it's needed.
Tried to look for a simple answer on Reddit and on StackOverflow, but couldn't find any. All the solutions use either an old std.build.Pkg
system, or b.addModule
but with a main.zig
build target.
Ok, so eventually I was able to figure this one out, but there could be some kind of a tutorial about this, because this was a trial and error.
So I've managed to add a main testing file to my file structure and it now looks like this:
src/
lib.zig
lib_test.zig
module_a/
file_a.zig
file_a_test.zig
module_b/
file_b.zig
file_b_test.zig
tools/
tools.zig
tools_test.zig
The content of lib_test.zig
is as follows:
const std = @import("std");
test {
_ = @import("module_a/file_a_test.zig");
_ = @import("module_b/file_b_test.zig");
_ = @import("tools/tools_test.zig");
}
test "my custom lib test" {
try std.testing.assert(1 == 1)
}
And my content of build.zig
is like this:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const tools = b.addModule("tools", .{ .source_file = .{ .path = "src/tools/tools.zig" } });
const module_a = b.addModule("module-a", .{ .source_file = .{ .path = "src/module_a/file_a.zig" } });
const module_b = b.addModule("module-b", .{ .source_file = .{ .path = "src/module_b/file_b.zig" } });
const unit_tests = b.addTest(.{
.root_source_file = .{ .path = "src/lib_test.zig" },
.target = target,
.optimize = optimize,
});
unit_tests.addModule("tools", tools);
unit_tests.addModule("module-a", module_a);
unit_tests.addModule("module-b", module_b);
const run_unit_tests = b.addRunArtifact(unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_unit_tests.step);
}
So we have to create our tools
module by addModule, and then when adding another modules to the build "namespace" we have to provide all the dependencies that those modules (i.e. .zig
files) use, we do that by providing them to unit_tests, because unit tests are in fact "ran".
We can gather all the tests into a single file with a special test syntax.
After that to run the tests we do:
zig build test
The tests are ran every time there is a change in the code, not every time we invoke the command.