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"

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

Решение от 2026-09-15: взаимоисключающая семантика основных источников пакетов (по типу Python venv / Node node_modules). Устаревшее описание «5-уровневой сквозной цепочки поиска» — либо vendor, либо глобальный кэш выступает единственным основным источником пакетов, std встроен в основной источник, локальные модули могут перекрывать всё остальное.

Определение основного источника пакетов (взаимоисключающее, никогда не смешивается):

  • Если в проекте существует .yaoxiang/vendor/ → vendor является единственным основным источником пакетов. Все use не-локальных модулей разрешаются только из vendor, отсутствие пакета в vendor приводит к ошибке (с подсказкой yaoxiang install), глобальный откат не выполняется.
  • Иначе → глобальный кэш является основным источником пакетов (директория установки std + глобальный кэш).

Не существует «по-пакетного проникновения» вида «если в vendor нет, откатываемся к глобальному кэшу» — смешивание двух источников и есть корень дрейфа версий и проблемы «у меня на машине работает».

Проектный режим (с yaoxiang.toml) ​

use foo.bar.baz;

Порядок поиска:
1. ./src/foo/bar/baz.yx     локальный модуль — наивысший приоритет, может перекрывать одноимённый модуль в основном источнике
2. <основной источник>/foo/bar/baz.yx
   · режим vendor: .yaoxiang/vendor/<pkg>-<ver>/src/foo/bar/baz.yx (std также находится в vendor)
   · глобальный режим: <install-dir>/yx/<ver>/std/foo/bar/baz.yx + ~/.yaoxiang/cache/...
3. Специальный резерв для std.*: встроенный бинарный (только пространство имён std.*; переходный слой до появления файловой системы std, версия привязана к компилятору)
4. Ошибка (модуль не существует); в режиме vendor при отсутствии пакета — подсказка `yaoxiang install`

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

  • yaoxiang add std@1.0.1 устанавливает std как обычную зависимость в vendor и фиксирует версию; в этом случае встроенный бинарный std более не действует (std из vendor имеет приоритет)
  • При наличии vendor, несовместимого с yaoxiang.lock, команды run/build возвращают ошибку с подсказкой yaoxiang install (семантика Node: без автоматической тихой установки)
  • При перекрытии локальным модулем одноимённого модуля в основном источнике по умолчанию выдаётся диагностическое сообщение уровня W о затенении (--deny-shadowing повышает до ошибки); при перекрытии std.* текст диагностики явно предупреждает
  • Зависимость path рассматривается как расширение локального модуля и разрешается напрямую по пути, минуя основной источник пакетов

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

use foo.bar.baz;

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

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

  • Понятие проектных зависимостей отсутствует, std берётся напрямую из глобального; путь глобальной стандартной библиотеки привязан к версии компилятора: <install-dir>/yx/<version>/std/
  • В режиме одиночного файла .yaoxiang/ никогда не читается (понятие vendor отсутствует)

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

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

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

Проектная стандартная библиотека ​

Решение от 2026-09-15: отдельный каталог .yaoxiang/std/ более не создаётся. std — обычный пакет в основном источнике: после yaoxiang add std@1.0.1 он попадает в .yaoxiang/vendor/std-<version>/ и управляется по тем же правилам, что и другие зависимости. Прежнее правило «при наличии проектного std глобальный std не действует» больше не требуется — взаимоисключающая природа основного источника пакетов гарантирует это естественным образом.

my-project/
├── yaoxiang.toml
├── yaoxiang.lock
├── .yaoxiang/
│   └── vendor/
│       ├── std-1.0.1/           # std как обычный пакет в vendor
│       └── foo-1.2.3/
├── src/
│   └── main.yx

Ключевые моменты проектирования:

  • Встроенный бинарный как слой совместимости: до полного появления файловой системы стандартной библиотеки модули std предоставляются через встроенный бинарный
  • Изоляция по версиям: yx/<version>/std/ позволяет сосуществовать разным версиям стандартной библиотеки без взаимного влияния
  • std и обычные зависимости используют один механизм (add/lock/vendor), без специальных каталогов и уровней поиска
  • В режиме одиночного файла — откат к глобальному std; при наличии vendor std должен поступать из vendor (либо явно зафиксирован через add 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 },  // ссылка на члена рабочего пространства
}

// Разрешённая зависимость (решение от 2026-09-15: для целостности используется только одно поле integrity формата "sha256-<hex>", без дублирующего checksum)
struct ResolvedDependency {
    name: String,
    version: Version,
    source: Source,
    integrity: Option<String>,
}

// Стратегия сборки
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>Добавление зависимости для разработки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 --githubАутентификация в GitHubyaoxiang 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
  • Токен никогда не записывается в 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], приоритет предкомпиляции / исходный код как запасной вариант, поддержка стратегий cargo/cmake/custom.

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

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

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

Компромиссы ​

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

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

Недостатки ​

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

Альтернативные варианты ​

ВариантПочему не выбран
Доступ к GitHub в реальном времениСложно гарантировать безопасность и повторное использование кэша
Глобальный кэш ($HOME/.yaoxiang)Слабая изоляция, сложные конфликты версий
Поддержка только реестра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Адаптерный слой GitHub, упаковка .yxpkg, publish --github (после сокращения объёма RFC-014a; официальный Registry/auth/yank отложены)Не начат
Phase 5Система сборки, предкомпилированные бинарные файлы (RFC-014b)Не начат
Phase 6Поддержка рабочих пространств (RFC-014c)Не начат

Корректировка порядка выполнения (2026-09-15): 3 → 3.5 → 6 → 4 → 5.

  • Рабочее пространство (Phase 6) перенесено перед системой сборки — оно не зависит от сети и системы сборки (чисто локальное разрешение по путям + общий lockfile) и даёт наибольший эффект при разработке нескольких пакетов.
  • Сокращение объёма Phase 4: сервер официального Registry, а также auth/yank откладываются на неопределённый срок; сначала поставляются адаптерный слой GitHub Release/Git + упаковка .yxpkg + `publish --github». Для холодного старта экосистемы достаточно каналов git/GitHub (аналогично раннему Go), затраты на эксплуатацию и управление сервером Registry на этапе отсутствия сторонних пакетов — чистый пассив.
  • Следствие: до запуска официального Registry yaoxiang add <имя-без-источника> недоступно, добавление зависимости требует явного указания источника (--git / --path).

Зависимости ​

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

Риски ​

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

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

  • [x] Синтаксис условной компиляции для dev-dependencies? → Обрабатывается единообразно системой сборки в RFC-014b
  • [x] Алгоритм проверки целостности (SHA-256 / BLAKE3)? → SHA-256
  • [x] Соглашение об именовании пакетов (поддержка namespace, например @org/pkg)? → На начальном этапе плоские имена пакетов, без namespace; @org/pkg зарезервировано (решение от 2026-09-15)
  • [x] Стратегия версионирования Registry API? → Путь URL /api/v1/ + версия протокола в заголовке ответа, при ломающих изменениях — параллельное сосуществование v2 (решение от 2026-09-15, см. RFC-014a)
  • [ ] excludes — исключение определённых файлов из загрузки?

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

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

Ссылки ​