1. 一个 build.zig 入门
Zig 项目的构建配置全部写在 build.zig 中。与 Makefile 或 CMake 不同,build.zig 是一段 Zig 代码,在编译项目前先被编译执行,描述构建过程本身:
// build.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 = "myapp",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// 安装目标
b.installArtifact(exe);
// 定义运行步骤
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd.addArgs(args);
const run_step = b.step("run", "运行应用");
run_step.dependOn(&run_cmd.step);
}
执行 zig build run 时,Zig 先编译并执行 build.zig,然后按照其中描述的步骤构建实际项目。
2. 构建目标与优化级别
2.1 目标平台选择
# 查看 Zig 支持的目标
zig targets
# 为特定目标构建
zig build -Dtarget=aarch64-linux-gnu
zig build -Dtarget=x86_64-windows-gnu
zig build -Dtarget=wasm32-wasi
Zig 会自动下载目标平台的 glibc 或 musl 头文件,无需在主机上安装交叉工具链。
2.2 优化级别
const optimize = b.standardOptimizeOption(.{});
// 命令行可覆盖: -Doptimize=ReleaseFast
| 模式 | 调试信息 | 安全检查 | 适用场景 |
|---|---|---|---|
| Debug | 完整 | 全部 | 开发调试 |
| ReleaseSafe | 精简 | 全部 | 生产部署(安全优先) |
| ReleaseFast | 无 | 无 | 内部工具(性能极致) |
| ReleaseSmall | 无 | 无 | 固件/嵌入式(体积极致) |
3. 依赖管理
Zig 使用 build.zig.zon 文件声明外部依赖:
// build.zig.zon
.{
.name = "myapp",
.version = "1.0.0",
.dependencies = .{
.zqlite = .{
.url = "https://github.com/karlseguin/zqlite.zig/archive/refs/heads/main.tar.gz",
.hash = "1220abc123...", // 首次编译时 Zig 提示正确的 hash
},
.network = .{
.path = "../network-lib", // 本地路径依赖
},
},
.paths = .{"src", "build.zig"},
}
// build.zig 中使用依赖
const zqlite = b.dependency("zqlite", .{});
exe.root_module.addImport("zqlite", zqlite.module("zqlite"));
// 源码中导入
const zqlite = @import("zqlite");
4. 自定义构建步骤
4.1 多目标构建
pub fn build(b: *std.Build) void {
// 构建库
const lib = b.addStaticLibrary(.{
.name = "mycore",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(lib);
// 构建测试程序
const test_exe = b.addExecutable(.{
.name = "test_runner",
.root_source_file = b.path("src/test.zig"),
.target = target,
.optimize = optimize,
});
test_exe.linkLibrary(lib);
b.installArtifact(test_exe);
}
4.2 运行测试
// 自动发现并运行所有单元测试
const test_step = b.step("test", "运行测试套件");
const unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_tests = b.addRunArtifact(unit_tests);
test_step.dependOn(&run_tests.step);
zig build test
4.3 自定义命令步骤
// 代码格式化检查
const fmt_step = b.step("fmt-check", "检查代码格式");
const fmt = b.addFmt(.{
.paths = &.{"src", "tests"},
.check = true, // 不修改文件,仅检查
});
fmt_step.dependOn(&fmt.step);
// 自定义脚本
const gen = b.addSystemCommand(&.{
"python3", "scripts/generate_version.py",
});
const gen_step = b.step("gen", "生成版本文件");
gen_step.dependOn(&gen.step);
5. 构建流程控制
5.1 步骤依赖关系
const compile = b.addExecutable(...);
const run = b.addRunArtifact(compile);
// run 必须在 compile 完成后执行
run.step.dependOn(&compile.step);
// install 必须先完成
const install = b.getInstallStep();
run.step.dependOn(install);
5.2 条件构建
const enable_tracy = b.option(bool, "tracy", "启用 Tracy 性能分析") orelse false;
if (enable_tracy) {
exe.linkSystemLibrary("tracy");
exe.defineCMacro("TRACY_ENABLE", "1");
}
zig build -Dtracy=true
5.3 多平台编译脚本
pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});
const targets = [_]std.Target.Query{
.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .gnu },
.{ .cpu_arch = .aarch64, .os_tag = .linux, .abi = .gnu },
.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu },
.{ .cpu_arch = .aarch64, .os_tag = .macos },
};
for (targets) |t| {
const resolved = b.resolveTargetQuery(t);
const exe = b.addExecutable(.{
.name = b.fmt("myapp-{s}-{s}", .{
@tagName(t.cpu_arch.?),
@tagName(t.os_tag.?),
}),
.root_source_file = b.path("src/main.zig"),
.target = resolved,
.optimize = optimize,
});
b.installArtifact(exe);
}
}
执行一次 zig build 即可同时生成四个平台的可执行文件。
6. C 代码集成
6.1 编译 C 源码
// 编译 C 文件并链接
const c_flags = &.{"-std=c11", "-Wall", "-O2"};
exe.addCSourceFile(.{
.file = b.path("deps/cJSON/cJSON.c"),
.flags = c_flags,
});
exe.addIncludePath(b.path("deps/cJSON"));
exe.linkLibC(); // 链接系统的 C 标准库
6.2 第三方库
// 使用 zig 提供的 glibc 替代
exe.linkLibC();
// 或使用 musl(静态链接)
const target = b.standardTargetOptions(.{
.default_target = .{
.cpu_arch = .x86_64,
.os_tag = .linux,
.abi = .musl,
},
});
7. 构建缓存与增量编译
Zig 的构建缓存位于 zig-cache/ 目录,采用内容寻址策略。每次编译时,Zig 计算输入源文件和编译选项的哈希值,只有当内容真正变化时才重新编译。对于大型项目,缓存命中率通常在百分之九十以上,这使得增量构建速度极快。
# 清理缓存
rm -rf zig-cache/
# 强制重新构建
zig build --summary all
# 查看构建过程详情
zig build -Dverbose=true
7.1 缓存机制
Zig 的缓存系统不仅缓存编译产物,还缓存 C 头文件的翻译结果。当使用 @cImport 导入大型 C 头文件时,翻译后的 Zig 代码会被缓存,后续编译直接复用。这对于频繁构建的项目来说,可以节省数秒甚至数十秒的翻译时间。
7.2 全局缓存目录
Zig 还在用户主目录维护一个全局缓存,存放下载的标准库和依赖包:
# 查看全局缓存位置
zig env | grep cache_dir
# 清理全局缓存
rm -rf ~/.cache/zig/
8. 实际项目构建策略
8.1 开发阶段配置
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "myapp",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// 开发时启用更多检查
exe.root_module.strip = (optimize == .ReleaseFast);
b.installArtifact(exe);
}
8.2 发布打包流程
对于命令行工具或服务器程序,发布时通常需要打包对应的可执行文件和配置文件:
const install_docs = b.addInstallDirectory(.{
.source_dir = b.path("docs/"),
.install_dir = .prefix,
.install_subdir = "share/doc/myapp",
});
b.getInstallStep().dependOn(&install_docs.step);
8.3 镜像体积优化
在容器化部署场景中,使用 musl 目标可以生成完全静态链接的可执行文件,无需任何基础镜像依赖:
zig build -Dtarget=x86_64-linux-musl -Doptimize=ReleaseSmall
这样生成的二进制文件可以直接放入 scratch 空镜像中,最终镜像体积仅数兆字节。
9. 完整项目结构示例
myproject/
├── build.zig # 构建配置
├── build.zig.zon # 依赖声明
├── src/
│ ├── main.zig # 入口
│ ├── lib.zig # 库代码
│ └── utils/
│ └── string.zig
├── tests/
│ ├── integration.zig
│ └── bench.zig
├── deps/
│ └── vendor-lib/ # 本地依赖
└── scripts/
└── gen_bindings.py
9. 常用构建命令速查
zig build # 默认目标
zig build run # 编译并运行
zig build test # 运行测试
zig build install # 安装到前缀目录
zig build uninstall # 移除安装
zig build -Dtarget=... # 指定目标平台
zig build -Doptimize=... # 指定优化级别
zig build --help # 查看可用步骤
10. 总结
Zig 的构建系统 build.zig 将项目构建逻辑代码化,带来了传统构建工具难以企及的灵活性:
| 场景 | Zig 方案 | 传统方案 |
|---|---|---|
| 交叉编译 | zig build -Dtarget=... | 配置交叉工具链 |
| 依赖管理 | build.zig.zon + 自动哈希验证 | git submodule / 包管理器 |
| 构建逻辑 | Zig 代码(类型安全、可调试) | Makefile / shell 脚本 |
| 多目标输出 | for 循环遍历目标数组 | 多配置文件 |
| C 代码集成 | addCSourceFile 内置支持 | 外部 configure/make |
这种"构建即代码"的理念不仅统一了工具链,更让复杂的构建流程变得可测试、可复用。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。