Pourquoi des packages
Un seul fichier .0 fait l'affaire quand vous apprenez le langage ou que vous testez un snippet. Dès que votre projet dépasse un fichier, vous voulez un package — un dossier avec un manifeste et une arborescence connue que la chaîne d'outils comprend.
Les bénéfices à passer de fichiers en vrac à un package :
- Un endroit unique pour le nom, la version et les métadonnées du projet.
- Plusieurs points d'entrée (exécutable, bibliothèque, tests) dans une seule arborescence.
- Une arborescence prévisible : les outils trouvent vos sources sans configuration.
- Un
zero check/zero buildsur toute l'arborescence, et pas fichier par fichier.
Échafauder un package
Le moyen le plus rapide de commencer, c'est zero new :
zero new cli hello
Ça crée un dossier hello/ organisé comme ça :
hello/
├── zero.json
└── src/
└── main.0
cli est le nom du template — il produit un programme exécutable en ligne de commande. Les autres templates (bibliothèque, programme système) suivent la même forme avec des défauts différents.
cd dans le nouveau dossier, lancez-le, et c'est parti :
cd hello
zero run
Quand vous invoquez zero run depuis l'intérieur d'un dossier de package sans nommer de fichier, il prend la cible par défaut du zero.json et l'exécute.
Le manifeste zero.json
Le manifeste d'un package cli échafaudé ressemble à ça :
{
"package": { "name": "hello", "version": "0.1.0" },
"targets": { "cli": { "kind": "exe", "main": "src/main.0" } }
}
Deux clés de premier niveau : package et targets. La première identifie le package ; la seconde indique au compilateur ce qu'il faut construire.
package
"package": {
"name": "hello",
"version": "0.1.0"
}
name— un slug identifiant le package. Utilisez des minuscules et des tirets.version— chaîne semver. Les packages pré-1.0 utilisent0.x.y.
D'autres champs de métadonnées (description, auteur, licence, dépôt) peuvent être supportés — référez-vous à la documentation Zero actuelle pour le schéma faisant autorité, puisque le manifeste évolue encore.
targets
"targets": {
"cli": { "kind": "exe", "main": "src/main.0" }
}
Les clés (cli ici) sont des noms de cibles que vous choisissez. Les valeurs décrivent chaque cible :
kind— ce qu'est la cible.exepour un exécutable. Les autres types (bibliothèque, test) suivent la même forme.main— le fichier source d'entrée, relatif à la racine du package.
Vous pouvez déclarer plus d'une cible dans le même package :
{
"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" }
}
}
Construisez une cible précise depuis la CLI en la nommant :
zero build convert
zero run resize
Le dossier src/
Tous les fichiers source vivent sous src/. Le compilateur parcourt ce dossier automatiquement — vous n'avez pas à lister chaque fichier dans le manifeste. Le champ main de chaque cible pointe vers son fichier d'entrée ; le compilateur suit les imports depuis là pour trouver tout le reste dont il a besoin.
Un package avec quelques modules utilitaires pourrait ressembler à ça :
image-tools/
├── zero.json
└── src/
├── convert.0
├── resize.0
├── lib.0
└── internal/
├── decoder.0
└── encoder.0
Le sous-dossier internal/ n'est qu'une convention — rien dans le manifeste ne nomme ces fichiers. Les imports dans convert.0 vont chercher internal/decoder.0 directement.
Construire et exécuter
Workflows courants une fois à l'intérieur d'un package :
zero check # vérifie les types de toute l'arborescence
zero run # construit et exécute la cible par défaut
zero run convert # construit et exécute une cible nommée précise
zero build # construit la cible par défaut
zero build --all # construit chaque cible (quand c'est supporté)
zero test # exécute chaque cible de test
La CLI lit zero.json, comprend ce qu'il faut faire, et y va. Vous avez rarement à épeler les chemins une fois que vous travaillez à l'intérieur d'un package.
Plusieurs fichiers source : un exemple rapide
Supposez que src/main.0 appelle un utilitaire depuis src/math.0. Le fichier utilitaire :
pub fun double(value: i32) -> i32 {
return value * 2
}
Le fichier d'entrée :
pub fun main(world: World) -> Void raises {
let result = double(21)
if result == 42 {
check world.out.write("forty two\n")
}
}
Lancez-le avec zero run. Le compilateur résout la référence à double par rapport au reste de l'arborescence source sans déclaration d'import explicite dans ce cas simple. Quand les packages grossissent, un système d'imports explicite gère la visibilité entre modules — référez-vous à la doc Zero actuelle pour la syntaxe d'import, qui fait partie des zones les plus susceptibles de bouger avant la 1.0.
Ce qu'il ne faut pas engager dans git
Un .gitignore pour un package Zero veut généralement :
# artefacts de build et caches
/build/
/target/
# encombrants d'éditeur
.DS_Store
*.swp
Le nom exact du dossier de sortie du build peut différer — vérifiez la doc de la chaîne d'outils actuelle — mais la règle est : les sources rentrent, les artefacts de build restent dehors.
Partager des packages
Zero est pré-1.0 et un registre de packages ne fait pas encore partie de la surface stable. Pour l'instant, les façons pratiques de partager un package sont :
- Git : clonez le dépôt et lancez
zero checkdessus. - Copie vendorisée : déposez une copie du code source dans un autre projet.
Quand un registre arrivera, les références de packages bougeront probablement dans un champ de dépendances de zero.json. Considérez ça comme une fonctionnalité à venir, pas comme quelque chose à scripter aujourd'hui.
La suite : les bases du langage
Vous avez maintenant tout ce qu'il faut pour organiser un vrai projet Zero. Le prochain chapitre zoome sur le langage lui-même, en commençant par les liaisons let — comment les valeurs Zero reçoivent des noms.
Questions fréquentes
Qu'est-ce qu'un package Zero ?
Un package Zero est un dossier contenant un manifeste zero.json et un dossier src/ avec des fichiers source .0. Le manifeste déclare le nom du package, sa version, et une ou plusieurs « cibles » — chaque cible indique au compilateur comment construire quelque chose (un exécutable, une bibliothèque, un binaire de test) à partir du code source.
Comment créer un nouveau package Zero ?
Lancez zero new <template> <nom>, par exemple zero new cli hello. La CLI échafaude un dossier avec un zero.json, un src/main.0, et tous les autres fichiers nécessaires au template choisi. À partir de là, vous pouvez lancer zero check, zero run et zero build dans le package.
Que contient zero.json ?
zero.json ?Au minimum, un objet package avec un name et une version, plus un objet targets décrivant chaque chose que le package construit. Une cible a un kind (comme exe pour un exécutable) et un main qui pointe vers le fichier source d'entrée. Vous pouvez déclarer plusieurs cibles dans un même manifeste.
Un même package Zero peut-il avoir plusieurs cibles ?
Oui. Un package peut déclarer un nombre quelconque de cibles — par exemple une cible exe pour une CLI, une cible lib pour une bibliothèque réutilisable, et une ou plusieurs cibles de test. Chaque cible a son propre point d'entrée sous src/, et vous pouvez les construire ou les exécuter individuellement depuis la CLI.
Où le compilateur place-t-il la sortie de build ?
Les artefacts de build atterrissent dans un dossier de build à l'intérieur du package (le chemin exact dépend de l'implémentation et peut changer pendant que Zero est pré-1.0). L'arborescence source sous src/ n'est jamais modifiée. Considérez le dossier de build comme jetable — l'engager dans git est une mauvaise idée.