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

Rx rx1513 на altlinux.org
Ср Окт 28 10:27:54 MSK 2026


        По результатам пересборки пакетов картина следующая:

Из 432 пакетов упало 29:
phrog   aris - Пакет использует устаревший макрос %__cargo. Исправление: 
phrog-0.53.0-alt2.src.rpm 
<https://git.altlinux.org/tasks/431040/gears/70400/phrog-0.53.0-alt2.src.rpm>

prek   dmaks @everybody  - Сборка проходила без отладочной информации. 
Её включение вызвало чрезмерное использование памяти на ix86. 
Исправление: отключение отладочной информации на ix86 
<https://git.altlinux.org/gitoskop/#/tasks/431040/gears/75370/git/-/commit/d2ac6cb56462865525aae491e792b4e904b65fff>.

cosmic-applibrary   aris - Сборка тестов проходила без отладочной 
информации. Её включение вызвало ошибку компиляции в одной из 
завендоренных библиотек. Отключение отладочной информации чинит сборку, 
но как таковых тестов у пакета нет:

> [00:01:07] + cargo test --release -j32 --no-fail-fast
> [00:01:08]    Compiling cosmic-app-library v1.11.0 (/usr/src/RPM/BUILD/cosmic-app-library-epoch-1.11.0)
> [00:01:12]     Finished `release` profile [optimized] target(s) in 4.79s
> [00:01:12]      Running unittests src/main.rs (target/release/deps/cosmic_app_library-cc2bbb419a3f8485)
> [00:01:12]
> [00:01:12] running 0 tests

influxdb3   amakeenk @everybody   - Из-за отказа от RUSTFLAGS сборка 
перестала игнорировать флаги, задававшие lld в качестве компоновщика и 
параметры для его корректной работы. Кроме того, из-за включения 
механизма синхронизации флагов между стадиями сборка %check падала  
из-за нехватки памяти. Исправление: установка отсутствующего lld и смена 
глобального уровня отладочной информации 
<https://git.altlinux.org/gitoskop/#/tasks/431040/gears/75300/git/-/commit/67d521cf910cf892387ca8030dd2198485dffcf3>.

ouch    amakeenk @everybody - Прямая конфигурация отладочной информации 
через `--config` заставила Cargo выставить переменную среды DEBUG, 
благодаря которой отладочная информация стала генерироваться и для кода 
на C++.  Падение сборки вызвано внутренней ошибкой gcc-15  на i586. 
Исправление: сборка через clang 
<https://git.altlinux.org/gitoskop/#/tasks/431040/gears/75360/git/-/commit/f3c0b54eb1a371d6585fa5f8a909f1b62e1ba832>; 
в качестве альтернативы можно отключить генерацию отладочной информации 
на ix86.

Просьба к мейнтейнерам пакетов, для которых подготовлены исправления 
выразить явное согласие: 431040 
<https://packages.altlinux.org/ru/tasks/431040/>

Следующие пакеты упали из-за включения --frozen:
casr    kuznetsovam @everybody
clevis-pin-tpm2    lvol @everybody
countryfetch    srebrov @everybody
droid-juicer    neko savoptik
dualsense-tools    minergenon @everybody
handy    ulysses @everybody
kryoptic    slev @everybody
jsonschema-rs    enimalojd @everybody
rot8    minergenon @everybody
seaweedfs    enimalojd @everybody
swaptop    zerospirit @everybody
television    amakeenk @everybody
tgt-client    sirius @everybody
volt-gui    minergenon @everybody
thoth    minergenon @everybody
vopono    nicourced @everybody
websocat    serjigva @everybody
xr-picker    minergenon @everybody
cosmic-minimon-applet  aris
cosmic-applets    aris
cosmic-viewer    aris
scope-tui    joycap savoptik
thoth    minergenon @everybody
treefetch    fiersik @everybody
vault-tasks    fiersik @everybody

Падение сборки для этих пакетов означает, что:

 1. Cargo не смог создать идентичный Cargo.lock из существующего Cargo.toml.
 2. Завендоренные зависимости не удовлетворяют сгенерированному Cargo.lock.

Например, в репозитории есть Cargo.lock, но апстрим его не обновляет. В 
одном из пакетов видел ситуацию, когда мейнтейнер устанавливает 
Cargo.lock, но Cargo его отбрасывает.

Обычно исправление сборки таких пакетов простое: делать вендоринг после 
%prep, сгенерированный Cargo.lock устанавливать в сборочную директорию в 
секции %prep либо, если используется %rust_prep, - внутрь архива с vendor/.
Однако для некоторых пакетов такое исправление не является достаточным. 
Например если апстрим вендорит некоторые зависимости внутрь vendor/, 
cargo-vendor-alt отказывается работать с такой директорией, перенос 
зависимостей требует изменений Cargo.toml, что, в свою очередь, влечёт 
за собой несоответствие Cargo.toml и Cargo.lock.

Отсутствие фиксированного Cargo.lock говорит о том, что нельзя из 
заданного Cargo.toml и списка завендоренных зависимостей создать 
однозначное соответствие зависимостей, по которому можно воспроизвести 
идентичную сборку в любой среде.

В дополнение к этому теряется гарантия отсутствия пересборки пакета на 
последующих стадиях после %build.

Тем не менее, ввиду того, что добавление --frozen влечёт заметное 
усложнение сборки на фоне малозаметных преимуществ, было решено отложить 
внедрение до востребования.


        По поводу отказа от безусловной установки RUSTFLAGS.

Сканирование применения апстримами rustflags показало следующую статистику:

Из 632 пакетов только в 183 апстрим упоминает rustflags напрямую либо 
косвенно.

Среди всех пакетов, зависящих от rust и rpm-build-rust, апстрим чаще 
всего выставляет флаги для статического связывания с musl libc 
(rustflags = ["-C", "target-feature=+crt-static"], 34%).
Вторым по распространённости  являются флаги изменения агрессивности 
линтера (11%).
Третьим по распространённости флагом является изменение cfg (11%).

Очень часто  апстрим выставляет rustflags таким образом, что случайно их 
перезаписать не получится. Нужно либо патчить сборочные скрипты, либо 
выставлять CARGO_ENCODED_RUSTFLAGS.

Ручная фильтрация показала, что из 183 пакетов только в 44 выставленные 
RUSTFLAGS могут повляить на апстримные флаги.

Из этих 44 пакетов только 18 используют макросы из rpm-build-rust. Из 18 
пакетов 2 пакета выставляют собственные RUSTFLAGS.

Из оставшихся 16 пакетов выставление RUSTFLAGS влечёт либо негативные, 
либо неопределимые эффекты, в частности:
8 пакетов потеряли cfg
6 пакетов потеряли флаги оптимизации размера/производительности/скорости 
сборки/отладочной информации
2 пакета потеряло LLVM-only сборку.
1 пакет потерял разрешение сборки с определённым предупреждениями.

Кроме того, в ~30-40 пакетах оптимизации, выставляемые мейнтейнером 
через rustflags в config.toml, полностью игнорировались.

Поэтому считаю, что полный отказ от выставления RUSTFLAGS более чем 
целесообразен.

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?
>
----------- следующая часть -----------
Вложение в формате HTML было удалено...
URL: <http://lists.altlinux.org/pipermail/devel/attachments/20261028/7fe1be39/attachment-0001.html>


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