[devel] Расширение функциональности rpm-build-rust

Danil Shein dshein на basealt.ru
Чт Сен 17 14:01:52 MSK 2026


Добрый день!

Комментарий ниже не относится к модификации макросов для сборки проектов 
на Раст: данные изменения выглядят вполне обоснованными на мой взгляд.

Вот тут обсуждаются всякие подходы к тому, чтобы втащить в сизиф кучу 
крэйтов раста как системные зависимости для "контроля и учёта" и вообще 
всеобщего блага.

Идея как будто бы понятная и даже имеющая под собой какое-то обоснование.

У меня несколько чисто практических вопросов больше с точки зрения 
разработчика на Раст:

1. Как быть с тем что в рамках одного проекта у вас может завендорится 
сразу несколько несовместимых версий одного и того же крэйта и это 
вообще абсолютно нормально для экосистемы Раст? Насколько я помню 
репозиторий такие сценарии поддерживает чуть более чем никак.

2. Что буде собой представлять упакеченный крэйт который нужен другим 
проектам исключительно в виде исходного кода без возможности 
предварительной компиляции в какие либо артефакты? Просто тарбол с сорцами?

3. Как вы себе представляете использование таких упакеченных крэйтов в 
апстримных проектах? Вот прям как именно в вашем понимании будет это 
выглядеть на практике? Километровые патчи в Cargo.toml и борьба с тем 
что локальные крэйты приезжают только с абсолютными путями не говоря уже 
о других сложностях?

Ну и если всё вышеуказанное легко решаемо, то кто будет сопровождать все 
эти зависимости и как?

Вот мой пакет например хочет версию крэйта 1.5 и я его обновляю ломая 
при этом чужие пакеты которые требуют не совместимую версию 0.9. И я 
полагаю тут может быть ситуация когда починить чужой пакет вообще не 
получится т.к. зависимость транзиентная и просто поползёт пол 
репозитория на каждое изменение.

Мне кажется мы уже достаточно ходили по этим граблям с другими языками, 
и если для интерпретируемых языков подход с втаскиванием всех 
зависимостей в репозиторий ещё как-то работает, то для Раст и например 
Го альтернативы вендорингу я лично не вижу вообще.

Надеюсь мои комментарии дадут некоторую пищу для ума участникам 
сообщества и позволят выработать правильный подход к упакечиванию 
проктов на Расте.

15.09.2026 15:55, Rx пишет:
>
> Привет!
>
> Недавно нашёл время решить проблемы с которыми сталкивался лично 
> и слышал от других мейнтейнеров при использовании макросов из 
> rpm-build-rust.
>
> Поскольку часть изменений может вызвать споры и непредвиденные 
> побочные эффекты, считаю что стоит поднять обсуждение по возможным 
> доработкам.
>
> https://packages.altlinux.org/ru/tasks/431040/
>
>
>         Использованные термины
>
> Пакет (ориг. package 
> <https://doc.rust-lang.org/cargo/appendix/glossary.html#package>) 
> - набор исходных файлов с манифестом Cargo.toml 
> <https://doc.rust-lang.org/cargo/reference/manifest.html>, описывающим 
> метаданные для сборки пакета.
>
> Cargo 
> <https://doc.rust-lang.org/cargo/guide/why-cargo-exists.html#enter-cargo> 
> - пакетный менеджер / система сборки нацеленная на пакеты на языке 
> программирования Rust.
>
> Рабочее пространство (ориг. workspace 
> <https://doc.rust-lang.org/cargo/reference/workspaces.html#workspaces>) 
> - набор пакетов, связанных единым манифестом и зависимостями.
>
>
>         Были добавлены аргументы путей для %rust_prep
>
> В некоторых случаях апстримный гит репозиторий может содержать 
> несколько пакетов несвязанных между собой через рабочее пространство, 
> для таких пакетов необходимо создавать собственную конфигурацию и 
> вендорить отдельные зависимости. Выполнение данного действия 
> подразумевает оборачивание rust_prep в cd или push/pop, что внешне 
> может ухудшать читаемость и внешний вид spec-файла. Примерами таких 
> пакетов могут выступать тестовые пакеты, представляющие 
> собой отдельные CLI утилиты использующие собранные бинарные артефакты. 
> Поэтому для решения этой проблемы был добавлен аргумент:
>
> -p <path> - путь до корня пакета, данная опция задаёт корень, 
> относительно которого заполняется конфигурация .cargo/config.toml и 
> выполняется вендоринг.
>
> Иногда апстрим может класть config.toml в нестандартные папки, 
> например cargo/, из которых потом другая системой сборки, например 
> Make или Meson, устанавливают cargo.config по нужному пути. Чтобы 
> изменить путь в котором находится config.toml с .cargo/ на 
> альтернативный можно использовать аргумент:
>
> -c <path> - путь относительно текущего корня пакета в котором стоит 
> искать config.toml.
>
> Для общей конфигурции корня или пути до .cargo/ были добавлены 
> глобальные переменные задающие значения по умолчанию:
>
> %rust_package_root ${PWD}
>
> %rust_cargo_config_home ".cargo"
>
>
>         Был добавлен механизм вендоринга на уровне макросов
>
> Вдохновишись подходом, описанным @aris для вендоринга зависимостей в 
> https://bugzilla.altlinux.org/48459 (например spec-файла 
> <https://packages.altlinux.org/ru/sisyphus/srpms/glycin-2/specfiles/>), 
> я решил реализовать данный механизм при помощи макросов и 
> интегрировать его в %rust_prep.
>
> Такой подход позволяет:
>
>  1. Не прибивать вендоринг к наличию дополнительных инструментов,
>     таких как etersoft-build-utils, zoryn или самописных решений: для
>     вендоринга достаточно иметь hasher или rpmbuild с программой,
>     выполняющей вендоринг.
>  2. Связать процесс вендоринга со spec-файлом.
>  3. Перевести ручной вендоринг на сторону сборочницы.  Если в будущем
>     появится подходящая инфраструктура, можно будет заменить вендоринг
>     обращением к внутреннему зеркалу.
>
>
>           Для добавления возможности вендоринга spec-файл должен
>           содержать:
>
> # При отключенном вендоринге брать vendor/ из заранее подготовленного 
> архива.
> %{!?_enable_rust_vendoring: Source1: vendor.tar }
>
> BuildRequires(pre): rpm-build-rust
> # При активном вендоринге, установить программу для вендоринга.
> # По умолчанию %rust_vendor использует cargo-vendor-alt из 
> cargo-vendor-filterer.
> %{?_enable_rust_vendoring:
> BuildRequires: cargo-vendor-filterer
> }
>
> %prep
> # Аналогично Source1.
> %setup %{!?_enable_rust_vendoring:-a1}
> %rust_prep
>
>
>           Сборка пакета с вендорингом.
>
> Для сборки пакета с вендорингом достаточно передать в rpmbuild  
> '--enable "rust_vendoring" '.
>
>
>         Для Hasher + gear весь процесс вендоринга выглядит следующим
>         образом:
>
> hsh --apt-config=<путь до используемого apt-conf> --initroot
> hsh-update-resolver-conf
> share_network=1 gear --hasher --commit -v -- hsh-rebuild -v 
> --rpmbuild-args="--enable rust_vendoring"
>
> По завершении %rust_prep архив c завендоренными зависимостями 
> помещается в RPM/SOURCES/ или же %_sourcedir. Его можно скопировать 
> сразу же после %prep или по окончании сборки, например так:
>
> "cp ~/hasher/chroot/usr/src/RPM/SOURCES/vendor.tar ."
>
> Полученный архив сохраняет путь до директории в которой был произведён 
> вендоринг относительно пути в котором был вызван %rust_prep. Например 
> если был вызов %rust_prep -p rust/ в полученном архиве корень будет 
> начинаться с rust/.
>
>
>           Конфигурация вендоринга.
>
> Название получаемого архива можно изменить опцией -o передаваемой 
> в %rust_prep, например %rust_prep -o cargo_vendor.tar
>
> Для конфигурации вендоринга можно переопределить следующие глобальные 
> макросы:
>
> %rust_vendor_prog - программа/скрипт выполняющая только вендоринг, 
> обязательным требованием к ней является передача в stdout списка 
> источников которые заменены вендорингом, подобно тому как это делает 
> cargo vendor или cargo-vendor-filterer. По умолчанию вендоринг 
> выполняется при помощи cargo-vendor-alt.
>
> %rust_vendor_options <аргументы для %rust_vendor_prog>
>
> %rust_pre_vendor <shell code or binary> - программа или скрипт 
> вызываемые до вендоринга.
>
> %rust_post_vendor <shell code or binary> - программа или скрипт 
> вызываемые после вендоринга, но до упаковки vendor/ в архив.
>
> %rust_vendor <shell code or binary> - программа выполняющая вендоринг, 
> фильтрацию списка зависимостей и сохранение его в vendor/.
>
>
>         Была добавлена поддержка профилей.
>
> Некоторые апстримы могут определять альтернативные конфигурации 
> сборки, например вместо обычного release апстрим может определить 
> release-lto/release-fast/release-small.
>
> Для изменения собираемого профиля было добавлены следующие макросы:
> %rust_upstream_profile - Какой апстримный профиль использовать для сборки.
>
> %rust_downstream_profile - Как назвать сборочный профиль 
> унаследованный от апстримного.
>
> Некоторые апстримы могут определять профили в .cargo/config.toml. В 
> таком случае при попытке переопределить его опции через конфигурацию  
> Cargo будет жаловаться на дублирование профилей. Во избежания этой 
> ситуации можно создать собственный профиль унаследованный от апстримного.
>
> %rust_build_profile - Какой профиль использовать в командах сборки, 
> установки и тестирования. В очень редких случаях апстрим может 
> использовать специализированный профиль для тестов.
>
>
>         Появился макрос для обозначения целевой директории.
>
> С появлением поддержки профилей был добавлен макрос который задаёт 
> директорию в которую cargo кладёт бинарные артефакты и из которой 
> производится установка. В первую очередь данный макрос нужен для 
> ручной установки артефактов из целевой директории, когда cargo install 
> и %rust_install не могут сделать это самостоятельно, например при 
> устнавке заголовочных файлов, ассетов и тд.
>
> Вместе с тем был добавлен макрос  %rust_resolve_target_dir, который 
> при вызове при помощи механизмов Cargo возвращает путь до target/.
>
>
>         RUSTFLAGS больше не задаётся по умолчанию через окружение.
>
> Переменная RUSTFLAGS это низкоуровневая переменная которая задаёт 
> флаги напрямую передаваемые компилятору на всех стадиях сборки в обход 
> механизмов Cargo. Её главное назначение передать флаги, которые Cargo 
> не умеет выставлять самостоятельно. В общем случае это может быть 
> бесполезно, а иногда вредно, потому что Cargo не умеет объединять 
> флаги с нескольких уровней. Это значит что если апстрим определяет 
> свои специфические флаги для лучшей поддержки целевой архитектуры, они 
> будут перезаписаны и, как следствие, можно ожидать нестабильную работу 
> приложения.
>
> Если всё же нужно выставить RUSTFLAGS, то никаких барьеров к тому 
> чтобы самостоятельно экспортировать флаги через export RUSTFLAGS нет.
>
> Если выставляемые RUSTFLAGS являются общими для всех пакетов и всех 
> стадий, то можно задать макрос %rustflags, который синхронизирует 
> rustflags между %rust_build, %rust_test, 
> %rust_cbuild, %rust_ctest, %rust_cinstall.
>
>
>         Отладочная информация теперь задаётся штатными механизмами Cargo.
>
> Теперь при вызове %rust_build отладочная информация задаётся напрямую 
> через конфигурацию профиля и аргументы командной строки.
>
> Таким образом в случае необходимости переопределить отладочную 
> информацию, это можно сделать через аргумент командной строки, например:
> %rust_build --config 'profile.%rust_build_profile.debug = false'
>
> Либо же можно переопределить новый макрос %rust_debug_level, который 
> синхронизирует отладочную информацию между всеми стадиями сборки.
>
>
>         Появилась возможность задавать некоторые опции компиляции
>         через макросы.
>
> Иногда при сборке пакета очень хочется выставить больше (или меньше) 
> оптимизаций, чем выставил апстрим. Раньше для этого требовалось 
> дописывать/писать собственный config.toml/привлекать дополнительные 
> инструменты, что не очень хорошо сочетается с автоматизацией. Поэтому 
> для глобального указания некоторых опций компиляции были добавлены:
> # https://doc.rust-lang.org/cargo/reference/profiles.html#codegen-units
> # https://doc.rust-lang.org/rustc/codegen-options/index.html#codegen-units
> %rust_codegen_units - Задаёт насколько сильно будет раздроблен пакет 
> на бинарные единицы при сборке. Чем меньше - тем лучше будет 
> оптимизировано приложение, но тем прожорливее будет сборка и LTO 
> оптимизации.
>
> # https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level
> %rust_opt_level - Уровень оптимизаций.
>
> # https://doc.rust-lang.org/cargo/reference/profiles.html#lto
> %rust_lto - уровень LTO оптимизаций. Для Rust пакетов одна из самых 
> мощных и капризных оптимизаций, поскольку она снимает ограничение на 
> inline оптимизации между различными модулями и внешними зависимостями.
>
> В отличие от RUSTFLAGS данные макросы используют штатные механизмы Cargo.
>
>
>         Были добавлены макросы для сборки пакетов с rust-cargo-c
>
> Команды из rust-cargo-c используют тот же интерфейс для вызова, что и 
> обычные cargo build/cargo install/cargo test с добавлением аргументов 
> путей ассоциированных с C-библиотеками.
>
> Если апстрим позаботился о добавлении возможности "-F capi", они 
> позволяют легко и просто собирать разделяемые библиотеки с 
> C-интерфейсом, вместе всеми необходимыми флагами компиляции, 
> заголовками, библиотеками и тд.
>
> Аналогично %rust_build, %rust_install и %rust_test новые макросы имеют 
> названия: %rust_cbuild, %rust_cinstall, %rust_ctest.
>
>
>         Все команды сборки  теперь имеют флаг --frozen вместо --offline.
>
> Раньше при сборке пакетов Cargo мог решить обновить зависимости на 
> основании содержимого vendor/, обычно это происходит при изменении 
> путей в Cargo.toml, при вызове cargo install или при отсутсвии 
> некоторых зависимостей.
>
> Именно поэтому, даже при одинаковых флагах компиляции, Сargo 
> перезапускал сборку при вызове cargo install.
>
> Если исходить из  смысла секций RPM пакета, то все зависимости должны 
> быть зафиксированны до %prep или в случае вендоринга в %prep, но точно 
> не на стадии сборки или установки артефактов. Поэтому логичным 
> решением будет запретить Cargo менять Cargo.lock.
>
> Для это Cargo можо передать опцию --locked или --frozen (--locked + 
> --offline).
>
> Полагаю, что некоторые пакеты могут перестать собираться. Это может 
> означать, что вендоринг был выполнен с ошибкой и по какой-то причине 
> не все зависимости попали в vendor/. Самым простым решением данной 
> проблемы является регенерация Cargo.lock через cargo generate-lockfile.
>
>
>         %rust_prep добавляет пустую строку перед записью в config.toml.
>
> Некоторые апстримы не имеют пустой строки в конце config.toml, что 
> приводило к накладыванию названия таблицы на существующие строки.
>
>
>         Зависимость на rust-cargo была заменена зависимостью на rust.
>
> Cargo может работать с любой версией компилятора, поэтому для 
> установки всех пакетов необходимых для сборки Rust пакета она является 
> неудачной, поскольку не задаёт однозначного соотвествия. В будущем 
> планируется убрать зависимость cargo на идентичную версию rustc.
>
>
>         Нерешённые вопросы.
>
>  1. Должен ли %rust_prep поддерживать переопределение директории
>     vendor/? Теоритически она может быть переопределена, но я не видел
>     практического использования данной возможности.
>  2. Должен ли %rust_prep высчитывать корень сборочной директории при
>     вендоринге зависимости в поддереве для формирования префикса
>     архива. Как это правильно сделать? В текущей реализации %rust_prep
>     считает корнем сборочной директории путь, в котором он был вызван,
>     что в общем случае неверно. Я хотел использовать какой-нибудь
>     специальный макрос, но не нашёл такого.
>  3. Должен ли %rust_prep выставлять хоть какие-то флаги компиляции?
>     Должны ли быть значения по умолчанию для макросов задающих опции
>     компиляции?
>  4. Должен ли %rust_install с появлением полной синхронизации между
>     %build и %install перейти на cargo install? %rust_install и cargo
>     install имеют несовместимые интерфейсы вызова. Стоит ли в таком
>     случае добавить макросы %cargo_build, %cargo_install и т.д.?
>  5. Должен ли %rust_build_dir безусловно вычислятся для текущего пути?
>  6. В текущей реализации макросов нет механизма который бы позволял
>     легко и просто изменять уже существующую конфигурацию. Стоит ли
>     добавить зависимость на внешние toml конфигураторы или стоит
>     написать собственный конфигуратор? Сейчас стоит очень большая
>     проблема, что всё содержимое config.toml дописывается в конец, что
>     не позволяет перезаписать уже существующие значения, например если
>     апстрим переопределит компилятор по умолчанию кросскомпилятором
>     для aarch64.
>  7. Стоит ли добавлять в rpm-build-rust зависимость на rust-cargo-c
>     или оставить выбор за пользователем?
>  8. Должен ли вендоринг сохранять Cargo.lock?
>  9. Должен ли %rust_prep регенерировать Cargo.lock?
>
>
> _______________________________________________
> Devel mailing list
> Devel на lists.altlinux.org
> https://lists.altlinux.org/mailman/listinfo/devel
-- 

*Данил Шеин / Danil Shein*

dshein на altlinux.org
dshein на basealt.ru
----------- следующая часть -----------
Вложение в формате HTML было удалено...
URL: <http://lists.altlinux.org/pipermail/devel/attachments/20260917/57a8a58b/attachment-0001.html>


Подробная информация о списке рассылки Devel