build.zig em Zig — O que é e Como Usar

build.zig em Zig — O que é e Como Usar

Definição

build.zig é o arquivo de configuração do sistema de build do Zig, escrito na própria linguagem Zig. Ele substitui ferramentas externas como Make, CMake ou Meson, permitindo que toda a lógica de compilação, testes, dependências e geração de artefatos seja expressa em código Zig normal. Isso significa que você tem acesso a toda a capacidade da linguagem (condicionais, loops, funções) para configurar seu build.

O sistema de build é executado pelo comando zig build, que compila e executa o build.zig para determinar o que fazer.

Por que build.zig Importa

  1. Sem ferramentas externas: O build system é parte do Zig — não precisa instalar Make, CMake, etc.
  2. Cross-compilation nativa: Configurar builds para diferentes plataformas é trivial.
  3. Integração C/C++: Pode compilar código C/C++ junto com Zig.
  4. Reprodutível: O mesmo build.zig produz resultados idênticos em qualquer máquina.

Exemplo Prático

build.zig Básico

const std = @import("std");

pub fn build(b: *std.Build) void {
    // Opções de target e otimização
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // Definir o 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());

    const run_step = b.step("run", "Executar o aplicativo");
    run_step.dependOn(&run_cmd.step);

    // Step para 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", "Executar testes unitários");
    test_step.dependOn(&run_testes.step);
}

build.zig com Dependência Externa

const std = @import("std");

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

    // Dependência declarada no build.zig.zon
    const zap = b.dependency("zap", .{
        .target = target,
        .optimize = optimize,
    });

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

    // Adicionar módulo da dependência
    exe.root_module.addImport("zap", zap.module("zap"));

    b.installArtifact(exe);
}

build.zig com Biblioteca 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 = "app-com-c",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Linkar com biblioteca C do sistema
    exe.linkSystemLibrary("sqlite3");
    exe.linkLibC();

    // Adicionar caminhos de include
    exe.addIncludePath(b.path("include"));

    b.installArtifact(exe);
}

Comandos Comuns

zig build          # Compilar o projeto
zig build run      # Compilar e executar
zig build test     # Executar testes
zig build -Dtarget=x86_64-linux-gnu  # Cross-compilation
zig build -Doptimize=ReleaseFast     # Build otimizado

Gerando Código com o Build System

Uma capacidade avançada do build.zig é executar passos de geração de código — como gerar enums a partir de schemas, rodar ferramentas de code generation ou emitir arquivos de configuração:

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

    // Executar um gerador de código como parte do build
    const gerador = b.addExecutable(.{
        .name = "gerador",
        .root_source_file = b.path("tools/gerador.zig"),
        .target = b.host, // roda no host, não no target
        .optimize = .ReleaseFast,
    });

    const rodar_gerador = b.addRunArtifact(gerador);
    rodar_gerador.addArg("src/gerado.zig");

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

    // O executável depende do passo de geração
    exe.step.dependOn(&rodar_gerador.step);
    b.installArtifact(exe);
}

Comparação com Outras Ferramentas de Build

FerramentaLinguagem de configTipagemDependência externa
build.zigZigForte, estáticaNão
CMakeDSL CMakeFracaSim
MakefileMake DSLNenhumaSim
CargoTOML + scripts RustParcialNão
GradleGroovy/Kotlin DSLParcialJVM

A principal vantagem do build.zig é que toda a lógica de build é código Zig real — com acesso a loops, condicionais, funções e o sistema de tipos completo da linguagem, sem aprender uma DSL separada.

Boas Práticas

  • Sempre use b.standardTargetOptions e b.standardOptimizeOption: Isso expõe flags -Dtarget e -Doptimize para o usuário sem você precisar declará-las manualmente.
  • Separe steps por função: Use b.step("lint", "..."), b.step("docs", "...") e b.step("bench", "...") para organizar tarefas além de build e test.
  • Use b.host para ferramentas de build: Ferramentas que rodam durante o build (geradores de código, formatadores) devem ter target b.host, não o target do projeto.
  • Versione o build.zig.zon: Esse arquivo declara dependências e o hash de cada pacote — faça commit dele junto com o build.zig.

Armadilhas Comuns

  • Esquecer b.installArtifact: Sem instalar o artefato, zig build não produz saída.
  • Caminhos relativos: Use b.path() para caminhos de arquivo, nunca strings de caminho absoluto.
  • Ordem de dependências: Steps devem declarar dependências com dependOn para garantir a ordem correta.
  • Confundir target e host: O build.zig roda no host, mas configura o target. Não confunda os dois.

Termos Relacionados

Tutoriais Relacionados

Continue aprendendo Zig

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