The part about a Zig source file being a member of only one module turns out to not be correct. Hadn’t occurred to me to try, so I did.
In fact, you can define two separate modules with the same .root_source_file
. This is not a useful thing to do, so far as I know, and I wouldn’t count on it always being true.
You can even define two modules with the same name, and different root source files! That, I assume, is not intended behavior, and it’s unclear what happens when you do that and then try to include the module by name as a dependency in other code. I’m not curious enough to find out, but I would very much not count on this behavior long term.
A module is a Zig build target, with a root file, which is intended to be included in another Zig project as a dependency. A dependency and a module are not the same thing, because a given dependency (which has a name defined in a build.zig.zon
) can export more than one module.
if (b.lazyDependency("somedependency", .{
.target = target,
.optimize = optimize,
})) |dep| {
my_program.addImport("firstmodule", dep.module("firstmodule"));
my_program.addImport("secondmodule", dep.module("secondmodule");
}
Here, we have a dependency “somedependency”, presumably fetched from a code forge using zig fetch --save
. It exports “firstmodule” and “secondmodule” in it’s own build.zig
like so:
// https://code.forge/somedependency/build.zig
const first_module = b.addModule("firstmodule", .{
.root_source_file = b.path("src/firstmodule.zig"),
.target = target,
.optimize = optimize,
});
// same for "secondmodule"
These can then be imported into my_program
with @import("firstmodule");
and @import("secondmodule");
.
As long as the two modules have a different name, and a different root source file, I’m confident that this is intended behavior, exporting more than one module in a dependency is a useful thing. For that matter, two modules with the same root source file and different names might be created with different build options, so maybe that use case is intended. I think the fact that you can make two differently-rooted modules with the same name is just something which isn’t currently checked for, due to the lack of an obvious mechanism for making use of the synonymous modules, or figuring out which one was intended.
But a source file which is the root of one module can be a dependency of a second module exported from the same build.zig
, that’s definitely fine, and a good way to expose subsets of a larger library directly.
Last point: a module is a type of build target, not a type of source file. A project can have several build targets, they can be rooted in the same source file (it’s common to have a test build for example), and it all works. Modules happen when you call b.addModule
, basically.