Cheatsheet: Build System em Zig
O build system do Zig é escrito em Zig puro — o arquivo build.zig é um programa Zig normal que descreve como seu projeto deve ser compilado. Isso significa que você tem toda a expressividade da linguagem para configurar builds complexos, sem precisar de ferramentas externas como CMake, Makefiles ou scripts shell.
build.zig Básico
const std = @import("std");
pub fn build(b: *std.Build) void {
// Opções padrão de target e otimização
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Compilar executável
const exe = b.addExecutable(.{
.name = "meu-app",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Instalar o artefato
b.installArtifact(exe);
// Step para rodar o executável
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", "Executar o aplicativo");
run_step.dependOn(&run_cmd.step);
// Step de testes
const testes = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const run_testes = b.addRunArtifact(testes);
const test_step = b.step("test", "Rodar testes unitários");
test_step.dependOn(&run_testes.step);
}
Estrutura Padrão de Projeto
meu-projeto/
├── build.zig # Configuração de build
├── build.zig.zon # Manifesto de dependências
├── src/
│ ├── main.zig # Ponto de entrada
│ ├── lib.zig # Biblioteca
│ └── utils.zig # Módulos auxiliares
└── tests/
└── test_main.zig # Testes adicionais
Comandos de Build
# Compilar o projeto (modo debug)
zig build
# Compilar e rodar
zig build run
# Rodar testes
zig build test
# Compilar em modo release
zig build -Doptimize=ReleaseSafe
zig build -Doptimize=ReleaseFast
zig build -Doptimize=ReleaseSmall
# Cross-compile para outro target
zig build -Dtarget=x86_64-linux-gnu
zig build -Dtarget=aarch64-macos
zig build -Dtarget=x86_64-windows-msvc
# Listar todos os steps disponíveis
zig build --help
# Verbose — ver comandos executados
zig build --verbose
Modos de Otimização
| Modo | Flag | Descrição |
|---|---|---|
Debug | (padrão) | Sem otimização, asserts ativados, stack traces |
ReleaseSafe | -Doptimize=ReleaseSafe | Otimizado, com verificações de segurança |
ReleaseFast | -Doptimize=ReleaseFast | Máxima performance, sem verificações |
ReleaseSmall | -Doptimize=ReleaseSmall | Menor binário possível |
Compilar Biblioteca
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Biblioteca estática
const lib = b.addStaticLibrary(.{
.name = "minha-lib",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(lib);
// Biblioteca dinâmica (shared)
const shared = b.addSharedLibrary(.{
.name = "minha-lib",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
b.installArtifact(shared);
}
Dependências Externas (build.zig.zon)
Manifesto de dependências
// build.zig.zon
.{
.name = "meu-projeto",
.version = "0.1.0",
.dependencies = .{
.zap = .{
.url = "https://github.com/zigzap/zap/archive/v0.1.0.tar.gz",
.hash = "1220abcdef1234567890...",
},
.mach = .{
.url = "https://github.com/hexops/mach/archive/main.tar.gz",
.hash = "1220fedcba0987654321...",
},
},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
}
Usando dependências no build.zig
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Obter dependência declarada no .zon
const zap_dep = b.dependency("zap", .{
.target = target,
.optimize = optimize,
});
const exe = b.addExecutable(.{
.name = "meu-app",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Adicionar módulo da dependência
exe.root_module.addImport("zap", zap_dep.module("zap"));
b.installArtifact(exe);
}
Buscar hash de dependência
zig fetch https://github.com/exemplo/lib/archive/v1.0.tar.gz
# Retorna o hash para usar no .zon
Linkar com Bibliotecas C
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "meu-app",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Linkar com libc
exe.linkLibC();
// Linkar com biblioteca do sistema
exe.linkSystemLibrary("SDL2");
exe.linkSystemLibrary("openssl");
// Adicionar caminhos de include e lib
exe.addIncludePath(b.path("vendor/include"));
exe.addLibraryPath(b.path("vendor/lib"));
// Compilar arquivos C junto
exe.addCSourceFiles(.{
.files = &.{
"src/wrapper.c",
"src/utils.c",
},
.flags = &.{
"-Wall",
"-Wextra",
"-std=c11",
},
});
b.installArtifact(exe);
}
Opções de Build Customizadas
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Opção booleana
const habilitar_logs = b.option(bool, "logs", "Habilitar logging verbose") orelse false;
// Opção string
const porta = b.option(u16, "porta", "Porta do servidor") orelse 8080;
const exe = b.addExecutable(.{
.name = "servidor",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Passar opções como constantes comptime
const opcoes = b.addOptions();
opcoes.addOption(bool, "habilitar_logs", habilitar_logs);
opcoes.addOption(u16, "porta", porta);
exe.root_module.addOptions("config", opcoes);
b.installArtifact(exe);
}
No código fonte:
const config = @import("config");
pub fn main() !void {
if (config.habilitar_logs) {
std.log.info("Logs habilitados", .{});
}
const porta = config.porta;
// ...
}
Uso:
zig build -Dlogs=true -Dporta=3000
Steps Customizados
pub fn build(b: *std.Build) void {
// Step que roda um comando do sistema
const gerar_docs = b.addSystemCommand(&.{
"python3", "scripts/gerar_docs.py",
});
const docs_step = b.step("docs", "Gerar documentação");
docs_step.dependOn(&gerar_docs.step);
// Step que depende de outro
const deploy = b.addSystemCommand(&.{
"rsync", "-avz", "zig-out/", "servidor:/opt/app/",
});
deploy.step.dependOn(b.getInstallStep()); // primeiro compila
const deploy_step = b.step("deploy", "Deploy para servidor");
deploy_step.dependOn(&deploy.step);
}
Compilação sem build.zig
Para projetos simples, você pode compilar diretamente:
# Compilar arquivo único
zig build-exe src/main.zig
# Com otimização
zig build-exe src/main.zig -OReleaseFast
# Cross-compile
zig build-exe src/main.zig -target x86_64-linux-gnu
# Compilar biblioteca
zig build-lib src/lib.zig
# Compilar objeto
zig build-obj src/modulo.zig
# Compilar e rodar diretamente
zig run src/main.zig
Erros Comuns
# ERRO: "FileNotFound" no root_source_file
# Verifique se o caminho está correto: b.path("src/main.zig")
# ERRO: hash inválido no .zon
# Execute: zig fetch <URL> para obter o hash correto
# ERRO: "DependencyNotFound"
# Verifique se o nome no b.dependency() bate com o .zon
# ERRO: Biblioteca C não encontrada
# Instale os pacotes -dev: apt install libsdl2-dev
Veja Também
- CLI do Zig — Todos os comandos do compilador
- Interop com C — Linkagem com código C
- Troubleshooting: Build Erros — Problemas com build.zig
- Cross-Compilation — Resolver erros de cross-compile
- FAQ Build System — Perguntas sobre o sistema de build