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, не изменяя движок разрешения.
Пример
# 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:
[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:
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/означает "стандартная библиотека уровня проекта включена", глобальная стандартная библиотека больше не участвует
Основные структуры данных
// Источник зависимости (расширяемый)
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 | Непосредственный вход в REPL | yaoxiang |
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 | Публикация пакета в Registry | yaoxiang publish |
yaoxiang publish --github | Публикация и создание GitHub Release | yaoxiang publish --github |
yaoxiang yank <pkg>@<ver> | Удаление опубликованной версии (необратимо) | yaoxiang yank foo@1.2.3 |
yaoxiang login --registry <url> | Аутентификация в Registry | yaoxiang login --registry https://reg.example.com |
yaoxiang login --github | GitHub аутентификация | 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 |
Пояснения ограничений команд
# Режим одного файла: 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# ~/.yaoxiang/config.toml
[cache]
dir = "~/.yaoxiang/cache"
max_size = "2GB"
ttl = "30d"Правила инвалидации кэша:
- Пакеты Registry: номера версий неизменяемы, кэш не инвалидируется никогда
- Git зависимости: кэшируются по tag/rev, если tag не изменился — не инвалидируется
yaoxiang cache cleanдля ручной очистки
Аутентификация
# ~/.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) | Плохая изоляция, сложные конфликты версий |
| Только поддержка Registry | GitHub является основной платформой хостинга кода в настоящее время |
Стратегия реализации
Разделение на этапы
| Этап | Содержание | Статус |
|---|---|---|
| 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-256 | sha2 | Проверка целостности |
| Сжатие | flate2 + tar | Обработка формата пакетов |
