Skip to content

RFC-014: Проектирование системы управления пакетами (общая спецификация)

Подчинённые RFC:

Краткое описание

Проектирование системы управления пакетами для языка YaoXiang с поддержкой семантического версионирования, локальных зависимостей и зависимостей GitHub, унифицированного синтаксиса импорта, конфигурационного файла yaoxiang.toml и файла блокировки yaoxiang.lock.

Мотивация

Зачем нужна эта функциональность/изменение?

Управление пакетами является основой инфраструктуры экосистемы современных языков программирования. В настоящее время языку YaoXiang не хватает:

  • Механизма объявления зависимостей
  • Возможностей управления версиями
  • Стандартного канала распространения

Текущие проблемы

my-project/
├── src/
│   └── main.yx          # Код зависит от других модулей
├── lib/                  # Вручную скопированные модули
│   ├── foo.yx
│   └── bar.yx
└── ???                   # Нет стандартного управления зависимостями

Предложение

Основной дизайн

Многоуровневая архитектура:

┌─────────────────────────────────────────────┐
│           Resolution Engine                  │ ← Разрешение зависимостей
└─────────────────┬───────────────────────────┘


┌─────────────────────────────────────────────┐
│            Global Cache                      │ ← ~/.yaoxiang/cache/
└─────────────────┬───────────────────────────┘


┌─────────────────────────────────────────────┐
│              Source Trait                    │ ← Расширяемый источник
├──────────┬──────────┬──────────┬────────────┤
│  Local   │   Git    │ Registry │   GitHub   │
│ (локаль) │  (VCS)   │  (открыт)│ (Release)  │
└──────────┴──────────┴──────────┴────────────┘


┌─────────────────────────────────────────────┐
│           Vendor Directory                   │ ← .yaoxiang/vendor/
└─────────────────────────────────────────────┘

Механизм расширения: Для добавления нового типа Source достаточно реализовать trait, не изменяя движок разрешения.

Пример

bash
# 1. Создание проекта
yaoxiang init my-project

# 2. Редактирование yaoxiang.toml для добавления зависимостей
[dependencies]
foo = "^1.0.0"
bar = { git = "https://github.com/user/bar", version = "0.5.0" }

# 3. Установка зависимостей
yaoxiang add foo

# 4. Использование в коде
use foo;
use bar.baz;

Структура проекта

my-project/
├── yaoxiang.toml        # Конфигурация пакета
├── yaoxiang.lock        # Файл блокировки (автогенерируемый)
├── src/
│   └── main.yx
└── .yaoxiang/
    └── vendor/              # Локальные зависимости
        ├── foo-1.2.3/
        └── bar-0.5.0/

Детальный дизайн

Формат конфигурационного файла

yaoxiang.toml:

toml
[package]
name = "my-package"
version = "0.1.0"
description = "A short description"
license = "MIT"
authors = ["Your Name <you@example.com>"]
repository = "https://github.com/you/my-package"
keywords = ["cli", "utility"]

[dependencies]
foo = "1.2.3"           # Точная версия
bar = "^1.0.0"          # Совместимая версия
baz = "~1.2.0"          # Патч-версия
qux = { git = "...", version = "0.5.0" }
local_pkg = { path = "./local-module" }

[dev-dependencies]
test-utils = "0.1.0"

[build]
strategy = "none"       # none | cargo | cmake | custom

[binaries]
"linux-x86_64" = { url = "...", sha256 = "..." }

[workspace.members]     # Только для корня рабочего пространства
core = "packages/core/yaoxiang.toml"

yaoxiang.lock:

toml
version = 1

[[package]]
name = "foo"
version = "1.2.3"
source = "git"
resolved = "https://github.com/user/foo?tag=v1.2.3"
integrity = "sha256-xxxx"

Порядок разрешения модулей

Порядок разрешения зависит от режима работы (наличия yaoxiang.toml).

Режим проекта (с yaoxiang.toml)

use foo.bar.baz;

Порядок поиска:
0. Встроенный бинарник                        (std/*.yx — встроен при компиляции, привязка к версии, только пространство имён std.*)
1. ./.yaoxiang/std/foo/bar/baz.yx             (стандартная библиотека уровня проекта — при наличии глобальная стандартная библиотека полностью игнорируется)
2. ./.yaoxiang/vendor/*/src/foo/bar/baz.yx    (vendor/)
3. ./src/foo/bar/baz.yx                       (локальные модули)
4. ~/.yaoxiang/cache/foo/<ver>/src/foo/bar/baz.yx  (глобальный кэш)
5. $YXPATH/foo/bar/baz.yx                     (глобальный путь, зарезервировано)

Правила режима проекта:

  • Встроенный бинарник применяется только к пространству имён std.*, наивысший приоритет
  • При наличии стандартной библиотеки уровня проекта (.yaoxiang/std/) глобальная стандартная библиотека полностью пропускается — обеспечивается детерминированность сборки
  • Проект может использовать yaoxiang add std@1.0.1 для управления стандартной библиотекой как зависимостью с блокировкой версии

Режим одного файла (без yaoxiang.toml)

use foo.bar.baz;

Порядок поиска:
0. Встроенный бинарник                        (std/*.yx — встроен при компиляции, привязка к версии)
1. <yaoxiang-install-dir>/yx/<version>/std/foo/bar/baz.yx  (глобальная стандартная библиотека)
2. ./src/foo/bar/baz.yx                                       (локальные модули)
3. $YXPATH/foo/bar/baz.yx                                     (глобальный путь, зарезервировано)

Правила режима одного файла:

  • Нет зависимостей уровня проекта, стандартная библиотека загружается напрямую из глобального пути
  • Путь к глобальной стандартной библиотеке привязан к версии компилятора: <install-dir>/yx/<version>/std/

Структура каталогов установки стандартной библиотеки

Глобальная стандартная библиотека

<yaoxiang-install-dir>/
├── yx/                          # Директория языка YaoXiang
│   ├── 1.0.1/                   # Директория версии
│   │   ├── std/
│   │   │   ├── test.yx          # Модули стандартной библиотеки на чистом YaoXiang
│   │   │   ├── math.yx          # Модули для будущей самокомпиляции
│   │   │   └── ...
│   │   └── ...
│   └── 1.1.0/
│       └── std/
│           └── ...
└── bin/
    └── yaoxiang                 # Бинарник компилятора

Стандартная библиотека уровня проекта

Проект может использовать yaoxiang add std@1.0.1 для добавления стандартной библиотеки как зависимости в проект, хранится в .yaoxiang/std/:

my-project/
├── yaoxiang.toml
├── yaoxiang.lock
├── .yaoxiang/
│   ├── std/                     # Стандартная библиотека уровня проекта (при наличии глобальная стандартная библиотека игнорируется)
│   │   ├── test.yx
│   │   ├── math.yx
│   │   └── ...
│   └── vendor/                  # Другие зависимости
│       └── ...
├── src/
│   └── main.yx

Ключевые аспекты дизайна:

  • Встроенный бинарник как слой совместимости: до полноценного появления файловой системной стандартной библиотеки модули стандартной библиотеки предоставляются через встроенный бинарник
  • Изоляция по версиям: yx/<version>/std/ позволяет сосуществовать стандартным библиотекам разных версий без взаимного влияния
  • Стандартная библиотека уровня проекта переопределяет глобальную: обеспечивается детерминированность сборки, независимость от изменений глобального окружения
  • При отсутствии yaoxiang.toml (режим одного файла) используется глобальная стандартная библиотека
  • Наличие .yaoxiang/std/ означает "стандартная библиотека уровня проекта включена", глобальная стандартная библиотека больше не участвует

Основные структуры данных

rust
// Источник зависимости (расширяемый)
enum Source {
    Local { path: PathBuf },
    Git { url: Url, version: Option<VersionConstraint> },
    Registry { registry: String, namespace: Option<String> },
    GitHub { owner: String, repo: String, ref_: GitRef },  // Нативный GitHub
}

enum GitRef {
    Tag(String),
    Branch(String),
    Rev(String),
    DefaultBranch,
}

// Объявление зависимости
enum DependencySpec {
    Version(VersionConstraint),
    Git { url: Url, version: Option<VersionConstraint> },
    Local { path: PathBuf },
    Workspace { member: String },  // Ссылка на член рабочего пространства
}

// Разрешённая зависимость
struct ResolvedDependency {
    name: String,
    version: Version,
    source: Source,
    integrity: Option<String>,
    checksum: Option<String>,  // SHA-256
}

// Стратегия сборки
enum BuildStrategy {
    None,          // Чистый .yx пакет
    Cargo,         # Вызов cargo build
    Cmake,         # Вызов cmake
    Custom,        # Выполнение скрипта build.yx
    Precompiled,   # Непосредственное использование предкомпилированных артефактов
}

Дизайн CLI команд

Используется унифицированный подход: компилятор, менеджер пакетов и REPL объединены в единый CLI инструмент:

Режим одного файла vs Режим проекта

КомандаОдин файлРежим проектаОписание
yaoxiang run <file>Запуск файла/входа проекта
yaoxiang buildСборка проекта
yaoxiang build <file>Сборка одного файла
yaoxiang init <name>Создание проекта
yaoxiang add <dep>Добавление зависимости
yaoxiang updateОбновление зависимостей
yaoxiang fmtФорматирование
yaoxiang checkПроверка типов
yaoxiang (без параметров)Непосредственный вход в REPL

Детали команд

КомандаФункцияПример
yaoxiangНепосредственный вход в REPLyaoxiang
yaoxiang run <file>Запуск одного файла/проектаyaoxiang run main.yx
yaoxiang init <name>Создание нового проектаyaoxiang init my-app
yaoxiang buildСборка проектаyaoxiang build
yaoxiang build <file>Сборка одного файлаyaoxiang build foo.yx
yaoxiang add <dep>Добавление зависимостиyaoxiang add foo
yaoxiang add -D <dep>Добавление dev-зависимостиyaoxiang add -D test
yaoxiang rm <dep>Удаление зависимостиyaoxiang rm foo
yaoxiang updateОбновление всех зависимостейyaoxiang update
yaoxiang update fooОбновление указаннойyaoxiang update foo
yaoxiang installУстановка всех зависимостейyaoxiang install
yaoxiang listСписок зависимостейyaoxiang list
yaoxiang outdatedПроверка устаревшихyaoxiang outdated
yaoxiang fmtФорматирование кодаyaoxiang fmt
yaoxiang checkПроверка типовyaoxiang check
yaoxiang cleanОчистка артефактов сборкиyaoxiang clean
yaoxiang task <name>Запуск пользовательских задачyaoxiang task lint
yaoxiang publishПубликация пакета в Registryyaoxiang publish
yaoxiang publish --githubПубликация и создание GitHub Releaseyaoxiang publish --github
yaoxiang yank <pkg>@<ver>Удаление опубликованной версии (необратимо)yaoxiang yank foo@1.2.3
yaoxiang login --registry <url>Аутентификация в Registryyaoxiang login --registry https://reg.example.com
yaoxiang login --githubGitHub аутентификацияyaoxiang login --github
yaoxiang logout --registry <url>Выходyaoxiang logout --registry https://reg.example.com
yaoxiang cache cleanОчистка глобального кэшаyaoxiang cache clean
yaoxiang workspace <cmd>Операции с рабочим пространствомyaoxiang workspace list

Пояснения ограничений команд

bash
# Режим одного файла: yaoxiang.toml не требуется
yaoxiang run hello.yx   # ✅ Работает нормально
yaoxiang add foo        # ❌ Ошибка: не директория проекта

# Режим проекта: требуется yaoxiang.toml
cd my-project
yaoxiang run main.yx    # ✅ Запуск точки входа
yaoxiang build          # ✅ Сборка проекта
yaoxiang add foo        # ✅ Добавление зависимости

Обратная совместимость

  • ✅ Существующий синтаксис use полностью сохранён
  • ✅ Существующая логика разрешения модулей не изменена
  • ✅ Новый каталог .yaoxiang/vendor не влияет на существующие проекты

Глобальный кэш

Все загруженные зависимости кэшируются в ~/.yaoxiang/cache/, каталог vendor проекта копируется из кэша.

~/.yaoxiang/
├── cache/
│   ├── registry/
│   │   └── foo-1.2.3/
│   ├── git/
│   │   └── github.com-user-bar-abc123/
│   └── binaries/
│       └── foo-1.2.3-linux-x86_64.tar.gz
├── credentials.toml
└── config.toml
toml
# ~/.yaoxiang/config.toml
[cache]
dir = "~/.yaoxiang/cache"
max_size = "2GB"
ttl = "30d"

Правила инвалидации кэша:

  • Пакеты Registry: номера версий неизменяемы, кэш не инвалидируется никогда
  • Git зависимости: кэшируются по tag/rev, если tag не изменился — не инвалидируется
  • yaoxiang cache clean для ручной очистки

Аутентификация

toml
# ~/.yaoxiang/credentials.toml
[github]
token = "ghp_xxxx"

[registries.my-company]
url = "https://yxreg.my-company.com"
token = "xxx"
  • Приоритет у переменных окружения: $YX_GITHUB_TOKEN, $YX_REGISTRY_TOKEN
  • Token никогда не записывается в yaoxiang.toml или yaoxiang.lock
  • Права доступа к файлу 600

Семантика yank

yaoxiang yank foo@1.2.3 выполняет удаление + блокировку номера версии:

  • Пакет полностью удаляется, восстановлению не подлежит
  • Номер версии永久но занят, нельзя переопубликовать с тем же номером версии
  • Проекты с lockfile, ссылающимся на эту версию, получат ошибку, требуется обновление
  • Цель безопасности: предотвращение атак цепочки поставок в стиле npm (атакующий регистрирует удалённую версию для внедрения вредоносного кода)

Протокол Registry

Подробнее в RFC-014a: Спецификация протокола Registry.

Основной дизайн: открытый протокол + адаптерный слой. Официальный Registry как основной, GitHub Release/ветка main как вспомогательные, поддержка пользовательских Registry.

Система сборки

Подробнее в RFC-014b: Система сборки и распространение бинарных файлов.

Основной дизайн: декларативная конфигурация [build], приоритет предкомпилированного / fallback в исходный код, поддержка стратегий cargo/cmake/custom.

Рабочие пространства

Подробнее в RFC-014c: Поддержка рабочих пространств.

Основной дизайн: объявление members в виде словаря, общий lockfile, path-зависимости, интеграция с Cargo workspace.

Компромиссы

Преимущества

  • Унифицированный синтаксис импорта, пользователям не нужно заботиться об источнике зависимости
  • Детерминированная сборка, lock файл гарантирует согласованность сборки
  • Поддержка офлайн-режима, можно разрабатывать офлайн после загрузки локально
  • Source trait упрощает дальнейшее расширение

Недостатки

  • Требуется дополнительное дисковое пространство (каталог .yaoxiang/vendor)
  • Конфликты версий требуют ручного разрешения пользователем

Альтернативные решения

РешениеПочему не выбрано
Прямой доступ к GitHubСложно гарантировать безопасность и повторное использование кэша
Глобальный кэш ($HOME/.yaoxiang)Плохая изоляция, сложные конфликты версий
Только поддержка RegistryGitHub является основной платформой хостинга кода в настоящее время

Стратегия реализации

Разделение на этапы

ЭтапСодержаниеСтатус
Phase 1Парсинг toml, локальные зависимости, генерация lock, базовые алгоритмы✅ Завершено
Phase 2Поддержка GitHub, управление .yaoxiang/vendor, инструмент загрузки✅ Завершено
Phase 3Глобальный кэш, замена semver crate, улучшение CLIЗапланировано
Phase 3.5Изменение Source trait на async, интеграция async-traitЗапланировано
Phase 4Протокол Registry, publish, аутентификация (RFC-014a)Запланировано
Phase 5Система сборки, предкомпилированные бинарники (RFC-014b)Запланировано
Phase 6Поддержка рабочих пространств (RFC-014c)Запланировано

Зависимости

  • Нет предварительных зависимостей
  • Требуется интеграция с ModuleGraph (middle/passes/module/)

Риски

РискМеры снижения
Сложный алгоритм разрешения зависимостейСначала реализовать простую версию, затем добавить обнаружение конфликтов
Нестабильная загрузка GitМеханизмы повторных попыток и кэширования
Проблемы производительностиЛенивая загрузка, инкрементальное разрешение

Открытые вопросы

  • [x] Синтаксис условной компиляции для dev-dependencies? → Единообразно обрабатывается системой сборки RFC-014b
  • [x] Алгоритм проверки целостности (SHA-256 / BLAKE3)? → SHA-256
  • [ ] Синтаксис excludes для исключения определённых файлов из загрузки?
  • [ ] Соглашения об именовании пакетов (поддержка namespace, например @org/pkg)?
  • [ ] Стратегия версионирования API Registry?

Зависимости (необходимо добавить в Cargo.toml)

НазначениеcrateОписание
Семантическое версионированиеsemverЗамена самописного парсера
HTTP клиентreqwestКоммуникация с Registry
SHA-256sha2Проверка целостности
Сжатиеflate2 + tarОбработка формата пакетов

Ссылки