Настало, наконец, время вернуться к теме пакетирования в Debian и Ubuntu.
Начну я с оправданий. Причиной долгой паузы, между четвертой и этой частью была не моя лень, не диплом, который я никак не допишу, и даже не положение звёзд, а уже упомянутый мною в предыдущих статьях (раз, два, три, четыре) досадный баг в одном из пакетов Debian. Как я, наконец, понял, скорого исправления этого бага ждать не стоит, поэтому я предлагаю тем, кто уже освоил сборку пакетов, изучить интересное средство, облегчающее как тестирование вашего пакета, так и сборку его под разные архитектуры — pbuilder.

pbuilder — это интересное средство, позволяющее нам создать архив, хранящий в себе образ свежеустановленной Debian или Ubuntu в минимальной комплектации — то есть, только с самыми необходимыми пакетами.

Зачем это нужно?


Представьте себе, ваш src-пакет скачал безвестный системный администратор Василий Дудочкин и хочет собрать из него пакет под свою mipsel-архитектуру. Потирая в предвкушении руки, он набирает заветную команду dpkg-buildpackage и… получает ошибку сборки. Дудочкин негодует, клянет кривых авторов программы, пишет содержательные багрепорты («Нисабирается, памагите!!!!!!») в трак апстрима. А всё из-за того, что вы забыли в графе Build-Depends вашего пакета указать gnutls-dev, которого у Дудочкина конечно же не стоит.
Именно в таких случаях нас спасает pbuilder — он скачает и установит все указанные в Build-Depends пакеты, попробует собрать ваш пакет исходников и, что тоже важно, в конечном итоге сохранит свой образ в неизменном виде для ваших дальнейших экспериментов.

Какие у этого подхода есть минусы?


Минуса два, но довольно больших.
Первый заключается в том, что для работы пакета требуется sudo или рутовый пароль. Пока вы работаете на своей домашней машине — всё замечательно, у вас есть все права, но если вы собираете на каком-то чужом сервере, то с этим могут возникнуть проблемы. Скажу честно, я пытался заставить pbuilder работать без рута, но мне не хватило терпения до конца доэкспериментировать с fakeroot.
Второй минус — это не самая высокая скорость работы. Дело в том, что образ системы хранится в .tgz файле. Соответственно типичный алгоритм сборки пакета выглядит как: распаковать образ — выкачать недостающие в кэше пакеты для сборки — установить пакеты для сборки — собрать пакет — вернуть всё на круги своя. Из-за этого сборка занимает довольно много времени, из которого большую часть составляет распаковка tgz-образа.

Как создать свой образ для pbuilder'а


Для начала ставим пакет pbuilder и открываем любимым редактором файл ~/.pbuilderrc:
  1. # кодовые названия дистрибутивов Debian
  2. UNSTABLE_CODENAME="unstable"
  3. TESTING_CODENAME="testing"
  4. STABLE_CODENAME="stable"
  5. DEBIAN_SUITES=($UNSTABLE_CODENAME $TESTING_CODENAME $STABLE_CODENAME
  6.     "sid" "squeeze" "lenny")
  7. # названия дистрибутивов Ubuntu
  8. UBUNTU_SUITES=("jaunty" "intrepid" "hardy" "gutsy")
  9.  
  10. # адреса зеркал с пакетами
  11. DEBIAN_MIRROR="ftp.us.debian.org"
  12. UBUNTU_MIRROR="mirrors.kernel.org"
  13.  
  14. # выбираем дистрибутив для использования
  15. : ${DIST:="$(lsb_release --short --codename)"}
  16. # а также архитектуру
  17. : ${ARCH:="$(dpkg --print-architecture)"}
  18.  
  19. # компоненты дистрибутива по умолчанию
  20. COMPONENTS="main contrib non-free"
  21.  
  22. # ну и давайте определим имя, которым мы будем обозначать отдельный образ
  23. NAME="$DIST"
  24. if [ -n "${ARCH}" ]; then
  25.     NAME="$NAME-$ARCH"
  26.     # следующая строчка нужна для того чтобы собирать под разные архитектуры
  27.     DEBOOTSTRAPOPTS=("--arch" "$ARCH" "${DEBOOTSTRAPOPTS[@]}")
  28. fi
  29.  
  30. # где мы будем создавать, а потом искать файл образа
  31. BASETGZ="/home/torkvemada/pbuilder/$NAME-base.tgz"
  32. DISTRIBUTION="$DIST"
  33. # и куда мы будем класть собранные пакеты
  34. BUILDRESULT="/home/torkvemada/pbuilder/$DIST/result/"
  35. # тут у нас будет лежать кэш слитых из сети пакетов
  36. APTCACHE="/home/torkvemada/pbuilder/$NAME/aptcache/"
  37. # а в это место будет распаковываться образ для сборки
  38. BUILDPLACE="/home/torkvemada/pbuilder/build/"
  39.  
  40. # если мы собираем под дебиан, то качать пакеты тута
  41. if $(echo ${DEBIAN_SUITES[@]} | grep -q $DIST); then
  42.     MIRRORSITE="http://$DEBIAN_MIRROR/debian/"
  43.     COMPONENTS="main contrib non-free"
  44. # а если под убунту, то качать тама
  45. elif $(echo ${UBUNTU_SUITES[@]} | grep -q $DIST); then
  46.     MIRRORSITE="http://$UBUNTU_MIRROR/ubuntu/"
  47.     COMPONENTS="main restricted universe multiverse"
  48. # а если вообще непонятно под что - то просто идти нафиг
  49. else
  50.     echo "Неизвестный дистрибутив: $DIST"
  51.     exit 1
  52. fi
  53.  
  54. # еще можно раскомментировать следующие два параметра по необходимости:
  55. # примонтировать каталог вашей системы в такой же каталог образа
  56. #BINDMOUNTS="/var/cache/archive"
  57. # подключить дополнительное зеркало помимо стандартного
  58. #OTHERMIRROR="deb file:///var/cache/archive unstable main"


Итак, полдела сделано. Главное, не забыть заменить в приведенном мною конфиге мой домашний каталог на свой или вообще на что-нибудь другое.
Теперь нам надо создать образ какой-нибудь системы. Например, так:
$ sudo ARCH=i386 DIST=hardy pbuilder --create

Именно здесь всплывает упомянутый мною баг. На Debian-системах cdebootstrap кривоватенько работает с созданием образов Ubuntu, в частности intrepid он у меня собрать отказывался категорически, а все дистрибутивы Debian у меня уже имелись в наличии. Поэтому данная статья пишется только сейчас, когда я настроил pbuilder на убунту для сборки убунтовых пакетов.

Таким образом мы можем создать себе пачку разных систем, которые дальше использовать в своё удовольствие. Например, данная система у меня лежит по адресу /home/torkvemada/pbuilder/hardy-i386-base.tgz.

Что теперь можно сделать с этим образом


С ним можно сделать несколько интересных вещей. Первая, для которой собственно всё и затевалось — это сборка пакетов. Заходим в произвольный каталог, в котором лежит наш исходный пакет и пробуем собрать:
$ cd mypackage-1.0.19/
$ sudo DIST=hardy ARCH=i386 pdebuild

Ждём, пока образ распакуется, выкачает все необходимые для сборки пакеты (пока кэш пустой, это займёт некоторое время, потом эти пакеты будут ставиться из кэша), установит их, и только затем приступит к сборке. Когда всё закончится, то если наш пакет собрался успешно мы можем его найти:
$ ls ~/pbuilder/hardy/result/*.deb
/home/torkvemada/pbuilder/hardy/result/mypackage_1.0.19-1_i386.deb

Что бы сделать еще? Еще можно посмотреть, а что же творится внутри нашего образа? Набираем:
$ sudo pbuilder --login --basetgz ~/pbuilder/hardy-i386-base.tgz

Вуаля! Мы внутри нашего образа, можем творить всё, что душе угодно, правда учитывайте, что в вашем распоряжении нет даже любимого многими Midnight Commander'а, а из текстовых редакторов — только sed. А что, не поверите, но я им вполне успешно пользовался для правки конфигов.
Как я уже говорил, все наши эксперименты не испортят систему — как только вы наберете «exit», чтобы выйти, образ вернется в своё начальное состояние, даже историю команд не сохранит. Но иногда возникает ситуация, ко��да необходимо изменить содержимое образа. Например, для одного моего пакета требуется наличие полных исходников PHP5. Как обойти эту проблему, я пока не знаю, а посему пакет просто ищет при сборке данные исходники по вполне определенному пути. Как же сохранить каталог исходников в pbuilder'е? Набираем:
$ sudo pbuilder --login --save-after-login --basetgz ~/pbuilder/hardy-i386-base.tgz

Теперь, всё что мы изменим, после выхода сохранится, можете быть уверены. Именно поэтому данную возможность надо использовать крайне осторожно.

Также часто возникает необходимость обновить версии пакетов в образе системы, Особенно, если мы являемся счастливыми обладателями образа Debian unstable. Всего лишь одна команда удовлетворит эту потребность:
$ sudo pbuilder --update --basetgz ~/pbuilder/hardy-i386-base.tgz


Ещё бывает необходимо использовать внешний репозиторий, например, наш домашний reprepro, упомянутый мною в четвертой статье. Для этого нам надо перед созданием образа раскомментировать в ~/.pbuilderrc строчку c OTHERMIRROR. Дополнительных зеркал может быть несколько, тогда разделять их надо вертикальной чертой. Если зеркало лежит не в сети, а на том же самом компьютере, то тогда надо раскомментировать и строчку BINDMOUNTS, указав в ней путь до монтируемого репозитория.
Если к моменту осознания вами необходимости стороннего репозитория вы уже создали образ без подключения оного — это печально, но у нас все равно есть два выхода. Первый — это просто поправить конфиг и создать образ заново. cdebootstrap опять будет долго выкачивать пакеты из интернета, но что поделать.
Второй способ проще. Набираем:
$ sudo pbuilder update --override-config --basetgz ~/pbuilder/hardy-i386-base.tgz --othermirror "deb myhost.ru/ubuntu hardy main"


P.s. Вот собственно и всё. По большому счёту, тема статьи себя исчерпала и о чём ещё написать, я пока даже не знаю. Поэтому если хотите более подробного освещения какой-нибудь темы — оставляйте заявки :)