A build option is a value passed to build.zig from the command line.
Build options let one build file describe several related builds. The user chooses the variant without editing source code.
The usual form is:
zig build -Dname=valueFor example:
zig build -Dtrace=trueInside build.zig, the option is read with b.option:
const trace = b.option(bool, "trace", "Enable trace output") orelse false;The first argument is the type. The second is the option name. The third is the help text. If the user does not pass the option, b.option returns null, so the expression uses orelse false.
The option now appears in:
zig build --helpA build option may be a boolean:
const trace = b.option(bool, "trace", "Enable trace output") orelse false;It may be an integer:
const port = b.option(u16, "port", "Default server port") orelse 8080;It may be a string:
const mode = b.option([]const u8, "mode", "Program mode") orelse "normal";The command line supplies them in the same style:
zig build -Dtrace=true -Dport=9000 -Dmode=debugAn option can change how the program is built:
if (trace) {
exe.root_module.addCMacro("TRACE", "1");
}More often, the option is passed into Zig source code as a compile-time configuration module.
const options = b.addOptions();
options.addOption(bool, "trace", trace);
options.addOption(u16, "port", port);
options.addOption([]const u8, "mode", mode);
exe.root_module.addOptions("config", options);The source file imports the generated module:
const std = @import("std");
const config = @import("config");
pub fn main() void {
std.debug.print("port: {d}\n", .{config.port});
if (config.trace) {
std.debug.print("trace enabled\n", .{});
}
}Build and run:
zig build run -Dtrace=true -Dport=9000The program sees the values at compile time.
This matters. Since the values are compile-time constants, the compiler can remove dead branches.
if (config.trace) {
expensiveTraceCode();
}When trace is false, the branch can disappear from the generated program.
The standard build options work the same way, but are provided by the build system.
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});They add common options such as:
zig build -Dtarget=x86_64-linux -Doptimize=ReleaseFastDo not invent a custom option when a standard one already exists. Use standard target and optimize options unless the project has a strong reason not to.
Options should have stable names. Once users and scripts depend on an option, renaming it breaks builds.
Good option names are short and specific:
trace
tls
sqlite
port
backend
log-levelBad option names are vague:
flag
thing
extra
mode2A build option should control one decision. If an option controls several unrelated things, split it.
Build options are part of the interface of the project. Treat them with the same care as command-line flags in the program itself.
Exercise 15-13. Add a boolean option named trace.
Exercise 15-14. Add an integer option named port.
Exercise 15-15. Pass both options into source code through a generated config module.
Exercise 15-16. Use the trace option to compile out a logging branch.