zig build em Zig — O que é e Como Usar

zig build em Zig — O que é e Como Usar

Definição

zig build é o comando principal do sistema de build integrado do Zig. Ele compila e executa o arquivo build.zig do projeto para determinar quais artefatos gerar, quais testes rodar e quais dependências resolver. Diferente de ferramentas como Make ou CMake, o sistema de build do Zig é parte da própria toolchain e usa a linguagem Zig para configuração.

Por que zig build Importa

  1. Tudo em um: Compilação, testes, instalação e execução em um único sistema.
  2. Portável: Funciona identicamente em qualquer plataforma onde Zig está instalado.
  3. Cross-compilation: Basta passar -Dtarget= para compilar para outra plataforma.
  4. Reprodutível: O mesmo build.zig + build.zig.zon produz o mesmo resultado.

Exemplo Prático

Comandos Básicos

# Compilar o projeto (gera artefatos em zig-out/)
zig build

# Compilar e executar
zig build run

# Executar testes
zig build test

# Listar todos os steps disponíveis
zig build --help

Cross-Compilation

# Compilar para Linux x86_64
zig build -Dtarget=x86_64-linux-gnu

# Compilar para macOS ARM
zig build -Dtarget=aarch64-macos

# Compilar para Windows
zig build -Dtarget=x86_64-windows-gnu

# Build otimizado
zig build -Doptimize=ReleaseFast

build.zig Mínimo para Entender o Fluxo

const std = @import("std");

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

    // Step "build" — compilar o executável
    const exe = b.addExecutable(.{
        .name = "app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    b.installArtifact(exe);

    // Step "run" — executar o programa
    const run = b.addRunArtifact(exe);
    run.step.dependOn(b.getInstallStep());
    if (b.args) |args| {
        run.addArgs(args);
    }
    b.step("run", "Executar o aplicativo").dependOn(&run.step);

    // Step "test" — rodar testes
    const testes = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    b.step("test", "Rodar testes").dependOn(&b.addRunArtifact(testes).step);
}

Opções Comuns

OpçãoDescrição
-Dtarget=TRIPLADefinir plataforma-alvo
-Doptimize=MODOModo de otimização (Debug, ReleaseSafe, ReleaseFast, ReleaseSmall)
--helpListar steps e opções disponíveis
-j NNúmero de jobs paralelos
--verboseMostrar comandos executados
-- ARGSPassar argumentos ao programa (com step “run”)

Armadilhas Comuns

  • Sem build.zig: O comando falha se não houver build.zig no diretório atual ou ancestral.
  • Cache agressivo: O Zig faz cache de compilação. Use zig build --summary all para verificar o que foi recompilado.
  • Argumentos do programa: Para passar argumentos ao executável, use zig build run -- arg1 arg2.
  • Diretório de saída: Artefatos ficam em zig-out/. Este diretório deve estar no .gitignore.

Termos Relacionados

Steps Personalizados

O sistema de build do Zig permite criar steps customizados para tarefas arbitrárias — geração de código, execução de ferramentas externas, publicação de artefatos, etc. Cada step pode depender de outros, formando um grafo de dependências que o zig build executa em ordem.

const std = @import("std");

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

    const exe = b.addExecutable(.{
        .name = "app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    b.installArtifact(exe);

    // Step de linting/formatação personalizado
    const fmt_step = b.step("fmt", "Formatar código-fonte");
    const fmt = b.addFmt(.{ .paths = &.{"src"} });
    fmt_step.dependOn(&fmt.step);

    // Step de documentação
    const docs_step = b.step("docs", "Gerar documentação");
    const docs = b.addInstallDirectory(.{
        .source_dir = exe.getEmittedDocs(),
        .install_dir = .prefix,
        .install_subdir = "docs",
    });
    docs_step.dependOn(&docs.step);
}

Comparação com Make e CMake

Diferente do Make, o build.zig é tipado e verificado em tempo de compilação — não há strings mágicas ou erros de sintaxe difíceis de depurar. Diferente do CMake, o sistema de build usa a mesma linguagem que o código-fonte, eliminando a necessidade de aprender uma DSL separada. O resultado é um sistema de build que é ao mesmo tempo poderoso e familiar para quem já sabe Zig.

Além disso, o sistema de build do Zig tem cross-compilation integrada de verdade. Em CMake, cross-compilar requer toolchain files complexos. Em Zig, basta -Dtarget=aarch64-linux-musl e o compilador cuida do resto — incluindo a libc.

Modos de Otimização

# Debug (padrão): sem otimizações, checks de segurança habilitados
zig build

# ReleaseSafe: com otimizações, checks de segurança mantidos
zig build -Doptimize=ReleaseSafe

# ReleaseFast: otimizações máximas, sem checks de segurança
zig build -Doptimize=ReleaseFast

# ReleaseSmall: otimizado para menor tamanho binário
zig build -Doptimize=ReleaseSmall

Para distribuição, ReleaseSafe é geralmente a melhor escolha — oferece performance próxima de ReleaseFast com a segurança de detectar comportamento indefinido em produção.

Tutoriais Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.