Руководство по упаковке 1: banner

В этом руководстве демонстрируется упаковка RPM на примере программы banner. Это простая программа с простым скриптом сборки GNU Autotools.

Для получения полной информации о создании RPM-файлов обратитесь к Справочному руководству по RPM. Если вы планируете создать RPM-пакет для репозитория Fedora, следуйте процессу Присоединения к сопровождающим пакетов, включая следование различным рекомендациям Fedora.

Это руководство предназначено для запуска в системе Fedora 42. Однако оно должно работать и для других выпусков Fedora. Просто замените строки типа f42 на номер вашего выпуска. Поскольку это руководство использует функции, специфичные для Fedora, которые могут быть недоступны в других средах, производные от Fedora, такие как CentOS Stream или Red Hat Enterprise Linux, могут как работать, так и не работать.

Руководство ведётся пошагово, причём большинство шагов заключается в редактировании spec-файла пакета. Финальный spec-файл приведён в конце, так что если возникнет неясность, как именно должно быть применено то или иное изменение, вы можете заглянуть туда.

Установка инструментов упаковщика

Создание каталога пакета

В Fedora инструкции по сборке пакетов организованы в так называемых репозиториях dist-git. Для каждого пакета существует отдельный репозиторий. Мы имитируем эту систему, создавая новый каталог для этого руководства. В dist-git имя репозитория соответствует имени пакета. Правила Fedora по именованию пакетов описаны в Рекомендациях по именованию. Для banner пакет должен называться просто banner. Это также имя официального пакета banner в Fedora.

$ mkdir banner && cd banner

Внутри spec-файла

RPM-пакеты настраиваются с помощью .spec-файлов. Инструменты, такие как rpmdev-newspec, можно использовать для создания пустых spec-файлов для различных целей. Для этого руководства просто создайте файл с именем banner.spec и вставьте следующий минимальный spec-файл. Он пока не работает, но мы попробуем его собрать и будем исправлять ошибки по мере их обнаружения.

Name:     banner
Version:  1.3.6
Release:  %autorelease
Summary:  Выводит короткую строку на консоль очень крупными буквами
License:  GPL-2.0-only
URL:      https://github.com/pronovic/banner
Source:   https://github.com/pronovic/banner/releases/download/BANNER_V%{version}/banner-%{version}.tar.gz

%description
Это классическая программа banner, похожая на ту, что была в Solaris или
AIX в конце 1990-х годов. Она выводит короткую строку на консоль очень
крупными буквами.

%prep
%autosetup

%build
%configure
%make_build

%install
%make_install

%files

%changelog
%autochangelog

Spec-файл начинается с набора тегов, таких как Name: и Version:, за которыми следуют разделы, такие как %description и %prep. Каждый тег занимает одну строку, тогда как каждый раздел продолжается до начала следующего.

Обратите внимание, что, как ни странно, помимо обозначения имён разделов, знак процента % также обозначает RPM макросы. Таким образом, %autosetup, %configure, %make_build, %make_install и %autochangelog не являются разделами.

Теги

Version содержит номер версии упаковываемого программного обеспечения.

Release numbers specfile updates, package rebuilds and other work within Fedora. The value used here, %autorelease, is part of rpmautospec, which is recommended for Fedora packages. It ties Release to package’s Git history. As we do not have a Git repository, %autorelease will evaluate to the default value of 1.

Часто Summary можно скопировать из README вышестоящего проекта. Первая буква должна быть заглавной, чтобы избежать предупреждений rpmlint.

License описывает лицензию результирующего двоичного пакета с использованием идентификатора лицензии SPDX. Он должен соответствовать рекомендациям по лицензированию Fedora. На практике определение правильного значения часто означает проверку уведомлений о лицензии в отдельных файлах исходного кода. Может также потребоваться запросить у разработчиков вышестоящего проекта разъяснения или исправления. В этом руководстве мы просто полагаемся на слово вышестоящего проекта о том, что лицензия — это GNU Public License, версия 2.

URL указывает на веб-сайт вышестоящего проекта, которым в данном случае является страница репозитория на GitHub.

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

Разделы

%description часто можно скопировать из README вышестоящего проекта.

%prep содержит скрипт оболочки для подготовки исходных кодов к сборке. Часто это просто один макрос %autosetup, который в данном случае просто извлекает исходные коды.

%build содержит скрипт оболочки для необходимых шагов сборки, таких как компиляция исходных кодов в двоичные файлы. Поскольку система сборки banner — это Autotools, её сборка включает запуск configure и make. Макросы %configure и %make_build вызывают эти команды с использованием флагов компиляции Fedora и других настроек.

%install содержит скрипт оболочки для копирования результатов из %build в изначально пустой каталог корня сборки. Поскольку banner использует Autotools, используется макрос %make_install.

%files перечисляет содержимое результирующего пакета. В основном файлы берутся из корня сборки, созданного в %install, но файлы документации и лицензии также могут быть добавлены непосредственно из исходных кодов. Этот раздел пока оставлен пустым, для заполнения позже.

%changelog документирует изменения в каждой новой версии и выпуске пакета. Данные журнала изменений можно отобразить с помощью rpm --query --changelog PACKAGE_NAME, что может быть полезно, например, для выяснения, включены ли конкретные исправления ошибок и безопасности. Его значение, %autochangelog, также поступает из rpmautospec. Он заполняет журнал изменений из сообщений коммитов Git. Поскольку у нас нет Git-репозитория, журнал изменений будет пустым.

Ненужные строки можно закомментировать с помощью символа #.

Дополнительную информацию можно найти в разделе Справочного руководства по RPM Формат spec-файла.

Загрузка исходных кодов

Нам нужен исходный код, определённый тегом Source, часто называемый вышестоящим исходным кодом. Это проще всего сделать с помощью команды spectool:

$ spectool -g banner.spec

Теперь у вас должен быть файл, указанный в Source, в вашем рабочем каталоге:

$ ls *.tar.gz
banner-1.3.6.tar.gz

Сборка пакета

Мы готовы к первому запуску для сборки исходных, двоичных и отладочных пакетов. Это и многие другие задачи выполняются с помощью инструмента fedpkg. Производственные сборки для Fedora выполняются в системе сборки Koji, которая, в свою очередь, использует Mock для управления изолированными средами сборки. Чтобы максимально приблизиться к производственной сборке локально, мы используем команду fedpkg mockbuild, которая также вызывает Mock:

$ fedpkg --release f42 mockbuild

Среда сборки, создаваемая Mock, очень базовая. По умолчанию в ней нет C-компилятора, поэтому сборка завершится ошибкой. Причина объясняется в выводе:

checking whether the C compiler works... no
configure: error: in `/builddir/build/BUILD/banner-6':
configure: error: C compiler cannot create executables
See `config.log' for more details

RPM build errors:
error: Bad exit status from /var/tmp/rpm-tmp.R4Tf16 (%build)
    Bad exit status from /var/tmp/rpm-tmp.R4Tf16 (%build)

Дополнительные инструменты сборки определяются добавлением строк BuildRequires: в spec-файл. В Fedora GCC является стандартным компилятором, поэтому нам нужно добавить строку для gcc. Autotools также использует make, поэтому для него тоже следует добавить строку. Добавьте эти строки после Source:

BuildRequires:   gcc
BuildRequires:   make

Запустите mockbuild снова.

Установка файлов

Следующее, на что пожалуется rpm, — это неупакованные файлы, то есть файлы, которые были бы установлены в систему, но не были объявлены как принадлежащие пакету. Нам нужно объявить их в разделе %files. Исправление этих ошибок — итерационный процесс. После объявления отсутствующего файла в spec-файле снова запустите fedpkg, затем объявите следующий отсутствующий файл и так далее.

Мы пройдёмся по списку файлов один за другим.

Исполняемый файл

Installed (but unpackaged) file(s) found:
/usr/bin/banner

Это исполняемая двоичная программа. Для /usr/bin, как и для многих других системных каталогов, определён стандартный RPM-макрос. Макросы всегда следует использовать, когда они доступны, поэтому исполняемый файл указывается в %files следующим образом:

%files
%{_bindir}/banner

Man-страницы

Installed (but unpackaged) file(s) found:
/usr/share/man/man1/banner.1.gz

В Рекомендациях по упаковке есть отдельный раздел для Man-страниц. Следуя его инструкциям, man-страницы указываются следующим образом:

%{_mandir}/man1/banner.1.*

На этом этапе mockbuild завершается успешно, но есть ещё файлы, которые мы должны добавить в пакет.

Файл лицензии

Каждый пакет должен устанавливать свою лицензию, помеченную директивой %license. В случае с banner, как и для многих других проектов, файл лицензии находится на верхнем уровне исходного тарболла и, возможно, вообще не копируется в корень сборки во время установки. Тем не менее, его можно установить в стандартный каталог лицензий, используя относительный путь:

%files
%license COPYING

Дополнительная документация

Часто исходные коды пакета содержат документацию, которая может быть полезна и конечным пользователям. Эти файлы можно установить и пометить как документацию с помощью директивы %doc. Аналогично %license, можно использовать относительные пути для включения файлов непосредственно из исходного тарболла, а не из корня сборки:

%doc AUTHORS ChangeLog NEWS README

Проверка результата с помощью rpmlint

Затем вы должны проверить соответствие правилам проектирования RPM, запустив rpmlint для spec-файла, исходного RPM и двоичного RPM. Команда fedpkg lint делает это:

$ fedpkg --release f42 lint

Если всё хорошо, предупреждений и ошибок быть не должно. В целях руководства мы намеренно оставили ошибку на предыдущих шагах:

 banner.x86_64: E: zero-length /usr/share/doc/banner/NEWS

Описания различных кодов ошибок можно запросить с помощью rpmlint -e <error_code>. В данном случае ненужный файл нулевой длины необходимо удалить. Измените строку документации на

%doc AUTHORS ChangeLog README

Снова запустите fedpkg mockbuild и fedpkg lint и убедитесь, что предупреждение исправлено.

Полный spec-файл

Вот финальная версия banner.spec:

Name:           banner
Version:        1.3.6
Release:        %autorelease
Summary:        Выводит короткую строку на консоль очень крупными буквами
License:        GPL-2.0-only
URL:            https://github.com/pronovic/banner
Source:         https://github.com/pronovic/banner/releases/download/BANNER_V%{version}/banner-%{version}.tar.gz
BuildRequires:  gcc
BuildRequires:  make

%description
Это классическая программа banner, похожая на ту, что была в Solaris или
AIX в конце 1990-х годов. Она выводит короткую строку на консоль очень
крупными буквами.

%prep
%autosetup

%build
%configure
%make_build

%install
%make_install

%files
%{_bindir}/banner
%{_mandir}/man1/banner.1.*
%license COPYING
%doc AUTHORS ChangeLog README

%changelog
%autochangelog

С этим spec-файлом вы должны иметь возможность успешно завершить процесс сборки и создать исходные и двоичные RPM-пакеты.

Проверка результата

Имея рабочий spec-файл и собранные из него RPM, результат можно проверить. Прежде чем проверять результат путём установки пакета, давайте выполним несколько простых проверок. Для этого можно использовать менеджер пакетов RPM rpm.

Файлы

Выведите список файлов, содержащихся в пакете:

$ rpm --query --package --list results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
/usr/bin/banner
/usr/lib/.build-id
/usr/lib/.build-id/01
/usr/lib/.build-id/01/360ae02508eaa0a77d216953b8b658a1e90b10
/usr/share/doc/banner
/usr/share/doc/banner/AUTHORS
/usr/share/doc/banner/ChangeLog
/usr/share/doc/banner/README
/usr/share/licenses/banner
/usr/share/licenses/banner/COPYING
/usr/share/man/man1/banner.1.gz

Вы можете видеть, что все файлы, перечисленные в разделе %files spec-файла, включены. Кроме того, в /usr/lib/.build-id находится автоматически сгенерированный файл. На самом деле это символическая ссылка, сопоставляющая идентификатор сборки с двоичным файлом banner для целей отладки.

Зависимости

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

$ rpm --query --package --requires results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
libc.so.6()(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.34)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsZstd) <= 5.4.18-1
rtld(GNU_HASH)

Чтобы проверить, какие пакеты в репозиториях Fedora предоставляют эти зависимости, вы можете использовать dnf repoquery:

$ dnf -C repoquery --whatprovides 'libc.so.6()(64bit)'
glibc-0:2.38-16.fc42.x86_64
glibc-0:2.38-7.fc42.x86_64

Вы увидите, что единственной зависимостью banner является glibc, который предоставляет символы в libc.so.6, а также rtld(GNU_HASH).

Зависимости rpmlib являются особыми. Они определяют различные функции rpm, используемые в самом rpm-пакете, ограничивая версию rpm, которая может быть использована для установки пакета.

Предоставляет

И наоборот, чтобы проверить, какие возможности предоставляет пакет, вы можете:

$ rpm --query --package --provides results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
banner = 1.3.6-1.fc42
banner(x86-64) = 1.3.6-1.fc42

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

Установка

В качестве финальной проверки пакет можно установить и запустить:

$ sudo dnf -C -y install ./results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
$ banner success

 #####   #     #   #####    #####   #######   #####    #####
#     #  #     #  #     #  #     #  #        #     #  #     #
#        #     #  #        #        #        #        #
 #####   #     #  #        #        #####     #####    #####
      #  #     #  #        #        #              #        #
#     #  #     #  #     #  #     #  #        #     #  #     #
 #####    #####    #####    #####   #######   #####    ##### ..

Чтобы очистить систему, отмените установку:

$ sudo dnf -C -y history undo last

Сборка в инфраструктуре Fedora

Несмотря на то, что пакет ещё не является частью дистрибутива Fedora, можно выполнить пробную сборку, чтобы убедиться, что пакет успешно собирается в системе сборки Koji Fedora и что он успешно собирается для всех архитектур, поддерживаемых Fedora. Такая сборка запускается путём передачи пакета исходного RPM в fedpkg scratch-build.

Обратите внимание, что Koji использует Kerberos для аутентификации. Подробнее см. Получение билета Kerberos.

$ fedpkg --release f42 scratch-build --srpm results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.src.rpm
Building banner-1.3.6-1.fc42.src.rpm for f42-candidate
Created task: 92465688
Task info: https://koji.fedoraproject.org/koji/taskinfo?taskID=92465688
Watching tasks (this may be safely interrupted)...

Вы можете открыть ссылку с информацией о задаче в браузере, чтобы просмотреть ход сборки, журналы и результаты. Программа командной строки также сообщает о ходе выполнения по мере его поступления. Успешное выполнение выглядит примерно так:

92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm): free
92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm): free -> open (buildvm-ppc64le-25.iad2.fedoraproject.org)
  92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org)
  92465745 buildArch (banner-1.3.6-1.fc42.src.rpm, x86_64): free
  92465748 buildArch (banner-1.3.6-1.fc42.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org)
  92465746 buildArch (banner-1.3.6-1.fc42.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org)
  92465747 buildArch (banner-1.3.6-1.fc42.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org)
  92465744 buildArch (banner-1.3.6-1.fc42.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org)
  92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org) -> closed
  1 free  5 open  1 done  0 failed
  92465745 buildArch (banner-1.3.6-1.fc42.src.rpm, x86_64): free -> open (buildhw-x86-06.iad2.fedoraproject.org)
  92465745 buildArch (banner-1.3.6-1.fc42.src.rpm, x86_64): open (buildhw-x86-06.iad2.fedoraproject.org) -> closed
  0 free  5 open  2 done  0 failed
  92465748 buildArch (banner-1.3.6-1.fc42.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org) -> closed
  0 free  4 open  3 done  0 failed
  92465746 buildArch (banner-1.3.6-1.fc42.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org) -> closed
  0 free  3 open  4 done  0 failed
  92465744 buildArch (banner-1.3.6-1.fc42.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org) -> closed
  0 free  2 open  5 done  0 failed
92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm): open (buildvm-ppc64le-25.iad2.fedoraproject.org) -> closed
  0 free  1 open  6 done  0 failed
  92465747 buildArch (banner-1.3.6-1.fc42.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org) -> closed
  0 free  0 open  7 done  0 failed

92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm) completed successfully