Por que pacotes
Um único arquivo .0 é suficiente quando você está aprendendo a linguagem ou testando um snippet. No momento em que seu projeto cresce além de um arquivo, você quer um pacote — um diretório com um manifesto e um layout conhecido que a toolchain entende.
Os benefícios de migrar de arquivos soltos para um pacote:
- Um lugar canônico para o nome, versão e metadados do projeto.
- Múltiplos pontos de entrada (executável, biblioteca, testes) em uma árvore.
- Layout previsível: as ferramentas acham o código-fonte sem configuração.
- Um
zero check/zero buildsobre a árvore inteira, não arquivo a arquivo.
Esqueletizando um pacote
A forma mais rápida de começar é zero new:
zero new cli hello
Isso cria um diretório hello/ organizado assim:
hello/
├── zero.json
└── src/
└── main.0
cli é o nome do template — ele produz um programa executável de linha de comando. Outros templates (biblioteca, programa de sistema) seguem a mesma forma com defaults diferentes.
cd para o diretório novo, rode e você está em ação:
cd hello
zero run
Quando você invoca zero run dentro de um diretório de pacote sem nomear um arquivo, ele pega o target padrão do zero.json e roda esse.
O manifesto zero.json
O manifesto de um pacote cli esqueletizado fica assim:
{
"package": { "name": "hello", "version": "0.1.0" },
"targets": { "cli": { "kind": "exe", "main": "src/main.0" } }
}
Duas chaves no nível superior: package e targets. A primeira identifica o pacote; a segunda diz ao compilador o que construir.
package
"package": {
"name": "hello",
"version": "0.1.0"
}
name— um slug identificando o pacote. Use letras minúsculas e hífens.version— string de semver. Pacotes pré-1.0 usam0.x.y.
Outros campos de metadados (descrição, autor, licença, repositório) podem ser suportados — consulte a documentação atual do Zero para o schema oficial, já que o manifesto ainda está evoluindo.
targets
"targets": {
"cli": { "kind": "exe", "main": "src/main.0" }
}
As chaves (cli aqui) são nomes de target que você escolhe. Os valores descrevem cada target:
kind— o que o target é.exepara um executável. Outros tipos (library, test) seguem a mesma forma.main— o arquivo-fonte de entrada, relativo à raiz do pacote.
Você pode declarar mais de um target no mesmo pacote:
{
"package": { "name": "image-tools", "version": "0.1.0" },
"targets": {
"convert": { "kind": "exe", "main": "src/convert.0" },
"resize": { "kind": "exe", "main": "src/resize.0" },
"lib": { "kind": "lib", "main": "src/lib.0" }
}
}
Construa um target específico pela CLI nomeando-o:
zero build convert
zero run resize
O diretório src/
Todos os arquivos-fonte vivem em src/. O compilador percorre esse diretório automaticamente — você não lista cada arquivo no manifesto. O campo main de cada target aponta para o arquivo de entrada; o compilador segue os imports a partir dali para achar todo o resto.
Um pacote com alguns módulos auxiliares pode ficar assim:
image-tools/
├── zero.json
└── src/
├── convert.0
├── resize.0
├── lib.0
└── internal/
├── decoder.0
└── encoder.0
A subpasta internal/ é só uma convenção — nada no manifesto nomeia esses arquivos. Imports dentro de convert.0 alcançam internal/decoder.0 diretamente.
Construir e executar
Fluxos comuns quando você está dentro de um pacote:
zero check # verifica tipos da árvore inteira
zero run # constrói e roda o target padrão
zero run convert # constrói e roda um target nomeado específico
zero build # constrói o target padrão
zero build --all # constrói todos os targets (quando suportado)
zero test # roda todos os targets de teste
A CLI lê o zero.json, descobre o que fazer e segue. Você raramente precisa escrever caminhos quando está trabalhando dentro de um pacote.
Múltiplos arquivos-fonte: um exemplo rápido
Suponha que src/main.0 chame um auxiliar em src/math.0. O arquivo auxiliar:
pub fun double(value: i32) -> i32 {
return value * 2
}
O arquivo de entrada:
pub fun main(world: World) -> Void raises {
let result = double(21)
if result == 42 {
check world.out.write("forty two\n")
}
}
Rode com zero run. O compilador resolve a referência a double contra o resto da árvore de código sem qualquer declaração explícita de import nesse caso simples. À medida que os pacotes crescem, um sistema explícito de imports cuida da visibilidade entre módulos — consulte a documentação atual do Zero para a sintaxe de import, que é uma das áreas com mais probabilidade de mudar antes da 1.0.
O que não versionar no git
Um .gitignore para um pacote Zero geralmente quer:
# artefatos de build e caches
/build/
/target/
# sujeira de editor
.DS_Store
*.swp
O nome exato do diretório de saída de build pode variar — confira a documentação atual da toolchain — mas a regra é: código-fonte entra, artefatos de build ficam de fora.
Compartilhando pacotes
Zero é pré-1.0 e um registro de pacotes ainda não faz parte da superfície estável. Por enquanto, as formas práticas de compartilhar um pacote são:
- Git: clonar o repo e rodar
zero checkem cima. - Cópia vendorizada: jogar uma cópia do código-fonte em outro projeto.
Quando um registro chegar, as referências de pacote provavelmente vão migrar para um campo de dependências no zero.json. Trate isso como uma funcionalidade para o futuro, não como algo para scriptar hoje.
A seguir: fundamentos da linguagem
Agora você tem tudo o que precisa para organizar um projeto Zero de verdade. O próximo capítulo aprofunda na linguagem propriamente dita, começando pelas ligações let — como os valores em Zero ganham nomes.
Perguntas frequentes
O que é um pacote Zero?
Um pacote Zero é um diretório com um manifesto zero.json e uma pasta src/ com arquivos-fonte .0. O manifesto declara o nome do pacote, a versão e um ou mais 'targets' — cada target diz ao compilador como construir algo (um executável, uma biblioteca, um binário de teste) a partir do código-fonte.
Como crio um pacote Zero novo?
Rode zero new <template> <nome>, por exemplo zero new cli hello. A CLI cria a estrutura de um diretório com um zero.json, um src/main.0 e quaisquer outros arquivos que o template escolhido precisar. A partir daí você pode rodar zero check, zero run e zero build dentro do pacote.
O que o zero.json contém?
zero.json contém?No mínimo, um objeto package com name e version, mais um objeto targets descrevendo cada coisa que o pacote produz. Um target tem um kind (como exe para um executável) e um main apontando para o arquivo-fonte de entrada. Você pode declarar múltiplos targets num único manifesto.
Um único pacote Zero pode ter múltiplos targets?
Pode. Um pacote pode declarar quantos targets quiser — por exemplo um target exe para uma CLI, um target lib para uma biblioteca reutilizável e um ou mais targets de teste. Cada target tem o próprio ponto de entrada em src/, e você pode construir ou rodar individualmente pela CLI.
Onde o compilador coloca a saída de build?
Os artefatos de build vão para um diretório de build dentro do pacote (o caminho exato é definido pela implementação e pode mudar enquanto o Zero é pré-1.0). A árvore de código em src/ nunca é modificada. Trate o diretório de build como descartável — versionar no git é má ideia.