Zig Package Manager: Guia Completo do build.zig.zon
Gerenciar dependências é uma das tarefas mais importantes em qualquer projeto de software. O Zig adota uma abordagem única com o build.zig.zon — um manifesto declarativo que funciona em conjunto com o build.zig para resolver, baixar e compilar pacotes automaticamente. Com as novidades do Zig 0.16.0, o sistema de pacotes ganhou melhorias significativas como o diretório local zig-pkg e cache comprimido global.
Neste guia completo, você vai aprender desde o básico do formato .zon até técnicas avançadas de publicação de bibliotecas.
O que é o build.zig.zon?
O arquivo build.zig.zon é o manifesto de metadados do seu projeto Zig. Ele descreve o nome do pacote, a versão, os caminhos expostos e, principalmente, as dependências externas. O formato ZON (Zig Object Notation) é uma sintaxe nativa do Zig — similar a JSON, mas com tipagem e avaliada pelo compilador.
// build.zig.zon
.{
.name = .meu_projeto,
.version = "0.1.0",
.minimum_zig_version = "0.16.0",
.paths = .{
"src",
"build.zig",
"build.zig.zon",
"LICENSE",
"README.md",
},
.dependencies = .{},
}
Cada campo tem uma função específica:
.name: identificador do pacote (usado em imports).version: versão semântica do seu projeto.minimum_zig_version: versão mínima do compilador necessária.paths: arquivos incluídos quando o pacote é consumido por terceiros.dependencies: mapa de dependências externas
Adicionando Dependências
Para adicionar uma dependência, você pode usar o comando zig fetch ou declarar manualmente no .zon. Vamos usar o exemplo da biblioteca zap (servidor HTTP):
Usando zig fetch
O comando zig fetch baixa o pacote e calcula o hash automaticamente:
zig fetch --save https://github.com/zigzap/zap/archive/refs/tags/v0.2.0.tar.gz
Isso adiciona a entrada em .dependencies automaticamente:
.dependencies = .{
.zap = .{
.url = "https://github.com/zigzap/zap/archive/refs/tags/v0.2.0.tar.gz",
.hash = "122054b0f5518a64b1769b1eb6475f44faa8da66120d14a1db0e0a60a0e6ca0c6e13",
},
},
Declaração manual
Você também pode declarar dependências apontando para repositórios Git:
.dependencies = .{
.ziglyph = .{
.url = "git+https://github.com/kubkon/ziglyph#v0.4.0",
.hash = "1220a1b...",
},
},
O campo .hash é um hash de conteúdo que garante integridade — se o conteúdo mudar, o build falha. Para obter o hash correto, rode zig fetch com a URL e copie o valor gerado.
Consumindo Dependências no build.zig
Depois de declarar a dependência no .zon, você precisa expô-la no build.zig. Veja como conectar a dependência zap ao seu executável:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Obtém a dependência declarada no build.zig.zon
const zap_dep = b.dependency("zap", .{
.target = target,
.optimize = optimize,
});
const exe = b.addExecutable(.{
.name = "meu-servidor",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Adiciona o módulo da dependência
exe.root_module.addImport("zap", zap_dep.module("zap"));
b.installArtifact(exe);
}
A função b.dependency() resolve o pacote usando o nome declarado no .zon. Depois, addImport() expõe o módulo para uso com @import("zap") no seu código-fonte.
Dependências Locais para Desenvolvimento
Durante o desenvolvimento, é comum trabalhar com pacotes locais — por exemplo, ao contribuir para uma biblioteca. O Zig permite apontar para caminhos no sistema de arquivos:
.dependencies = .{
.minha_lib = .{
.path = "../minha-lib",
},
},
Isso é útil para:
- Desenvolvimento simultâneo de biblioteca + aplicação
- Testes locais antes de publicar uma versão
- Monorepos com múltiplos pacotes interdependentes
Quando estiver pronto para publicar, substitua .path por .url + .hash.
Novidades do Zig 0.16: zig-pkg e Cache Comprimido
O Zig 0.16.0 trouxe melhorias importantes no gerenciamento de pacotes:
Diretório zig-pkg
As dependências agora residem em um diretório local zig-pkg no projeto, em vez de ficarem apenas no cache global. Isso traz vantagens:
meu-projeto/
├── build.zig
├── build.zig.zon
├── zig-pkg/ # ← Novo no 0.16
│ ├── zap/
│ └── ziglyph/
└── src/
└── main.zig
- Reprodutibilidade: cada projeto tem suas dependências isoladas
- Offline builds: após o primeiro fetch, tudo funciona offline
- Transparência: você pode inspecionar o código das dependências diretamente
Cache comprimido global
O Zig mantém um cache global comprimido que economiza espaço significativo. Por exemplo, o pacote freetype ocupa 13MB no zig-pkg local mas apenas 2.4MB no cache comprimido. Pacotes menores como opus vão de 707KB para apenas 4KB.
Flag –fork para debug
A nova flag --fork permite depurar o processo de resolução de dependências:
zig build --fork
Isso é especialmente útil quando você precisa diagnosticar problemas de resolução ou loops de dependência.
Criando uma Biblioteca Publicável
Para transformar seu código em uma biblioteca que outros possam consumir, você precisa configurar o build.zig.zon corretamente e expor módulos no build.zig.
Estrutura do projeto
minha-lib-zig/
├── build.zig
├── build.zig.zon
├── src/
│ ├── lib.zig # Ponto de entrada da biblioteca
│ └── internal.zig # Módulos internos
├── tests/
│ └── test_lib.zig
├── LICENSE
└── README.md
Configurando o build.zig.zon
O campo .paths é crucial — ele define quais arquivos são incluídos quando alguém consome sua biblioteca. O Zig remove tudo que não está listado antes de comprimir:
.{
.name = .minha_lib,
.version = "1.0.0",
.minimum_zig_version = "0.16.0",
.paths = .{
"src",
"build.zig",
"build.zig.zon",
"LICENSE",
},
.dependencies = .{},
}
Expondo módulos no build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Módulo que será exposto para consumidores
const lib_module = b.addModule("minha_lib", .{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
// Testes unitários
const tests = b.addTest(.{
.root_source_file = b.path("tests/test_lib.zig"),
.target = target,
.optimize = optimize,
});
tests.root_module.addImport("minha_lib", lib_module);
const run_tests = b.addRunArtifact(tests);
const test_step = b.step("test", "Roda os testes unitários");
test_step.dependOn(&run_tests.step);
}
Publicando via tag Git
Para que outros consumam sua lib, basta criar uma tag no repositório:
git tag v1.0.0
git push origin v1.0.0
Os consumidores usam a URL do tarball da tag:
.minha_lib = .{
.url = "https://github.com/seu-user/minha-lib-zig/archive/refs/tags/v1.0.0.tar.gz",
.hash = "1220...",
},
Encontrando Pacotes na Comunidade
O ecossistema Zig está crescendo rapidamente. Alguns recursos para encontrar pacotes:
- Zigistry — registro de pacotes e programas Zig
- awesome-zig — lista curada de projetos
- GitHub Topics — busque por
zig-packageouzig-library
Antes de adicionar uma dependência, verifique:
- Compatibilidade de versão com seu
minimum_zig_version - Atividade do repositório — commits recentes indicam manutenção ativa
- Testes — bibliotecas com CI configurado são mais confiáveis
- Licença — compatível com seu projeto
Boas Práticas
Após trabalhar com o sistema de pacotes do Zig em vários projetos, estas são as práticas recomendadas:
- Sempre use
zig fetch --saveem vez de copiar hashes manualmente — evita erros de digitação - Fixe versões com tags — nunca aponte para branches como
mainem produção - Liste apenas arquivos necessários em
.paths— reduz o tamanho do pacote drasticamente - Teste com
zig buildapós adicionar dependências — garante que tudo resolve corretamente - Use dependências locais durante desenvolvimento e mude para URLs antes de fazer merge
- Verifique hashes após atualizar — um hash diferente do esperado pode indicar problemas
Conclusão
O sistema de pacotes do Zig com build.zig.zon oferece uma solução elegante e reprodutível para gerenciamento de dependências. Com as melhorias do 0.16.0 — diretório zig-pkg, cache comprimido e melhor detecção de loops — o fluxo de trabalho ficou ainda mais robusto.
Se você está começando com Zig, recomendo seguir nosso tutorial de introdução e explorar o glossário sobre ZON para entender melhor a sintaxe. Para projetos mais avançados, confira nosso guia do build system que complementa este artigo.
O gerenciamento de pacotes é essencial tanto para quem está começando quanto para quem desenvolve em Rust ou Go e quer comparar abordagens. Cada linguagem de sistemas tem sua filosofia — e o Zig aposta na simplicidade e transparência.