Zig Build Options
A build option is a named value given to zig build with a -D flag. This lesson reads a bool flag, a greeting word, and a number through build options.
A bool flag with a fallback
The build script reads a bool flag and falls back to false when no flag is given.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "hello",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const extra = b.option(bool, "extra", "Print an extra line") orelse false;
const greeting = b.option([]const u8, "greeting", "Greeting word") orelse "Hello";
const name = b.option([]const u8, "name", "Name to greet") orelse "World";
const options = b.addOptions();
options.addOption(bool, "extra", extra);
options.addOption([]const u8, "greeting", greeting);
options.addOption([]const u8, "name", name);
exe.root_module.addOptions("config", options);
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
Flipping the flag on
Passing -Dextra=true flips the flag on, so the program takes the other branch.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "hello",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const extra = b.option(bool, "extra", "Print an extra line") orelse true;
const greeting = b.option([]const u8, "greeting", "Greeting word") orelse "Hello";
const name = b.option([]const u8, "name", "Name to greet") orelse "World";
const options = b.addOptions();
options.addOption(bool, "extra", extra);
options.addOption([]const u8, "greeting", greeting);
options.addOption([]const u8, "name", name);
exe.root_module.addOptions("config", options);
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
String flags
String flags work the same way, with a word after the equals sign.
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "hello",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const extra = b.option(bool, "extra", "Print an extra line") orelse false;
const greeting = b.option([]const u8, "greeting", "Greeting word") orelse "Hi";
const name = b.option([]const u8, "name", "Name to greet") orelse "Zig";
const options = b.addOptions();
options.addOption(bool, "extra", extra);
options.addOption([]const u8, "greeting", greeting);
options.addOption([]const u8, "name", name);
exe.root_module.addOptions("config", options);
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
Example
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "counter",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const count = b.option(u32, "count", "How many lines to print") orelse 3;
const options = b.addOptions();
options.addOption(u32, "count", count);
exe.root_module.addOptions("config", options);
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
Key points
- Build option: a build option is a named value given to zig build with a -D flag.
- Default: a default is the value used when no flag is given.
- Options module: an options module is a small module the build script fills with chosen values, which the program reads with @import.
- A bool flag switches a feature on or off.
- A string flag replaces a word in the program.
- Flags are read when the build runs, so changing a flag rebuilds the program with the new value.
The build script reads a count flag and falls back to 3. The count travels into the program through the config module. The program prints one Tick line per count, numbered from 1. Running without a flag prints three lines, and a -Dcount flag would change that number.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Which flag turns the extra feature on?