- How to create a Linux RPM package
- More about automation
- What is an RPM package?
- How to create an RPM package
- Installing the required software
- Place the script in the designated directory
- Create a .spec file
- Checking the .spec file on error (rpmlint)
- Building the package (rpmbuild)
- Installing the RPM package
- Verify the package has been installed
- See what’s in the RPM package
- Removing the RPM package
- Сборка пакетов библиотек для rpm-based дистрибутивов Linux
- Перед сборкой пакета
- spec-файл для сборки пакета
- Сборка
- Пара советов
How to create a Linux RPM package
Photo by Ketut Subiyanto from Pexels
This article shows you how to package a script into an RPM file for easy installation, updating, and removal from your Linux systems. Before I jump into the details, I’ll explain what an RPM package is, and how you can install, query, remove, and, most importantly, create one yourself.
This article covers:
- What an RPM package is.
- How to create an RPM package.
- How to install, query, and remove an RPM package.
More about automation
What is an RPM package?
RPM stands for Red Hat Package Manager. It was developed by Red Hat and is primarily used on Red Hat-based Linux operating systems (Fedora, CentOS, RHEL, etc.).
An RPM package uses the .rpm extension and is a bundle (a collection) of different files. It can contain the following:
- Binary files, also known as executables ( nmap , stat , xattr , ssh , sshd , and so on).
- Configuration files ( sshd.conf , updatedb.conf , logrotate.conf , etc.).
- Documentation files ( README , TODO , AUTHOR , etc.).
The name of an RPM package follows this format:
Some packages also include a shorthand version of the distribution they were built for, such as:
How to create an RPM package
You’ll need the following components to build an RPM package:
- A workstation or a virtual machine running an RPM-based distribution, such RHEL or Fedora.
- Software to build the package.
- Source code to package.
- SPEC file to build the RPM.
Installing the required software
The following packages need to be installed to build the RPM package:
After installing rpmdevtools , create the file tree you need to build RPM packages:
You build RPM packages as a normal (not root) user, so your build environment is placed into your home directory. It contains this directory structure:
- The BUILD directory is used during the build process of the RPM package. This is where the temporary files are stored, moved around, etc.
- The RPMS directory holds RPM packages built for different architectures and noarch if specified in .spec file or during the build.
- The SOURCES directory, as the name implies, holds sources. This can be a simple script, a complex C project that needs to be compiled, a pre-compiled program, etc. Usually, the sources are compressed as .tar.gz or .tgz files.
- The SPEC directory contains the .spec files. The .spec file defines how a package is built. More on that later.
- The SRPMS directory holds the .src.rpm packages. A Source RPM package doesn’t belong to an architecture or distribution. The actual .rpm package build is based on the .src.rpm package.
A .src.rpm package is very flexible, because it can be built and re-built on every other RPM-based distribution and architecture.
You’re now familiar with what each directory holds, so now create a simple script to distribute:
This creates a shell script called hello.sh , which prints «Hello world» to the terminal. It’s simple, but it’s enough to demonstrate packaging.
Place the script in the designated directory
To build a package for your script, you must put your script in the directory that the RPM build system expects it to be in. Create a directory for it, using semantic versioning as most projects do, and then move hello.sh into it:
Most source code is distributed as an archive, so use the tar command to create an archive file:
Then move the tarball you’ve just created into the SOURCES directory:
Create a .spec file
An RPM package is defined by a .spec file. The syntax of a .spec file is strict, but rpmdev can generate a boilerplate file for you:
This generates a file called hello.spec , which you must move to the SPECS directory. Run tree
/rpmbuild to see what the directory structure looks like:
The generated hello.spec file provides a good starting point, but it doesn’t have any specific information about what you’re building. The generated .spec file assumes that I am going to compile and build software.
You’re packaging a Bash script, so there’s some simplification you can do. For instance, there’s no Build process because there’s no code to compile. I’ve added BuildArch: noarch because this package is valid for 32-bit, 64-bit, Arm, and any other CPU architecture that runs Bash.
I’ve also added Requires: bash so that the package ensures that Bash is installed. This simple «hello world» script runs on any shell, of course, but that’s not true for all scripts, so this is a good way to demonstrate dependencies.
As you can tell, there are a lot of shortcuts in .spec files. They’re called macros, and there’s an excellent list of what’s available in the Fedora packaging documentation. It’s important to use macros in your .spec files. They help ensure consistency across all RPM systems, they help you avoid mistakes in filenames and version numbering, and they make it easier to update the .spec file when you release a new version of your script.
For example, it’s required that you specify exactly which files are installed under the %files section. Here I’ve explicitly put the following line:
This works because I want the script to go to % (which is a macro that translates to /usr/bin by default, but is configurable when users want to install to a different location, such as /usr/local/bin ). You can verify macro values by running:
Other useful macros:
- %
name of the package (as defined in the Name: field) - %
version of the package (as defined in the Version: field) - % <_datadir>shared data ( /usr/sbin by default)
- % <_sysconfdir>configuration directory ( /etc by default)
Checking the .spec file on error (rpmlint)
The rpmlint command can find errors in .spec files:
There are 2 errors reported, but they’re both acceptable. There’s no code to build, so there’s no need for a %build section, and the source archive is a local file and has no network URL.
Everything looks good.
Building the package (rpmbuild)
To build the RPM package, use the rpmbuild command. Earlier in this tutorial, I mentioned the difference between the .src.rpm (Source RPM package) and the .rpm package.
To create the .src rpm package:
The flags -bs have the following meanings:
To create the binary .rpm package:
The flags -bb have the following meanings:
Use -ba to build both.
After the build process is finished, you have the following directory structure:
Installing the RPM package
After a successful build of the package, you can install the RPM package using the dnf command:
It can alternately be installed with the rpm command directly:
Verify the package has been installed
To verify the package has correctly been installed, run the following command:
The %changelog entry of a package can be viewed, too:
See what’s in the RPM package
It’s easy to see which files an RPM package contains:
Removing the RPM package
Removing the package from the system is just as easy as installing it. You can use the dnf command:
Источник
Сборка пакетов библиотек для rpm-based дистрибутивов Linux
Во многих наших проектах используются open-source библиотеки. Когда разработка ведется под одну конкретную платформу, нет смысла собирать одни и те же библиотеки из исходников каждый раз, когда к проекту подключается новый разработчик. Кроме того, установка библиотек а-ля make && sudo make install считается плохим тоном, поскольку система засоряется «бесхозными» файлами, о которых нет информации в базе данных менеджера пакетов RPM.
В качестве решения предлагается из скомпилированных библиотек собирать RPM-пакеты и хранить их в едином репозитории, доступном для всех разработчиков. Ниже приводится инструкция и некоторые советы по сборке пакетов.
Инструкция будет основываться на примере Red Hat Enterprise Linux 6, но с небольшими изменениями ее можно будет адаптировать и для других дистрибутивов. Для примера будем собирать пакет из библиотеки zeromq.
Перед сборкой пакета
Первое, что нужно сделать перед сборкой — убедиться, что нужный вам пакет не собрал кто-то до вас. Часто на таких ресурсах, как rpmfind.net и rpm.pbone.net можно найти то, что вам нужно. Но если не нашлось необходимой версии библиотеки или нет сборки под вашу платформу, то придется собирать пакет самому.
rpmbuild
Создаем файл конфигурации утилиты rpmbuild, чтобы она узнала, где находится созданное дерево каталогов:
rpmbuild при запуске будет искать файлы пакета в директории
/rpmbuild/BUILDROOT/ . Разберемся, как именуются RPM-пакеты, на примере zeromq:
Здесь:
- zeromq — собственно, имя пакетируемого ПО;
- 3.2.4 — версия ПО;
- 1.rhel6 — номер сборки пакета (release number) — сколько раз данная версия ПО собиралась в rpm-пакет. Суффиксом rhel6 или el6 обычно обладают пакеты для Red Hat Enterprise Linux 6;
- x86_64 — процессорная архитектура, под которую скомпилировано ПО.
Обратите внимание на знаки, разделяющие поля имени пакета. Они должны быть именно такими, как в примере.
Итак, создаем директорию для zeromq в BUILDROOT:
Сборка библиотеки
Само собой, перед сборкой бинарного пакета, нужно скомпилировать саму библиотеку. Если библиотека использует систему сборки GNU Autotools, то обычно это делается командами:
Теперь устанавливаем библиотеку в созданную нами директорию в BUILDROOT:
Параметр DESTDIR не всегда обрабатывается в мейкфайлах. Например, qmake генерирует мейкфайлы, которые игнорируют этот параметр. Если библиотека использует систему сборки, отличную от GNU Autotools, то прочитайте в соответствующем руководстве, какие параметры нужно передать при сборке, чтобы установить библиотеку в указанную директорию.
spec-файл для сборки пакета
/rpmbuild/SPECS. Рассмотрим пример файла zmq.spec для библиотеки zeromq:
В начале файла указывается минимальный набор полей с информацией о пакете. Из значений первых трех полей (Name, Version, Release) формируется имя пакета, поэтому важно, чтобы там были указаны правильные значения. Если значения не будут соответствовать имени каталога с деревом файлов собираемого пакета, rpmbuild выдаст ошибку. Поле License также является обязательным — без него rpmbuild откажется собирать пакет.
Назначение секции %description очевидно. Секции %post и %postun содержат скрипты, выполняющиеся после установки файлов пакета в систему и после удаления файлов пакета из системы, соответственно. Это полезно, если пакет устанавливает динамические библиотеки (.so) в нестандартные директории (т. е. не в /lib, /usr/lib, /lib64 или /usr/lib64). В этом случае пакет должен предоставлять файл конфигурации для ldconfig и устанавливать его в /etc/ld.so.conf.d. Команда ldconfig обновляет кэш динамического загрузчика, добавляя в него все библиотеки, найденные в директориях, указанных в конфигурационных файлах.
В секции %files указывается список файлов, которые пакуются в rpm. Директива %defattr указывает атрибуты файлов по умолчанию в формате:
указывается в восьмеричном виде, например, «644» для rw-r—r—. Атрибут может быть опущен. Вместо атрибутов, которые не должны меняться для устанавливаемых файлов, можно указать дефис. Директории, указанные в секции %files, будут внесены в пакет вместе со всем их содержимым.
Дальше самое интересное. Фактически существует два типа RPM-пакетов библиотек. В одних находятся собственно сами файлы динамических библиотек, необходимые для работы программ, которые скомпонованы с этими библиотеками. Например, пакет zeromq-3.2.4-1.rhel6.x86_64.rpm предоставляет только два файла: /usr/lib64/libzmq.so.3.0.0 и символьную ссылку на него, /usr/lib64/libzmq.so.3. Другой тип пакетов содержит файлы, необходимые для разработки приложений с использованием предоставляемой библиотеки. К имени таких пакетов добавляется суффикс «-devel», например, zeromq-devel-3.2.4-1.el6.x86_64.rpm. В таких пакетах обычно содержатся заголовочные файлы C/C++, документация, статические библиотеки (.a), и эти пакеты являются зависимыми от пакетов первого типа.
В приведенном выше spec-файле директива %package позволяет собрать «дочерний» пакет одним запуском rpmbuild. Значения полей заголовков дочернего пакета наследуются от родительского, но их можно переопределить. Поле Requires задает дополнительную зависимость от родительского пакета. Заметьте, что секция %files пакета zeromq-devel содержит файл /usr/lib64/libzmq.so. Это символьная ссылка на настоящий файл с динамической библиотекой. Он необходим компоновщику ld на этапе сборки приложения с использованием библиотеки, поскольку он ищет файлы динамических библиотек, начинающиеся на «lib» и заканчивающиеся на «.so».
Сборка
Перед сборкой нужно иметь в виду две вещи.
Первое: при успешной сборке пакета rpmbuild очистит директорию BUILDROOT. Так что на всякий случай сделайте резервную копию пакетируемых файлов.
Второе: никогда не собирайте пакеты с правами root. Здесь объясняется, почему так нельзя делать.
Теперь все готово для сборки пакета. Запускаем rpmbuild:
Параметр -bb означает «build binary», то есть, собрать бинарный пакет. Помимо бинарных пакетов есть еще пакеты исходных кодов, но они здесь не обсуждаются.
В случае успеха полученный rpm-пакет будет сохранен в папке RPMS.
Пара советов
Если не знаете, что писать в полях заголовка spec-файла для пакетируемой библиотеки, можно взять RPM-пакет для другого дистрибутива c указанных выше ресурсов и посмотреть, что пишут там:
Здесь «q» означает «режим запросов (query)», «i» — получение информации о пакете, «p» — получение информации об указанном файле пакета (без этой опции будет получена информация о пакете, установленном в системе, если он установлен).
Если не знаете, какие файлы принадлежат пакету devel, а какие — пакету с библиотеками, но у вас есть оба пакета для другого дистрибутива, можно распаковать дерево файлов, предоставляемых данным пакетом, в текущую директорию:
Утилита rpm2cpio пишет в стандартный вывод cpio-архив, хранящийся в rpm-пакете; утилита cpio распаковывает архив, принятый из стандартного ввода. Параметр «i» включает режим распаковки, а «d» создает нужные директории.
Посмотреть, какие файлы предоставляет пакет, можно и не распаковывая его, с помощью опции «l»:
Источник