Zig 构建系统

28 阅读2分钟

Zig可以使用Zig本身来编写构建文件

WOW! So Amazing! Zig使用build.zig文件来描述项目的。

zig构建脚本build.zig的入口函数必须命名为build。

build函数参数是std.Build的实例指针。

std.Build的实例不是用户创建的,而是zig编译器自动创建的。

当运行zig build,Zig会:

  • 加载当前目录的build.zig
  • 创建一个std.Build的实例
  • 调用用户自己编写的build函数,该函数接受std.Build实例指针,通常命名为b,通过该实例指针的方法可以注册artifact(构建产物)和step(构建步骤)
  • 再根据函数中注册的artifact(构建产物)和step(构建步骤),执行构建

std.Build的实例就是整个构建系统的上下文对象。

pub fn build(b:*std.Build) void {
    // ...
}

在zig中通过std.Build实例指针可以生成三种主要类型的构建产物(build artifacts)

  1. 可执行程序
pub fn build(b:*std.Build) void {
    const exe = b.addExecutable(.{
        .name="myapp",
        .root_source_file = b.path("src/main.zig"),
    })
}
  1. 静态库
pub fn build(b:*std.Build) void {
    const staticLib = b.addLibrary(.{
        .linkage = .static,
        .name= "mystaticlib",
        .root_source_file = b.path("src/main.zig"),
    })
}
  1. 动态库
pub fn build(b:*std.Build) void {
    const staticLib = b.addLibrary(.{
        .linkage = .dynamic,
        .name= "mystaticlib",
        .root_source_file = b.path("src/main.zig"),
    })
}
const std = @import("std");
// zig构建脚本的入口函数,必须命名为build
// b:*std.Build 是标准库Build实例的指针
pub fn build(b: *std.Build) void {
    // addExecutable告诉构建系统要创建一个可执行程序
    const exe = b.addExecutable(.{
        // 指定可执行文件名,不含扩展名
        .name = "hello",
        // 指定程序的入口模块
        // createModule创建一个模块对象
        .root_module = b.createModule(.{
            // 指定模块的入口源文件为根目录下的hello.zig
            .root_source_file = b.path("hello.zig"),
            // 指定编译目标为当前主机
            // b.graph.host 等价于 std.Target.current
            .target = b.graph.host,
        }),
    });
    // 将编译好的可执行文件安装到输出目录
    // 默认zig-out
    b.installArtifact(exe);
    
    // addRunArtifact(exe)创建一个“运行某个已构建产物(artifact)”的构建步骤
    // exe是之前通过addExecutable创建的可执行对象
    const run_exe = b.addRunArtifact(exe)
    // 创建一个用户可调用的顶层构建步骤
    const run_step = b.step("run", "Run the application");
    // 给上述构建步骤建立依赖
    // run_exe是Run的步骤对象,其.step字段是其基类
    run_step.dependOn(&run_exe.step);
}