Menu

Pacotes Zero: zero.json, src/ e targets explicados

Como um pacote Zero é organizado: o manifesto zero.json, o diretório src/ e o sistema de targets que permite a um pacote produzir executáveis, bibliotecas e testes a partir da mesma árvore de código.

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 build sobre 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 usam 0.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 é. exe para 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 check em 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?

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.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR