Создание RPM пакета для Fedora

Иногда встречаются полезные программы, доступные только в виде исходных кодов (и/или в виде установочных пакетов для других ОС), но есть необходимость их установки на несколько компьютеров. Чтобы не выполнять компиляцию на каждом компьютере отдельно, можно на одном подготовить установочный пакет и установить его штатными средствами на других компьютерах.
Ниже приведён пример создания RPM пакета для Fedora 21 (для других версий Fedora процедура не отличается) из исходных текстов очень приятной и полезной программы Boomaga версии 0.7.0.

Готовим инструменты сборки RPM

Для начала я попытался установить необходимые инструменты (как мне посоветовала статья "How to create a GNU Hello RPM package"):
sudo dnf install @development-tools
но эта команда не выполнилась, ссылаясь на отсутствие группы development-tools. Тогда я установил всё другой командой, которую мне подсказала статья "Создание RPM пакетов из исходников":

sudo dnf groupinstall "Development Tools"
и ещё две команды из обеих вышеуказанных статей:

sudo dnf install rpmdevtools
sudo dnf install fedora-packager
Затем надо сгенерировать рабочее пространство для сборки RPM:
rpmdev-setuptree
В результате этой команды создадутся необходимые каталоги в домашнем каталоге текущего пользователя (показываю содержимое нового каталога rpmbuild):
[oleg@o ~]$ ls ~/rpmbuild/

BUILD  BUILDROOT  RPMS  SOURCES  SPECS  SRPMS
В каталог SOURCES сразу перемещаю архив исходников (boomaga-0.7.0.tar.gz), как он есть. Кстати, тут есть небольшой подвох от github, - ссылка на закачку не даётся напрямую, а генерируется только после клика по ней. Из-за этого не получилось указать прямую ссылку на архив в интернете в SPEC файле, о котором пойдёт речь ниже.

Готовим SPEC файл

Для упаковки исходных текстов программы в RPM пакет нужен специальный файл с описанием необходимых действий. Сгенерируем шаблон:
rpmdev-newspec boomaga
В результате этой команды будет создан файл boomaga.spec в каталоге ~/rpmbuild/SPEC. Тут важно название SPEC файла. Оно должно совпадать с названием программы (т.е. без номера версии). После автоматической генерации SPEC файла переходим к его редактированию. В моём случае это получилось так:

Name:           boomaga
Version:        0.7.0
Release:        1%{?dist}
Summary:        Boomaga is a virtual printer for viewing a document before printing

License:        GPLv2 and LGPLv2+
URL:            http://boomaga.github.io
Source0:        %{name}-%{version}.tar.gz

BuildRequires:  cmake,cups-devel,poppler-devel,poppler-cpp-devel,qt5-qtbase-devel,qt5-qttools-devel,snappy-devel
Requires:       cups

%description
Boomaga (BOOklet MAnager) is a virtual printer for viewing a document before printing it out using the
physical printer.
The program is very simple to work with. Running any program, click “print” and select “Boomaga” to
see in several seconds (CUPS takes some time to respond) the Boomaga window open.
If you print out one more document, it gets added to the previous one, and you can also print them out as one.


%prep
%setup -q


%build
mkdir build
cd build
cmake ..


%make_install


%files
%defattr(0755,root,root,-)
/usr/lib/cups/backend/boomaga
/usr/lib/cups/filter/boomaga_pstopdf
/usr/local/bin/boomaga
/usr/local/lib/boomaga/boomagabackend
/usr/local/lib/boomaga/boomagamerger
/usr/local/share/applications/boomaga.desktop
/usr/local/share/boomaga/translations/boomaga_cs.qm
/usr/local/share/boomaga/translations/boomaga_de.qm
/usr/local/share/boomaga/translations/boomaga_el.qm
/usr/local/share/boomaga/translations/boomaga_fr.qm
/usr/local/share/boomaga/translations/boomaga_it.qm
/usr/local/share/boomaga/translations/boomaga_lt.qm
/usr/local/share/boomaga/translations/boomaga_pl_PL.qm
/usr/local/share/boomaga/translations/boomaga_ru.qm
/usr/local/share/boomaga/translations/boomaga_uz@Latn.qm
/usr/local/share/dbus-1/services/org.boomaga.service
/usr/local/share/icons/hicolor/128x128/apps/boomaga.png
/usr/local/share/icons/hicolor/16x16/apps/boomaga.png
/usr/local/share/icons/hicolor/32x32/apps/boomaga.png
/usr/local/share/icons/hicolor/64x64/apps/boomaga.png
/usr/local/share/mime/packages/boomaga.xml
/usr/share/ppd/boomaga/boomaga.ppd
%attr(0644,root,root)
%doc
/usr/local/share/man/man1/boomaga.1.gz


%changelog
* Mon Jun 22 2015 Oleg
- 
Всё, что идёт после знака процента является макросом (например, %build) или предопределённым значением (например, %{name}). Как сказано в документации Fedora, перечень и описание всех макросов можно найти в каталогах:
  • /etc/rpm/*
  • /usr/lib/rpm
  • /usr/lib/rpm/macros
Много полезной информации можно почерпнуть, выполнив команду

rpm --showrc
Прокомментирую указанные значения.
Параметр Name должен совпадать с именем SPEC файла и названием программы (указывается без номера версии).
Параметр Source0 должен по-хорошему указывать на архив в интернете, который имеет такое же название, как и файл в каталоге ~/rpmbuild/SOURCES, но т.к. ссылки на boomaga-0.7.0.tar.gz в интернете я не нашёл, то указал локальную ссылку. Без пути. Только название файла и с использованием переменных (берутся из указанных выше одноимённых параметров).
Перед тем, как пытаться собрать RPM пакет, я пробовал скомпилировать программу обычным образом. Для этого понадобилось установить инструмент cmake и зависимости данной программы: cups-devel, poppler-devel, poppler-cpp-devel, qt5-qtbase-devel, qt5-qttools-devel, snappy-devel. Все эти пакеты я указал в параметре BuildRequires.
Т.к. boomaga может работать в роли виртуального принтера как прослойка между CUPS, то я указал cups в параметре Requires.
Далее идут макросы, которые будут выполняться при сборке RPM пакета.
После макроса %description делаем переход на новую строку и вставляем описание из родного сайта проекта.
Макрос %setup -q распаковывает исходные коды в каталог ~/rpmbuild/BUILD/%{name}-%{version}, т.е. в нашем случае - ~/rpmbuild/BUILD/boomaga-0.7.0
Далее начинается самое ответственное. Нужно описать всё для автоматической компиляции проекта. Я поступил так. Открыл официальную инструкцию по установке данного приложения и переделал под текущую ситуацию. Инструкция по установке оказалась весьма лаконичной и понятной:

mkdir ~/boomaga/build
cd ~/boomaga/build
cmake ..
make && sudo make install
В форме макросов в SPEC файле эти инструкции выразились так:

%build
mkdir build
cd build
cmake ..


%make_install
Первый макрос %build отвечает за сборку исходников. В этой фазе создаём каталог build в текущем каталоге (т.е. в ~/rpmbuild/BUILD/boomaga-0.7.0) и перемещаемся в него. Потом запуск cmake для генерации Makefile. Т.е. всё то, что написано в инструкции по обычной установке данной программы.
Затем макрос %make_install собирёт всё каталоге в ~/rpmbuild/BUILDROOT/boomaga-0.7.0-1.fc21.R.x86_64 так, как если бы шла нормальная установка. Т.е. там создаётся каталог usr со всеми задействованными подкаталогами.
Операции макросов %files (тут нужно указать список всех файлов, входящих в RPM пакет) и %doc (вся документация) заполнил в соответствии с подсказками после первых неудачных запусков, - при сборке пакета выводилось сообщение:

Processing files: boomaga-debuginfo-0.7.0-1.fc21.R.x86_64
Проверка на неупакованный(е) файл(ы): /usr/lib/rpm/check-files /home/oleg/rpmbuild/BUILDROOT/boomaga-0.7.0-1.fc21.R.x86_64
ошибка: Обнаружен(ы) установленный(е) (но не упакованный(е)) файл(ы):
   /usr/lib/cups/backend/boomaga
   /usr/lib/cups/filter/boomaga_pstopdf
   /usr/local/bin/boomaga
   /usr/local/lib/boomaga/boomagabackend
   /usr/local/lib/boomaga/boomagamerger
   /usr/local/share/applications/boomaga.desktop
   /usr/local/share/boomaga/translations/boomaga_cs.qm
   /usr/local/share/boomaga/translations/boomaga_de.qm
   /usr/local/share/boomaga/translations/boomaga_el.qm
   /usr/local/share/boomaga/translations/boomaga_fr.qm
   /usr/local/share/boomaga/translations/boomaga_it.qm
   /usr/local/share/boomaga/translations/boomaga_lt.qm
   /usr/local/share/boomaga/translations/boomaga_pl_PL.qm
   /usr/local/share/boomaga/translations/boomaga_ru.qm
   /usr/local/share/boomaga/translations/boomaga_uz@Latn.qm
   /usr/local/share/dbus-1/services/org.boomaga.service
   /usr/local/share/icons/hicolor/128x128/apps/boomaga.png
   /usr/local/share/icons/hicolor/16x16/apps/boomaga.png
   /usr/local/share/icons/hicolor/32x32/apps/boomaga.png
   /usr/local/share/icons/hicolor/64x64/apps/boomaga.png
   /usr/local/share/man/man1/boomaga.1.gz
   /usr/local/share/mime/packages/boomaga.xml
   /usr/share/ppd/boomaga/boomaga.ppd


Ошибки сборки пакетов:
    Обнаружен(ы) установленный(е) (но не упакованный(е)) файл(ы):
   /usr/lib/cups/backend/boomaga
   /usr/lib/cups/filter/boomaga_pstopdf
   /usr/local/bin/boomaga
   /usr/local/lib/boomaga/boomagabackend
   /usr/local/lib/boomaga/boomagamerger
   /usr/local/share/applications/boomaga.desktop
   /usr/local/share/boomaga/translations/boomaga_cs.qm
   /usr/local/share/boomaga/translations/boomaga_de.qm
   /usr/local/share/boomaga/translations/boomaga_el.qm
   /usr/local/share/boomaga/translations/boomaga_fr.qm
   /usr/local/share/boomaga/translations/boomaga_it.qm
   /usr/local/share/boomaga/translations/boomaga_lt.qm
   /usr/local/share/boomaga/translations/boomaga_pl_PL.qm
   /usr/local/share/boomaga/translations/boomaga_ru.qm
   /usr/local/share/boomaga/translations/boomaga_uz@Latn.qm
   /usr/local/share/dbus-1/services/org.boomaga.service
   /usr/local/share/icons/hicolor/128x128/apps/boomaga.png
   /usr/local/share/icons/hicolor/16x16/apps/boomaga.png
   /usr/local/share/icons/hicolor/32x32/apps/boomaga.png
   /usr/local/share/icons/hicolor/64x64/apps/boomaga.png
   /usr/local/share/man/man1/boomaga.1.gz
   /usr/local/share/mime/packages/boomaga.xml
   /usr/share/ppd/boomaga/boomaga.ppd
В результате успешной сборки формируются RPM пакеты:
~/rpmbuild/RPMS/x86_64/boomaga-0.7.0-1.fc21.R.x86_64.rpm
~/rpmbuild/RPMS/x86_64/boomaga-debuginfo-0.7.0-1.fc21.R.x86_64.rpm
~/rpmbuild/SRPMS/boomaga-0.7.0-1.fc21.R.src.rpm
А вот, собственно, как запускать сборку:

rpmbuild --target=x86_64 -ba ~/rpmbuild/SPECS/boomaga.spec
Команда отрабатывает за пару минут. В это время в консоли пролетают красивые разноцветные строчки.
Позже, когда дистрибутив Fedora обновится до следующей версии, можно будет попробовать перепаковать пакет boomaga-0.7.0-1.fc21.R.src.rpm такой командой:

rpmbuild --rebuild boomaga-0.7.0-1.fc21.R.src.rpm
Теоретически это позволит сократить время сборки RPM пакета.
Для проверки SPEC файла и формируемого пакета можно перейти в каталог ~/rpmbuild/SPEC и воспользоваться командой:

rpmlint boomaga.spec ../SRPMS/boomaga* ../RPMS/*/boomaga*
В результате будут показаны различные предупреждения и ошибки. В моём случае есть ошибки расположения файлов. Но для личного пользования подойдёт и так. Хотя с такими ошибками в официальные репозитории не пропустят.
Посмотреть описание ошибки можно, указав её название после ключа -I в следующей команде:

rpmlint -I hardcoded-library-path

Полезные ссылки

Различных параметров и макросов существует довольно много. В официальной документации Fedora есть исчерпывающие полезные и обширные материалы "How to create an RPM package" и "Packaging:Guidelines". Также есть пример с пояснениями SPEC файла в материале "Annotated spec file".

Делаем RPM лучше 

Чтобы полученный RPM пакет не только выполнял свою функцию, но и делал это правильно, нужно избавиться от всех ошибок, на которые указывает rpmlint.
Основная ошибка состоит в том, что полученные файлы в системе устанавливаются не туда, куда положено. Во-первых, всё должно соответствовать стандарту Filesystem Hierarchy Standard, который недавно обновился. Во-вторых RPM пакет для Fedora должен соответствовать правилам этого дистрибутива.
Нужно избавиться от жёстко прописанных путей в секции %files. Для этого применяются макросы. В моём случае исходный код программы в нескольких местах имел жёстко прописанный путь в подкаталог lib, а для архитектуры x86_64 нужно было указывать lib64. Поэтому потребовалось немного подкорректировать исходный код программы.
В результате общения с разработчиками программы на github.com, SPEC файл пополнился также автоматическим прописыванием принтера в системе. Плюс программа Boomaga успела обновиться до версии 0.7.1. Результирующий SPEC файл:

Name:           boomaga
Version:        0.7.1
Release:        1%{?dist}
Summary:        A virtual printer for viewing a document before printing
License:        GPLv2 and LGPLv2+
URL:            http://boomaga.github.io
Source0:        %{name}-%{version}.tar.gz

BuildRequires:  cmake,cups-devel,poppler-devel,poppler-cpp-devel,qt5-qtbase-devel,qt5-qttools-devel,snappy-devel
Requires:       cups,snappy

%description
Boomaga (BOOklet MAnager) is a virtual printer for viewing a document
before printing it out using the physical printer.
The program is very simple to work with.
Running any program, click “print” and select “Boomaga” to see in several
seconds (CUPS takes some time to respond) the Boomaga window open.
If you print out one more document,
it gets added to the previous one, and you can also print them out as one,
and you can also print them out as one.
Regardless of whether your printer supports duplex printing or not,
you would be able to easily print on both sides of the sheet.
If your printer does not support duplex printing,
point this out in the settings, and Booklet would ask you to turn
over the pages half way through printing your document.
The program can also help you get your documents prepared a bit
before printing. At this stage Boomaga makes it possible to:
* Paste several documents together.
* Print several pages on one sheet.
* 1, 2, 4, 8 pages per sheet
* Booklet. Folding the sheets in two, you’ll get a book.

%prep
%setup -q


%build
%ifarch x86_64
  %cmake -DLIB_SUFFIX=64 -DCUPS_BACKEND_DIR=%{_libdir}/cups/backend -DCUPS_FILTER_DIR=%{_libdir}/cups/filter .
%else
  %cmake -DCUPS_BACKEND_DIR=%{_libdir}/cups/backend -DCUPS_FILTER_DIR=%{_libdir}/cups/filter .
%endif
make %{?_smp_mflags}

%install
make install DESTDIR=%{buildroot}


%__mkdir -p %{buildroot}%{_datadir}/%{name}/scripts
%__install -m 755 scripts/installPrinter.sh %{buildroot}%{_datadir}/%{name}/scripts/
chmod +x %{buildroot}%{_datadir}/%{name}/scripts/installPrinter.sh

# Add translation lang tags
(cd %{buildroot} && find . -name '*.qm') | %__sed -e 's|^.||' | sed -e \
's:\(.*/translations/boomaga_\)\([a-z_A-Z]\+\)\(.*qm$\):%lang(\2) \1\2\3:'\
>> %{name}.lang

%pre
# Start cups if is stopped
if [ "$(systemctl is-active cups.service)" != "active" ]; then
  systemctl start cups
  sleep 2
fi

%post
# Install the printer to cups backends
if [ $1 = 1 ]; then
  sh %{_datadir}/%{name}/scripts/installPrinter.sh
fi

%preun
# Uninstall the printer
lpadmin -x "Boomaga"


%files
%defattr(755,root,root,-)
%{_libdir}/cups/backend/%{name}
%defattr(-,root,root,-)
%{_libdir}/cups/filter/boomaga_pstopdf
%{_bindir}/%{name}
%{_libdir}/%{name}/boomagabackend
%{_libdir}/%{name}/boomagamerger
%{_datadir}/applications/boomaga.desktop
%{_datadir}/%{name}/translations/*
%{_datadir}/dbus-1/services/org.boomaga.service
%{_datadir}/icons/hicolor/*
%{_datadir}/mime/packages/boomaga.xml
%{_datadir}/ppd/%{name}/boomaga.ppd
%{_datadir}/%{name}/scripts/installPrinter.sh

%doc COPYING GPL LGPL README.md
%{_mandir}/man1/boomaga.1.gz


%changelog
* Tue Jun 30 2015 Oleg Ekhlakov <subspam@mail.ru> 0.7.1-1.fc21.R
- Initial version of the package

Комментарии

Популярные сообщения из этого блога

Пропорциональное распределение суммы

Битрикс: своя геолокация

Bitrix24 API - разбор демо приложения третьего типа