Skip to content

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

Данный RFC является под-RFC к RFC-014: Проект системы управления пакетами.

Решение по рассмотрению от 2026-09-15 ​

Следующие решения были утверждены владельцем 2026-09-15:

  1. Доверительный шлюз 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;
    • Полный механизм песочницы продолжает исследоваться как открытый вопрос, но доверительный шлюз является обязательным нижним пределом.
  2. Переупорядочивание этапов: 5a → 5b → 5c (cargo) → 5d ([binaries]) → 5f (bindgen, зависит от RFC-026b) → 5e (custom в конце, с доверительным шлюзом). Декларативный путь (cargo) идёт первым, выполнение произвольного кода — последним.
  3. Унификация распространения бинарных файлов: [binaries] является единственным механизмом распространения бинарных файлов (соответствует решению 3 из RFC-014a — .yxpkg содержит только исходный код).
  4. Кросс-компиляция: на начальном этапе не поддерживается, многоплатформенные артефакты создаются CI на нескольких хостах (в соответствии с подходом RFC-037 cargo-dist).
  5. Размер артефактов сборки: ограничение сверху не устанавливается, контролируется каналом распространения.
  6. Несовместимость версий Cargo: используется предварительная проверка через [build.requirements] с сообщением об ошибке + инструкцией по установке (определено в основном тексте, без дополнительных механизмов).

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

Определяет механизмы сборки системы управления пакетами YaoXiang: декларативная конфигурация сборки, стратегии сборки (cargo/cmake/custom/none), распространение предкомпилированных бинарных файлов, проверка системных зависимостей.

Мотивация ​

Некоторые пакеты представляют собой чистый код .yx, не требующий сборки. Некоторым требуется компиляция FFI-связываний (с вызовом Cargo, CMake и др.). Необходим единый механизм, позволяющий авторам пакетов декларировать требования к сборке, а менеджеру пакетов — автоматически их обрабатывать.

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

  • Отсутствует декларация конфигурации сборки (в yaoxiang.toml нет секции [build])
  • Отсутствует механизм распространения предкомпилированных бинарных файлов
  • Сборка FFI-пакетов полностью зависит от ручных действий пользователя
  • Отсутствует проверка системных зависимостей

Предложение ​

Основной дизайн: декларативная сборка + приоритет предкомпиляции ​

Автор пакета декларирует требования к сборке в yaoxiang.toml, менеджер пакетов автоматически принимает решения на основе декларации.

Стратегии сборки ​

rust
enum BuildStrategy {
    None,          // 纯 .yx 包,无需构建
    Cargo,         // 调用 cargo build,读 [build.cargo] 配置
    Cmake,         // 调用 cmake
    Custom,        // 执行 build.yx 脚本
}

Примечание: вариант Precompiled удалён. Наличие секции [binaries] автоматически запускает поведение приоритета предкомпиляции, явное объявление стратегии не требуется.

Декларация сборки в yaoxiang.toml ​

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] и формируется команда:

toml
[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"] }

Фактически выполняемая команда:

bash
# 基础
cargo build --release --features ffi

# 有平台覆盖时(以 linux 为例)
cargo build --release --features ffi,linux-ffi

Декларация предкомпилированных бинарных файлов ​

toml
# 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).

Условия пропуска сборки:

  1. В [binaries] есть запись для текущей платформы
  2. Проверка SHA-256 прошла успешно
  3. Загрузка успешно завершена

Все три условия выполнены → пропустить сборку. Иначе → откат к сборке из исходного кода.

Скрипт сборки build.yx ​

Когда strategy = "custom", выполняется build.yx.

Модель выполнения (минимальная спецификация):

  • Скрипт представляет собой обычный код .yx с полным доступом к std
  • Доверительный шлюз (решение от 2026-09-15, обязательно): перед первым выполнением требуется интерактивное подтверждение, в неинтерактивных средах по умолчанию отклоняется (см. решение 1 выше)
  • Рабочая директория: корень пакета (vendor/<pkg>-<ver>/)
  • Успех: код выхода 0
  • Неудача: ненулевой код выхода, установка прерывается
  • Менеджер пакетов не ограничивает поведение скрипта, только проверяет код выхода
yx
# 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.

toml
[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.rs

yaoxiang 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 ARM64aarch64-unknown-linux-gnu
Windows x86_64 (MSVC)x86_64-pc-windows-msvc
Windows x86_64 (MinGW)x86_64-pc-windows-gnu
macOS ARM64aarch64-apple-darwin
macOS x86_64x86_64-apple-darwin

Используется Rust target triple вместо упрощённого формата, потому что:

  1. Различает разные ABI на одной ОС (gnu vs musl, msvc vs gnu)
  2. Совместим с экосистемой Rust/Cargo, уменьшает ошибки сопоставления
  3. Будущее расширение не требует изменения формата

Структура каталогов артефактов сборки ​

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)

Ссылки ​