产物构建:Executable、Library 与 Test
在 Zig 构建系统中,生成最终二进制产物(可执行文件、静态库/动态库、测试程序)的任务由 Step.Compile 负责。
💡 配套可运行示例 关于标准应用程序产物与单元测试构建的完整代码工程,可参考 GitHub 示例:
examples/01-zig-app,以及后续实战章节 实战一:标准 Zig CLI 应用与单元测试。
1. 构建可执行程序:b.addExecutable
const exe = b.addExecutable(.{
.name = "my_app",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});
// 将产物安装到 zig-out/bin/ 目录下
b.installArtifact(exe);
关键配置:
root_module:挂载主程序的编译上下文与依赖;- 产物安装:通过
b.installArtifact(exe)将生成的可执行文件输出到zig-out/bin/my_app(在 Windows 平台会自动追加.exe后缀)。
2. 构建库文件:b.addLibrary
静态库(.a / .lib)与动态库(.so / .dylib / .dll)统一通过 b.addLibrary 声明,通过 .linkage 枚举区分:
// 1. 静态库
const static_lib = b.addLibrary(.{
.name = "my_lib",
.linkage = .static,
.root_module = my_module,
});
b.installArtifact(static_lib);
// 2. 动态共享库
const shared_lib = b.addLibrary(.{
.name = "my_lib",
.linkage = .dynamic,
.version = .{ .major = 1, .minor = 2, .patch = 0 },
.root_module = my_module,
});
b.installArtifact(shared_lib);
动态库版本控制:
构建动态库时,通过设置 .version(std.SemanticVersion),Zig 会为目标系统生成带有主次版本号的产物与对应的软链接(例如在 Linux 上输出 libmy_lib.so.1.2.0 并创建 libmy_lib.so.1 软链接)。
3. 运行与单元测试:b.addTest 与 b.addRunArtifact
构建脚本中运行单元测试分为两步:
- 编译单元测试可执行文件(
addTest); - 执行该测试二进制进程(
addRunArtifact)。
// 1. 声明测试编译步骤
const unit_tests = b.addTest(.{
.root_module = b.createModule(.{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
}),
});
// 2. 声明测试运行步骤
const run_unit_tests = b.addRunArtifact(unit_tests);
// 3. 绑定到 "zig build test" 入口
const test_step = b.step("test", "Run all unit tests");
test_step.dependOn(&run_unit_tests.step);
将编译与运行拆分的用途:
- 支持交叉编译下的测试验证:若指定目标为其他平台架构(如在 macOS 上交叉编译 Linux aarch64 产物),测试程序可以在宿主机缺少仿真环境时,仅执行编译验证;
- 配置执行环境:
run_unit_tests允许定制工作目录、环境变量,以及断言进程退出码:run_unit_tests.expectExitCode(0); run_unit_tests.setEnvironmentVariable("LOG_LEVEL", "DEBUG");
4. 测试解耦与产物管理局限
4.1 跨平台测试执行器配置
addTest 与 addRunArtifact 的拆分在交叉编译时具有实际用途:
- 仿真器配置(QEMU Runner):在 x86_64 开发机上交叉编译 ARM64 或 RISC-V 测试程序时,可以通过
run_unit_tests.setExecCmd指定仿真器:if (target.result.cpu.arch != builtin.target.cpu.arch) { run_unit_tests.setExecCmd(&.{ "qemu-aarch64", "-L", "/usr/aarch64-linux-gnu" }); } - 仅编译检查(Check-only in CI):在缺少运行环境的 CI 机器上,可以仅调度
&unit_tests.step(只编译测试二进制),提前发现目标平台的语法和类型错误。
4.2 局限与不足
- 缺少内置的
clean目标: Zig 官方未提供zig build clean命令。当需要释放磁盘空间或清理缓存时,开发者需要通过外部命令手动删除.zig-cache和zig-out,在跨平台脚本(特别是 Windows 环境)中缺乏统一的内置支持; - 交付目录缺少失效产物清理:
若在
build.zig中重命名或删除了某个产物,重新构建时旧的二进制文件仍会留在zig-out/bin/目录中,系统不会自动清理当前构建图未声明的残留文件。