Skip to content

RFC-014b: Система сборки и бинарное распространение

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

Резюме

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

Мотивация

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

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

  • Нет объявления конфигурации сборки (отсутствует секция [build] в yaoxiang.toml)
  • Нет механизма распространения предкомпилированных бинарных файлов
  • Сборка 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"] # Опционально: C заголовочные файлы для автоматической обработки yx-bindgen

[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. Скачивание прошло успешно

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

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

Выполняется когда strategy = "custom".

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

  • Скрипт — обычный код .yx с полным доступом к std
  • Рабочая директория: корневая директория пакета (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          # FFI код на Rust
    └── 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. Объявляет [build] + [binaries] в yaoxiang.toml
  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 5eВыполнение скриптов build.yx
Phase 5fИнтеграция yx-bindgen (поле headers)

Зависимости

  • Зависит от RFC-014a (протокол Registry, используется для скачивания предкомпилированных артефактов)
  • Зависит от crate sha2 (проверка целостности)

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

  • [ ] Нужна ли изоляция в песочнице для скриптов build.yx?
  • [ ] Какое максимальное ограничение размера артефактов сборки?
  • [ ] Поддерживается ли кросс-компиляция (сборка Windows артефактов на Linux)?
  • [ ] Как обрабатывать несовместимость версий Cargo?

Ссылки