RFC-014b: Система сборки и распространение бинарных файлов
Данный RFC является под-RFC к RFC-014: Проект системы управления пакетами.
Решение по рассмотрению от 2026-09-15
Следующие решения были утверждены владельцем 2026-09-15:
- Доверительный шлюз build.yx (реализация открытого вопроса о «песочнице»): выполнение произвольного кода в рамках стратегии
customявляется крупнейшей поверхностью атаки на цепочку поставок в менеджере пакетов —yaoxiang addвредоносного пакета равнозначно передаче полных правstd.os. Обязательный минимум:- Перед первым выполнением
build.yxпакета требуется интерактивное подтверждение; yaoxiang add --trust <pkg>/install --trustсохраняет запись о доверии в~/.yaoxiang/config.toml([trust] build-scripts = ["name@version"]);- В неинтерактивных средах (CI) сборка
customпо умолчанию отклоняется, если явно не указан--trust; - Полный механизм песочницы продолжает исследоваться как открытый вопрос, но доверительный шлюз является обязательным нижним пределом.
- Перед первым выполнением
- Переупорядочивание этапов:
5a → 5b → 5c (cargo) → 5d ([binaries]) → 5f (bindgen, зависит от RFC-026b) → 5e (custom в конце, с доверительным шлюзом). Декларативный путь (cargo) идёт первым, выполнение произвольного кода — последним. - Унификация распространения бинарных файлов:
[binaries]является единственным механизмом распространения бинарных файлов (соответствует решению 3 из RFC-014a —.yxpkgсодержит только исходный код). - Кросс-компиляция: на начальном этапе не поддерживается, многоплатформенные артефакты создаются CI на нескольких хостах (в соответствии с подходом RFC-037 cargo-dist).
- Размер артефактов сборки: ограничение сверху не устанавливается, контролируется каналом распространения.
- Несовместимость версий Cargo: используется предварительная проверка через
[build.requirements]с сообщением об ошибке + инструкцией по установке (определено в основном тексте, без дополнительных механизмов).
Краткое описание
Определяет механизмы сборки системы управления пакетами YaoXiang: декларативная конфигурация сборки, стратегии сборки (cargo/cmake/custom/none), распространение предкомпилированных бинарных файлов, проверка системных зависимостей.
Мотивация
Некоторые пакеты представляют собой чистый код .yx, не требующий сборки. Некоторым требуется компиляция FFI-связываний (с вызовом Cargo, CMake и др.). Необходим единый механизм, позволяющий авторам пакетов декларировать требования к сборке, а менеджеру пакетов — автоматически их обрабатывать.
Текущие проблемы
- Отсутствует декларация конфигурации сборки (в
yaoxiang.tomlнет секции[build]) - Отсутствует механизм распространения предкомпилированных бинарных файлов
- Сборка FFI-пакетов полностью зависит от ручных действий пользователя
- Отсутствует проверка системных зависимостей
Предложение
Основной дизайн: декларативная сборка + приоритет предкомпиляции
Автор пакета декларирует требования к сборке в yaoxiang.toml, менеджер пакетов автоматически принимает решения на основе декларации.
Стратегии сборки
enum BuildStrategy {
None, // 纯 .yx 包,无需构建
Cargo, // 调用 cargo build,读 [build.cargo] 配置
Cmake, // 调用 cmake
Custom, // 执行 build.yx 脚本
}Примечание: вариант Precompiled удалён. Наличие секции [binaries] автоматически запускает поведение приоритета предкомпиляции, явное объявление стратегии не требуется.
Декларация сборки в yaoxiang.toml
[package]
name = "native-foo"
version = "1.0.0"
[build]
strategy = "cargo" # 构建策略
headers = ["include/sqlite3.h"] # 可选:yx-bindgen 自动处理的 C 头文件
[build.cargo]
features = ["ffi"] # cargo build --features ffi
target = "release" # cargo build --release
[build.requirements]
cargo = ">= 1.70" # 构建时需要的工具
cmake = ">= 3.20"
[build.platforms] # 平台特定覆盖
"x86_64-unknown-linux-gnu" = { cargo-features = ["linux-ffi"] }
"x86_64-pc-windows-msvc" = { cargo-features = ["win-ffi"] }
"aarch64-apple-darwin" = { cargo-features = ["mac-ffi"] }Дерево принятия решений при установке
yaoxiang install foo
│
├─ 1. [binaries] 有当前平台条目?
│ → 有:下载,校验 SHA-256,直接安装(跳过构建)
│ → 无:继续
│
├─ 2. 下载源码包
│
├─ 3. [build].headers 有值?
│ → 有:自动运行 yx-bindgen 生成绑定文件
│
├─ 4. 读 [build].strategy
│ → "none":直接安装
│ → "cargo":读 [build.cargo] 配置,拼 cargo build 命令
│ → "cmake":调用 cmake
│ → "custom":执行 build.yx 脚本
│
└─ 5. 安装到 vendor/Приоритет предкомпиляции, исходный код как запасной вариант. Наличие секции [binaries] автоматически запускает проверку предкомпиляции, явная стратегия не требуется.
Подробности стратегии cargo
При strategy = "cargo" считывается конфигурация [build.cargo] и формируется команда:
[build]
strategy = "cargo"
[build.cargo]
features = ["ffi"] # → cargo build --features ffi
target = "release" # → cargo build --release
[build.platforms] # 平台覆盖
"x86_64-unknown-linux-gnu" = { cargo-features = ["linux-ffi"] }
"x86_64-pc-windows-msvc" = { cargo-features = ["win-ffi"] }
"aarch64-apple-darwin" = { cargo-features = ["mac-ffi"] }Фактически выполняемая команда:
# 基础
cargo build --release --features ffi
# 有平台覆盖时(以 linux 为例)
cargo build --release --features ffi,linux-ffiДекларация предкомпилированных бинарных файлов
# yaoxiang.toml
[binaries]
"x86_64-unknown-linux-gnu" = { url = "releases/download/v1.0.0/foo-linux-x86_64.tar.gz", sha256 = "abc123" }
"x86_64-pc-windows-msvc" = { url = "https://example.com/foo-win-x86_64.tar.gz", sha256 = "def456" }
"aarch64-apple-darwin" = { url = "releases/download/v1.0.0/foo-macos-aarch64.tar.gz", sha256 = "ghi789" }Формат URL: поддерживаются абсолютные URL и относительные пути. Относительные пути указаны относительно адреса репозитория пакета (URL репозитория GitHub или корневой URL Registry).
Условия пропуска сборки:
- В
[binaries]есть запись для текущей платформы - Проверка SHA-256 прошла успешно
- Загрузка успешно завершена
Все три условия выполнены → пропустить сборку. Иначе → откат к сборке из исходного кода.
Скрипт сборки build.yx
Когда strategy = "custom", выполняется build.yx.
Модель выполнения (минимальная спецификация):
- Скрипт представляет собой обычный код
.yxс полным доступом кstd - Доверительный шлюз (решение от 2026-09-15, обязательно): перед первым выполнением требуется интерактивное подтверждение, в неинтерактивных средах по умолчанию отклоняется (см. решение 1 выше)
- Рабочая директория: корень пакета (
vendor/<pkg>-<ver>/) - Успех: код выхода 0
- Неудача: ненулевой код выхода, установка прерывается
- Менеджер пакетов не ограничивает поведение скрипта, только проверяет код выхода
# build.yx — 包的构建脚本
use std.os
use std.io
fn main() {
let platform = os.platform()
let arch = os.arch()
if os.file_exists("Cargo.toml") {
io.println("Building native extension via Cargo...")
let result = os.exec("cargo build --release")
if result.exit_code != 0 {
io.println("Build failed!")
os.exit(1)
}
}
io.println("Build complete!")
}Проверка системных зависимостей
Перед установкой автоматически проверяются все [build.requirements], при невыполнении выдаётся ошибка:
Error: Build requirement not satisfied
cargo >= 1.70 required, but cargo is not installed
Install: https://rustup.rsИнтеграция yx-bindgen (поле headers)
[build].headers декларирует C-заголовки, которые должны быть обработаны yx-bindgen. Система сборки автоматически запускает yx-bindgen для генерации файлов связывания .yx.
[build]
strategy = "cargo"
headers = ["include/sqlite3.h", "include/json.h"]Процесс сборки:
1. [binaries] 有预编译?→ 跳过全部构建
2. [build].headers 有值?→ yx-bindgen 自动生成绑定
3. 执行 [build].strategy(cargo/cmake/custom)
4. 安装yx-bindgen разбирает сигнатуры функций и определения типов из C-заголовков (.h) и автоматически генерирует декларации связывания .yx. Пользователю не нужно запускать его вручную — система сборки обрабатывает это автоматически при обнаружении конфигурации headers.
Связь с RFC-026: RFC-026 определяет языковую семантику yx-bindgen (синтаксис native("symbol"), unsafe типы). RFC-014b определяет способ его интеграции в процесс сборки (конфигурация headers). Они дополняют друг друга.
Интеграция с Cargo Workspace
Если в пакете есть FFI-код, можно одновременно определить Cargo workspace:
my-package/
├── yaoxiang.toml # YaoXiang 包配置
├── Cargo.toml # Cargo workspace(FFI 部分)
├── src/
│ └── lib.yx # YaoXiang 代码
└── native/
├── Cargo.toml # Rust FFI 代码
└── src/
└── lib.rsyaoxiang build автоматически обнаруживает и вызывает cargo build для компиляции нативной части.
Детальный дизайн
Идентификация платформы
Используется формат Rust target triple (arch-vendor-os-env):
| Платформа | Идентификатор |
|---|---|
| Linux x86_64 (glibc) | x86_64-unknown-linux-gnu |
| Linux x86_64 (musl) | x86_64-unknown-linux-musl |
| Linux ARM64 | aarch64-unknown-linux-gnu |
| Windows x86_64 (MSVC) | x86_64-pc-windows-msvc |
| Windows x86_64 (MinGW) | x86_64-pc-windows-gnu |
| macOS ARM64 | aarch64-apple-darwin |
| macOS x86_64 | x86_64-apple-darwin |
Используется Rust target triple вместо упрощённого формата, потому что:
- Различает разные ABI на одной ОС (gnu vs musl, msvc vs gnu)
- Совместим с экосистемой Rust/Cargo, уменьшает ошибки сопоставления
- Будущее расширение не требует изменения формата
Структура каталогов артефактов сборки
build/
└── native/
├── x86_64-unknown-linux-gnu/
│ └── libfoo.so
├── x86_64-pc-windows-msvc/
│ └── foo.dll
└── aarch64-apple-darwin/
└── libfoo.dylibПолный жизненный цикл предкомпилированного пакета
开发者:
1. 写 .yx 代码 + FFI 绑定
2. 在 yaoxiang.toml 声明 [build] + [binaries]
3. yaoxiang publish
→ 自动在 CI 上构建多平台二进制
→ 上传源码 + 预编译产物
用户:
yaoxiang add native-foo
→ 检测到有预编译产物 → 直接下载(秒级)
→ 没有预编译产物 → 下载源码 + 执行构建(分钟级)Компромиссы
Преимущества
- Декларативная конфигурация — пользователю не нужно вникать в детали сборки
- Приоритет предкомпиляции — установка происходит очень быстро
- Поддержка нескольких платформ с автоматическим выбором
- Бесшовная интеграция с экосистемой Cargo
Недостатки
- Предкомпилированные артефакты требуют поддержки CI
- Многоплатформенная сборка увеличивает сложность публикации
- Скрипты build.yx требуют механизма безопасности песочницы
Альтернативы
| Подход | Почему не выбран |
|---|---|
| Распространение только исходного кода | Пользователю необходимо установить цепочку инструментов сборки, высокий порог входа |
| Бинарный формат наподобие Python wheel | Слишком сложно, экосистеме YaoXiang на раннем этапе не требуется |
| Отсутствие поддержки FFI-сборки | Ограничивает расширяемость языка |
Стратегия реализации
Разделение на этапы
| Этап | Содержание |
|---|---|
| Phase 5a | Разбор конфигурации [build] + enum BuildStrategy |
| Phase 5b | Проверка системных зависимостей |
| Phase 5c | Интеграция сборки Cargo (чтение [build.cargo] и формирование команды) |
| Phase 5d | Загрузка и проверка предкомпилированных бинарных файлов |
| Phase 5f | Интеграция yx-bindgen (поле headers, зависит от RFC-026b) |
| Phase 5e | Выполнение скрипта build.yx (последним, с доверительным шлюзом) |
Порядок выполнения (решение 2 от 2026-09-15): 5a → 5b → 5c → 5d → 5f → 5e. Декларативная сборка идёт первой, выполнение произвольного кода — последним.
Зависимости
- Зависит от RFC-014a (протокол Registry, для загрузки предкомпилированных артефактов)
- Зависит от crate
sha2(проверка целостности)
Открытые вопросы
- [x] Нужна ли изоляция скриптов build.yx в песочнице? → Доверительный шлюз является обязательным минимумом (решение 1 от 2026-09-15); полная песочница продолжает исследоваться
- [x] Ограничение максимального размера артефактов сборки? → Ограничение не устанавливается, контролируется каналом (решение 5 от 2026-09-15)
- [x] Поддерживать ли кросс-компиляцию (сборку Windows-артефактов на Linux)? → На начальном этапе не поддерживается, CI на нескольких хостах (решение 4 от 2026-09-15)
- [x] Как обрабатывать несовместимость версий Cargo? → Предварительная проверка
[build.requirements]с сообщением об ошибке + инструкцией по установке (решение 6 от 2026-09-15)
