Zig Build System
Zig has a powerful built-in build system. This chapter will cover how to use build.zig to configure and manage complex build tasks.
Build System Basics
Simple Build Script
The most basic build.zig file:
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
// Get target platform and optimization options
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Create executable
const exe = b.addExecutable(.{
.name = "my-app",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// Install executable
b.installArtifact(exe);
// Create run step
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
// Pass command line arguments
if (b.args) |args| {
run_cmd.addArgs(args);
}
// Register run step
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}Build Options
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Custom build options
const enable_logging = b.option(bool, "enable-logging", "Enable logging") orelse true;
const max_connections = b.option(u32, "max-connections", "Maximum connections") orelse 100;
const server_port = b.option(u16, "port", "Server port") orelse 8080;
const exe = b.addExecutable(.{
.name = "server",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// Add build options as compile-time constants
const options = b.addOptions();
options.addOption(bool, "enable_logging", enable_logging);
options.addOption(u32, "max_connections", max_connections);
options.addOption(u16, "server_port", server_port);
exe.addOptions("build_options", options);
b.installArtifact(exe);
// Example using build options
std.debug.print("Build configuration:\n");
std.debug.print(" Logging: {}\n", .{enable_logging});
std.debug.print(" Max connections: {}\n", .{max_connections});
std.debug.print(" Port: {}\n", .{server_port});
}Multi-Target Builds
Executables and Libraries
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Static library
const lib = b.addStaticLibrary(.{
.name = "mylib",
.root_source_file = .{ .path = "src/lib.zig" },
.target = target,
.optimize = optimize,
});
b.installArtifact(lib);
// Shared library
const shared_lib = b.addSharedLibrary(.{
.name = "mylib",
.root_source_file = .{ .path = "src/lib.zig" },
.target = target,
.optimize = optimize,
.version = .{ .major = 1, .minor = 0, .patch = 0 },
});
b.installArtifact(shared_lib);
// Executable (linking static library)
const exe = b.addExecutable(.{
.name = "myapp",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
exe.linkLibrary(lib);
b.installArtifact(exe);
// Test executable
const test_exe = b.addTest(.{
.root_source_file = .{ .path = "src/lib.zig" },
.target = target,
.optimize = optimize,
});
const run_tests = b.addRunArtifact(test_exe);
const test_step = b.step("test", "Run library tests");
test_step.dependOn(&run_tests.step);
}C/C++ Integration
Compiling C Source Files
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "mixed-app",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// Link C standard library
exe.linkLibC();
// Add C source files
exe.addCSourceFiles(&[_][]const u8{
"src/c/helper.c",
"src/c/math_utils.c",
"src/c/string_utils.c",
}, &[_][]const u8{
"-std=c99",
"-Wall",
"-Wextra",
"-O2",
});
// Add C++ source files
exe.addCSourceFiles(&[_][]const u8{
"src/cpp/algorithm.cpp",
"src/cpp/data_structure.cpp",
}, &[_][]const u8{
"-std=c++17",
"-Wall",
"-Wextra",
"-O2",
});
// Link C++ standard library
exe.linkLibCpp();
// Add include paths
exe.addIncludePath(.{ .path = "src/c" });
exe.addIncludePath(.{ .path = "src/cpp" });
exe.addIncludePath(.{ .path = "include" });
// Add system libraries
if (target.isWindows()) {
exe.linkSystemLibrary("ws2_32");
exe.linkSystemLibrary("advapi32");
} else {
exe.linkSystemLibrary("pthread");
exe.linkSystemLibrary("m");
}
b.installArtifact(exe);
}Test Configuration
Unit Tests
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Main program
const exe = b.addExecutable(.{
.name = "app",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
// Unit tests
const unit_tests = b.addTest(.{
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
const run_unit_tests = b.addRunArtifact(unit_tests);
// Module tests
const test_files = [_][]const u8{
"src/utils/math.zig",
"src/utils/string.zig",
"src/config.zig",
"src/logger.zig",
};
for (test_files) |test_file| {
const module_test = b.addTest(.{
.root_source_file = .{ .path = test_file },
.target = target,
.optimize = optimize,
});
run_unit_tests.step.dependOn(&b.addRunArtifact(module_test).step);
}
// Integration tests
const integration_tests = b.addTest(.{
.root_source_file = .{ .path = "tests/integration.zig" },
.target = target,
.optimize = optimize,
});
integration_tests.addModule("app", b.addModule("app", .{
.source_file = .{ .path = "src/lib.zig" },
}));
const run_integration_tests = b.addRunArtifact(integration_tests);
// Test steps
const test_step = b.step("test", "Run all tests");
test_step.dependOn(&run_unit_tests.step);
test_step.dependOn(&run_integration_tests.step);
// Separate test steps
const unit_test_step = b.step("test-unit", "Run unit tests");
unit_test_step.dependOn(&run_unit_tests.step);
const integration_test_step = b.step("test-integration", "Run integration tests");
integration_test_step.dependOn(&run_integration_tests.step);
}Cross-Compilation
Multi-Platform Builds
zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});
// Define target platforms
const targets = [_]std.zig.CrossTarget{
.{ .cpu_arch = .x86_64, .os_tag = .linux },
.{ .cpu_arch = .x86_64, .os_tag = .windows },
.{ .cpu_arch = .x86_64, .os_tag = .macos },
.{ .cpu_arch = .aarch64, .os_tag = .linux },
.{ .cpu_arch = .aarch64, .os_tag = .macos },
};
// Create build target for each platform
for (targets) |target| {
const target_name = b.fmt("{s}-{s}", .{
@tagName(target.cpu_arch.?),
@tagName(target.os_tag.?)
});
const exe = b.addExecutable(.{
.name = b.fmt("app-{s}", .{target_name}),
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// Platform-specific configuration
if (target.os_tag == .windows) {
exe.linkSystemLibrary("ws2_32");
} else {
exe.linkSystemLibrary("pthread");
}
const install_exe = b.addInstallArtifact(exe, .{
.dest_dir = .{ .override = .{ .custom = target_name } },
});
const target_step = b.step(
b.fmt("build-{s}", .{target_name}),
b.fmt("Build for {s}", .{target_name})
);
target_step.dependOn(&install_exe.step);
}
// Build all platforms
const build_all_step = b.step("build-all", "Build for all platforms");
for (targets) |target| {
const target_name = b.fmt("{s}-{s}", .{
@tagName(target.cpu_arch.?),
@tagName(target.os_tag.?)
});
const target_step = b.step(b.fmt("build-{s}", .{target_name}), "");
build_all_step.dependOn(target_step);
}
}Summary
This chapter covered various aspects of the Zig build system:
- ✅ Basic build scripts and build options
- ✅ Multi-target builds and dependency management
- ✅ C/C++ integration and external library linking
- ✅ Test configuration and benchmarking
- ✅ Custom build steps and code generation
- ✅ Cross-compilation and multi-platform support
- ✅ Advanced build techniques and best practices
Zig's build system provides powerful and flexible project management capabilities. By properly using these features, you can build complex, cross-platform applications.
In the next chapter, we'll learn about Zig's style guide.