Gerenciador de Pacotes do Zig — Guia Completo

Gerenciador de Pacotes do Zig — Guia Completo

O gerenciador de pacotes do Zig é uma peça fundamental do ecossistema, integrado diretamente ao sistema de build. Diferente de gerenciadores de pacotes centralizados como npm ou crates.io, o sistema do Zig adota uma abordagem descentralizada baseada em URLs e hashes, garantindo reprodutibilidade total das builds sem depender de um registro central único.

Arquitetura do Sistema de Pacotes

O gerenciamento de pacotes no Zig é feito através de dois arquivos que trabalham em conjunto:

  • build.zig.zon: Declara as dependências do projeto, incluindo URLs e hashes de integridade
  • build.zig: Configura como as dependências são usadas no processo de compilação

Essa separação permite que o sistema de build seja flexível enquanto as dependências permanecem declarativas e verificáveis.

Estrutura do build.zig.zon

O arquivo build.zig.zon usa o formato ZON (Zig Object Notation), que é essencialmente um subconjunto da sintaxe de inicializadores do Zig:

.{
    .name = "meu-projeto",
    .version = "1.0.0",
    .minimum_zig_version = "0.13.0",
    .dependencies = .{
        .httpz = .{
            .url = "https://github.com/zig-community/httpz/archive/refs/tags/v0.2.0.tar.gz",
            .hash = "1220a1b2c3d4e5f6...",
        },
        .zap = .{
            .url = "git+https://github.com/zigzap/zap.git#v0.5.0",
            .hash = "1220f1e2d3c4b5a6...",
        },
        .minha_lib_local = .{
            .path = "../minha-lib",
        },
    },
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
        "LICENSE",
        "README.md",
    },
}

Campos Importantes

  • .name: Nome do pacote, usado como identificador
  • .version: Versão semântica do pacote
  • .minimum_zig_version: Versão mínima do compilador necessária
  • .dependencies: Mapa de dependências com URLs ou caminhos locais
  • .paths: Arquivos incluídos quando o pacote é consumido como dependência

Adicionando Dependências

Via Comando fetch

A forma mais simples de adicionar uma dependência é usando zig fetch:

# Adicionar dependência e calcular hash automaticamente
zig fetch --save https://github.com/exemplo/lib/archive/refs/tags/v1.0.0.tar.gz

# O comando adiciona automaticamente ao build.zig.zon

Manualmente

Você pode adicionar dependências manualmente ao build.zig.zon. Para calcular o hash:

zig fetch https://github.com/exemplo/lib/archive/refs/tags/v1.0.0.tar.gz
# Retorna o hash que deve ser colocado no campo .hash

Dependências Git

O Zig suporta repositórios Git diretamente:

.minha_dep = .{
    .url = "git+https://github.com/usuario/repo.git#tag-ou-commit",
    .hash = "1220...",
},

Dependências Locais

Para desenvolvimento com bibliotecas locais:

.minha_lib = .{
    .path = "../caminho/para/lib",
},

Usando Dependências no build.zig

Após declarar as dependências no build.zig.zon, use-as no 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 = "minha-app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Importar dependência
    const httpz = b.dependency("httpz", .{
        .target = target,
        .optimize = optimize,
    });

    // Adicionar módulo ao executável
    exe.root_module.addImport("httpz", httpz.module("httpz"));

    // Para bibliotecas C empacotadas como dependências Zig
    const sqlite = b.dependency("sqlite", .{
        .target = target,
        .optimize = optimize,
    });
    exe.linkLibrary(sqlite.artifact("sqlite3"));

    b.installArtifact(exe);
}

No código fonte, use normalmente:

const httpz = @import("httpz");
const std = @import("std");

pub fn main() !void {
    var server = try httpz.Server.init(std.heap.page_allocator, .{ .port = 8080 });
    defer server.deinit();
    // ...
}

Criando Pacotes para Publicação

Para criar um pacote Zig que outros possam usar como dependência, siga estas práticas:

Estrutura Recomendada

minha-lib/
├── build.zig
├── build.zig.zon
├── src/
│   ├── lib.zig        # Ponto de entrada do módulo
│   └── internal/
│       └── utils.zig
├── tests/
│   └── test_lib.zig
├── LICENSE
└── README.md

build.zig para uma Biblioteca

const std = @import("std");

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

    // Expor módulo para consumidores
    _ = b.addModule("minha-lib", .{
        .root_source_file = b.path("src/lib.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Testes
    const tests = b.addTest(.{
        .root_source_file = b.path("src/lib.zig"),
        .target = target,
        .optimize = optimize,
    });

    const run_tests = b.addRunArtifact(tests);
    const test_step = b.step("test", "Executar testes");
    test_step.dependOn(&run_tests.step);
}

build.zig.zon para Publicação

.{
    .name = "minha-lib",
    .version = "0.1.0",
    .minimum_zig_version = "0.13.0",
    .dependencies = .{},
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
        "LICENSE",
    },
}

Publicação

Como o sistema é descentralizado, publique seu pacote em qualquer serviço de hospedagem Git:

  1. GitHub/GitLab: Crie releases com tags semânticas
  2. Tar archives: Hospede em qualquer servidor HTTP
  3. Registros comunitários: Use plataformas como aquila ou astrolabe.pm

Registros de Pacotes Comunitários

Embora o Zig não tenha um registro central oficial, a comunidade mantém diretórios de pacotes:

  • aquila: Registro e busca de pacotes Zig
  • astrolabe.pm: Catálogo de pacotes com busca e metadados
  • GitHub Topics: Busque por repositórios com a tag “zig-package”

Esses recursos são ótimos para descobrir bibliotecas do ecossistema como frameworks web, bibliotecas de criptografia e drivers de banco de dados.

Cache e Reprodutibilidade

O gerenciador de pacotes mantém um cache local em ~/.cache/zig/ (Linux) ou equivalente. As dependências são baixadas uma única vez e reutilizadas entre builds.

A verificação de hash garante que:

  • Dependências não podem ser alteradas após publicação sem que o hash mude
  • Builds são reproduzíveis em qualquer máquina
  • Ataques de supply chain são detectáveis
# Limpar cache se necessário
rm -rf ~/.cache/zig/p/

# Forçar re-download de dependências
zig build --fetch

Dependências Transitivas

O sistema resolve automaticamente dependências transitivas. Se seu projeto depende de A, e A depende de B, o Zig resolve toda a árvore de dependências e garante que não haja conflitos de versão.

Boas Práticas

  1. Use tags semânticas para versionar seus pacotes
  2. Declare .paths explicitamente para controlar o que é incluído no pacote
  3. Especifique minimum_zig_version para ajudar consumidores
  4. Teste com múltiplas versões do compilador usando zigup
  5. Documente o módulo público com doc comments no código fonte
  6. Mantenha dependências mínimas para reduzir a árvore de dependências

Próximos Passos

Com o gerenciador de pacotes dominado, explore as bibliotecas disponíveis no ecossistema Zig. Consulte nossos tutoriais para projetos práticos que utilizam dependências externas e veja como projetos reais gerenciam pacotes nos cases de sucesso.

Continue aprendendo Zig

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