23 Эволюция функциональности RPM

Несмотря на то, что разные реализации RPM максимально совместимы между собой от версии к версии, сборщик пакетов должен иметь в виду, что RPM - развивающаяся система и разработчики добавляют функционал в каждую новую версию (кроме того, имеются форки сторонних разработчиков - прим. перев.). Когда собирается пакет, автор сборки должен принимать во внимание потенциальную аудиторию пользователей пакета. Какие версии RPM используют наши потребители? Среди этих версий необходимо выбрать "наименьший общий знаменатель" набора свойств системы, то есть использовать наиболее старую версию RPM. В качестве справочной информации, можно использовать сведения, приведенные в данной главе, касающиеся особенностей разных версий. Это руководство опирается на версию 4.1, главные же изменения в системе происходили в версиях RPM 2.5, 3.0.5, 4.0.4 и 4.1.
RPM 2.5 практически не используется, собирать под ней имеет смысл только в том случае, если пакет должен устанавливаться абсолютно из под всех версий системы.
RPM 3.0.5 - это финальный релиз серии 3.х. Этот релиз поставлялся с Red Hat 6.2. Он все еще используется некоторыми вендорами, например, Cobalt Linux.
RPM 4.0.4 использовался с выпусками Red Hat линейки 7.х, версия 4.1 - начиная с Red Hat 8.0.
RPM 2.5 поддерживает все основные функции, а также расширенные функции, такие как триггеры, интернационализация Summary:, Description:, и Group: в хэдере. Также эта версия была первой, в которой использовался формат файла RPM 3.
В RPM 2.5.3 добавлена поддержка тэга Epoch в хэдере пакета.
В RPM 2.5.4 добавлены типы %license и %readme для указания на файлы лицензии и README.
В RPM 2.5.6 включена поддержка директивы Epoch: в spec-файле. Она заменила Serial:, используя сходное поведение.
В RPM 2.5.7 была придана сила ранее введенному стандарту, касающемуся символа "-", который не должен использоваться в полях Version или Release в spec-файле.
В RPM 2.90 введена поддержка подписей и проверка пакетов с помощью технологии GPG.
В RPM 2.91 начинается использование Provides:, директивы, указывающей на абсолютные пути предоставляемых файлов. До этой версии Provides: предоставляла только списки предоставляемых возможностей без указания путей к файлам.
В RPM 3.0.2 стало возможным указывать множественные Provides:, это позволило отказаться от необходимости указывать предоставляемые возможности и имена файлов в одной строке.
RPM 3.0.3 предоставила возможность анализа зависимостей версий. До 3.0.3 в spec-файле можно было указывать зависимость от возможности или пакета, но без конкретной версии.
В RPM 3.0.4 добавлена поддержка CompressedFileNames. До этой версии RPM упаковывала абсолютные имена файлов всех архивов внутрь пакета. Хэдеры пакетов содержали определения, подобные этим:

fileName #0: /usr/bin/ar

fileName #1: /usr/bin/as

fileName #2: /usr/bin/gasp

fileName #3: /usr/bin/gprof

С началом поддержки CompressedFileNames хэдеры содержат только базовые имена файлов. Теперь в хэдерах имеются определения, как показано в примере ниже, то есть для заданного каталога - номера файлов:

dirName #0: /usr/bin

baseName dirIndex

#0 ar 0

#1 as 0

#2 gasp 0

#3 gprof 0

Каждая запись о файле теперь содержит базовое имя файла внутри заданного каталога, а также индекс номеров, каждый из которых ссылается на запись каталога. Такая технология хранения имен позволяет экономить значительное количество памяти при обработке rpm-файлов во время инсталляции.
В RPM 3.0.5 вводится поддержка компрессора bzip2. С этого момента можно использовать как архивы .tar.gz, так и архивы .tar.bz2. Несмотря на поддержку bzip2 на практике она используется сравнительно редко, так как bzip2 обладает более высокой степенью сжатия, но работает значительно медленнее и потребляет больше памяти. Кроме того, в RPM 3.0.5 начал поддерживаться формат файла RPM 4.
RPM 4.0 содержит некоторые весьма значительные изменения системы. Совершен переход на использование формата файлов RPM 4. БД RPM - вместо Berkeley db 1.85 используется Berkeley db 3.1. Изменилось имя файла БД. Изменение имени файла БД с /var/lib/rpm/packages.rpm на /var/lib/rpm/Packages позволило сосуществовать старой и новой базам вместе, если это необходимо, упрощая переход со старых релизов RPM к новым. Также была введена возможность PayloadFilesHavePrefix, эта особенность позволяет изменять путевые имена устанавливаемых файлов. С введением PayloadFilesHavePrefix все файлы в cpio-архиве имеют корневой префикс, например, ./usr/bin/ar. В этой версии RPM добавлена проверка синтаксиса spec-файла. Начиная с rpm 4.0 отпала необходимость в символьных ссылках, содержащих BuildRoot. Это сразу ликвидировало целый класс ошибок при сборке пакета. Наконец, в этой версии системы автоматически генерируются Provides: , поэтому нет необходимости заполнять эти поля в spec-файле.
В RPM 4.0.2 введено использование дайджеста SHA-1 для верификации различных областей хэдера.
RPM 4.0.3 добавляет директиву spec-файла %dev(type,major,minor), которая позволяет создавать файлы устройств в статическом варианте. Кроме того, %configure теперь поддерживает --target и –host, облегчающие кросс-сборку. Директива %files дополнена субдирективой %exclude, позволяющей задать исключения из списков и шаблоны исключений. Наконец, в 4.0.3 формат файла пакета по умолчанию возвращен к версии 3, хотя версия 4 также поддерживается.
RPM 4.0.4 предоставляет поддержку PartialHardlinkSets. Иногда пакеты создаются с несколькими экземплярами одного файла, которые представлены жесткими ссылками для экономии места. До этой версии RPM обрабатывал коллекции жестких ссылок в идеологии "все-или-ничего"; или создавались все жесткие ссылки, или ни одной. Такое поведение может привести к проблемам, если некоторые ссылки относятся к файлам, помеченным атрибутами %doc или %lang. В определенных ситуациях rpm могла не установить ни одного файла, помеченного как %doc . PartialHardlinkSet исправляет эту проблему, вводя возможность создания подмножества коллекции жестких ссылок. Из интересных новшеств в RPM 4.0.4 также следует отметить возможность автоматической генерации Requires: для модулей Perl. Кроме того, с RPM 4.0.4 поддерживаются транзакции.
RPM 4.1 предоставляет подписи DSA и RSA отдельно для хэдера, что позволяет верифицировать собственно хэдер.

.....

RPM 4.6
Разработчики планируют долгое время поддерживать совместимость с пакетами версии 4.4.2. Основные изменения:

Изменения в сборке пакетов
Значение макроса %{_topdir} по умолчанию переключено на $(HOME)/rpmbuild/ вместо долгое время использовавшегося /usr/src/redhat/.
Rpm принудительно применяет BuildRoot из конфигурации для всех пакетов, игнорируя директиву spec-файла.
Поле Group в spec-файле больше не является обязательным, до тех пор, пока значение не задано, используется "Unspecified".
Patches are applied with zero fuzz tolerance by default.
Макросы для вспомогательных программ, такие как %{__tar} и %{__gzip} теперь имеют значение везде в rpmbuild.
Списки каталогов отныне могут задаваться через макросы.
Добавлены новые макросы: %{patches} и %{sources}, эта возможность может использоваться в spec-файле для перебора исходников и патчей в цикле.
rpmbuild автоматически добавляет расширенную информацию об архитектуре в пакет. Требуется для правильной обработки зависимостей через dlopen() в различных плагинах и пакетах разработки.
Зависимости для pkg-config и libtool генерируются автоматически утилитой rpmbuild.
Некоторые исправления для сборки в tar-build режиме:
spec-файл из архива извлекается с разумными правами (RhBug:253648);
попытки сборки из архива, в котором отсутствует spec-файл больше не вызывают генерацию безобразных файлов по завершении (RhBug:281391).
Применяется строгая проверка spec-файла на соответствие синтаксису.
Множественные определения одинаковых номеров patch- и source- файлов больше не позволяются. %patch теперь не тождественен %patch0.
rpmbuild -bs и сходные команды применяют --nodeps автоматически (RhBug:235507)
rpmbuild автоматически создает нужную структуру каталогов, если это необходимо.
Произведены исправления ошибок обработки имен файлов, содержащих пробелы (RhBug:430428).
noarch-субпакеты можно генерировать в процессе сборки архитектурно-зависимого основного пакета (RhBug:227790).
Спустя несколько лет опция --nodirtokens снова применяется(RhBug:462391).
Многие старые ограничения, заданные в коде, теперь отменены или конфигурируются через макросы.
Генерация отладочной информации больше не вызывает ошибок утилиты "file" (последних ее версий) (RhBug:468129).
Размер пакетов вычисляется корректно с учетом %excludes и дублирующихся файлов (RhBug:247374).
Контекст SELinux больше не хранится в хэдере. Контексты могут варьироваться в широком диапазоне политик и версий политик, независимо от содержимого хэдера.
Включена экспериментальная поддержка для сжатия нагрузки с помощью LZMA. Эта возможность не поддерживается в текущей версии. Официальная поддержка будет включена, когда появится стабильная версия xz-utils (ранее известных как lzma-utils).

Изменения в API, внутренние улучшения и подчистки
API манипуляции со значениями полей хэдера полностью переработан.
Данные полей хэдера и расширений теперь передаются в специальном контейнере, который "знает", как выделялась память, какой тип данных в поле, поддерживает итерации, безопасный доступ к соответствующему типу и многое другое.
headerGet() можно применять также и для получения данных из расширения.
Поведение выделения памяти headerGet() можно контролировать флагами.
headerSprintf() утратил значение в пользу более простого вызова headerFormat().
headerSprintf/Format() несколько увеличил свое значение в плане обработки типа данных "массив".
Включена поддержка 64bit целых типов.
Семейство старых вызовов headerGetEntry() утратило значение, но все еще поддерживается в режиме обратной совместимости.
Проверки подписей практически полностью выключены из сета транзакций.
Добавлен новый абстрактный интерфейс работы с ключами. Он используется низкоуровневыми функциями проверки подписей.
БД RPM все еще используется для постоянного хранения публичных ключей по умолчанию, но для текущих проверок используются ключи, хранимые во время сессии в памяти.
Публичные ключи могут хранится не в БД RPM.
Правильный обратный вызов добавлен в инфраструктуру rpmlog.
Ошибки и предупреждения времени выполнения скриптлетов теперь обрабатываются через обратный вызов в транзакции.
Добавлены новые методы для итеративного обхода сетов и доступа к данным.
Успешные вызовы TagGetName() больше не разрушают результаты более ранних вызовов.
Внутренний парсер OpenPGP допускает многократные вхождения.
64bit rpm_loff_t type используется для внутренних целей и вовне для обработки пакетов и размеров файлов.
Библиотеки librpmdb и librpm слиты. Это разделение было во многом искусственным и многие проблемы в результате слияния решились сами собой.
В librpmio добавлены некоторые вспомогательные функции для обработки строк и файлов.
Внутренний сетевой транспорт и относящиеся к нему функции "RPC" удалены из librpmio. Возможность удаленного транспорта теперь реализуется вызовом внешнего вспомогательного приложения, которое конфигурируется макросами.
Использование не портируемого и не безопасного вызова alloca() полностью исключено из всего кода.
БОльшая часть случаев использования буферов фиксированного размера исключено из кода. Во всех таких местах теперь используются буфера с динамически выделяемой памятью.
БОльшая часть статических переменных исключена. Предпочитается передача через параметры.
Уменьшено количество дублирующего кода.
Рефакторинг кода идет по пути бОльшей ясности и простоты.
Сильно вычищены API и ABI:
Множество внутренних функций и глобальных переменных удалено, очищено пространство имен в публичных API и ABI.
В случаях, когда это поддерживается компилятором, внутренние функции скрыты в экспортированном ABI.
Некоторые ранее экспортированные внутренние структуры скрыты.
Некоторые заголовочные файлы сделаны приватными.
Приватные и публичные заголовочные файлы правильно разделены. Публичные заголовочные файлы всегда доступны в стиле <rpm/header.h>.
Многие (подобные перечислениям) определения перенесены в более логичные места, rpmlib.h больше не является "помойкой для всего".
Висячие комментарии удалены из кода, это серьезно повысило читаемость.
Пересмотрены имена переменных, функций и параметров в сторону более длинных в пользу ясности кода. Имена сделаны более согласованными, как во внутренних блоках, так и в экспортированном API.
Подходы стандартов POSIX и C99 используются где это возможно. Bogus const on pointers to allocated memory have been removed from exported API and mostly internally too.
rpmlog() используется везде для журналирования, rpmError() и rpmMessage() утратили значение и оставлены только для совместимости.
Все вызовы mktemp() заменены на вызовы mkstemp().
Rpm теперь содержит метаданные pkg-config (.pc) для более простой сборки и линковки по сравнению с librpm.

Привязки Python
Привязки Python в основном оставлены как есть в целях максимальной совместимости. Основной фокус разработки сосредоточен на добавлении новых функций, которые не являются вполне совместимыми.
Python code tracebacking in rpm transaction callback now aborts the entire transaction (RhBug:463447)
Тип, возвращаемый при обработке данных хэдера, теперь всегда консистентный.
rpmfi получил новый метод FDigest() для замены прежнего MD5(), теперь алгоритм проверки контрольной суммы конфигурируемый.
rpmts.addInstall() больше не принимает тип пакета "available".
Доступ к данным хэдера по имени поля ускорился благодаря bsearch() импользуемой вместо линейного поиска.
Два новых метода в rpmds : Rpmlib() для получения возможностей rpmlib, и Search() для поиска в сете зависимостей.
rpmrc и rpmfts поскольку были не завершены, не использовались и не были удобны для использования.

Cборка RPM
RPM больше не поставляется со сторонними библиотеками, внутренние копии Berkeley DB, Lua, popt и libmagic удалены. Тем не менее, все еще поддерживается сборка со встроенной Berkeley DB, инструкции для этого имеются в INSTALL.
Процесс сборки очищен от лишних деталей, модернизированы механизмы использования автоконфигурационных технологий.
Для низкоуровневого шифрования RPM теперь использует NSS, beecrypt больше не поддерживается.
Для сборки RPM теперь требуется C99-совместимый компилятор.
Добавлен новый стек автоматизированных тестов (первоначальная версия).
Для поддержки внутренних Lua-скриптов требуется версия Lua >= 5.1 .
./configure принимает --libdir взамен попыток определить, будет использоваться каталог lib или lib64.

Итак, принимая во внимание особенности функционала RPM, необходимого в пакетах, которые вы собираете, следует иметь в виду, что некоторые особенности добавляются автоматически при сборке в зависимости от версии RPM, другие же указаны вручную в spec-файле. Например, использование директивы Requires: с конкретными версиями зависимостей возможно только начиная с версии 3.0.3. Подобно этому, релизы RPM версии 4.0 или более поздние генерируют такие rpm-пакеты, с которыми можно манипулировать лишь системами RPM, поддерживающими функционал PayloadFilesHavePrefix. В первом случае вы выбираете производство пакетов для работы с RPM версии 3.0.3 или свежее, но не с версией 2.5, во втором случае вы собираете пакеты, которые будут правильно пониматься лишь RPM версии 4.0 или более поздними.
Таким образом, наиболее верной практикой будет сборка пакетов в наиболее старой версии RPM из всех тех, которые вы собираетесь поддерживать.

Далее - Раздел 24. Формат файла rpm-пакета
Назад - Журнал изменений
Содержание