Создание пакетов Manjaro
Руководство по созданию пакетов Manjaro
Эта статья призвана помочь пользователям в создании собственных пакетов с помощью оптимизированных инструментов разработчика Manjaro, а также для отправки в бинарные репозитории Manjaro. В ней рассказывается о создании PKGBUILD, файла описания сборки пакета, который используется makepkg
для создания бинарного пакета из исходного кода. Если у вас уже есть PKGBUILD
(см. makepkg). Инструкции относительно существующих правил и способов улучшения качества пакетов смотрите в Стандарт пакетизации Manjaro.
Обзор
Пакеты в Manjaro Linux собираются с помощью утилиты makepkg и информации, хранящейся в файле PKGBUILD. Когда запускается makepkg
, она ищет PKGBUILD
в текущем каталоге и следует инструкциям в нем чтобы скомпилировать или иным образом получить необходимые файлы для упаковки в файл пакета (pkgname.pkg.tar.xz
). Полученный пакет содержит двоичные файлы и инструкции по установке; легко устанавливаемый с помощью pacman.
Пакет Manjaro - это не более чем tar-архив, или "tarball", сжатый с помощью xz, содержащий следующие файлы, созданные makepkg:
- Бинарные файлы для установки.
.PKGINFO
: содержит все метаданные, необходимые pacman для работы с пакетами, зависимостями и т.д..MTREE
: содержит хэши и временные метки файлов, включаемые в локальную базу данных, чтобы pacman мог проверить целостность пакета..INSTALL
: необязательный файл, используемый для выполнения команд после этапа установки/обновления/удаления. (Этот файл присутствует, только если он указан вPKGBUILD
)..Changelog
: необязательный файл, хранящийся у сопровождающего пакета и документирующий изменения пакета. (Он присутствует не во всех пакетах).
Подготовка
Необходимое программное обеспечение
Сначала убедитесь, что необходимые инструменты установлены. Группы пакетов base-devel должно быть достаточно; она включает make и дополнительные инструменты, необходимые для компиляции из исходного кода.
# pacman -S base-devel
Одним из ключевых инструментов для сборки пакетов является makepkg (доступный в pacman), который делает следующее:
- Проверяет, установлены ли зависимости пакета.
- Скачивает исходный файл(ы) с указанного сервера(ов).
- Распаковывает исходный файл(ы).
- Компилирует программу и устанавливает ее в окружении fakeroot.
- Удаляет символы из двоичных файлов и библиотек.
- Генерирует метафайл пакета, включаемый в каждый пакет.
- Сжимает окружение fakeroot в файл пакета.
- Сохраняет файл пакета в настроенном каталоге назначения, который по умолчанию является текущим рабочим каталогом.
Загрузка и тестирование установки
Загрузите исходный tarball программы, которую вы хотите упаковать, распакуйте его и следуйте указаниям автора для установки программы. Запишите все команды и/или шаги, необходимые для компиляции и установки. Вы будете повторять эти же команды в файле PKGBUILD.
Большинство авторов программного обеспечения придерживаются трехэтапного цикла сборки:
./configure make make install
Это подходящее время, чтобы убедиться, что программа работает правильно.
Создание PKGBUILD
Когда вы запускаете makepkg
, он будет искать файл PKGBUILD
в текущем рабочем каталоге. Если файл PKGBUILD
найден - он загрузит исходный код программы и скомпилирует его в соответствии с инструкциями, указанными в файле PKGBUILD
. Инструкции должны быть полностью интерпретируемы оболочкой [[1]]. После успешного завершения, полученные двоичные файлы и метаданные пакета (версия пакета и зависимости) упаковываются в пакетный файл pkgname.pkg.tar.xz
, который может быть установлен с помощью pacman -U <файл пакета>
.
Чтобы начать работу с новым пакетом, сначала нужно создать пустой рабочий каталог (предпочтительно ~/abs/pkgname
), перейти в этот каталог и создать файл PKGBUILD
. Вы можете либо скопировать прототип PKGBUILD /usr/share/pacman/PKGBUILD.proto
в свой рабочий каталог, либо скопировать PKGBUILD
из аналогичного пакета. Последний вариант может быть полезен, если вам нужно изменить всего несколько параметров.
Определение переменных PKGBUILD
Примеры PKGBUILD находятся в /usr/share/pacman/
. Объяснение возможных переменных PKGBUILD
можно найти в статье PKGBUILD.
makepkg определяет три переменные, используемые в процессе сборки и установки:
startdir
- Содержит абсолютный путь к директории, в которой находится файл
PKGBUILD
. Раньше эта переменная использовалась в сочетании с постфиксами/src
или/pkg
, но современным методом является использование переменныхsrcdir
иpkgdir
.$startdir/src
не гарантированно совпадает с$srcdir
, и то же самое для$pkgdir
. Использование этой переменной является устаревшим и настоятельно не рекомендуется. srcdir
- Указывает на каталог, куда makepkg извлекает или копирует все исходные файлы.
pkgdir
- Указывает на каталог, где makepkg собирает установленный пакет, который становится корневым каталогом вашего собранного пакета.
Все они содержат абсолютные пути - это означает, что вам не нужно беспокоиться о рабочем каталоге, если вы правильно используете эти переменные.
.
.
Функции PKGBUILD
Существует 5 функций, перечисленных здесь в порядке их выполнения, если все они существуют. Если одна из них отсутствует - она просто пропускается.
Функция pkgver()
Начиная с pacman 4.1, вы можете обновлять переменную pkgver во время makepkg. pkgver()
запускается сразу после получения и извлечения исходных текстов.
Это особенно полезно, если вы создание пакетов git/svn/hg/итд, где процесс сборки может оставаться неизменным, но исходники могут обновляться каждый день, даже каждый час. Старый способ сделать это состоял в том, чтобы поместить дату в поле pkgver, которое, если программа не была обновлена, makepkg все равно пересобирал ее, думая, что версия изменилась. Некоторые полезные команды для этого - git describe
, hg identify -ni
и т.д. Пожалуйста, проверьте их перед отправкой PKGBUILD, так как сбой в функции pkgver()
может остановить сборку на корню.
.
Функция prepare()
В Pacman 4.1 появилась функция prepare()
. В этой функции выполняются команды, используемые для подготовки исходных текстов к сборке, например, патчинг. Эта функция выполняется перед функцией сборки и после извлечения пакета. Если извлечение пропущено (makepkg -e
), то prepare()
не выполняется.
Функция build()
Теперь вам нужно реализовать функцию build()
в файле PKGBUILD
. Эта функция использует обычные команды оболочки в синтаксисе [[2]] для автоматической компиляции программного обеспечения и создания каталога pkg
для установки программного обеспечения. Это позволяет makepkg упаковывать файлы без необходимости рыться в файловой системе.
Первым шагом в функции build()
является переход в каталог, созданный в результате распаковки исходного tarball. makepkg изменит текущий каталог на srcdir
перед выполнением build()
, поэтому в большинстве случаев первая команда будет выглядеть следующим образом:
cd "$pkgname-$pkgver"
Файл /usr/share/pacman/PKGBUILD.proto
предлагает сделать
cd "$srcdir/$pkgname-$pkgver"
вместо этого. Опять же, поскольку $srcdir
является абсолютным путем, это не имеет никакого значения.
Теперь вам нужно перечислить те же команды, которые вы использовали при ручной компиляции программы. Функция build()
по сути автоматизирует все, что вы делали вручную, и компилирует программу в среде сборки fakeroot. Если программное обеспечение, которое вы упаковываете, использует сценарий configure, хорошей практикой будет использование --prefix=/usr
при сборке пакетов для pacman. Многие программы устанавливают файлы относительно каталога /usr/local
, что следует делать только при ручной сборке из исходников. Все пакеты Arch Linux должны использовать каталог /usr
. Как видно из файла /usr/share/pacman/PKGBUILD.proto
, следующие две строки обычно выглядят следующим образом:
./configure --prefix=/usr make
Функция check()
Место для вызовов make check
и подобных процедур тестирования. Настоятельно рекомендуется иметь check()
, так как это помогает убедиться, что программное обеспечение было собрано правильно и отлично работает со своими зависимостями.
Пользователи, которым это не нужно (и иногда сопровождающие, которые не могут исправить пакет, чтобы это прошло), могут отключить его с помощью !check
в опциях PKGBUILD/makepkg или вызвать makepkg
с флагом --nocheck
.
Функция package()
Последний шаг - поместить скомпилированные файлы в каталог, из которого makepkg сможет получить их для создания пакета. По умолчанию это каталог pkg
- простая среда fakeroot. Каталог pkg
повторяет иерархию корневой файловой системы путей установки программного обеспечения. Если вам нужно вручную поместить файлы в корень вашей файловой системы, то вы должны установить их в каталог pkg
в той же структуре каталогов. Например, если вы хотите установить файл в /usr/bin
- вместо этого его следует поместить в $pkgdir/usr/bin
. Очень немногие процедуры установки требуют от пользователя копирования десятков файлов вручную. Вместо этого для большинства программ достаточно вызвать команду make install
. Чтобы правильно установить программу в каталог pkg
последняя строка должна выглядеть следующим образом:
make DESTDIR="$pkgdir/" install
.
В некоторых странных случаях программа ожидает запуска из одного каталога. В таких случаях разумно просто скопировать их в $pkgdir/opt
.
Чаще всего процесс установки программного обеспечения создает все подкаталоги внутри каталога pkg
. Однако если этого не происходит - makepkg будет выдавать множество ошибок и вам придется вручную создавать подкаталоги, добавляя соответствующие команды mkdir -p
в функцию build()
перед запуском процедуры установки.
В старых пакетах не было функции package()
. Поэтому файлы помещались в каталог pkg в конце функции build()
. Если package()
отсутствует - build()
запускается через fakeroot. В новых пакетах функция package()
обязательна и запускается через fakeroot, а build()
запускается без специальных привилегий.
makepkg --repackage
запускает только функцию package()
, поэтому создает файл *.pkg.*
без компиляции пакета. Это может сэкономить время, например, если вы просто изменили переменную пакета depends
.
.
Тестирование PKGBUILD и пакета
В процессе написания функции build()
Вам придется часто тестировать свои изменения чтобы убедиться в отсутствии ошибок. Это можно сделать с помощью команды makepkg
в каталоге, содержащем файл PKGBUILD
. При правильно оформленном PKGBUILD
makepkg создаст пакет; при поврежденном или незавершенном PKGBUILD
он выдаст ошибку.
Если makepkg завершится успешно - он поместит файл с именем pkgname-pkgver.pkg.tar.xz
в ваш рабочий каталог. Этот пакет можно установить с помощью команды pacman -U
. Однако то, что файл пакета был собран, не означает что он полностью работоспособен. Он может содержать только каталог и ни одного файла, если, например, префикс был указан неправильно. Вы можете использовать функции запроса pacman для отображения списка файлов, содержащихся в пакете, и зависимостей, которые он требует, с помощью pacman -Qlp [файл пакета]
и pacman -Qip [файл пакета]
соответственно.
Если пакет выглядит нормально, то все готово! Однако, если Вы планируете выпустить файл PKGBUILD
- обязательно проверьте и перепроверьте содержимое массива depends
.
Также убедитесь что двоичные файлы пакета действительно "запускаются" безупречно! Очень неприятно выпускать пакет, содержащий все необходимые файлы, но работающий со сбоями из-за какого-то непонятного параметра конфигурации, который не совсем хорошо работает с остальной системой. Однако, если вы собираетесь компилировать пакеты только для своей системы, то не стоит слишком беспокоиться об этом этапе проверки качества, поскольку, в конце концов, вы единственный человек, страдающий от ошибок.
Проверка исправности пакета
После тестирования функциональности пакета проверьте его на наличие ошибок с помощью namcap:
$ namcap PKGBUILD $ namcap <имя файла пакета>.pkg.tar.xz
Namcap будет:
- Проверять содержимое PKGBUILD на наличие распространенных ошибок и иерархию файлов пакета на наличие ненужных/замещенных файлов.
- Сканировать все ELF-файлы в пакете с помощью
lddd
, автоматически сообщая, какие пакеты с необходимыми разделяемыми библиотеками отсутствуют вdepends
, а какие могут быть опущены как переходные зависимости. - Эвристически искать отсутствующие и избыточные зависимости
и многое другое. Возьмите за привычку проверять свои пакеты с помощью namcap чтобы избежать необходимости исправлять простейшие ошибки после отправки пакета.
Отправка пакетов в AUR
Пожалуйста, прочитайте Arch User Repository - Отправка пакетов для подробного описания процесса отправки.
Резюме
- Скачайте исходный tarball программы, которую вы хотите упаковать.
- Попробуйте скомпилировать пакет и установить его в произвольный каталог.
- Скопируйте прототип
/usr/share/pacman/PKGBUILD.proto
и переименуйте его вPKGBUILD
во временный рабочий каталог - предпочтительно~/abs/
. - Отредактируйте
PKGBUILD
в соответствии с потребностями вашего пакета. - Запустите
makepkg
и проверьте правильно ли собран полученный пакет. - Если нет - повторите два последних шага.
Предупреждения
- Прежде чем автоматизировать процесс сборки пакета Вы должны были хотя бы раз проделать это вручную, если только не знаете точно, что Вы делаете заранее, и в этом случае не читали бы это в первую очередь. К сожалению, хотя многие авторы программ придерживаются трехэтапного цикла сборки "
./configure
;make
;make install
" - он не всегда таков и ситуация может стать действительно ужасной, если придется применять патчи, чтобы заставить все работать. Эмпирическое правило: если Вы не можете заставить программу скомпилироваться из исходного tarball'а и установить ее в определенный временный подкаталог - не стоит даже пытаться упаковать ее. Вmakepkg
нет волшебного порошка, который заставит проблемы с исходниками исчезнуть. - В некоторых случаях пакеты даже не доступны в виде исходников и придется использовать что-то вроде
sh installer.run
чтобы заставить их работать. Вам придётся провести довольно много исследований (прочитать README, инструкции INSTALL, man-страницы, возможно, ebuilds от Gentoo или других установщиков пакетов, возможно, даже MAKEFILE или исходный код), чтобы заставить его работать. В некоторых действительно плохих случаях Вам придется редактировать исходные файлы чтобы заставить его работать вообще. Однако,makepkg
должен быть полностью автономным - не вмешивать пользователя. Поэтому, если Вам нужно отредактировать make-файлы, то возможно, придется подключить пользовательский патч кPKGBUILD
и установить его изнутри функцииprepare()
, или же придется выполнить некоторые командыsed
изнутри функцииprepare()
.
Создание файл патча
Пример для отдельного файла
$ diff -Naur filename.ext.old filename.ext > filename-patchname.diff # PKGBUILD cd "${srcdir}/${pkgname}-${pkgver}" patch -uN filename.ext ../filename-patchname.diff || return 1
Пример для нескольких файлов
$ diff -Naur package-ver.old package-ver > package-patchname.diff # PKGBUILD cd "${srcdir}/${pkgname}-${pkgver}" patch -uNp1 -i ../${pkgname}-patchname.diff || return 1