Переход ROSA с RPM 5 на RPM 4

Материал из Rosalab Wiki
Перейти к: навигация, поиск
Начиная с rosa2019.1, дистрибутив ROSA Fresh переходит с пакетных менеджеров RPM 5 и urpmi на RPM 4 и DNF. Эта статья описывает основные отличия для пользователей и сборщиков пакетов.

Откуда куда переход

Когда-то давно был создан форк RPM 4, который назвали RPM 5, он просуществовал, потом его разработку забросили, а разработку RPM 4 наоборот возродили. Mandriva, предок ROSA, когда-то давно перешла с RPM 4 на RPM 5, а теперь ROSA переходит обратно на RPM 4.

Было:

  • низкоуровневая система управления пакетами RPM 5.4.10
  • высокоуровневый пакетный менеджер urpmi
  • mock-urpm

Стало:

  • низкоуровневая система управления пакетами RPM 4.15.1+
  • высокоуровневый пакетный менеджер DNF
  • исчез RPM-тег DistEpoch (не путать с Epoch)
  • mock
  • наиболее часто используемые в командах urpmi и urpme функции преобразовываются в команды dnf (dnf-URPM)
  • будет работающий packagekit, в т.ч. графический "Магазин приложений"

Затронутые платформы: rosa2019.1 (в будущем релизы Rosa Desktop Fresh >= R12, Rosa Enterprise Desktop >= X5) и новее, в старых (rosa2012.1, rosa2012lts, rosa2014.1, rosa2016.1, rosa2019.0) пакетная система не меняется.

В данный момент для rosa2019.1 создаются одновременно метаданные и для urpmi (директория media_info), и для dnf (директория repodata). Метаданные urpmi обновляются при публикации пакетов, как положено, а метаданные dnf временно создаются через cron раз в 5 минут и пока только для main/release, main/updates, contrib/rlease contrib/updates, для non-free и restricted пока нет, но скоро появятся. Если вы парсите метаданные, то не стоит ориентироваться на метаданные от urpmi (media_info), потому что, как написано ниже, пока не ясно, останется он или нет. В rpm4 нет %__NVRA, нет distepoch, но есть disttag. Лучше всего парсить новые метаданные, как метаданные Fedora. В данный момент urpmi в rosa2019.1 вообще не тестируется, метаданные для него могут быть сломаны.

Причины для перехода

  • ни RPM 5, ни urpmi более не разрабатываются, ROSA и PLD остались единственными их использующими дистрибутивами, а PLD уже более года прорабатывает переход на rpm4; в мире Linux нецелесообразно пытаться малыми силами тащить такую важную инфраструктурную вещь, как пакетная система
  • в RPM 5 в свое время были важные функции, которых не было в RPM 4, но это более не так, теперь наоборот
  • апстрим RPM 4 в последнее время очень живой, RPM 4 активно развивается
  • плохое качество кода RPM 5: много весьма диких костылей времен спешного перехода Mandriva на RPM 5, много недоделанного функционала, отвечающий за что-то одно код размазан по огромному количеству файлов, например, см. коммит 5bf4d7: банально идентификаторы алгоритмов хеширования пришлось добавить в большое количество файлов
  • urpmi, конечно, немного жалко, но желающих в одиночку тянуть urpmi и perl-URPM не нашлось, а какого-либо критически важного функционала, отсутствующего в DNF, в urpmi нет
  • нет качественных биндингов urpmi<->PackageKit, а их разработка и поддержка займет большое количество времени, которое можно потратить на другие вещи, и не очень целесообразна, поскольку есть много нюансов; если делать их только самим, то качество получится низким

Общий план перехода

(возможны изменения, то, что еще не сделано, является приблизительным видением дальнейшей работы)

  • (СДЕЛАНО) собрать стек rpm4 с временными хаками, чтобы можно было использовать ранее собранные rpm5 пакеты *.rpm, например, игнорируя отсутствующую в стеке rpm4 %DISTEPOCH
  • (СДЕЛАНО) обеспечить совместимость нового rpm4 с максимально возможным количеством старых макросов
  • (СДЕЛАНО) автоматизированно внести массовые изменения в спеки (*.spec) так, чтобы они стали совместимы с RPM 4: меняются как места, которые строго необходимо заменить, так и те, где старый и продолжающий работать макрос меняется на его новый вариант
  • (СДЕЛАНО) обеспечить совместимость старого rpm5 с измененными спеками, чтобы можно было из одного спека собирать пакеты и для rpm5 в платформах rosa2016.1 и rosa2019.0 и для rpm4 в платформе rosa2019.1
  • (СДЕЛАНО) научить abf-console-client работать с RPM 4 (теперь апстрим общий с OpenMandriva — https://github.com/OpenMandrivaSoftware/abf-console-client, а старый клиент из ROSA на python2 — https://abf.io/soft/abf-console-client — остается только для RPM5)
  • (В ПРОЦЕССЕ) провести массовую пересборку пакетов main и contrib, выявив и исправив типовые проблемы (например, уже запатчен find-lang.sh из rpm4)
  • (В ПРОЦЕССЕ) ранее применявшимся в OpenMandriva скриптом автоматического обновления пакетов, где это возможно, обновить пакеты
  • починить макросы: было сообщено, что rpm4 не подхватывает /etc/rpm/macros.d/meson.macros, а /etc/rpm/macros.d/macros.meson — подхватывает, а rpm5 — наоборот; нужно разобраться, почему так, если это и правда так, а заставить подхватывать нельзя, то переименовать все кастомные макросы в репозитории (возможно, перейдя на астримные макросы вместо своих, сохранив совместимость со своими, чтобы снять с себя поддержку макросов под новые версии ПО); есть мысль сделать макрос %install_macro meson %{SOURCE9}, который будет правильнос тавить дополнительные макросы, куда надо
  • привести файловые триггеры RPM 5 и %trigger* к файловым триггерам RPM 4 (возможно, замапить новые %trigger* в старые для переиспользования спеков rpm4 в rpm5...)
  • обновить и починить gdb (gdb-add-index теперь используется в rpm, а gdb сейчас сломан из-за несовместимости с Python 3.8)
  • починить не собирающиеся пакеты, возможно, снова обновив glibc и gcc
  • либо отвязать drakxtools от perl-URPM (или перейти на manatools, как минимум настройку часов оттуда точно нужно взять, т.к. она умеет не только в ntpd, а еще и в chrony и systemd-timesyncd, а это важно), либо придется оставить urpmi в качестве существующего параллельно с DNF пакетного менедежера, как в Mageia
  • если будет решено оставить urpmi и perl-URPM, то, во-первых, взять их версии из Mageia (они умеют работать c rpm4), во-вторых, перенести /usr/{sbin,bin}/{urpmi,urpme} куда-нибудь в /usr/lib/, а в (s)bin отставить dnf-URPM
  • после обновления perl-URPM до версии из Mageia или его убирания обновить perl
  • если получится избавиться от urpmi, наверняка стоит избавиться от префикса lib64 в названии пакетов, который существует из-за неумения urpmi отличать пакеты с одинаковым названием, но одинаковой архитектурой (но вопрос требует тщательного обдумывания, в т.ч. — не пострадает ли wine)
  • переработать пакет rosa-repos: вынести main, contrib, non-free и т.д. в отдельные подпакеты
  • собрать и обеспечить работу GUI для управления пакетами dnfdranoga
  • сделать генерацию метаданных appstream из всего репозитория
  • во все пакеты автоматически добавлять метаданные /usr/share/metainfo/*.xml, чтобы в графических "магазинах приложений" были все пакеты, а не только лишь те, в которых есть /usr/share/metainfo/*.xml; возможно, скрыть системные пакеты, имена которых начинаются на lib
  • обновить весь стек GNOME и затем обеспечить работу gnome-software
  • поскольку в drmdrake был GUI для управления репозиториями, а в dnfdranoga его нет, в пакеты rosa-repos-* добавить метаданные с описанием назначения этих репозиториев и с его переводом на русский язык; в магазинах приложений сделать отдельную категорию пакетов "Репозитории ROSA"; это позволит включать и отключать репозитории одной кнопкой "Установить"/"Удалить" пакет, также улучшит централизацию поставки конфигураций репозиториев
  • собрать, обновить и обеспечить работу packagekit
  • обеспечить работу оффлайн-обновлений через packagekit+systemd
  • портировать хеши файлов по ГОСТ Р 34.11-2012 из rpm5 в rpm4 и желательно заапстримить (rpm4 уже переключен на libgcrypt по умолчанию)
  • начать использовать security.ima и интегрировать подписывание в сборочницу, в т.ч. проработать вопрос с ГОСТ
  • портировать генератор зависимостей QML (?)
  • придумать, как существующие системы обновить до rosa2019.1 с rpm4 и задокументировать (будут проблемы с конвертированием БД rpm)
  • осуществить полный переезд в /usr
  • проработать нюансы, возникшие после смены %_libexecdir = %_libdir на %_libexecdir = /usr/libexec
  • инсталлятор, скорее всего Anaconda, в которой есть в т.ч. режим, похожий на rsync в draklive-install, а также можно сделать выбор пакетов для установки, и есть поддержка kickstart-файлов
  • сделать что-то с "бекендом" для urpmi в пакете system-config-printer, желательно выкинуть и использовать апстримную интеграцию с PackageKit; а сам system-config-printer отвязать от consolehelper и перейти на апстримную интеграцию с policykit, чтобы работала печать тестовых заданий с авторизацией по тикету Kerberos текущего пользователя
  • ...

Особенности перевода спеков на RPM 4

Скрипт rpm5-to-rpm4.sh, который автоматически вносит правки в спеки, здесь: https://gitlab.com/abf-mirror/abf-mirror-scripts

Если вы видите коммиты от "NixTux Commit Bot" с текстом: "bot: rpm5 -> rpm4 (N)", — где N — номер итерации прохода скрипта по всем пакетам в abf.io/import/, то это коммиты, сделанные этим скриптом. Каковы были изменения в скрипте между итерациями, можно посмотреть в git по ссылке выше.

  • уменьшено количество пакетов в базовой сборочной системе, так, basesystem-build больше не зависит от initscripts, gpg и др. (см. коммиты), а из-за отсутствия initscripts больше нет, например, procps-ng с командой ps; минимизация сборочной системы — это скорее хорошо, чем плохо, т.к. ускоряет сборку, а мейнтейнер пакета будет вынужден лучше понимать, как происходит его сборка; при необходимости "потерянные" зависимости добавьте в BuildRequires вручную, пример.
  • Suggests и Requires(missingok) теперь Recommends: в RPM 5 были только Suggests и Requires(missingok) (а Suggests был алиасом Requires(missingok), а в RPM 4 есть и то, и то, но Recommends работает так, как работал Suggests, а Suggests используется для иных вещей, поэтому заменяем "Suggests:" на "Recommends:", а чтобы такие спеки продолжали работать в RPM 5, мы научили его понимать Suggests: теперь он считает и Suggests, и Recommends одинаково эквивалентными "Requires(missingok)"
  • Фильтры для автоматического генератора зависимостей (requires) и провайдов (provides) поменялись следующим образом, ниже сначала вариант RPM 4 (новый), затем RPM 5 (старый):
 %__requires_exclude -> %__noautoreq
 %__provides_exclude -> %__noautoprov
 %__requires_exclude_from -> %__noautoreqfiles
 %__provides_exclude_from -> %__noautoprovfiles

Нет возможности легко научить RPM 4 понимать %__noautoreq, %__noautoprov, %__noautoreqfiles и %__noautoprovfiles, но есть возможность легко научить RPM 5 понимать оба варианта, что мы и сделали. Теперь, если в спеке указаны одновременно старый макрос и эквивалентный ему новый макрос, например:

 %define __noautoreq 'libGL.*'
 %global __requires_exclude 'libGL.*'

...то rpm5 будет брать только значение старого (__noautoreq) и игнорировать новый (__requires_exclude). Если же указан только новый (__requires_exclude), то будет браться его значение. В большинстве случаев достаточно использовать только новый вариант от RPM 4, т.е. только

 %global __requires_exclude 'libGL.*'

...но, если вдруг понадобится задать разные правила для RPM 5 и RPM 4, то укажите оба варианта, тогда RPM 5 возьмет только свой прежний вариант, а RPM 4 только свой. Обратите внимание, что RPM 4 не понимает старые варианты от RPM 5, поэтому для RPM 4 обязательно указать __requires_exclude, а не __noautoreq. %global и %define здесь примерно одно и то же и для RPM 4, и для RPM 5, но документация от разработчиков RPM 4 рекомендует использовать %global, когда как в rpm5 более предпочтительно было %define.

Про варианты от RPM 4 читайте здесь.

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

  • В пакете rpm-openmandriva-setup собраны макросы, которые существовали в RPM 5 и которых теперь нет в RPM 4, чтобы они продолжали работать в ROSA. Какие-то макросы просто скопированы, какие-то преобразовываются в их новые варианты. Также мы добавили некоторые широко распространенные новые макросы от rpm4 в rpm5, чтобы после их замены в спеках описанным выше скриптом спеки продолжали работать для rosa2016.1 и rosa2019.0 без изменений.

Типовые замены макросов:

 %make -> %make_build
 %makeinstall_std -> %make_install
 %configure2_5x -> %configure
 %setup_compile_flags -> %set_build_flags
 %ldflags -> %build_ldflags

Также появились %build_cflags (CFLAGS, флаги компилятора Си), %build_cxxflags (CXXFLAGS, флаги компилятора Cи++), %build_fflags (FFLAGS, флаги компилятора Фортран); в rpm5 они сделаны эквивалентными %optflags; %optflags продолжает существовать, как и раньше.

Макросы %make_* стали унифицированы с %ninja_*, %meson_* и др., т.е. build означает сборку, install — установку. Возможно изменение политики в отношение макросов.

  • rpm5 с описанными выше изменениями уже опубликован в rosa2019.0 и rosa2016.1
  • Если нет иного выхода, то можно сделать if/else:
 %if %{mdvver} >= 201910
 < вариант для rpm4 >
 %else
 < вариант для rpm5 >
 %endif
  • rpm4 не позволяет закомментировать %define:
 #%define xxx yyy

не будет работать, нужно заменить "#%define" на "#define"

  • в rpm4 не поддерживаются стадии BuildRequires, т.е. записи BuildRequires(check), BuildRequires(pre) заменяем на BuildRequires; потеря не велика, это использовалось очень редко и, как оказалось, во всем репозитории только одним из авторов этой статьи, при чем там, где без этого можно обойтись, просто для пущей красоты было
  •  %_libexecdir теперь не /usr/lib(64), а /usr/libexec
  • в RPM 5 директории %_bindir, %_libdir и др. наследовали значение %_prefix, в rpm4 не наследуют, пример правок в пакете libressl (мы думаем над тем, как решить эту проблему, чтобы снова наследовалось значение %_prefix)
  • в RPM 4 есть такой макрос:
 %__pkgconfig_path    ^((%{_libdir}|%{_datadir})/pkgconfig/.*\.pc|%{_bindir}/pkg-config)$

Если значение %_libdir переназначено, то файлы *.pc для создания Requires и Provides скриптом scripts/pkgconfigdeps.sh будут искаться, возможно, не там, где вы хотите

Пример решения (переназначим этот макрос, указав нужные пути):

 %global __pkgconfig_path ^(%{_olibdir}/pkgconfig/.*\\.pc|%{_obindir}/pkg-config)$

В RPM 5 такого макроса нет, поэтому этот %global/%define ему безразличен.

  • в RPM нельзя поставить %attr() на символическую ссылку, RPM 5 игнорировал такое, а RPM 4 выдает ошибку в явном виде, пример:
 Explicit %attr() mode not applicable to symlink: /builddir/build/BUILDROOT/log4cpp-1.0-6.i386/usr/lib/liblog4cpp.so

Исправление — убрать лишний %attr

  • в сборочнице теперь отключен доступ в сеть, часть пакетов не собирается с ошибкой вида:
 BUILDSTDERR: error: Bad source: /builddir/build/SOURCES/mds-2.4.2.2.tar.gz: No such file or directory

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

  • rpm5 съедал все содержимое папки с %doc, даже если туда положить что-то лишнее, а rpm4 требует явного указания всего содержимого папки /usr/share/doc/%name. Пример ошибки:
 DEBUG: BUILDSTDERR: error: Installed (but unpackaged) file(s) found:
 DEBUG: BUILDSTDERR:    /usr/share/doc/miau/examples/miaurc

При этом в пакете было:

 %doc AUTHORS ChangeLog README TODO misc/miaurc

Файл examples/miaurc не прописан ни в %files, ни в %doc, а rpm5 игнорировал такую недоработку спека.

  • rpm5 позволял написать: "%package -n %{name}", а rpm4 выдает ошибку:
 BUILDSTDERR: error: line 133: %package -n ipa-client47: package ipa-client47 already exists

Это логично, потому что %package, грубо говоря, используется для подпакетов, а пакет с именем %name уже и так автоматически задан. Пример исправления.

  • в RPM4 в макрос %configure входит:
 find . -name config.guess -o -name config.sub | while read i ; do 
          [ -f /usr/share/libtool/config/"$(basename "$i")" ] && /bin/rm -f "$i" && /bin/cp -fv /usr/share/libtool/config/"$(basename "$i")" "$i" ; 
 done ; 
 if [ -e configure.ac -a -e Makefile.am ]; then 
   find . -name configure.ac |xargs dirname |while read D; do 
     pushd $D; 
     if grep -qE '(LT_INIT|LIBTOOL)' configure.ac >/dev/null; then 
       libtoolize --force ; 
     fi ; 
     aclocal $((find . -name "*.m4" 2>/dev/null |grep -vE 'ac(local|include).m4' | xargs dirname) | grep -v '^.$' |sort |uniq |cut -d/ -f2- |while read R; do [ -e $R/configure.ac ] || echo -n "-I$R "; done) ; 
     automake -a --foreign ; 
     autoconf ; 
     popd ; 
   done ; 
 fi ;

Этого не было и нет в %configure(2_5x) в RPM 5, но представляется полезным действием для актуализации сборочных скриптов тарболлов. Это может потребовать добавления новых BuildRequires, например, gettext-devel.

  •  %exclude работает по-разному: в rpm, если в списке файлов (%files) есть %exclude, то он применяется, чтобы какой-то из файлов, попадающий в перечисленные файлы, не включать в этот список, например: есть файлы file.php, file.sh, file.c, а вы пишите:
 %files
 file.*
 %exclude file.php

Тогда в пакет попадут file.c и file.sh, а file.php не попадет. Но, если вы его вручную не удалите и не положите ни в один пакет, rpm5 выдаст ошибку о неупакованном файле, а rpm4 не выдаст и сам удалит этот файл. Изменение поведения rpm4 обсуждается здесь.