Menu

Zero Packages: zero.json, src/ и targets

Как устроен пакет Zero: манифест zero.json, каталог src/ и система целей (targets), позволяющая из одного дерева исходников собирать исполняемые файлы, библиотеки и тесты.

Зачем пакеты

Одного файла .0 достаточно, когда учите язык или пробуете фрагмент. Как только ваш проект перерастает один файл, нужен пакет — каталог с манифестом и известным layout, который понимает тулчейн.

Польза от перехода с россыпи файлов к пакету:

  • Одно каноничное место для имени, версии и метаданных проекта.
  • Несколько точек входа (исполняемый, библиотека, тесты) в одном дереве.
  • Предсказуемый layout: инструменты находят ваш исходник без конфигурации.
  • zero check / zero build по всему дереву, а не файл за файлом.

Скаффолдинг пакета

Самый быстрый способ начать — zero new:

zero new cli hello

Создаёт каталог hello/ с такой структурой:

hello/
├── zero.json
└── src/
    └── main.0

cli — это имя шаблона; он производит исполняемую CLI-программу. Другие шаблоны (библиотека, системная программа) следуют той же форме с другими дефолтами.

cd в новый каталог, запустите — и поехали:

cd hello
zero run

Когда вы дёргаете zero run из каталога пакета без имени файла, она подбирает цель по умолчанию из zero.json и запускает её.

Манифест zero.json

Манифест из скаффолдинга пакета cli выглядит так:

{
    "package": { "name": "hello", "version": "0.1.0" },
    "targets": { "cli": { "kind": "exe", "main": "src/main.0" } }
}

Два ключа верхнего уровня: package и targets. Первый идентифицирует пакет, второй говорит компилятору, что собирать.

package

"package": {
    "name": "hello",
    "version": "0.1.0"
}
  • name — slug, идентифицирующий пакет. Используйте нижний регистр и дефисы.
  • version — semver-строка. Пакеты pre-1.0 используют 0.x.y.

Другие поля метаданных (описание, автор, лицензия, репозиторий), возможно, поддерживаются — обратитесь к актуальной документации Zero за авторитетной схемой, так как манифест ещё эволюционирует.

targets

"targets": {
    "cli": { "kind": "exe", "main": "src/main.0" }
}

Ключи (cli здесь) — это имена целей, которые вы выбираете. Значения описывают каждую цель:

  • kind — что это за цель. exe для исполняемого. Другие виды (библиотека, тест) следуют той же форме.
  • main — файл-точка входа, относительно корня пакета.

В одном пакете можно объявить больше одной цели:

{
    "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" }
    }
}

Соберите конкретную цель из CLI по имени:

zero build convert
zero run resize

Каталог src/

Все исходные файлы живут под src/. Компилятор автоматически обходит этот каталог — каждый файл в манифесте не перечисляют. Поле main каждой цели указывает на её файл-точку входа; компилятор идёт по импортам оттуда, чтобы найти всё остальное.

Пакет с несколькими вспомогательными модулями может выглядеть так:

image-tools/
├── zero.json
└── src/
    ├── convert.0
    ├── resize.0
    ├── lib.0
    └── internal/
        ├── decoder.0
        └── encoder.0

Подкаталог internal/ — это просто соглашение, ничего в манифесте эти файлы не называет. Импорты внутри convert.0 достают internal/decoder.0 напрямую.

Сборка и запуск

Частые рабочие схемы внутри пакета:

zero check        # проверить типы по всему дереву
zero run          # собрать и запустить цель по умолчанию
zero run convert  # собрать и запустить именованную цель
zero build        # собрать цель по умолчанию
zero build --all  # собрать каждую цель (когда поддержано)
zero test         # запустить каждую тестовую цель

CLI читает zero.json, понимает, что делать, и делает. Внутри пакета пути почти не приходится прописывать.

Несколько файлов исходника: короткий пример

Допустим, src/main.0 вызывает помощник из src/math.0. Файл-помощник:

pub fun double(value: i32) -> i32 {
    return value * 2
}

Файл-точка входа:

pub fun main(world: World) -> Void raises {
    let result = double(21)
    if result == 42 {
        check world.out.write("forty two\n")
    }
}

Запустите через zero run. Компилятор разрешает ссылку на double против остального дерева исходников без явного объявления импорта в таком простом случае. По мере роста пакетов система явных импортов обрабатывает межмодульную видимость — обратитесь к актуальной документации Zero за синтаксисом импортов, это одна из областей, которая, скорее всего, изменится до 1.0.

Что не коммитить в git

.gitignore для пакета Zero обычно хочет:

# артефакты сборки и кэши
/build/
/target/

# мусор от редактора
.DS_Store
*.swp

Точное имя каталога вывода сборки может отличаться — сверьтесь с актуальной документацией тулчейна — но правило такое: исходник внутри, артефакты сборки снаружи.

Шеринг пакетов

Zero — pre-1.0, и реестр пакетов пока не часть стабильной поверхности. Сегодня практичные способы поделиться пакетом:

  • Git: клонируйте репозиторий и запустите zero check в нём.
  • Вендоринг: положите копию исходников в другой проект.

Когда появится реестр, ссылки на пакеты, скорее всего, переедут в поле зависимостей в zero.json. Считайте это форвард-смотрящей фичей, а не тем, под что сегодня стоит писать скрипты.

Дальше: основы языка

Теперь у вас есть всё необходимое, чтобы организовать настоящий проект Zero. Следующая глава приближается к самому языку, начиная с let-привязок — как значения в Zero получают имена.

Часто задаваемые вопросы

Что такое пакет Zero?

Пакет Zero — это каталог с манифестом zero.json и папкой src/ с файлами .0. Манифест объявляет имя пакета, версию и одну или больше «целей» — каждая цель говорит компилятору, как собрать что-то (исполняемый, библиотеку, тестовый бинарник) из исходников.

Как создать новый пакет Zero?

Запустите zero new <template> <name>, например zero new cli hello. CLI скаффолдит каталог с zero.json, src/main.0 и любыми другими файлами, которые нужны выбранному шаблону. Дальше внутри пакета можно zero check, zero run и zero build.

Что содержит zero.json?

Как минимум объект package с name и version, плюс объект targets, описывающий каждую вещь, которую собирает пакет. У цели есть kind (например, exe для исполняемого) и main, указывающий на файл-точку входа. В одном манифесте можно объявить несколько целей.

Может ли один пакет Zero иметь несколько целей?

Да. Пакет может объявлять любое число целей — например, одну exe-цель для CLI, одну lib-цель для переиспользуемой библиотеки и одну или несколько тестовых целей. У каждой цели своя точка входа в src/, и собирать или запускать их можно по отдельности из CLI.

Куда компилятор кладёт результаты сборки?

Артефакты сборки оказываются в build-каталоге внутри пакета (точный путь — реализационно-зависимый и может меняться, пока Zero pre-1.0). Дерево src/ никогда не изменяется. Считайте build-каталог расходным — коммитить его в git плохая идея.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ