zig 编译器安装及使用

Jony 发布于 19 天前 12 次阅读


AI 摘要

本文介绍了Zig编译器的安装与使用方法,涵盖Linux下的安装配置、常用命令、如何将Zig作为C/C++编译器使用、交叉编译技巧、在CMake项目中集成Zig,以及Zig语言基础示例和内存管理特点。适合需要快速上手Zig进行系统编程或跨平台编译的开发者。
内容纲要

Zig 安装与使用指南

Zig 既是一门系统编程语言,也是一套非常实用的 C/C++ 工具链。对嵌入式和 Linux 开发者来说,它有两个很直接的价值:

  • 可以直接把 zig cczig c++ 当作 gccg++ 使用
  • 对交叉编译支持很好,很多场景下比手工维护交叉工具链更省事

本文按“安装、环境配置、常用命令、交叉编译、工程构建”的顺序整理,适合拿来直接落地。


1. Zig 是什么

先明确一点,Zig 不只是“一门新语言”。

它至少有两种常见用法:

  1. 把 Zig 当作编程语言使用,编写系统工具、命令行程序或底层模块。
  2. 把 Zig 当作 C/C++ 编译工具链使用,用 zig cczig c++ 来编译已有工程。

如果你当前主要做嵌入式软件、Linux 应用或服务端程序,第二种用法通常更容易快速产生价值。


2. Linux 下安装 Zig

最稳妥的方式是从 Zig 官方发布包安装,而不是依赖系统仓库里的旧版本。

2.1 下载并解压

下面以 Linux x86_64 平台为例。实际使用时,把文件名替换成你下载的 Zig 版本即可。

wget https://ziglang.org/download/<version>/zig-linux-x86_64-<version>.tar.xz
tar -xf zig-linux-x86_64-<version>.tar.xz
sudo mv zig-linux-x86_64-<version> /opt/zig

如果你下载的是开发版构建包,目录名通常会更长,处理方式相同。

2.2 配置环境变量

echo 'export PATH="/opt/zig:$PATH"' >> ~/.bashrc
source ~/.bashrc

如果你使用的是 zsh,则改写到 ~/.zshrc

2.3 验证安装

zig version
zig env
  • zig version 用于确认 Zig 已经可执行
  • zig env 用于查看 Zig 当前使用的缓存目录、目标平台信息和工具链配置

3. 第一次上手:最常用的几个命令

如果你以前主要使用 GCC/CMake,可以先记住下面几条命令。

3.1 创建一个 Zig 工程

zig init

这会生成一个最小工程骨架,通常包含:

  • build.zig
  • build.zig.zon
  • src/main.zig

3.2 编译、运行、测试

zig build
zig build run
zig test src/main.zig

常见理解如下:

  • zig build:按 build.zig 描述构建工程
  • zig build run:构建并运行默认可执行文件
  • zig test:编译并执行测试代码

3.3 直接编译单文件

如果只是临时写一个小工具,不一定要先建工程。

zig build-exe hello.zig
./hello

也可以直接运行:

zig run hello.zig

4. 把 Zig 当作 C/C++ 编译器使用

这部分往往是 Zig 最先带来收益的地方。

4.1 基本编译

zig cc 对应 gcczig c++ 对应 g++

zig cc main.c -o main
zig c++ main.cpp -o main

如果你已有 C/C++ 项目,可以先从这里替换编译器开始,而不必立即引入 Zig 语言代码。

4.2 常见编译选项

zig cc -O2 main.c -o main
zig cc -g main.c -o main
zig cc -Wall -Wextra main.c -o main

这些用法和 GCC 基本一致,迁移成本很低。

4.3 使用 Zig 做交叉编译

Zig 的一个强项是交叉编译。目标平台通过 -target 指定,格式通常为:

架构-操作系统-ABI

例如:

# 编译为 x86_64 Linux 程序
zig cc -target x86_64-linux-gnu main.c -o main

# 编译为 ARM Linux 硬浮点程序
zig cc -target arm-linux-gnueabihf main.c -o main

# 编译为 aarch64 Linux 程序
zig cc -target aarch64-linux-gnu main.c -o main

# 编译为 Windows 可执行文件
zig cc -target x86_64-windows-gnu main.c -o main.exe

如果你的目标设备比较老,还可以显式指定 glibc 版本:

zig cc -target x86_64-linux-gnu.2.27 main.c -o main

这对“开发机系统较新,目标机系统较旧”的部署场景很有帮助。

4.4 静态链接 musl

如果希望可执行文件尽量摆脱目标机运行库依赖,可以考虑使用 musl 目标:

zig cc -target x86_64-linux-musl main.c -o main_static

这个方式常见于:

  • 小型部署环境
  • 容器镜像精简
  • 嵌入式 Linux 设备分发

但要注意,静态链接不是所有项目都适合,尤其是涉及插件、运行时加载或某些系统库依赖时,需要单独评估。


5. 在现有 CMake 工程里使用 Zig

如果项目已经使用 CMake,通常不需要立刻重写构建系统。更现实的做法是先让 Zig 接管编译器。

mkdir -p build
cd build

CC="zig cc -target aarch64-linux-gnu" \
CXX="zig c++ -target aarch64-linux-gnu" \
cmake -DCMAKE_BUILD_TYPE=Release ..

cmake --build . -j4

这个方式适合:

  • 已有大型 C/C++ 工程
  • 先验证 Zig 交叉编译是否稳定
  • 不想马上替换掉原有 CMake 流程

如果你修改过编译器配置,建议清理旧缓存后再重新生成:

rm -rf build
mkdir build
cd build

6. Zig 语言最小示例

如果你想顺手试一下 Zig 语法,可以先看一个最小程序。

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Hello, Zig!\n", .{});
}

编译并运行:

zig run hello.zig

这段代码里有几个 Zig 的典型特征:

  • const 默认不可变
  • !void 表示函数可能返回错误
  • try 用于向上传递错误

7. Zig 的内存管理特点

Zig 的一个重要设计点是:内存分配尽量显式化,不鼓励隐藏分配。

下面是一个带注释的简单示例:

const std = @import("std");

pub fn main() !void {
    // 通用分配器,适合学习和一般开发阶段使用。
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

    const allocator = gpa.allocator();

    // 显式申请 128 字节缓冲区。
    const buf = try allocator.alloc(u8, 128);
    defer allocator.free(buf);

    // 对缓冲区进行写入。
    @memset(buf, 0);

    const stdout = std.io.getStdOut().writer();
    try stdout.print("buffer size = {}\n", .{buf.len});
}

这类“显式分配、显式释放”的风格,对嵌入式和高性能系统会更友好,因为资源边界更清晰。


8. Zig 调用 C 代码

Zig 与 C 的互操作性很好,这也是它适合作为工程过渡语言的原因之一。

const c = @cImport({
    @cInclude("stdio.h");
});

pub fn main() void {
    _ = c.printf("Hello from C API\n");
}

如果工程里已经有很多 C 头文件和库,这种方式可以帮助你逐步迁移,而不必一次性重写整个项目。


9. 最小 build.zig 示例

如果你不想继续使用 CMake,也可以直接使用 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 = "my_app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    b.installArtifact(exe);
}

然后执行:

zig build
zig build run

如果项目是 C 工程,也可以在 build.zig 中加入 C 源文件:

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "my_c_app",
        .target = target,
        .optimize = optimize,
    });

    exe.addCSourceFile(.{
        .file = b.path("src/main.c"),
        .flags = &.{"-std=c11"},
    });
    exe.linkLibC();

    b.installArtifact(exe);
}
生活太苦了
最后更新于 2026-05-06