Archlinux Building System: система построения пакетов

Автор: Алексей Федорчук
5 июля 2005 г

Самое интересное, что есть в Archlinux — это система построения пакетов Arch Building System (сокращенно ABS). Это развитие концепции портов CRUX, которые, в свою очередь, являют собой прямое продолжение системы портов FreeBSD. Подобно последней, ABS — автоматизированная система построения и установки пакетов из исходных текстов, обладающая, однако, рядом особенностей.

Краткое вступление

Основное назначение порта FreeBSD (и идеологически сходным с ними портежей Gentoo) — инкорпорация собранного пакета в дерево текущей файловой системы. Конечно, посредством системы портов можно также собрать и бинарный пакет, предназначенный для автономного распространения — более того, все содержимое коллекции packages именно так и собирается, однако это требует небольшого дополнительного телодвижения.

В портах CRUX’а, напротив, главная цель — это сборка автономного пакета, устанавливаемого стандартными для этого дистрибутива средствами пакетного менеджмента. Хотя, конечно, и здесь есть возможность выполнения обеих процедур в один заход.

ABS же в равной мере приспособлен и к тому, и к другому. Хотя, в отличие от FreeBSD, автономный пакет создается в любом случае. Впрочем, по порядку

Получение ABS

Порядок же в Archlinux таков, что для того, чтобы начать работать с ABS, ее следует получить. В отличие от портов FreeBSD или портежей Gentoo, приобрести дерево ABS в виде единого тарбалла не удастся (впрочем, в CRUX с некоторого времени ежедневный тарбалл дерева портов также стал недоступен). Соответственно, поиметь дерево ABS наиболее простым способом можно из уже установленной системы Archlinux. В принципе, получить к нему доступ можно и другими способами, например, через интерфейс cvsweb, или через cvs просто, но это показалось мне менее удобным.

А под Archlinux — все просто: достаточно дать (от лица суперпользователя) команду abs (это простой bash-скрипт в каталоге /usr/bin). Которая и выполнит (при наличии подключения к Сети любого рода) соединение с сервером Archlinux и скачает с него актуальное (обновляемое ежедневно) ABS-дерево. Суммарный объем которого (в несжатом состоянии) чуть больше 3 Мбайт, то есть посилен даже для модема. В результате в файловой системе волшебным образом появится каталог /usr/abs, включающий всю систему построения пакетов. А далее ABS-дерево потребует только периодического обновления — процедуры, при мало-мальски нормальной телефонной линии занимающей считанные минуты даже по модему.

Что именно скачивается по команде abs — определяется конфигурационными файлами из /etc/abs. Полное дерево ABS включает в себя все пакеты Arch Linux, как официальные (official — это те, что имеются на полном CD), за получение которых отвечает файл /etc/abs/supfile, так и неофициальные (unofficial или contrib) и нестабильные (unstable), что определяется файлами /etc/abs/supfile.unofficial и /etc/abs/supfile.unstable, соответственно. Если пакеты unofficial (contrib) и unstable не нужны, для предотвращения скачивания их портов нужно просто стереть соответствующие файлы.

Порты официальных пакетов по умолчанию берутся из дерева current. При желании иметь только порты стабильной версии, следует отредактировать файл /etc/abs/supfile, заменив строку

*default tag=CURRENT

на

*default tag=STABLE

Конечно, для построения пакетов из исходников потребуются еще и сами исходники. Как и во всех системах портирования, в ABS предусмотрен механизм их автоматического получения из Сети (как правило, с мастер-сайтов разработчиков) по потребности. Однако тут счет пойдет уже не на мегабайты. И потому в домашне-модемных условиях исходники желательно скачивать заблаговременно (например, по служебной выделенке). И размещать в специально предназначенном для них месте — забегая вперед, скажу, что по умолчанию таковым выступает каталог /var/cache/pacman/src.

Правда, простого способа автоматически получить список тарбаллов, необходимых для установки данного пакета в Archlinux (в отличие от FreeBSD или Gentoo) не предусмотрено. Тем не менее, выкопать все потребное (с учетом зависимостей) можно: только для этого придется залезть во внутренности ABS’а. Это мы сделаем несколько позже, а пока посмотрим на

ABS снаружи

Первое, что можно (и нужно) сделать по получении дерева ABS — это ознакомиться с его устройством. Как уже было сказано, произрастает оно из каталога /usr/abs, включающего подкаталоги, соответствующие группам пакетов (тем самым, которые мы видели при установке Archlinux в меню setup, если выполняли ее с полного диска):

$ ls /usr/abs
base/ editors/ kde/ local/ office/
unofficial/ xfce4/
daemons/ gnome/ kernels/ multimedia/
PKGBUILD.proto unstable/
devel/ install.proto lib/ network/
system/ x11/

Кроме того, в корне /usr/abs можно видеть два файла — PKGBUILD.proto и install.proto. Это — прототипы скриптов для разработки собственных abs-портов, о чем мы поговорим под занавес.

В каждом из подкаталогов /usr/abs можно видеть каталоги следующего уровня вложенности, соответствующие отдельным пакетам. А в них уже — минимум по одному файлу, всегда именуемому PKGBUILD. Это и есть собственно сценарий построения пакета, аналог make-файлов из портов FreeBSD и ebuild’ов из портежей Gentoo.

В каталогах некоторых пакетов можно обнаружить и другие файлы. Ими могут быть прототипы конфигов или патчи, необходимые для успешной сборки пакетов и адаптации их к Arch-окружению. Подобно портам FreeBSD, все дистрибутив-специфичные патчи интегрированы непосредственно в дерево ABS, а не скачиваются из общего репозитория с исходниками, как в портежах Gentoo. Прочем, на сервере Archlinux такого общего репозитория и нет — все исходники берутся или с мастер-сайтов разработчиков, или, реже, с крупных ftp-архивов типа www.sourceforge.net.

Как работает ABS

А работает ABS, как и все в Archlinux, до безобразия просто. Для построения пакета в общем случае достаточно перейти в каталог нужной программы (например, /usr/abs/base/bash) и дать команду

$ makepkg

без всяких опций и аргументов. По этой команде выполняются следующие действия:

* проверка каталога /var/cache/pacman/src на наличие исходников пакета и, при отсутствии таковых, их скачивание;
* проверка базы данных установленных пакетов на предмет зависимостей; в случае их удовлетворения процедура продолжается, иначе выдается сообщение об ошибке;
* копирование тарбалла исходников в каталог /usr/abs/category/pkg_name/src, распаковка его там же (в результате чего образуется подкаталог ~/src.pkg_name) и, при необходимости, наложение соответствующих патчей;
* переход в корень дерева исходников пакета и запуск сценария ./configure —prefix=/usr (и, возможно, другими опциями конфигурирования);
* запуск make на предмет сборки пакета;
* промежуточная инсталляция скомпилированных компонентов в подкаталоги каталога /usr/abs/category/pkg_name/pkg (~/bin, ~/etc и т.д.);
* удаление из дерева собранного пакета «ненужных» подкаталогов (например, с info- и html-документацией);
* очистка сгенерированного кода от отладочной информации;
* архивирование и компрессия компонентов пакета (из каталога ~/pkg) в единый тарбалл.

Если все стадии процесса завершились успешно, то в результате в каталоге /usr/abs/category/pkg_name/ появится файл pkg_name.pkg.tar.gz, который и представляет собой скомпилированный пакет, могущий быть установленным обычным образом — командой pacman -A, или использован для обновления уже установленного пакета путем pacman -U (что, впрочем, не является единственным способом инсталляции, как будет показано чуть ниже).

В процедуре построения пакета обращает на себя внимание то, что проверка зависимостей производится фактически дважды. Первый раз — при сверке базы установленных пакетов (из /var/lib/pacman/) со списком зависимостей приведенных в build-файле (а, забегая вперед, замечу, что в нем описываются отнюдь не все зависимости пакета). Если на этой стадии проверка не проходит, по умолчанию, как уже было сказано, просто выдается сообщение об ошибке без попытки разрешения ситуации. Однако с этим можно бороться: опция -b, она же —builddeps, именно и предназначена для построения пакетов, от которых зависит данный, в ходе его сборки.

Второй раз зависимости проверяются уже в реальности, при исполнении скрипта ./configure. И здесь можно ожидать, что нарушение зависимостей приведет просто к прекращению сборки. Я с таким пока не сталкивался, но, теоретически рассуждая, исключить вероятность такой ситуации, учитывая характер описания зависимостей в build-файле (о чем — ниже) нельзя.

Правда, всегда остается возможность собрать пакет, игнорируя нарушение зависимостей, для чего предназначена опция -d, сиречь —nodeps. Правда, гарантировать его работоспособность в этом случае вряд ли кто возьмется.

По умолчанию ABS не устанавливает собранный пакет, требуя для этого привлечения pacman. Однако если команда makepkg дана с опцией -i, —install, то успешное завершение сборки пакета повлечет за собой и его инсталляцию. При этом и сборка, и установка проводятся в один прием. Если же дать команду

$ makepkg -i

в отношении уже построенного пакета, последует сообщение об ошибке. Избежать этого можно, присоединив еще и опцию -f, —force:

$ makepkg -if

В этом случае существующий пакет будет принудительно пересобран и, вслед за тем, установлен.

Легко видеть, что в процессе построения пакета задействуется большой объем дискового пространства: под тарбалл исходников в /var/cache/pacman/src, его дубликат в дереве /usr/abs, под развернутое дерево исходников со всеми промежуточными продуктами компиляции, под дерево собранных бинарников в подкаталоге пакета, и, наконец, под тарбалл окончательно собранного пакета. Причем в полезном остатке окажется только последний, да и то только в том случае, если он сразу же не будет установлен в файловой системе. Все остальное же следует отнести к непроизводительным тратам дискового пространства — по крайней мере, для большинства пользователей, не отягощенных необходимостью отлаживать собственные abs-порты.

Возникает резонный вопрос — а есть ли способ борьбы с таким расточительством, помимо ручного вычищения дерева /usr/abs?

Разумеется, есть — последует столь же резонный ответ. Это — опция -c, —clean, которая очищает дерево /usr/abs от всех промежуточных продуктов жизнедеятельности, оставляя только тарбалл собранного пакета *.pkg.tar.gz.

Есть и более жесткая опция -C, —cleancache, которая заодно вычищает и исходный тарбалл из /var/cache/pacman/src. Чего, впрочем, я не стал бы делать без крайнейшей необходимости — никогда не следует зарекаться от того, что возникнет необходимость пересобрать уже собранный пакет.

Подводя итог длинным рассуждениям, приведу форму использования команды makepkg, которая представляется разумной в большинстве случаев:

$ makepkg -ifc

для установки построенного пакета, вне зависимости от того, имела ли место предыдущая сборка, или нет, с последующей очисткой дерева /usr/abs и сохранением исходного тарбалла в /var/cache/pacman/src.

У команды makepkg есть еще несколько опций, одна из которых нам скоро понадобится. Это — -p имя_файла, предписывающая использовать в качестве build-сценария не штатный PKGBUILD пакета, а некий файл с произвольным именем.

ABS изнутри

Главным средством построения пакета является PKGBUILD-сценарий. Посмотрим на него повнимательней, для чего обратимся к примеру все того же bash, привлеченного в прошлой заметке.

«Заголовочная» часть build-пакета представляет собой комментарий, содержащий краткие сведения о построении пакета, имя сборщика и разместителя:

# $Id: PKGBUILD,v 1.17 2003/11/06 08:26:12 dorphell Exp $
# Maintainer: judd
# Committer: Judd Vinet

Далее идут имя пакета, номер версии и номер сборки. Первые два — авторские, номер же сборки дается в рамках системы ABS.

pkgname=bash
pkgver=2.05b
pkgrel=8

Затем следует краткое описание пакета, адрес сайта разработчика (не ftp-сервера, откуда он скачивается), опциональная строка с именем конфига, подлежащего сохранению в целевой системе, и описание зависимостей:

pkgdesc=»The GNU Bourne Again shell»
url=»http://www.gnu.org/software/bash/bash.html»
backup=(etc/profile)
depends=(‘glibc’ ‘readline’)

Если сравнить описание зависимостей build-файла с таковым из файла depends базы данных пакетов (/var/lib/pacman/), можно увидеть, что в первом случае они ни в коей мере не охватывают всех пакетов, от которых зависит данный. Насколько я смог понять, в build-файле включаются а) самые важные из «жестких» зависимости (в приведенном примере — glibc), б) опциональные зависимости из числа «мягких», которые разработчики сочли необходимым включить (в приведенном примере — readline), и в) зависимости от пакетов, которые могут быть альтернативно заменимыми (так, для текстового редактора nedit здесь можно видеть зависимость от lesstif, альтернативой чему мог бы выступить OpenMotif). Именно поэтому, как я уже говорил, нельзя исключить ситуации, когда при реальном конфигурировании исходника будет обнаружена недостача какого-либо компонента из числа «жестких» или умолчальных «мягких» зависимостей.

В следующей строке build-файла указывается URL сервера, с которого следует брать исходник программы, если его не окажется в /var/cache/pacman/src:

source=(ftp://ftp.ibiblio.org/pub/gnu/\
$pkgname/$pkgname-$pkgver.tar.gz profile)

Именно его следует использовать, подставив вместо переменных $pkgname и $pkgver их значения, для предварительного скачивания исходников при отсутствии прямого подключения машины (или плохом коннекте с нее). Правда, придется еще пройтись по build-файлам пакетов, от которых зависит устанавливаемый, для извлечения адресов для их скачивания. Способа автоматизации этой процедуры я не обнаружил. Хотя принципиальных препятствий к написанию соответствующего скрипта также не просматривается.

В приведенном примере в строке source мы видим еще одни компонент — файл profile без указания адреса. Это значит, что он берется непосредственно из каталога пакета в дереве /usr/abs. И действительно, если просмотреть содержимое его для пакета bash, можно увидеть там файл с этим именем — прототип общесистемного /etc/profile. А в пакетах, которые для установки в Arch должны быть пропатчены, в строке source обнаружится имя патча, а одноименный файл будет присутствовать в каталоге пакета.

Наконец, далее идет собственно описание процесса сборки пакета и его последующей обработки. В общем случае оно включает в себя следующие директивы:

1. переход в каталог развернутого дерева исходников:

cd $startdir/src/$pkgname-$pkgver

2. выполнение конфигурационного сценария с опцией, предполагающей (для большинства пакетов) последующую установку в каталог /usr:

./configure —prefix=/usr

3. собственно компиляцию и линковку:

make

и, наконец, собранных компонентов пакета в промежуточный каталог:

make prefix=$startdir/pkg/usr install

Дополнительно могут присутствовать строки, предписывающие истребление лишней документации (info и html), удаление отладочной информации, создание необходимых ссылок — в случае с bash это будет

ln -sf $pkgname sh

и, возможно, описания еще каких-нибудь дополнительных действий.

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

Индивидуализируем ABS

Индивидуализация ABS включает в себя два аспекта — глобальную настройку системы построения пакетов и локальное редактирование build-сценария конкретного пакета.

Глобальные настройки условий сборки описываются в файле /etc/makepkg.conf. Она сводится к определению серии переменных окружения, влияющих на получение исходников, и условий компиляции.

В первой, после комментариев, строке /etc/makepkg.conf определяется корневой каталог для всей ABS, по умолчанию:

export ABSROOT=»/usr/abs»

Что менять не вижу ни малейшего резона.

Далее определяется программа, вызываемая при необходимости скачивания исходников:

export FTPAGENT=»/usr/bin/wget —continue \
—passive-ftp —tries=3 —waitretry=3″

Меня лично wget более чем устраивает, но желающие могут выбрать что-то из приведенного ниже

#export FTPAGENT=»/usr/bin/snarf»
#export FTPAGENT=»/usr/bin/lftpget -c»

или любой иной наличный ftp-клиент.

Далее идут закомментированные примеры флагов оптимизации для gcc, отличные от умолчальных:

# Pentium Pro/Pentium II/Pentium III+/Pentium 4/Athlon optimized (but
binaries
# will run on any x86 system)
#export CHOST=»i686-pc-linux-gnu»
#export CFLAGS=»-mcpu=i686 -O2 -pipe»
#export CXXFLAGS=»-mcpu=i686 -O2 -pipe»

Включение их позволит запускать собранные пакеты на машинах, более слабых, чем PentiumPro. Напомню, что штатно Arch и все его пакеты собираются с флагом -march=i686. Разумеется, флаги компиляции можно изменить в любую сторону — как смягчив, так и ужесточив, впрочем, как говаривали в до-застойные времена — исключительно под личную ответственность (разговор на эту тему был в предшествующей главе)

Опций для SMP-систем касаться не будем — это пока не актуально для подавляющего большинства пользователей. А вот последней строкой можно прославить свое имя в веках (по крайней мере, среди пользователей своей локальной машины — скорее всего, себя же, любимого), указав его в качестве значения переменной PACKAGER, и сопроводив своим e-mail’ом:

export PACKAGER=»Имя рек «

На этом глобальные настройки в первом приближении заканчиваются. Переходим к конкретным пакетам. И вот здесь самое время вспомнить об опции -p file_name. Каковая позволяет нам, дабы не курочить штатный build-файл, скопировать его

$ cp BUILDPKG MYBUILD

и, отредактировав должным образом последний, собрать пакет командой

$ makepkg -p MYBUILD

В каком направлении редактировать? Если вспомнить строение build-файла, ясно, что ближайшим кандидатом является строка ./configure. Здесь с помощью опций with/without и enable/disable можно прибавить данному пакету функциональности или, напротив, отнять оной. Правда, для этого хорошо бы знать, какие значения этих опций предусмотрел автор. Но тут я вам не помощник — единственный к тому способ, известный мне, заключается в предварительной распаковке исходного тарбалла и запуске скрипта

$ ./configure —help

Далее, можно изменить значение опции —prefix в соответствие со своими привычками, заменив умолчальное для большинства пакетов /usr на, скажем, /opt. Впрочем, это имеет смысл делать только для больших «самодостаточных» пакетных комплексов типа KDE, а они и так в Archlinux по умолчанию устанавливаются в /opt.

А вот для любимой командной оболочки (если ею является не bash) есть смысл добавить еще опцию —bindir=/bin: завсегда полезно, чтобы главный рабочий инструмент POSIX’ивиста находился под рукой (сиречь непосредственно в корневой файловой системе — ведь и /usr, и /opt вполне могут лежать на отдельных разделах).

Наконец, здесь же (или в строке make) можно задать флаги компиляции, отличающиеся от умолчальных (определенных, напомню, в файле /etc/makepkg.conf) — более жесткие при критичности быстродействия или, напротив, смягченные для пакетов, отказывающихся собираться при высоких уровнях оптимизации.

Как это ни парадоксально, но подкорректировать можно и строку описания зависимостей. Указав здесь, скажем, возможный альтернативный пакет (как в приведенном выше примере для nedit). Или, напротив, исключив зависимость заведомо необязательную. Так, в строке depends build-файла для редактора joe я с удивлением обнаружил gpm — сколько раз я ни собирал свой любимый редактор, а ни малейшей потребности в этом самом gpm’е не наблюдал…

В общем, простор для индивидуальной модернизации build-файла любимого и хорошо известного пакета весьма широк. Можно даже сделать build-файл для построения пакета более свежей, нежели наличная, версии — для этого потребуется только подкорректировать строки pkgver и pkgrel. Впрочем, здесь мы уже вплотную подходим к вопросу создания собственных abs-портов, а это увлекательное занятие описываетося в следующем разделе.

А дабы окончательно заинтриговать читателя, замечу наперед, что, кроме команды построения пакета — makepkg, в Arch’е есть и команда переустройства мира — makeworld, аналог известных средств make world из FreeBSD или emerge world из Gentoo.

Предварительные итоги

А пока подведем предварительный итог нашего рассмотрения систем управления пакетами и их построения в сравнении с аналогами — портами FreeBSD, портами CRUX и портежами Gentoo.

С первого же взгляда бросается в глаза, то ABS Archlinux’а далеко уступает в универсальности Gentoo’шным портежам. Если в последних все зависимости можно отрегулировать раз и навсегда, варьируя значения переменной USE (что не исключает их индивидуального переопределения при необходимости), то здесь для этого требуется ручная правка build-файла.

Однако универсализм портежей оборачивается подчас непредсказуемостью их поведения, особенно при смене версии portage или обновлении дерева портежей. Тогда как ABS произвела на меня впечатление системы исключительно прогнозируемой (действительно, что может быть более прогнозируемо, чем то, что вписано собственными руками).

В сравнении с портами FreeBSD abs’ы от Archlinux (да простят мне читатели этот неологизм) выглядят менее гибкими в использовании. Так, если выполнение полного цикла установки порта во FreeBSD можно ограничить на любой стадии — только скачать исходник, скачать и распаковать, скачать, распаковать и собрать без инсталляции, и т.д. — то в ABS предусмотрено, в сущности, только два target’а — построение пакета и его построение с установкой. Причем даже во втором случае в качестве отхода жизнедеятельности остается собранный бинарный пакет (а при сборке с одновременной инсталляцией он, скорее всего, будет именно отходом).

Тем не менее, есть область, где ABS однозначно выигрывает у портов и, особенно, портежей: это — простота использования и простота индивидуализации. Доказать это довольно трудно, а потому предлагаю либо поверить мне на слово, либо попробовать самому.

При сравнении же ABS с портами CRUX в первую голову проступает их кровное родство, обусловившее фенотипическое сходство. И тем не менее, различие есть — опять же в простоте, теперь уже — только использования. Особенно наглядное при сравнении не собственно портов того и другого дистрибутива, а их систем пакетного менеджмента (внимательный читатель наверняка понял: во всех поминаемых здесь системах, от FreeBSD до Archlinux, пакетный менеджмент есть лишь частное проявление механизма портирования). Если в CRUX каждое действие в отношении пакета (установка, удаление, получение информации, и т.д.) требует своей отдельной команды, то Arch во всех случаях обходится одной — pacman, причем с очень логично разделенными опциями первого порядка (то есть действиями) и собственно опциями.

В общем, выражаю свое скромное личное мнение: система обращения с пакетами дистрибутива Arch (не будем разрывать pacman и ABS) — а) одна из самых простых в использовании, какие я видел, б) очень логично построенная, и в силу этого, в) легко индивидуализируемая. А не к тому ли стремится множество пользователей, которых, с одной стороны, не устраивают жесткие рамки пакетной дистрибуции, а, с другой — не нуждающихся во всеохватности и универсализме?

Строим свой ABS-порт

Система управления пакетами Archlinux не то чтобы подталкивает, а прямо-таки провоцирует пользователя на создание собственных портов. Для начала возникает желание сделать порты для более свежих версий, нежели включены в дистрибутив. Однако торопиться здесь не надо: порты, включенные в официальную ветку, обновляются практически мгновенно после выхода свежей версии соответствующего пакета. Так что стоит подождать денек-другой и синхронизировать abs-дерево. После чего подкорректировать нужный порт, как это было описано ранее.

С портами ветки unofficial ситуация иная: частота их обновления зависит исключительно от активности контрибьютора данного пакета. Ну и, конечно, есть немало пакетов, просто не охваченных ни официальной, ни неофициальной ветвями: ведь первая — практически не расширяема (и это — принципиальная установка разработчиков дистрибутива), а во второй есть только то, что интересно уже действующим пользователям Archlinux.

В любом случае, идет ли речь об обновлении порта или создании его с нуля, процесс не сложен. И подробно описан в официальной документации. В abs-дереве предусмотрен даже специальный каталог для собственного творчества — /usr/abs/local. Отправляемся туда и создаем подкаталог, имя которого должно совпадать с авторским наименованием портируемого пакета (без указания версии). Далее туда из корня abs-дерева копируем прототип build-файла (без указания префикса):

$ cp /usr/abs/PKGBUILD.proto /usr/abs/local/pkg_name/PKGBUILD

И спокойно приступаем к его потрошению. Устроен build-прототип следующим образом:

pkgname=NAME
pkgver=VERSION
pkgrel=1
pkgdesc=""
url=""
depends=()
conflicts=()
backup=()
install=
source=($pkgname-$pkgver.tar.gz)
md5sums=()

build() {
  cd $startdir/src/$pkgname-$pkgver
  ./configure --prefix=/usr
  make || return 1
  make prefix=$startdir/pkg/usr install
}

Смысл каждой строки достаточно прозрачен. В первые две вносим имя пакета и номер его версии — они даются в авторском исполнении, однако — в соответствие с требованиями ABS-номенклатуры, Согласно последней, имя пакета образуется только буквами в нижнем регистре и цифрами, без дефисов и прочих спецсимволов. Так что если авторское наименование этим требованиям не соответствует, придется его чуть подкорректировать. В третьей строке указывается номер сборки — поскольку мы делаем это в первый раз, очевидно, что он равен единице).

В четвертой строке задается URL домашней страницы проекта, типа http://www.имя_рек.org. Если, как это иногда бывает, единственный адрес для пакета — это ftp-сервер, с которого его качают, эту строку можно оставить пустой.

В пятой строке перечисляются зависимости пакета — в виде списка имен, заключенных в одинарные кавычки и разделенных пробелами, например, так:

depends=('glibc' 'ncurses')

Поскольку эта строка проверяется по базе установленных пакетов, то имена зависимостей должны точно соответствовать в ней фигурирующим (без всяких номеров версий и прочего).

Увлекаться перечислением зависимостей, насколько я понимаю, не следует. Достаточно указать пакеты а) критически важные для установки, б) те, которые обеспечивают необходимые дополнительные опции (например, gpm — для консольных приложений, оный поддерживающих) и в) пакеты, для которых возможен альтернативный выбор (например, lesstif или OpenMofit).

Строка conflicts=(), как явствует из названия, по смыслу противоположна предыдущей: в ней следует перечислить (по тем же правилам) пакеты, с которыми конфликтует устанавливаемый. Впрочем, возможно, что таковых не имеется — в этом случае строку просто опускаем.

Также необязательны и две следующие строки. В строке backup перечисляются файлы, для которых следует сохранить наличные в файловой системе версии. Обычно это касается конфигурационных файлов из каталога /etc и его аналогов. А строка install указывает, при необходимости, на имя установочного скрипта, который должен вызываться после построения пакета для завершения его инсталляции, например, для Иксов она имеет вид:

install=xfree86.install

А вот следующая строка — очень важна. В данный шаблон следует вписать точный адрес того ftp- или http-сервера, с которого будут скачиваться исходники портируемого пакета примерно в таком виде:

source=(ftp://ftp/path/$pkgname-$pkgver.tar.gz)

Если пакет для адаптации к Archlinux потребует каких-либо патчей собственного изготовления, они также должны быть перечислены здесь поименно, разделяясь пробелами, но без указания адресов:

source=(ftp://ftp/path/$pkgname-$pkgver.tar.gz patch1.patch ...)

Вслед за этим можно заполнить строку с контрольной суммой оригинального пакета (а можно этого и не делать). На этом вступительная часть build-файла заканчивается, и начинается (вызовом функции build) описание процесса его сборки.

Описание это стандартно, начинаясь с перехода в каталог с распакованными исходниками

cd $startdir/src/$pkgname-$pkgver

за которым следуют три сакраментальные команды

$ ./configure
$ make
$ make install

Здесь важны:

  • указание префикса конфигурирования — --prefix=/usr, так как по умолчанию пакеты из исходников обычно устанавливаются в /usr/local, где система контроля зависимостей Arch’а может их потом и не найти (во всяком случае в отношении библиотек этого правила лучше придерживаться неукоснительно);
  • указание кода возврата return 1, предписывающего начать промежуточную установку пакета только после успешного завершения его сборки (что, в принципе, очевидно);
  • указание префикса для промежуточной инсталляции собранных бинарников — prefix=$startdir/pkg/usr: без этого makepkg не сможет собрать их в бинарный тарбалл (который сам временно помещается непосредственно в каталог $startdir.

Закончив редактирование build-файла и озаботившись выходом в Сеть (или разместив предварительно скачанные исходники в /var/cache/pacman/src), можно запустить пробную сборку пакета:

$ makepkg

Это безопасно — без указания опций будут выполнены: а) распаковка исходников в каталог $startdir/src, б) его конфигурирование и сборка, в) промежуточная инсталляция в подкаталоги $startdir/pkg/usr/{bin,etc,share...}, и г) сборка и компрессия бинарного тарбалла в $startdir. Сам пакет установлен не будет. Зато все промежуточные отходы жизнедеятельности при этом сохраняются — они могут понадобиться при неудачной сборке для разбора полетов.

Потому что гарантировать безошибочность сборки с первого раза я бы не стал, вполне возможно появление сообщений об ошибках различного рода. В этом случае следует проанализировать а) сообщения об ошибках, и б) make-файлы из дерева исходников (не зря же мы их сохранили в каталоге $startdir/src/$pkgname-$pkgver при пробной сборке). Часто причина ошибок очень тривиальна — например, в make-файле жестко прописаны какие-либо важные пути, и они не соответствуют таковым в файловой системе Archlinux.

Решается эта проблема просто: первозданное дерево исходников копируется

$ cp pkgname-pkgver pkgname-pkgver-orig

Затем в нужный файл (или файлы) первого каталога вносятся необходимые коррективы, после чего командой diff создается patch-файл, например, вот так:

diff -Naur pkgname-pkgver-orig/Makefile \
pkgname-pkgver/Makefile > pkgname.patch

Каковой и следует поместить в корень порта, наравне с build-файлом. А в последний — внести изменения: дополнить строку source именем патча, а в описании сборки строку ./configure предварить командой наложения патча, типа:

patch -Np1 -i ../pkgname.patch

И еще: система управления пакетами Archlinux весьма сурова по отношению ко всякого рода балласту, безжалостно вычищая из дерева промежуточной инсталляции (каталога $startdir/pkg/usr/) всякого рода подкаталоги с дополнительной (по отношению к man-страницам) документацией типа doc. Само по себе это можно приветствовать, однако в ряде случаев ведет к потерям примеров конфигурационных файлов (разработчики подчас помещают их вместе с документами).

Однако это легко обходимо: все нужные конфиги (причем предварительно доведенные под собственные задачи) также помещаются в корень каталога $startdir, имена их прописываются в строке source (разумеется, без указания URL — ведь они будут браться с локального хранилища), а в конец директивной части build-файла добавляется несколько строк, определяющих, где эти конфиги должны быть размещены, например:

mkdir -p $startdir/pkg/etc
cp ../profile $startdir/pkg/etc

Добившись безошибочной сборки пакета, его можно, не отходя от кассы (то бишь не покидая каталога $startdir) установить обычным способом, командой

$ pacman -A (или -U) pkgname-pkgver.pkg.tar.gz

Или, что предпочтительней, еще раз пересобрать его с одновременной инсталляцией:

$ makepkg -if

Обратим внимание на опцию -f — поскольку файл бинарного тарбалла (пусть и ошибочно собранного) в наличии имеется, без нее повторить процедуру сборки не удастся.

Почему второй способ предпочтительней? Использование команды makepkg без опций быстро приводит к захламлению abs-дерева промежуточными продуктами компиляции — скопированными тарбаллами исходников, каталогами с результатами их развертывания, деревом промежуточной инсталляции бинарников. Каковые при успешной сборке больше никогда не понадобятся. А вот результаты работы — бинарные тарбаллы, — очень даже могут пригодиться. И выуживать их потом из развесистой кроны ABS-дерева — не самое лучшее занятие.

Обе эти проблемы решаются парой дополнительных опций: -c, предписывающей очистить abs-дерево от отходов производства (каталогов $startdir/src и $startdir/pkg), и -w /path, благодаря которой итоговые бинарные тарбаллы будут сконцентрированы в некоем специально предназначенном для них каталоге (например, $HOME/mypkg). В результате финальная команда для нашего порта приобретет такой вид:

$ makepkg -ifc -w $HOME/mypkg

Причем в отношении последнего действия жизнь можно сделать еще проще. Я, например, определил такой псевдоним для makepkg:

alias makepkg='makepkg -w $HOME/mypkg'

и занес его в профильный файл root’а (у меня это /root/.zshrc): излишне напоминать, что хотя вся работа по созданию и тестированию порта может выполняться обычным пользователем, для итоговой установки (вне зависимости, через pacman или через makepkg) потребуются привилегии администратора.

Вот, собственно, и все. Не знаю, насколько мне удалось отразить в своем описании простоту подготовки собственного abs-порта. Если нет — уверяю вас, достаточно внимательно ознакомиться с несколькими build-файлами и чуть-чуть потренироваться самому — и все станет кристально ясно.