RPM/Rust
Быстрая сборка Rust-пакета
Вендоринг
Вендоринг — сохранение внешних зависимостей (крейтов) вместе с исходным пакетом (в отличии от помещения их в отдельные пакеты и использования BuildRequires).
В директории программы на Rust:
$ cargo vendor
$ find vendor -name '*.a' -delete
$ sed -Ei 's!,"[^"]+\.a":"[^"]+"!!g' $(find vendor -name .cargo-checksum.json)
$ git add -A -f vendor Cargo.lock
$ git commit -m "cargo vendor"
cargo vendor- поместит все зависимости в диру vendor/. Желательно, чтоб она была пустая.find- удалит бинарные библиотеки из виндовых зависимостей (winapi*). См. более полный и правильный пример в полезных советах.sed- удалит упоминания checksum из файлов типа.cargo-checksum.jsonудалённых бинарных библиотек.git add -f- чтобы избежать возможных проблем с.gitignore.
Spec-файл: без использования специализированных макросов
BuildRequires: rust-cargo
В секции %prep после %setup[1]:
mkdir -p .cargo cat >> .cargo/config.toml <<EOF [source.crates-io] replace-with = "vendored-sources" [source.vendored-sources] directory = "vendor" [term] verbose = true quiet = false [install] root = "%buildroot%_prefix" [build] rustflags = ["-Copt-level=3", "-Cdebuginfo=1"] [profile.release] strip = false EOF
- эта конструкция подключит завендореные исходники, настроит опции сборки и инсталляции.
В %build:
cargo build %_smp_mflags --offline --release
В %install (если пакет не библиотека, а бинарник):
cargo install %_smp_mflags --offline --no-track --path .
В %check, если нужен:
cargo test %_smp_mflags --release --no-fail-fast
Spec-файл: с макросами из rpm-macros-rust
BuildRequires(pre): rpm-macros-rust BuildRequires: rpm-build-rust
В секции %prep после %setup:
%rust_prep
В случае, если команда cargo vendor указала на дополнительные источники rust-крейтов, например:
To use vendored sources, add this to your .cargo/config.toml for this project: [source.crates-io] replace-with = "vendored-sources" [source."git+https://github.com/influxdata/arrow-datafusion.git?rev=1c10b8b635831e87cb043a1e3fa8eb89be430d54"] git = "https://github.com/influxdata/arrow-datafusion.git" rev = "1c10b8b635831e87cb043a1e3fa8eb89be430d54" replace-with = "vendored-sources" [source.vendored-sources] directory = "vendor"
Дополните секцию %prep после %rust_prep:
cat >> .cargo/config.toml <<EOF [source."git+https://github.com/influxdata/arrow-datafusion.git?rev=1c10b8b635831e87cb043a1e3fa8eb89be430d54"] git = "https://github.com/influxdata/arrow-datafusion.git" rev = "1c10b8b635831e87cb043a1e3fa8eb89be430d54" replace-with = "vendored-sources" EOF
Секции %build, %install и %check:
%build %rust_build
%install %rust_install
%check %rust_test
RUSTFLAGS, которая по умолчанию инициализируется в макросах %rust_build и %rust_test, отменяет любые установки rustflags через файл .cargo/config.toml.
При использовании макроcов %rust_build и %rust_test из-за невозможности установить rustflags через файл .cargo/config.toml в секциях %build и %check необходимо, например, переопределить переменную среды:
export RUSTFLAGS="*ваши флаги*"
Или нужно задать rustflags, например, так[1]:
%build %rust_build -- --config 'build.rustflags = ["--html-in-header", "header.html"]'
%check %rust_test -- --config 'build.rustflags = ["--html-in-header", "header.html"]'
Также данный макрос жёстко задаёт параметр -Cdebuginfo=2. Если вам нужно понизить уровень debuginfo до 1, то придётся использовать суровые меры, вроде:
export CARGO_ENCODED_RUSTFLAGS=-Cdebuginfo=1 (переменную среды наивысшего порядка, которая, правда, отменяет установки более низкого порядка, например, из RUSTFLAGS и ниже)
%check важно продублировать настройки конфигурации из блока %build для корректности прохождения тестов.
Полезные советы
Очистка от бинарных артефактов (мы всё-таки собираем из исходников)
Вручную
$ find vendor/ \( -name '*.a' -o -name '*.lib' -o -name '*.dll' -o -name '*.obj' \) -delete
$ sed -Ei 's!,"[^"]+\.(a|lib|dll|obj)":"[^"]+"!!g' $(find vendor -name .cargo-checksum.json)
Такая чистка часто ломает rustix, что решается включением use-libc feature (например добавлением при сборке к rustflags --cfg=rustix_use_libc) или включением cc feature — пример как это выглядит в Cargo.toml:
[dependencies]
rustix = { features = ["cc"] }
Или с помощью опции --config[1]:
cargo build %_smp_mflags --offline --release -- --config 'build.rustflags = ["--cfg=rustix_use_libc"]'
С использованием cargo-vendor-filterer
cargo-vendor-filterer - инструмент для более глубокой очистки каталога vendor/. Например, с его помощью вы можете:
- Оставить только зависимости для указанных платформ (чтобы отфильтровать зависимости специфические для Windows или MacOS)
$ cargo vendor-filterer \
--platform=x86_64-unknown-linux-gnu \
--platform=i686-unknown-linux-gnu \
--platform=aarch64-unknown-linux-gnu \
--platform=loongarch64-unknown-linux-gnu \
--platform=riscv64gc-unknown-linux-gnu
- Удалить тесты и/или примеры из зависимостей с использованием синтаксиса
CRATENAME#PATH:
$ cargo vendor-filterer --exclude-crate-path '*#tests' --exclude-crate-path '*#examples'
CRATENAME - имя крэйта (может содержать wildcards)
PATH - относительный путь к файлу, каталогу или символической ссылке (может содержать wildcards)
- Оставить только необходимый тип зависимостей [2] [3]:
- all (normal + build + dev)
- normal
- build
- dev
- no-normal (build + dev)
- no-build (normal + dev)
- no-dev (normal + build)
$ cargo vendor-filterer --keep-dep-kinds no-dev
Подробнее о возможностях смотрите в документации.
В пакете cargo-vendor-filterer кроме самой программы также содержится скрипт-обертка cargo-vendor-alt, который устанавливает некоторые флаги по умолчанию (например, указаны поддерживаемые в репозитории архитектуры) для удобства.
$ cargo-vendor-alt <дополнительные опции>
Решение проблем с windows/unix кодировкой текстовых файлов
$ grep -sq -w 'text' .gitattributes && echo '* -text' > vendor/.gitattributes
Оптимизации сборки пакетов[4]
- Часто
cargo installначинает пересобирать исходники, поэтому лучше делать обычныйinstall
install -Dp target/release/%name -t %buildroot%_bindir
- Сборка упала на 32-битных архитектурах с
LLVM ERROR: out of memoryAllocation failed
Возможно, апстрим включил излишнюю оптимизацию в Cargo.toml. Её можно перекрыть в создаваемом выше .cargo/config.toml (в зависимости от того, что было включено), например:
cat >> .cargo/config.toml <<EOF
[profile.release]
lto = "thin"
codegen-units = 16
EOF
Другие вспомогательные утилиты для сборки пакетов
В etersoft-build-utils предусмотрена автоматизация обновления в git-репозитории пакетов rust, требуемых для сборки[5].
Примеры пакетов на Rust
- influxdb3
- hyperfine
- b3sum
- bugstalker (обратите внимание на макрос
%rust_install, где имя бинарника при установке не совпадает с названием проекта).