Thank you for reading this post, don't forget to subscribe!
Мы рассмотрим пример работы с исходниками nginx, а также разберем подробнее опции, которые можно задействовать при сборке. На практике, данное действие не имеет смысла, так как уже собранный nginx можно получить на сайте разработчика или в репозитории системы
Подготовка системы
Процесс сборки требует установки дополнительных компонентов, что приводит к скоплению мусора из ненужных пакетов. Рекомендуется делать сборку на отдельном компьютере или в контейнере Docker.
Независимо от среды, в которой мы будем собирать пакеты, необходимо выполнить предварительные настройки.
1. Установка пакетов:
apt-get update
apt-get install dpkg-dev devscripts wget
* где:
- dpkg-dev — содержит набор инструментов для работы с исходными файлами для пакетов deb.
- devscripts — набор скриптов для сборки пакетов.
- wget — утилита для загрузки файлов по http. Нужна для загрузки архивов с исходниками.
2. Создание пользователя.
Делать готовые установочные сборки пакетов очень опасно от пользователя root. Если мы допустим ошибку с путями, файлы могут перетереть или удалить важные для работы директории. Стоит создать отдельного пользователя и работать под ним. Однако, если мы работаем в специальной виртуальной среде или контейнере Docker, нам это не страшно. Тогда данный пункт можно пропустить и работать из-под root.
Выполняем команду:
useradd builder -m
* в данном примере мы создадим пользователя builder. Опция -m сразу создаст домашний каталог для пользователя.
Теперь заходим под данным пользователем — последующие команды мы будем выполнять от него:
su - builder
3. Создадим каталог, в котором будет происходит сборка:
mkdir -p debbuild
Перейдем в debbuild:
cd debbuild
Мы готовы к сборке.
Сборка из исходников
В нашем примере мы возьмем исходники для сборки nginx (для выполнения configure, make, make install …) и соберем из них свой пакет для установки NGINX. Процесс будет разбит на несколько этапов:
- Предварительная настройка.
- Создание файлов с инструкциями для сборки пакета.
- Выполнение сборки и проверки.
Рассмотрим каждый из этапов подробнее.
Подготовка
Создадим каталог с названием собираемого приложения (с учетом версии):
mkdir -p nginx-1.20.1/debian
* в нем обязательно каталог debian.
Перейдем в созданный каталог:
cd nginx-1.20.1
Теперь создадим несколько важных файлов.
Создание файлов сборки (основные)
Для выполнения сборки нужно создать, минимум, 4 файла.
1. Control-файл.
Это основной файл с описанием процесса сборки. Вводим:
vi debian/control
Пример для нашего случая:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Source: nginx Section: misc Priority: optional Maintainer: test testovich <master@test.ru> Build-Depends: libpcre3-dev, zlib1g-dev Standards-Version: 1.20.1 Homepage: https://nginx.org Package: nginx Architecture: amd64 Provides: nginx Description: NGINX packages. The description can be written in several lines. Each line have to be 73 chars maximum. |
* значения для опции Build-Depends задаются экспериментально — лучше всего попробовать сначала собрать требуемый пакет вручную, чтобы понять, какие потребуется доустановить пакеты. Рекомендуется это делать на чистой системе, чтобы не получить искаженный результат (на используемой системе уже могут быть пакеты, которых не будет на другом компьютере, где будет происходить сборка).
* более подробное описание файла control представлено ниже.
2. Файл changelog.
В данном файле описывается история изменений пакета. Также сборщик берет из этого файла номер версии и релиза.
Создаем файл командой:
vi debian/changelog
1 2 3 |
nginx (1.20.1) stable; urgency=medium * Initial release -- test testovich <master@test.ru> Tue, 03 Aug 2021 17:34:42 +0300 |
* в файле указано, что первые изменения внес test testovich 03 августа. Для начала сборки этого будет достаточно. Описание ниже.
3. Файл rules.
Описываем правила компиляции пакета во время его сборки. Создаем файл:
vi debian/rules
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/usr/bin/make -f export DH_VERBOSE = 1 url='http://nginx.org/download/nginx-1.20.1.tar.gz' build_dir='nginx' override_dh_auto_clean: if [ ! -f $(build_dir) ]; then rm -rf $(build_dir); fi mkdir $(build_dir) dh_auto_clean override_dh_auto_configure: wget $(url) -O $(build_dir).tar.gz tar -xzf $(build_dir).tar.gz -C $(build_dir)/ --strip-components=1 rm -f $(build_dir).tar.gz cd $(build_dir) && ./configure override_dh_usrlocal: %: dh $@ --sourcedirectory=$(build_dir)/ |
* важно обратить внимание на факт, что содержимое файла может сильно отличаться в зависимости от того, что мы собираем и какой версии собираемое программное обеспечение. В данном примере мы создали файл для независимой работы — сборщик сам скачает исходник и распакует его в рабочий каталог (в данном примере, nginx). Также мне пришлось переопределить этап dh_usrlocal, так как на нем возникала ошибка, связанная с невозможностью удалить каталог командой rmdir.
* в нашей системе должен быть установлен wget, как и все остальные утилиты, которыми мы захотим воспользоваться.
* более подробное описание файла rules ниже.
4. Файл compat.
Указываем на уровень совместимости с debhelper (вспомогательный инструмент для сборки пакетов). Создаем файл:
vi debian/compat
9
* на момент обновления инструкции рекомендовано использовать версию не ниже 9. Сама по себе сборка без данного файла (или при указании версии ниже 9) запустится, но быстро остановится с ошибкой dh_auto_clean: Compatibility levels before 9 are deprecated (level X in use), где Х — текущий уровень совместимости.
Дополнительные файлы сборки
Данные файлы не являются обязательными. Они могут увеличить возможности собираемого пакета, а также нужны для нашего удобства.
1. Файл postinst.
Является скриптом, который будет запущен после установки пакета на целевой системе. Любые постинсталляционные настройки можно выполнить с его помощью, например:
vi debian/postinst
1 2 3 4 5 6 7 8 |
#!/bin/sh # postinst script for test # # see: dh_installdeb(1) set -e useradd test |
* в данном примере мы просто создадим учетную запись test. Опция set -e говорит о том, что при возникновении ошибки, необходимо сразу прервать работу скрипта.
Может быть использован более сложный сценарий с обработкой аргументов, например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
... case "$1" in configure) systemctl is-enabled --quiet nginx && systemctl disable nginx ;; abort-upgrade|abort-remove|abort-deconfigure) ;; upgrade) systemctl is-active --quiet nginx ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac exit 0 |
* таким образом, при установке приложения посредством, например, команды apt-get upgrade, после инсталляции будет выполнена только команда sytemctls is-active --quiet nginx.
2. Файл postrm.
Это скрипт, который выполнится после удаления пакета:
vi debian/postrm
1 2 3 4 5 6 7 8 9 |
#!/bin/sh # postrm script for test # # see: dh_installdeb(1) set -e rm -rf /var/log/app rm -rf /opt/app/test |
* в данном примере мы предположили, что после удаления нужно удалить 2 каталога /var/log/app и /opt/app/test.
3. Файл preinst.
Скрипт выполнения перед установкой пакета.
4. Файл prerm.
Скрипт выполнения перед удалением пакета.
Сборка пакета
У нас созданы все необходимые файлы, выполнены предварительные действия, и мы готовы к сборке.
Проверяем, что у нас установлены необходимые пакеты и, при необходимости, установим их:
mk-build-deps --install
* команда является частью пакета devscripts, который мы установили в начале инструкции. Она читает опцию Build-Depends файла control и устанавливает необходимые пакеты.
Выполним сборку командой:
debuild -us -uc -b
Если мы все сделали правильно, в конце мы увидим что-то на подобие:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
W: nginx: missing-depends-line E: nginx: no-copyright-file E: nginx: description-starts-with-package-name E: nginx: dir-in-usr-local usr/local/nginx/ E: nginx: dir-in-usr-local usr/local/nginx/conf/ E: nginx: file-in-usr-local usr/local/nginx/conf/fastcgi.conf W: nginx: file-in-unusual-dir usr/local/nginx/conf/fastcgi.conf E: nginx: file-in-usr-local usr/local/nginx/conf/fastcgi.conf.default W: nginx: file-in-unusual-dir usr/local/nginx/conf/fastcgi.conf.default E: nginx: file-in-usr-local usr/local/nginx/conf/fastcgi_params W: nginx: file-in-unusual-dir usr/local/nginx/conf/fastcgi_params E: nginx: file-in-usr-local usr/local/nginx/conf/fastcgi_params.default W: nginx: file-in-unusual-dir usr/local/nginx/conf/fastcgi_params.default E: nginx: file-in-usr-local usr/local/nginx/conf/koi-utf W: nginx: file-in-unusual-dir usr/local/nginx/conf/koi-utf E: nginx: file-in-usr-local usr/local/nginx/conf/koi-win W: nginx: file-in-unusual-dir usr/local/nginx/conf/koi-win E: nginx: file-in-usr-local usr/local/nginx/conf/mime.types W: nginx: file-in-unusual-dir usr/local/nginx/conf/mime.types E: nginx: file-in-usr-local usr/local/nginx/conf/mime.types.default W: nginx: file-in-unusual-dir usr/local/nginx/conf/mime.types.default E: nginx: file-in-usr-local usr/local/nginx/conf/nginx.conf W: nginx: file-in-unusual-dir usr/local/nginx/conf/nginx.conf E: nginx: file-in-usr-local usr/local/nginx/conf/nginx.conf.default W: nginx: file-in-unusual-dir usr/local/nginx/conf/nginx.conf.default E: nginx: file-in-usr-local usr/local/nginx/conf/scgi_params W: nginx: file-in-unusual-dir usr/local/nginx/conf/scgi_params E: nginx: file-in-usr-local usr/local/nginx/conf/scgi_params.default W: nginx: file-in-unusual-dir usr/local/nginx/conf/scgi_params.default E: nginx: file-in-usr-local usr/local/nginx/conf/uwsgi_params W: nginx: file-in-unusual-dir usr/local/nginx/conf/uwsgi_params E: nginx: file-in-usr-local usr/local/nginx/conf/uwsgi_params.default W: nginx: file-in-unusual-dir usr/local/nginx/conf/uwsgi_params.default E: nginx: file-in-usr-local usr/local/nginx/conf/win-utf W: nginx: file-in-unusual-dir usr/local/nginx/conf/win-utf E: nginx: dir-in-usr-local usr/local/nginx/html/ E: nginx: file-in-usr-local usr/local/nginx/html/50x.html W: nginx: file-in-unusual-dir usr/local/nginx/html/50x.html E: nginx: file-in-usr-local usr/local/nginx/html/index.html W: nginx: file-in-unusual-dir usr/local/nginx/html/index.html E: nginx: dir-in-usr-local usr/local/nginx/logs/ E: nginx: dir-in-usr-local usr/local/nginx/sbin/ E: nginx: file-in-usr-local usr/local/nginx/sbin/nginx W: nginx: file-in-unusual-dir usr/local/nginx/sbin/nginx Finished running lintian. |
Пакет сформирован и должен находится в директории на уровень ниже:
ls ../
Среди списка файлов мы должны увидеть пакет с нашим названием:
1 2 |
nginx-1.20.1 nginx_1.20.1_amd64.build nginx_1.20.1_amd64.changes nginx-dbgsym_1.20.1_amd64.deb nginx_1.20.1_amd64.buildinfo nginx_1.20.1_amd64.deb |
Описание служебных файлов
Попробуем разобраться в синтаксисе обязательных файлов, которые мы создали для выполнения сборки.
Control
Данный файл содержит основную информацию о собираемом пакете. Рассмотрим по отдельности обязательные опции и дополнительные.
Основные (без которых сборщик вернет ошибку):
Опция | Описание | Пример |
---|---|---|
Source | Определяет имя пакета источника. | nginx |
Maintainer | Имя и адрес электронной почты сборщика пакета. | test testovich <master@test.ru> |
Package | Имя собираемого пакета. | nginx |
Architecture | Архитектура собираемого пакета. | amd64 |
Дополнительные опции файла control:
Опция | Описание |
---|---|
Section | Классификация задачи, для которой может быть использовано приложение. Чаще всего применяются: misc, utils, net, mail, text, x11. Возможные значения: admin, base, comm, contrib, devel, doc, editors, electronics, embedded, games, gnome, graphics, hamradio, interpreters, kde, libs, libdevel, mail, math, misc, net, news, non-free, oldlibs, otherosfs, perl, python, science, shells, sound, tex, text, utils, web, x11. |
Priority | Определяет важность пакета для системы. Возможные варианты: required, standard, optional, extra, important. Влияет на поведение при удалении — например, пакет, отмеченный как required, не может быть удален. |
Build-Depends | Перечисляет список пакетов, которые требуются для сборки. Если в системе не будет перечисленных пакетов, сборщик вернет ошибку. Есть разные форматы записи, например: 1. Перечисляем зависимости: libpcre3-dev, zlib1g-dev 2. Используем логическое или: apache2 | httpd | nginx, php-fpm 3. Указание версии: libpcre3-dev (= 13), zlib1g-dev (> 14), apache2 (>= 15), httpd (< 16), nginx (<= 17) (обратите внимание, данный перечень можно записать через запятую в одну строчку или по одной/несколько пакетов на каждой строчке также через запятую). |
Standards-Version | Указывает на версию пакета. |
Homepage | Домашняя страница для собираемого пакета. |
Provides | Имя пакета, под которым будет зарегистрировано приложение после установки. Как правило, указывается таким же, как и имя собираемого пакета. Но в редких случаях, может понадобиться поменять на свое. |
Depends | Список пакетов, которые требуются для установки собираемого пакета на конечной системе. Также как и в Build-Depends, возможен разный формат написания. |
Description | Произвольное описание для пакета. Необходимо проследить, чтобы размер одной строки не превышал 73 символа. Каждая последующая строка описания должна начинаться, как минимум, с одного пробела. |
Полный перечень опций можно найти в официальном руководстве.
Rules
В данном файле мы задаем поведение при компиляции пакета. Как правило, его содержимое сводится к:
1 2 |
%: dh $@ |
* отступы должны быть табуляциями, иначе система вернет ошибку.
… что означает, что все действия по установке пакета из исходника должны быть шаблонные.
При компиляции будет запущено три группы команд:
- debian/rules clean. Выполняет чистку каталога сборки и его подготовку.
- debian/rules build. Подготовка к сборке и сборка.
- debian/rules binary. Установка и создание бинарного пакета.
У каждой выше озвученной группы есть свои этапы, через которые проходит процесс сборки. Подробнее про данные этапы можно почитать на сайте debian.org.
Однако, для каждого из этапов мы можем переопределять поведение и задавать настройки (с помощью приставки override_ в файле). Рассмотрим примеры некоторых этапов и настроек.
Каталог источника
Задается с помощью параметра --sourcedirectory, например:
dh $@ --sourcedirectory=src/
* в данном примере мы укажем сборщику, что брать исходные файлы нужно в каталоге src (относительно рабочего каталога). При таком определении источника, не забываем заранее создать каталог (в данном примере, mkdir src).
override_dh_auto_configure
Выполняет конфигурирование. Нам может потребоваться изменить опции на свои, например:
override_dh_auto_configure:
cd src/ && ./configure --prefix=/usr
* обратите внимание, что если у нас исходник находится в отдельном каталоге, мы должны перейти в него и сразу (&&) запустить команду для конфигурирования. Если эти команды ввести в разных строках, то мы получим ошибку — перед выполнением каждой команды сборщик возвращается в исходную директорию.
dh_auto_build
На данном этапе выполняется сборка (make). Можно перед этим процессом закачивать исходник и распаковывать его в каталог src:
1 2 3 |
override_dh_auto_build: dh_auto_build -- PG_CONFIG=/opt/pgpro/std-11/bin/pg_config |
* в конечном итоге, мы запускаем тот же dh_auto_build, но с передачей дополнительной опции.
dh_auto_test
Выполняем цель test файла Makefile. Иногда, в процессе сборки пакета на данном этапе возвращается ошибка, хотя сама по себе компиляция и сборка прошли корректно. В таком случае, этап можно пропустить:
1 |
override_dh_auto_test: |
* для пропуска любого из этапов просто вставляем соответствующую строку с пустым перечнем действий.
dh_auto_install
На данном этапе выполняется установка пакета (make install). Рассмотрим такой пример:
1 2 |
override_dh_auto_install: dh_auto_install -- PG_CONFIG=/opt/pgpro/std-11/bin/pg_config |
* такая настройка выполнит установку, передав команде make install дополнительный параметр PG_CONFIG=/opt/pgpro/std-11/bin/pg_config. На практике, эта опция задает путь расположения конфига postgresql pro.
dh_fixperms
Задает стандартные права на файлы. Мы же можем захотеть назначить свои или отдельного владельца, например:
1 2 3 |
override_dh_fixperms: dh_fixperms chown nginx:nginx -R nginx |
* в данном примере всем файлам внутри каталога будет задан владелец пользователь nginx. Обратите внимание, что мы сначала позволяем системе выставить права по своему алгоритму (dh_fixperms), после чего выполняем свою команду.
Changelog
Файл используется системой сборки для получения номера версии пакета, его ревизии, срочности и раздела. Также в него можно заносить список изменений.
Типичный пример для файла:
gentoo (0.9.12-1) unstable; urgency=medium
* Initial release. (Closes: #nnnn) <nnnn is the bug number of your ITP>
-- Josip Rodin <joy-mg@debian.org> Mon, 22 Mar 2010 00:37:31 +0100
* где:
- первая строчка указывает на:
- имя пакета (gentoo).
- версию (0.9.12-1).
- релиз (unstable).
- важность пакета (urgency=medium).
- вторая строка является примером для описания изменения. Таких строк, начинающихся со звездочки, может быть несколько.
- третья строка — имя и адрес автора правок и дата редактирования.