суббота, 31 марта 2012 г.

Hello RPM

Here I'm giving a brief guidance how to create a simplest RPM file for a QT4 based application. If you want this post to be translated to English just contact me and I will do it upon first request with giving you all possible assistance in urgent case. In return I will expect your help with checking it on grammatical mistakes.

В интернете можно найти много литературы по RPM, о формате .spec файла и о том как пользоваться rpmbuild.
В этом посте я приведу краткое руководство о том как создать простейший RPM пакет не углубляясь в детали. Пост будет особенно интересен тем, кому нужно создать RPM для проекта написанного на Qt.
Итак, у меня есть приложение HelloWorld, написанное на QT 4.8 и доступное для загрузки отсюда. Минимальные требования, для сборки проекта - наличие Qt4.8 и qmake (qt и qt-devel пакеты для Fedora Linux соответственно). 
Комментарии к исходникам:
  1. Когда распакуете архив с исходниками обратите внимание что корневая папка называется "helloworld-1.0". Это первый важный момент. "helloworld" - это название приложения и название пакета, который мы сейчас будем создавать. Нужно чтобы название приложения совпадало с названием пакета. "1.0" - это версия нашего продукта. "-" между названием и версией соответствует соглашению о построении полных названий пакетов. Очень важно чтобы корневая папка именовалась как [название приложения/пакета]-[версия приложения]. Без этого вы получите ошибку на стадии %prep при сборке. От пакетов требуется, чтобы все символы названия были в нижнем регистре поэтому позаботьтесь, чтобы исполнителный файл тоже соответствовал этому требованию.
  2. В файле HelloWorld.pro обратите внимание на строчки:  
    unix {
        target.path = /$(DESTDIR)
        INSTALLS += target
    }
    На основании этой строки qmake сгенерируют инструкцию в Makefile для команды "make install". Назначение макроса DESTDIR я поясню позже. Сейчас же обратите внимание, что он начинается с символа "/". Он необходим, инача qmake допишет в Makefile еще и путь к файлу проекта, что приведет к проблемам на фазе %install.
  3. В корневом каталоге лежит скрипт configure который просто вызывает qmake. Этот скрипт будет автоматически вызываться на стадии %prep и его назначение в том, чтобы подготовить Makefile. Именно поэтому я поместил в него вызов qmake. Проследите, чтобы этот скрипт был помечен как исполняемый файл (chmod +x configure)
Для создания и проверки правильности rpm пакетов вам понадобятся rpmdevtools и rpmlint. Устанавливаем их командой
sudo yum install rpmdevtools rpmlint
Теперь создаем дерево сборки командой
rpmdev-setuptree
В результате у вас появится каталог ~/rpmbuild с дочерними каталогами SPECS, SOURCES, RPMS, SRPMS, BUILD и BUILDROOT. Информацию о назначении каталогов вы найдете на rpm.org.  Полученное дерево каталогов вы можете использовать для построения rpm пакетов для произвольных версий любых программних продуктов.

Скопируйте архив с исходниками в ~/rpmbuild/SOURCES.


Теперь переходим к самому главному. Скачайте spec файл перейдя по следующей ссылке (скачать) и положите его в папку ~/rpmbuild/SPECS.
Перейдите в этот каталог (cd ~/rpmbuild/SPECS) и запустите на исполнение команду
rpmbuild -ba helloworld.spec
В результате в папке RPMS (со смещением на текущую архитектуру) будет лежать ваш RPM с бинарниками, а в папке SRPMS - с исходниками и spec файлом. Если вам нужен только RPM с бинарниками замените -ba  на -bb.

Несколько комментариев к spec файлу:
  1. Поле Name содержит имя rpm файла, который будет сгенерирован. Это имя должно совпадать с названием приложения.
  2. Поле Source0 содержит название нашего архива с исходниками
  3. Обратите внимание на строку 
    make install DESTDIR=$RPM_BUILD_ROOT%{_bindir}
    в разделе %install. Помните, что в HelloWorld.pro мы устанавливали target.path в /$(DESTDIR)? Теперь же мы инициализируем эту переменную путем взятым из контекста сборки и передаем ее команде make install, которая в свою очередь создаст такой каталог (он будет находиться по адресу ~/rpmbuild/BUILDROOT/[полное имя пакета]/usr/bin) и скопирует туда собранный исполняемый файл. 
  4. Строка  %{_bindir}/%{name} в разделе %files инструктирует сборщик, что в результирующий RPM необходимо включить файл с именем helloworld (именно в это значение развернется макрос %name) лежащий со смещением usr/bin (значение макроса %_bindir) относительно $RPM_BUILD_ROOT (т.е. ~/rpmbuild/BUILDROOT/[полное имя пакета]). Без этой строки ваш RPM файл останется пустым.
После запуска команды rpm -i helloworld-1.0-1.fc16.x86_64.rpm программа helloworld будет установлена в папку /usr/bin (значение макроса _bindir)

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

Кроме того у описаной процедуры есть недостаток. Если нужно установить несколько файлов из одного пакета в разные места назначения, передача usr/bin через DESTDIR не очень подходит. Возможно лучше было бы захардкодить /usr/bin в  HelloWorld.pro. Другое решение расширить набор входных параметров. В общем тут тоже есь над чем подумать.

Если этот пост был полезен вам, чиркните пару слов. Также буду признателен тем кто будет давать дополнительную полезную информацию на данную тему.

Комментариев нет:

Отправить комментарий