Build system question about what’s idiomatic/the happy path.
At TigerBeetle, we have a bunch of sourcecode under the ./src folder. There multiple entry points (pub fn mains) among the source files — there’s:
src/tigerbeetle/main.zigfor the main binary./src/unit_tests.zigfor unit-tests,./src/fuzz_tests.zigfor fuzznig,./src/scripts/main.zigfor various CI helpers (implemented in Zig of course)- and also a bunch of completely wiled things here and there like
src/clients/c/tb_client_header.zigwhich I am not even fully aware about myself
The way this works under Zig 0.11 is that, for all those entry points, we set .main_pkg_path = "./src", and then happily @import("../stdx.zig") or what not.
My understanding is that under Zig 0.12 main_pkg_path is gone: if ./foo/bar.zig is the root file of the module, then all code has to reside under ./foo subfolder.
What’s the best source code layout in this world? One thing we can do (and probably will do at least just for migration) is to say that non-entry-point stuff in src is a separate module, and then in various files with main do
const baz = @import("tigerbetle").bar.baz;
instead of the current
const baz = @import("../bar/baz.zig");
But that doesn’t seem like a proper long-term solution:
- philosophically, we don’t really have good library level interfaces yet, and would rather treat everything like “one pile of code”, rather than introducing libary/binary internal boundaries.
- practically, it would be a bit confusing if some code would be able to import file paths, and other code would have to use dotted access.
- additionally, for dotted access to work we’d have to manually add
pub constreexports everywhere, which also feels like needless work in this context, where we dont’ really care about API boundaries.
So, what’s the happy path here? What’s the right mental model to use in this case?