Как стать автором
Обновить

Создание deb пакета без использования стандартных утилит Debian

В этой статье я рассужу как создать пакет для установки в Debian не используя стандартные утилиты из Debian, такие как devhelper, dh_make, cdbs, alien и т.д. Мы будем использовать только стандартные Linux утилиты, которые есть в любом современном дистрибутиве такие как sh, tar, cat, fakeroot, date. Нижеизложенную методику можно легко применить для создания deb пакета из любого программного продукта распространяемого производителем в бинарном виде.

Для примера давайте возьмём стандартную бинарную сборку Firefox с сайта Mozilla и создадим для него deb пакет. Для удобства все необходимые команды запишем в скрипт на стандартном shell, который можно легко будет изменить позднее под конкретные нужды.

Для начала зададим несколько переменных которые мы будем использовать в скрипте. В переменных зададим название пакета, версию, имя загружаемого архива, минорную версию, архитектуру собираемого пакета, имя создателя пакета и его почтовый адрес, ссылку для скачивания с сайта Mozilla и дату создания пакета в формате RFC-2822

#!/bin/sh

echo "Setting variables..."

PACKAGE=firefox
VERSION=3.5.5
FILE=${PACKAGE}-${VERSION}.tar.bz2
MINOR=1
ARCH=i386
USER='Your Name'
EMAIL='your@e-mail.here'
URL=ftp://ftp.mozilla.org/pub/firefox/releases/${VERSION}/linux-i686/ru/${PACKAGE}-${VERSION}.tar.bz2
DATE=`date -R`
...


Скачаем бинарный пакет Firefox с сайта производителя, если нет его в локальной директории:

...
echo "Downloading package..."
[ ! -f ${FILE} ] && wget $URL
...


Стандартный бинарный пакет Debian состоит из двух архивов data.tar.gz и control.tar.gz и файла debian-binary, которые запакованы в архив командой ar. С помощью ar собираются статические библиотеки из объектных файлов. Ее можно найти в любом дистрибутиве в пакете binutils.

debian-binary — содержит версию бинарной сборки. На момент написания статьи текущая версия была 2.0.
data.tar.gz — содержит данные которые будут установлены в систему пользователя
control.tar.gz — содержит файл control с метаданными о пакете и вспомогательные скрипты для установки удалении пакета.

Такое разделение позволяет быстро извлекать информацию о пакете прямо из пакета без разархивирования всего пакета.

Давайте создадим файлы которые необходимо будет добавить в control.tar.gz

...
echo "Creating control file..."

cat > control << EOF;
Package: ${PACKAGE}
Version: ${VERSION}-${MINOR}
Maintainer: ${USER} <${EMAIL}>
Section: non-free/web
Architecture: ${ARCH}
Homepage: http://www.firefox.com/
Priority: optional
Replaces: mozilla-firefox
Provides: www-browser
Depends: fontconfig, psmisc, procps, libc6, libgcc1, libstdc++6
Description: This is the original version of Firefox from Mozilla
Package built with dh-firefox utility
EOF

cat > debian-binary << EOF;
2.0
EOF
...


Создадим структуру каталогов будущего пакета и добавим README, changelog.Debian и файл с лицензией, который возьмем из репозитария с исходниками Firefox. Чтобы у пользователя они занимали меньше места на диске их мы сразу запакуем:

...
echo "Creating doc files..."
rm -Rf usr
mkdir -p usr/share/doc/firefox

cat << EOF | gzip -9 - > usr/share/doc/${PACKAGE}/changelog.Debian.gz
firefox (${VERSION}-1) unstable; urgency=low

* Initial release.

-- ${USER} <${EMAIL}> ${DATE}

EOF

cat << EOF | gzip -9 - > usr/share/doc/${PACKAGE}/README.Debian.gz
Firefox has been packged by dh-firefox utility.
EOF

echo "Downloading copyright file..."
#wget -O - http://hg.mozilla.org/mozilla-central/raw-file/f09961c1d5fa/LICENSE \
#> usr/share/doc/${PACKAGE}/copyright
[ ! -f LICENSE ] && wget http://hg.mozilla.org/mozilla-central/raw-file/f09961c1d5fa/LICENSE.
cp LICENSE usr/share/doc/${PACKAGE}/copyright
...


Создадим desktop файл для рабочих окружении которые поддерживают стандарты freedesktop.

...
echo "Creating desktop file..."
mkdir -p usr/share/applications
cat << EOF > usr/share/applications/firefox.desktop
[Desktop Entry]
Encoding=UTF-8
Name=Firefox Web Browser
Name[ru]=Веб браузер Firefox
Comment=Browse the World Wide Web
Comment[ru]=Просмотрщик для WWW
GenericName=Web Browser
GenericName=Веб браузер
Exec=firefox-original %u
Terminal=false
X-MultipleArgs=false
Type=Application
Icon=/usr/share/firefox/icons/mozicon128.png
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;applicat
StartupWMClass=Firefox-bin
StartupNotify=true
EOF
...


Файловое имя /usr/bin/firefox используется в пакете iceweasel. Конечно можно использовать утилиту dpkg-divert для подстановки и замены файлов в системе, но мы будем придерживаться условий задачи и не будем использовать стандартные утилиты Debian. Поэтому мы просто создадим ссылку с другим именем на скрипт запуска firefox. Эту ссылку назовем firefox-original.



...
mkdir -p usr/bin
ln -s ../share/firefox/firefox usr/bin/firefox-original
...


Теперь создадим три скрипта postinst, prerm и postrm, которые будут запускаться после установки и перед удалением пакета и после удаления. Из этих скриптов запускаются утилиты, которые обновят базу desktop файлов, базу MIME типов и алтернатив.

...
echo "Creating install/uninstall scripts..."

cat << EOF > postinst
#!/bin/sh -e

if [ "\$1" = "configure" ] || [ "\$1" = "abort-upgrade" ] ; then
update-alternatives --install /usr/bin/x-www-browser \\
x-www-browser /usr/bin/firefox-original 70
update-alternatives --install /usr/bin/mozilla mozilla \\
/usr/bin/firefox-original 0
fi

if [ -x /usr/sbin/update-desktop-database ]; then
/usr/sbin/update-desktop-database
fi

if [ "\$1" = "configure" ] && [ -x "\`which update-mime 2>/dev/null\`" ]; then
update-mime
fi

if [ "\$1" = "configure" ] && which update-desktop-database >/dev/null 2>&1 ; then
update-desktop-database -q
fi

EOF

cat << EOF > postrm
#!/bin/sh -e

#if [ -x "\`which update-menus 2>/dev/null\`" ]; then update-menus ; fi
if which update-mime >/dev/null 2>&1; then update-mime; fi
if [ "\$1" = "remove" ] && which update-desktop-database >/dev/null 2>&1 ; then
update-desktop-database -q
fi

EOF

cat << EOF > prerm
#!/bin/sh -e

if [ "\$1" = "remove" ] || [ "\$1" = "deconfigure" ] ; then
update-alternatives --remove x-www-browser /usr/bin/firefox-original
update-alternatives --remove mozilla /usr/bin/firefox-original
fi

EOF

chmod +x postinst postrm prerm
...


Распакуем полученный бинарный архив с сайта Mozilla в директорию user/share. Также уберем флаг исполнения с динамически подгружаемых библиотек и подсчитаем контрольные суммы всех файлов:

...
echo "Unpacking ${PACKAGE} ${VERSION} archive..."

tar -C usr/share -xjf firefox-${VERSION}.tar.bz2

echo "Fixing permission for *.so files..."
find usr/share -type f -name *.so -exec chmod -x {} \;

echo "Calculating MD5 sums..."
find usr -type f -exec md5sum {} >> md5sums \;
...


Теперь пришло время упаковать все созданные файлы в архивы и сложить их в deb файл:

...
echo "Creating data.tar.gz ..."
fakeroot tar cvfz data.tar.gz usr

echo "Creating control.tar.gz ..."
fakeroot tar cvfz control.tar.gz control postinst postrm prerm

echo "Creating ${PACKAGE}_${VERSION}-${MINOR}_${ARCH}.deb ..."
rm -f ${PACKAGE}-${VERSION}-${MINOR}.deb
ar r ${PACKAGE}_${VERSION}-${MINOR}_${ARCH}.deb debian-binary control.tar.gz data.tar.gz
echo "The END..."


Чтобы убедится в том что deb файл создан корректно, запустим проверку на валидность:

man@work:~/tmp/firefox$ lintian -v firefox_3.5.5-1_i386.deb
N: Setting up lab in /tmp/UmQRWztbi7 ...
N: Processing 1 packages...
N: ----
N: Processing binary package firefox (version 3.5.5-1) ...
W: firefox: binary-without-manpage usr/bin/firefox-original
W: firefox: new-package-should-close-itp-bug
N: Removing /tmp/UmQRWztbi7 ...
man@work:~/tmp/firefox$


Как мы видим, пакет имеет только два несущественных предупреждения. Теперь можно его установить и насладится проделанной работой :)

dpkg -i firefox_3.5.5-1_i386.deb


Спасибо, за внимание!

P.S. Мне нужно то что было у всех зарегистрированных здесь пользователей ;)
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.