Modules can be initiated with null target and optimization, in which case these will be inherited.
However, in order for you to compile a module, at least the target needs to be explicitly specified, and the optimization mode will default to debug if not specified.
Also note that standardOptimizeOption and its target counterpart do not return optionals. If you don’t explicitly specify these options in your build command, zig will give you a default value, which is not null.
Put it all together, and you get this footgun:
const optimize = b.standardOptimizeOption(.{});
const target = b.standardTargetOption(.{});
const exported_module = b.addModule("foo", .{
.root_source_file = b.path("src/root.zig"),
// Here you have given the module a non-null
// optimize and target, so they will not be inherited.
// If you don't specify them when importing your module
// you'll end up with .Debug and native target
.optimize = optimize,
.target = target.
});
The proper way of doing it is:
// This is suitable for importing, but unsuitable for compilation.
const exported_module = b.addModule("foo", .{
.root_source_file = b.path("src/root.zig"),
});
const optimize = b.standardOptimizeOption(.{});
const target = b.standardTargetOption(.{});
// This is suitable for compilation, but unsuitable for importing.
const compiled_module = b.createModule(
.root_source_file = b.path("src/root.zig"),
.optimize = optimize,
.target = target
);
// Only `compiled_module` can be used for compilation.
const exe = b.addExecutable(.{
.name = "foo",
.root_module = compiled_module,
});
// Tests are compiled as well
const test_exe = b.addTest(.{
.name = "foo",
.root_module = compiled_module,
});