Создание RPM-пакетов с нуля

Thank you for reading this post, don't forget to subscribe!

Для рабо­ты по сбор­ке паке­тов луч­ше исполь­зо­вать отдель­ный ком­пью­тер, вир­ту­аль­ную маши­ну или кон­тей­нер Docker.

1. Уста­но­вим пакеты:

yum install rpmdevtools rpmlint

* где:

  • rpmdevtools — поз­во­лит нам исполь­зо­вать ути­ли­ту rpmdev-setuptree, с помо­щью кото­рой мы смо­жем создать рабо­чую сре­ду в виде ката­ло­гов для сборки.
  • rpmlint — поз­во­ля­ет про­те­сти­ро­вать пакет RPM.

А так­же ставим:

yum group install "Development Tools"

* дан­ная груп­па паке­тов вклю­ча­ет все необ­хо­ди­мое для сбор­ки. Ее не реко­мен­ду­ет­ся ста­вить на рабо­чий ком­пью­тер, так как уста­нав­ли­ва­ет­ся мно­го ненуж­но­го для стан­дарт­ной систе­мы мусора.

2. Созда­ем пользователя.

Делать гото­вые уста­но­воч­ные сбор­ки паке­тов очень опас­но от поль­зо­ва­те­ля root. Если мы допу­стим ошиб­ку с путя­ми, фай­лы могут пере­те­реть или уда­лить важ­ные для рабо­ты дирек­то­рии. Сто­ит создать отдель­но­го поль­зо­ва­те­ля и рабо­тать под ним. Одна­ко, если мы рабо­та­ем в вир­ту­аль­ной сре­де или кон­тей­не­ре Docker, нам это не страш­но. Тогда дан­ный пункт мож­но про­пу­стить и рабо­тать из под root.

Выпол­ня­ем команду:

useradd builder -m

* в дан­ном при­ме­ре мы созда­дим поль­зо­ва­те­ля builder. Опция -m сра­зу создаст домаш­ний ката­лог для пользователя.

Теперь захо­дим под дан­ным поль­зо­ва­те­лем — после­ду­ю­щие коман­ды мы будем выпол­нять от него:

su - builder

3. Созда­дим струк­ту­ру ката­ло­гов для сборки:

rpmdev-setuptree

В нашей теку­щем ката­ло­ге долж­на появить­ся пап­ка rpmbuild — а в ней:

  1. BUILD содер­жит все фай­лы, кото­рые появ­ля­ют­ся при созда­нии пакета.
  2. RPMS сюда будут скла­ды­вать­ся гото­вые пакеты.
  3. SOURCES для исход­ни­ков, из кото­рых и будут соби­рать­ся RPM-пакеты.
  4. SPECS для фай­лов с опи­са­ни­ем про­цес­са сборки.
  5. SRPMS — для исход­ни­ков RPM-файлов.

Мы гото­вы к сборке.

Сборка из исходников

Рас­смот­рим при­мер созда­ния RPM из паке­та, кото­рый нуж­но соби­рать из исход­ни­ков с помо­щью коман­ды make. Напри­мер, возь­мем дан­ную про­грам­му: github.com/brettlaforge/pg_redis_pubsub.

Созда­дим файл spec:

rpmdev-newspec rpmbuild/SPECS/pg_redis_pubsub.spec

Теперь откро­ем его и при­ве­дем к виду:

vi rpmbuild/SPECS/pg_redis_pubsub.spec

* что­бы понять, как запол­нить spec-файл, реко­мен­ду­ет­ся для нача­ла собрать и уста­но­вить при­ло­же­ние вруч­ную с помо­щью make и make install. Так­же необ­хо­ди­мо изу­чить доку­мен­та­цию уста­нав­ли­ва­е­мо­го паке­та или (при нали­чие воз­мож­но­сти) пого­во­рить с раз­ра­бот­чи­ка­ми про­грамм­но­го обеспечения.

Уста­но­вим зави­си­мо­сти, кото­рые необ­хо­ди­мы для сбор­ки (BuildRequires). В дан­ном при­ме­ре это:

yum install epel-release

yum install postgresql-devel postgresql-server-devel hiredis-devel

* кон­крет­но, в моем при­ме­ре для уста­нов­ки hiredis-devel необ­хо­ди­мо поста­вить репо­зи­то­рий epel-release. Спи­сок паке­тов, необ­хо­ди­мый для сбор­ки кон­крет­но­го паке­та необ­хо­ди­мо уточ­нить в документации.

Теперь копи­ру­ем исход­ник на свой ком­пью­тер. В моем при­ме­ре кло­ни­ру­ем репозиторий:

git clone https://github.com/brettlaforge/pg_redis_pubsub.git

Гото­вим архив и поме­ща­ем его в ката­лог rpmbuild/SOURCES:

tar -czvf rpmbuild/SOURCES/pg_redis_pubsub-1.0.2.tar.gz pg_redis_pubsub

Про­ве­ря­ем кор­рект­ность SPEC-файла:

rpmlint rpmbuild/SPECS/pg_redis_pubsub.spec

В моем при­ме­ре коман­да вер­ну­ла ответ:

rpmbuild/SPECS/pg_redis_pubsub.spec: W: invalid-url Source0: pg_redis_pubsub-1.0.2.tar.gz
0 packages and 1 specfiles checked; 0 errors, 1 warnings.

Дан­ное пре­ду­пре­жде­ние мож­но проигнорировать.

Выпол­ня­ем сборку:

rpmbuild -bb rpmbuild/SPECS/pg_redis_pubsub.spec

Если она прой­дет без оши­бок, мы долж­ны най­ти RPM-пакет в ката­ло­ге rpmbuild/RPMS/x86_64, где x86_64 — архи­тек­ту­ра пакета.

Описание файла SPEC

Дан­ный файл явля­ет­ся инструк­ци­ей по сбор­ке паке­та. В нем мы опи­сы­ва­ем сам пакет, зада­ем мета­дан­ные и ука­зы­ва­ем, как извле­кать фай­лы и куда их копи­ро­вать при уста­нов­ке паке­та. Син­так­сис фай­ла вклю­ча­ет такие эле­мен­ты, как раз­де­лы, мак­ро­сы, опе­ра­то­ры, опции. Рас­смот­рим их отдельно.

Опции заголовка

Опре­де­ля­ют опи­са­ние паке­та, а так­же неко­то­рые важ­ные для сбор­ки параметры.

Опция Опи­са­ние При­мер
Name Назва­ние для паке­та RPM pg_redis_pubsub
Version Вер­сия соби­ра­е­мо­го пакета 1.0.2
Release Релиз или вер­сия программы 1%{?dist}
?dist обо­зна­че­ние вер­сии доработки
Summary Крат­кое опи­са­ние пакета Redis Publish from PostgreSQL
License Спо­соб лицензирования X11 License
URL Адрес источ­ни­ка пакета https://github.com/brettlaforge/pg_redis_pubsub
Source0 Источ­ник дан­ных, из кото­рых дол­жен соби­рать­ся пакет.
Мож­но ука­зать несколь­ко источ­ни­ков: Source1, Source2 … SourceN
%{name}-%{version}.tar.gz
Дан­ная запись озна­ча­ет, что сбор­щик будет искать архив
pg_redis_pubsub-1.0.2.tar.gz в ката­ло­ге rpmbuild/SOURCES/
BuildRequires Тре­бо­ва­ния к паке­там, кото­рые нуж­ны для сбор­ки пакета.
Мож­но напи­сать боль­шим спис­ком, а мож­но доба­вить несколь­ко отдель­ных строк BuildRequires.
Так­же мы можем задать тре­бо­ва­ние к вер­сии пакета.
postgresql-devel postgresql-server-devel hiredis-devel
Requires Тре­бо­ва­ния к паке­там, кото­рые нуж­ны для уста­нов­ки собран­но­го пакета.
Мож­но напи­сать боль­шим спис­ком, а мож­но доба­вить несколь­ко отдель­ных строк Requires.
Так­же мы можем задать тре­бо­ва­ние к вер­сии пакета.
hiredis >= 0.13.3-1

Разделы (теги)

В каж­дом раз­де­ле опи­сы­ва­ет­ся своя часть логи­ки про­цес­са сбор­ки пакета.

Раз­дел Опи­са­ние
%description Опи­са­ние паке­та. Может состо­ять из несколь­ких строк, но каж­дая стро­ка долж­на содер­жать до 73 символов.
%prep Пред­ва­ри­тель­ная обра­бот­ка. Исполь­зу­ет­ся для под­го­тов­ки исход­ни­ков. Как пра­ви­ло, в дан­ном раз­де­ле про­ис­хо­дит их рас­па­ков­ка. Так­же на дан­ном эта­пе могут при­ме­нять­ся патчи.
%build Этап сбор­ки паке­та. Как пра­ви­ло, это make.
%install Уста­нов­ка паке­та. Это может быть make install или копи­ро­ва­ние кон­крет­ных фай­лов в кон­крет­ные дирек­то­рии или запуск про­из­воль­но­го скрипта.
%clean Раз­дел содер­жит инструк­ции по уда­ле­нию уста­рев­ших фай­лов, кото­рые боль­ше не нужны.
%files Пере­чис­ля­ем фай­лы, кото­рые долж­ны попасть в конеч­ную систе­му при уста­нов­ке пакета.
%changelog Спи­сок изме­не­ний в рабо­те про­грамм­но­го обеспечения.

Макросы для команд

Неко­то­рые систем­ные коман­ды луч­ше писать не напря­мую, а через мак­ро­сы. Это поз­во­лит добить­ся боль­шей ста­биль­но­сти при сбор­ке на раз­лич­ных систе­мах. При­ве­дем в при­мер дан­ные команды:

Мак­рос Коман­да Опи­са­ние
%{__rm} rm Уда­ле­ние файлов
%{__mv} mv Пере­нос файлов
%{__tar} tar Рас­па­ков­ка или созда­ние архивов

* пол­ный спи­сок мак­ро­сов мож­но полу­чить коман­дой rpm --showrc.

Макросы для каталогов

Ката­ло­ги луч­ше писать не бук­валь­но, а через макросы:

Мак­рос Путь
%{_prefix} /usr
%{_libdir} %{_prefix}/lib64
%{_datarootdir} %{_prefix}/share
%{_datadir} %{_datarootdir}

* обра­ти­те вни­ма­ние, что неко­то­рые мак­ро­сы ведут не на кон­крет­ные пути, а на дру­гие макросы.
* пол­ный спи­сок мак­ро­сов мож­но полу­чить коман­дой rpm --showrc.

Операторы сравнения

SPEC файл поз­во­ля­ет зада­вать логи­ку с помо­щью опе­ра­то­ров срав­не­ния. При­ве­дем при­ме­ры их использования:

При­мер Опи­са­ние
%if 0%{?rhel} < 8
Requires:       hiredis-last >= 0.13.3-1
%else
Requires:       hiredis
%endif
В дан­ном при­ме­ре мы про­ве­ря­ем вер­сию систе­мы, на кото­рой идет сбор­ка. Если rhel (релиз систе­мы) мень­ше 8, то мы ука­зы­ва­ем в каче­стве тре­бо­ва­ния hiredis-last. В дан­ном при­ме­ре это име­ет смысл, так как в CentOS 8 пакет hiredis-last пере­име­но­ва­ли в hiredis.