Przejdź to tekstu

Tworzenie paczek deb

Kategoria: Artykuły, etykiety: ccache, chroot, apt, debootstrap, devscripts, gpg, kompilacja, pbuilder

Dodany przez: morfik, 2014-09-28 19:54 (zmodyfikowany: 2014-09-29 20:07)

Wyświetleń: 8300

W poprzednim artykule postawiliśmy sobie lokalne repozytorium. Wszystkie paczki .deb, które wpadły nam w łapy, mamy już zassane, zainstalowane i włączone do naszego repozytorium. A co w przypadku gdy pożądany przez nas pakiet jest, co prawda, dostępny w repozytorium debiana ale nie jest skompilowany/skonfigurowany tak jak my byśmy tego chcieli, lub zwyczajnie pojawiła się nowsza wersja w upstreamie, a ta jeszcze nie zdążyła trafić do oficjalnego repozytorium debiana, albo też, co gorsza, pakiet, który nas interesuje nie jest w ogóle dostępny w oficjalnym repozytorium i nikt przy tym też nie zrobił paczek .deb , które moglibyśmy sobie zaimportować?

Jeśli chodzi o aktualizację pakietów czy lekkie zmiany paczek w oparciu o informacje znalezione na necie, to raczej nie ma z tym większego problemu. Najgorsze jest stworzenie paczki mając dostępne tylko źródła samego pakietu. Ja znowu ekspertem debiana aż takim to nie jestem i stworzenie paczki "from scratch" przerasta jeszcze nieco moje możliwości, choć od czasu do czasu sobie coś tam doczytuję. Niemniej jednak, przeciętny użytkownik debiana jest w stanie zbudować własną modyfikację paczki w oparciu o wcześniej przygotowane i obecne w oficjalnym repozytorium źródła. Przy czym, trzeba pamiętać, że debianizowanie źródeł, które ktoś przeprowadził już za nas, odbywało się pod kątem określonej wersji aplikacji i przy wprowadzaniu większych zmian, czy też przy pobraniu nowszej wersji mainstreamowych źródeł, nie zawsze pakiet może się nam zbudować z powodzeniem i aby tak się stało, potrzebna będzie nasza interwencja. W każdym razie nie ma co się zniechęcać.

By uprościć i maksymalnie zautomatyzować proces budowania/aktualizowania pakietów, debian dostarcza szereg narzędzi. Poniżej jest lista rzeczy, które będą nam potrzebne:

# aptitude install build-essential ccache devscripts dpkg-dev dh-make pbuilder

Dodatkowo, w zależności od budowanych pakietów, trzeba będzie doinstalować również i inne paczki -- info o nich zostanie wyrzucone przy wykonywaniu konkretnych operacji. Głównie to będą paczki mające w nazwie dh- . Wszelkie inne pakiety potrzebne do kompilacji źródeł będą automatycznie pobierane w chroocie stworzonym przez narzędzie pbuilder i co z tym się wiąże, nie narobimy sobie zbytnio syfu w systemie.

By móc budować paczki jak debian przykazał, musimy pierw skonfigurować narzędzia pbuilder oraz devscripts .

Konfiguracja pbuilder

Przykładowy plik konfiguracyjny znajduje się w /usr/share/doc/pbuilder/examples/pbuilderrc -- trzeba go skopiować do katalogu /etc/pbuilderrc i odpowiednio przerobić. Można także zrobić sobie lokaną wersję tego pliku i umieścić go w katalogu domowym w ~/.pbuilderrc . Poniżej jest mój plik konfiguracyjny:

# pbuilder defaults; edit /etc/pbuilderrc to override these and see
# pbuilderrc.5 for documentation

BASETGZ=/media/Server/pbuilder/base.tgz
EXTRAPACKAGES="apt-utils debconf-utils ccache eatmydata"
#export DEBIAN_BUILDARCH=athlon
BUILDPLACE=/media/Server/pbuilder/build/
MIRRORSITE=http://ftp.de.debian.org/debian/
#OTHERMIRROR="deb http://www.home.com/updates/ ./"
#export http_proxy=http://your-proxy:8080/
USEPROC=yes
USEDEVPTS=yes
USENETWORK=no
USERUNSHM=yes
USEDEVFS=no
BUILDRESULT=/media/Server/pbuilder/result/

# specifying the distribution forces the distribution on "pbuilder update"
DISTRIBUTION=testing
# specifying the architecture passes --arch= to debootstrap; the default is
# to use the architecture of the host
ARCHITECTURE=`dpkg --print-architecture`
# specifying the components of the distribution, for instance to enable all
# components on Debian use "main contrib non-free" and on Ubuntu "main
# restricted universe multiverse"
COMPONENTS="main"
#specify the cache for APT 
APTCACHE="/media/Server/pbuilder/pbuilder_apt_cache/"
APTCACHEHARDLINK="no"
REMOVEPACKAGES="no"
#HOOKDIR="/usr/lib/pbuilder/hooks"
HOOKDIR="/media/Server/pbuilder/hooks"
# NB: this var is private to pbuilder; ccache uses "CCACHE_DIR" instead
# CCACHEDIR="/var/cache/pbuilder/ccache" ccache -M 20G
CCACHEDIR="/media/Server/pbuilder/ccache"
export CCACHE_DIR="/media/Server/pbuilder/ccache"

# make debconf not interact with user
export DEBIAN_FRONTEND="noninteractive"

DEBEMAIL=""

#for pbuilder debuild
BUILDSOURCEROOTCMD="fakeroot"
PBUILDERROOTCMD="sudo -E"
# use cowbuilder for pdebuild
#PDEBUILD_PBUILDER="cowbuilder"

# additional build results to copy out of the package build area
#ADDITIONAL_BUILDRESULTS=(xunit.xml .coverage)

# command to satisfy build-dependencies; the default is an internal shell
# implementation which is relatively slow; there are two alternate
# implementations, the "experimental" implementation,
# "pbuilder-satisfydepends-experimental", which might be useful to pull
# packages from experimental or from repositories with a low APT Pin Priority,
# and the "aptitude" implementation, which will resolve build-dependencies and
# build-conflicts with aptitude which helps dealing with complex cases but does
# not support unsigned APT repositories
#PBUILDERSATISFYDEPENDSCMD="/usr/lib/pbuilder/pbuilder-satisfydepends"
PBUILDERSATISFYDEPENDSCMD="/usr/lib/pbuilder/pbuilder-satisfydepends-experimental"

# Arguments for $PBUILDERSATISFYDEPENDSCMD.
# PBUILDERSATISFYDEPENDSOPT=()

# You can optionally make pbuilder accept untrusted repositories by setting
# this option to yes, but this may allow remote attackers to compromise the
# system. Better set a valid key for the signed (local) repository with
# $APTKEYRINGS (see below).
ALLOWUNTRUSTED=no

# Option to pass to apt-get always.
export APTGETOPT=()
# Option to pass to aptitude always.
export APTITUDEOPT=()

#Command-line option passed on to dpkg-buildpackage.
#DEBBUILDOPTS="-IXXX -iXXX"
DEBBUILDOPTS="-j2 -pgpg -k771B6520 -sa"

#APT configuration files directory
APTCONFDIR="/media/Server/pbuilder/pbuilder_apt_conf/"

# the username and ID used by pbuilder, inside chroot. Needs fakeroot, really
BUILDUSERID=1234
BUILDUSERNAME=morfik

# BINDMOUNTS is a space separated list of things to mount
# inside the chroot.
BINDMOUNTS="${CCACHE_DIR}"

# Set the debootstrap variant to 'buildd' type.
DEBOOTSTRAPOPTS=(
    '--variant=buildd'
    '--keyring' '/usr/share/keyrings/debian-archive-keyring.gpg'
    )
# or unset it to make it not a buildd type.
# unset DEBOOTSTRAPOPTS

# Keyrings to use for package verification with apt, not used for debootstrap
# (use DEBOOTSTRAPOPTS). By default the debian-archive-keyring package inside
# the chroot is used.
APTKEYRINGS=()

# Set the PATH I am going to use inside pbuilder: default is "/usr/sbin:/usr/bin:/sbin:/bin"
#export PATH="/usr/sbin:/usr/bin:/sbin:/bin"
export PATH="/usr/lib/ccache:${PATH}"

# SHELL variable is used inside pbuilder by commands like 'su'; and they need sane values
export SHELL=/bin/bash

# The name of debootstrap command, you might want "cdebootstrap".
DEBOOTSTRAP="debootstrap"

# default file extension for pkgname-logfile
PKGNAME_LOGFILE_EXTENTION="_$(dpkg --print-architecture).build"

# default PKGNAME_LOGFILE
PKGNAME_LOGFILE=""

# default AUTOCLEANAPTCACHE
AUTOCLEANAPTCACHE="no"

#default COMPRESSPROG
COMPRESSPROG="gzip"

Jeśli ktoś nie rozumie konkretnych opcji, wszystkie są przystępnie opisane w manie.

Przy tak stworzonej konfiguracji, możemy przejść do zrobienia minimalnego i do tego spakowanego chroota, który będzie używany przy każdej kompilacji pakietów. Takie minimalistyczne środowisko ma na celu zapewnienie, że pakiet będzie się budował poprawnie na 99% maszyn, pod warunkiem, że się zbuduje bez problemu w tym chroocie. Jeśli przejrzeliśmy i dostosowaliśmy już wszystkie opcje, musimy stworzyć szereg katalogów i dostosować konfigurację dla apt:

$ mkdir /media/Server/pbuilder
$ mkdir /media/Server/pbuilder/{hooks,build,result,pbuilder_apt_cache,ccache,pbuilder_apt_conf}
$ cp /etc/apt/sources.list /media/Server/pbuilder/pbuilder_apt_conf/

W pliku sources.list zostawiłem jedynie wpisy od testinga oraz swojego lokalnego repozytorium:

# jessie - testing #
       deb     http://ftp.pl.debian.org/debian/ testing main non-free contrib
       deb-src http://ftp.pl.debian.org/debian/ testing main non-free contrib
       deb     http://security.debian.org/ testing/updates main contrib non-free
       deb-src http://security.debian.org/ testing/updates main contrib non-free

# local #
#      deb     file:/media/Server/repozytorium/debian/ sid main contrib non-free
#      deb-src file:/media/Server/repozytorium/debian/ sid main contrib non-free

       deb     http://deb.morfikownia.lh/debian/ sid main contrib non-free
       deb-src http://deb.morfikownia.lh/debian/ sid main contrib non-free

Wszystkie zewnętrzne repo będą wymagać publicznych kluczy gpg -- trzeba je również dostarczyć. Można to zrobić na dwa sposoby, albo po całym procesie wejść do chroota i pobrać klucze ręcznie, albo dostarczyć keyring apt pbuilderowi i z tego drugiego wyjścia skorzystamy:

$ cp /etc/apt/trusted.gpg /media/Server/pbuilder/pbuilder_apt_conf/

W katalogu /usr/share/doc/pbuilder/examples/ jest również szereg skryptów, z których pbuilder może skorzystać podczas operacji budowania pakietu. Doszukałem się tam C10shell -- umożliwia on przerwanie operacji przy ewentualnych błędach podczas budowania paczki i zrzucenie nas do shella wewnątrz środowiska chroot -- standardowo pbuilder by przerwał akcję i posprzątał po sobie. Jeśli potrzebujemy któregoś z tych skryptów, linkujemy go do katalogu hooks/ :

$ ln -s /usr/share/doc/pbuilder/examples/C10shell /media/Server/pbuilder/hooks/

Konfiguracja gotowa, tworzymy spakowane środowisko chroot. Po wydaniu poniższego polecenia, zostanie zainicjowany debootstrap, który pobierze minimalnego debiana (testing), który to zostanie wstępnie skonfigurowany i upchnięty w paczce .tgz :

$ sudo pbuilder create
Set cache size limit to 20.0 Gbytes
W: /root/.pbuilderrc does not exist
I: Distribution is testing.
I: Current time: Sat Sep 27 19:44:06 CEST 2014
I: pbuilder-time-stamp: 1411839846
I: Building the build environment
I: running debootstrap
/usr/sbin/debootstrap
I: Retrieving Release
I: Retrieving Release.gpg
I: Checking Release signature
I: Valid Release signature (key id A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553)
I: Retrieving Packages
I: Validating Packages
...
I: unmounting dev/pts filesystem
I: unmounting run/shm filesystem
I: unmounting proc filesystem
I: creating base tarball [/media/Server/pbuilder/base.tgz]
I: cleaning the build env
I: removing directory /media/Server/pbuilder/build//3227 and its subdirectories

W ten sposób utworzona paczka będzie wypakowywana za każdym razem gdy będziemy budować jakiś pakiet przy pomocy sudo pbuilder --build , niemniej jednak całe wypakowane środowisko, niezależnie od powodzenia akcji budowania, zostanie na zakończenie usunięte. Jeśli będziemy budować wiele razy i to tylko jeden pakiet, można edytować tego spakowanego chroota i doinstalować tam szereg zależności, tak by podczas instalacji nie były w kółko pobierane i instalowane. By edytować środowisko, wpisujemy poniższe polecenie:

$ sudo pbuilder --login --save-after-login

Każdy system, nawet ten minimalny chroot zrobiony przy pomocy debootstrapa, wymaga by go aktualizować w miarę regularnie, a konkretnie, przed budowaniem pakietu. By zaktualizować środowisko, wpisujemy:

$ sudo pbuilder --update

By przyśpieszyć budowanie pakietów, pbuilder wykorzystuje ccache. Można określić ilość miejsca dla cache oraz też jego położenie. Obie opcje precyzuje się w pliku /etc/pbuilderrc w linijce:

...
CCACHEDIR="/media/Server/pbuilder/ccache" ccache -F 0 -M 20G
...

Po zakończeniu budowania pakietu, wszystkie stworzone w ten sposób pliki zostaną przeniesione do katalogu /media/Server/pbuilder/result/ .

Konfiguracja sudo

Narzędzia pbuilder standardowo możemy używać tylko jako root. Przydałoby się umożliwić korzystanie z niego zwykłemu użytkownikowi. W tym celu edytujemy konfigurację sudo wpisując w termunalu visudo i dopisujemy poniższe linijki:

Host_Alias HOSTY = localhost,morfikownia

morfik     HOSTY = (root) NOPASSWD: /usr/sbin/pbuilder

Więcej infomracji na temat samego sudo jak i pliku konfiguracyjnego można znaleźć tutaj.

Źródła pakietu

Zanim jednak stworzymy pierwszą paczkę, rzućmy okiem na to jak wyglądają zdebianizowane już źródła dostępne w repozytorium debiana. By mieć do nich dostęp, potrzebujemy dodatkowy wpis zawierający deb-src w pliku /etc/apt/sources.list , przykładowo dla sida:

deb http://ftp.pl.debian.org/debian/ sid main non-free contrib
deb-src http://ftp.pl.debian.org/debian/ sid main non-free contrib

Aktualizujemy listy pakietów przy pomocy aptitude update i pobieramy źródła pakietu, w tym przypadku jest to wpasupplicant:

$ apt-get source wpasupplicant
Reading package lists... Done
Building dependency tree
Reading state information... Done
Picking 'wpa' as source package instead of 'wpasupplicant'
Selected version '2.2-1' (testing) for wpa
NOTICE: 'wpa' packaging is maintained in the 'Svn' version control system at:
svn://anonscm.debian.org/pkg-wpa/wpa/trunk/
Need to get 1,801 kB of source archives.
Get:1 http://ftp.pl.debian.org/debian/ sid/main wpa 2.2-1 (dsc) [2,483 B]
Get:2 http://ftp.pl.debian.org/debian/ sid/main wpa 2.2-1 (tar) [1,725 kB]
Get:3 http://ftp.pl.debian.org/debian/ sid/main wpa 2.2-1 (diff) [74.3 kB]
Fetched 1,801 kB in 1s (1,458 kB/s)
gpgv: Signature made Wed 17 Sep 2014 09:53:09 PM CEST using RSA key ID C2B35520
gpgv: Can't check signature: public key not found
dpkg-source: warning: failed to verify signature on ./wpa_2.2-1.dsc
dpkg-source: info: extracting wpa in wpa-2.2
dpkg-source: info: unpacking wpa_2.2.orig.tar.xz
dpkg-source: info: unpacking wpa_2.2-1.debian.tar.xz
dpkg-source: info: applying 01_use_pkg-config_for_pcsc-lite_module.patch
dpkg-source: info: applying 02_dbus_group_policy.patch
dpkg-source: info: applying 06_wpa_gui_menu_exec_path.patch
dpkg-source: info: applying 07_dbus_service_syslog.patch
dpkg-source: info: applying 12_wpa_gui_knotify_support.patch
dpkg-source: info: applying wpa_gui_desktop_add-keywords-entry.patch
dpkg-source: info: applying wpa_supplicant-MACsec-fix-build-failure-for-IEEE8021.patch
dpkg-source: info: applying ap_config_c_fix-typo-for-capabilities.patch

Paczki budowane ze źródeł nie zawsze mają nazwy takie same jak ich źródła ale to nie stanowi problemu dla apt i ten sobie odszuka odpowiednie pakiety, tak jak nam to wyżej oznajmił: Picking 'wpa' as source package instead of 'wpasupplicant' . Dalej w logu widzimy, że z repozytorium zostały pobrane trzy pliki: .dsc , .tar oraz .diff .

Poniżej przykładowy plik .dsc :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 3.0 (quilt)
Source: wpa
Binary: hostapd, wpagui, wpasupplicant, wpasupplicant-udeb
Architecture: linux-any kfreebsd-any
Version: 2.2-1
Maintainer: Debian wpasupplicant Maintainers <pkg-wpa-devel@lists.alioth.debian.org>
Uploaders: Kel Modderman <kel@otaku42.de>, Stefan Lippers-Hollmann <s.l-h@gmx.de>, Jan Dittberner <jandd@debian.org>
Homepage: http://w1.fi/wpa_supplicant/
Standards-Version: 3.9.5
Vcs-Browser: http://anonscm.debian.org/viewvc/pkg-wpa/wpa/trunk/
Vcs-Svn: svn://anonscm.debian.org/pkg-wpa/wpa/trunk/
Build-Depends: debhelper (>> 9.20120115), libdbus-1-dev, libssl-dev, libqt4-dev, libncurses5-dev, libpcsclite-dev, libnl-3-dev [linux-any], libnl-genl-3-dev [linux-any], libnl-route-3-dev [linux-any], libpcap-dev [kfreebsd-any], libbsd-dev [kfreebsd-any], libreadline-dev, pkg-config, qt4-qmake, docbook-to-man, docbook-utils
Package-List:
 hostapd deb net optional arch=linux-any,kfreebsd-any
 wpagui deb net optional arch=linux-any,kfreebsd-any
 wpasupplicant deb net optional arch=linux-any,kfreebsd-any
 wpasupplicant-udeb udeb debian-installer standard arch=linux-any
Checksums-Sha1:
 6d2e42ff162c70cd4c77661f29e1b3fba1338dab 1724720 wpa_2.2.orig.tar.xz
 49250e12bf31014cca489347daca31477d8d6b95 74252 wpa_2.2-1.debian.tar.xz
Checksums-Sha256:
 ed27e9db9e65dd0c31dcf9801c5f144a370213ec6ea31b24564ebf443edfc169 1724720 wpa_2.2.orig.tar.xz
 9e2837b8afd6f8a7c790a9a709250b8ee866539ac5ef039b5bfb29cdd55ebea6 74252 wpa_2.2-1.debian.tar.xz
Files:
 e95163755c70b87ea785ca7a01e60e98 1724720 wpa_2.2.orig.tar.xz
 0bda870563d2e9b895994461c52b9379 74252 wpa_2.2-1.debian.tar.xz

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iQIcBAEBAgAGBQJUGealAAoJEP+RSvDCs1Ug4rsP/jP98RV5lo3WfdJn7XuOHRxb
8iwpk4IzYPewx4uXQQiAK3sGhqCn9/+8jGHgCkEBkYrv/Omxp/UjHjp2aO8BX2Mu
oZFXJUoxwAnsIX5qEeWZj+46JRJMy7ITbxP6+VaotD0ImTBKvvloCTAoigZHwz5g
h/70gsIGGm+UaWakTngOukRZ3FqC4Q7/d9+fYIaQKHMfSWfH3EhixsUrVD+5gFY4
lmQUW1JTry3XgklNbZbqpLEweTfuE2S5JkR4000L9VUgjiIU9LZp9L+TpxIXBbq6
5U9pwoUqjmADpFBPXrifo8vJYtykQ4Wr1oi2DIYp7cAB94XTYR4H5eVM0WuDQXOX
AeHK+hm5syGJLb5fGnGzNttdFERyO3bLO5QreUKkLz5uOkoP1XkLG5U+DuXdA5Lm
HKzAnw8q6y0gTJWJP6qLstzCbrBlGoTeobAZc9y4sWdAl3kfgoj7tJUCQM3DIsRV
QZ7oFlw4cUV3ZN2w/ldjlbtPXVVmTP+oOHi4gl6zfH+sZ5313RQ6fUc/hLLXy1yP
F76Fpkqa9R6ViqVwtukn+rw/bdIgo1H0ewHKpBFeFcONy2+PG89VzHYir0PT8uPu
eDS50Ay7SmQ20LKOy9nnzMeNz95rBAt6ipdaShn5zMnENl7ePRyviyC8ExtttuDQ
kCrc46uCrc4w4U5z+P0O
=Y6rq
-----END PGP SIGNATURE-----

Zawiera on szereg informacji opisujących pliki, źródła i ludzi, którzy opiekują się daną paczką, jak i również są linki, pod którymi można znaleźć dany projekt. Dodatkowo, są zawarte też informacje na temat sum kontrolnych źródeł oraz katalogu debian/ . Całość jest podpisana cyfrowo, co gwarantuje integralność danych, które właśnie pobraliśmy. Jeśli uważnie przejrzeliśmy log pobierania źródeł, możemy tam zauważyć, że apt nie może zweryfikować sygnatury. By zweryfikować podpis, potrzebny nam jest klucz publiczny osoby, która podpisała powyższy plik. Pobranie klucza i weryfikację podpisu możemy przeprowadzić ręcznie przy pomocy poniższych linijek:

$ gpg --verify wpa_2.2-1.dsc
gpg: Signature made Wed 17 Sep 2014 09:53:09 PM CEST
gpg:                using RSA key 0xFF914AF0C2B35520
gpg: Can't check signature: public key not found

$ gpg --search-keys 0xFF914AF0C2B35520
gpg: searching for "0xFF914AF0C2B35520" from hkps server hkps.pool.sks-keyservers.net
(1)     Cyril Brulebois <kibi@mraw.org>
        Cyril Brulebois <cyril@mraw.org>
        Cyril Brulebois <kibi@debian.org>
          4096 bit RSA key 0xFF914AF0C2B35520, created: 2009-07-12
Keys 1-1 of 1 for "0xFF914AF0C2B35520".  Enter number(s), N)ext, or Q)uit > 1
gpg: requesting key 0xFF914AF0C2B35520 from hkps server hkps.pool.sks-keyservers.net
gpg: key 0xFF914AF0C2B35520: public key "Cyril Brulebois <kibi@mraw.org>" imported
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   2  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: depth: 1  valid:   1  signed:   0  trust: 1-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2017-07-15
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

$ gpg --verify wpa_2.2-1.dsc
gpg: Signature made Wed 17 Sep 2014 09:53:09 PM CEST
gpg:                using RSA key 0xFF914AF0C2B35520
gpg: Good signature from "Cyril Brulebois <kibi@mraw.org>" [unknown]
gpg:                 aka "Cyril Brulebois <cyril@mraw.org>" [unknown]
gpg:                 aka "Cyril Brulebois <kibi@debian.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: B60E BF29 8445 3C70 D74C  F478 FF91 4AF0 C2B3 5520

Jak widzimy wyżej, podpis został zweryfikowany ale my nie mamy określonego zaufania do tej osoby, której klucz publiczny posiadamy. Samo ostrzeżenie nie wpływa jednak na weryfikację podpisu, a ten jest w porządku, zatem możemy przejść dalej.

Poza plikiem .dsc , pobrał się także plik .tar -- zawiera on spakowane źródła aplikacji, zwykle te udostępnianie przez jej developera. W pliku .dif zaś są umieszczone wszelkie zmiany jakie muszą być poczynione, by zdebianizować oryginalne źródła. Po pobraniu tych plików, źródła są wypakowywane i dostosowywane, wliczając w to też łaty, jakie opiekun pakietu wprowadził. Po tym zabiegu mamy przygotowany katalog wpa/ .

W katalogu z wypakowanymi źródłami znajduje się podkatalog debian/ i to w nim będziemy dokonywać praktycznie wszelkich zmian. Jeśli byśmy nanosili jakieś poprawki na źródła z jakiegoś powodu, przy budowaniu źródeł zostanie wyrzucony komunikat z informacją o tym, że zostały one zmienione i budowanie nie powiedzie się. Dla przykładu zmieniłem nieco źródła, tak by zasymulować opisywaną sytuację:

dpkg-source: info: building wpa using existing ./wpa_2.2.orig.tar.xz
dpkg-source: info: local changes detected, the modified files are:
 wpa-2.2/src/tls/x509v3.h.test
dpkg-source: error: aborting due to unexpected upstream changes, see /tmp/wpa_2.2-1.diff.OyD5Df
dpkg-source: info: you can integrate the local changes with dpkg-source --commit
dpkg-buildpackage: error: dpkg-source -b wpa-2.2 gave error exit status 2
debuild: fatal error at line 1364:
dpkg-buildpackage -rfakeroot -d -us -uc -S -sa failed

Skopiowałem zwyczajnie jeden plik wewnątrz wypakowanych źródeł. Oczywiście zmiany jakich będziemy dokonywać mogą być różne ale zawsze przy budowaniu zmienionych lokalnie źródeł dostaniemy powyższy komunikat. By móc zbudować takie źródła, trzeba dodać patcha przy pomocy dpkg-source --commit -- wtedy źródła dalej będą niezmienione ale za to w katalogu debian/patches/ zostanie utworzony plik, w którym się znajdą wszelkie zmiany jakich dokonaliśmy na źródłach.

W każdym razie, edycja źródeł to już wyższa szkoła jazdy, a my się głównie skupimy na edycji plików katalogu debian/ . Sam katalog jest odrębną całością i jest pakowany oddzielnie i można go przenosić między kolejnymi wersjami źródeł. Jeśli zajrzymy do katalogu gdzie pobraliśmy źródła, możemy dostrzec również spakowany plik wpa_2.2-1.debian.tar.xz -- to tam właśnie jest ulokowany katalog debian/ .

Budowa paczuszki

Weźmy może przykład z życia -- jakiś czas temu, próbowałem sobie zaktualizować pakiet minitube, bo w repo była dostępna wersja sprzed chyba 2 lat. Co w takim przypadku należy zrobić, by zaktualizować pakiet? Na początek pobieramy stare źródła przy pomocy apt-get source minitube . Po ich pobraniu, będziemy mieli dostęp do pliku minitube_2.0-1.debian.tar.xz . Pobieramy ze strony projektu najnowsze źródła i zapisujemy je w tym samym katalogu. Zmieniamy nazwę pliku z nowymi źródłami, na taką według wzoru: program_versja.orig.tar.{gz,bz2,xz} , po czym wypakowujemy pliki -- ten ze źródłami oraz minitube_2.0-1.debian.tar.xz. Następnie kopiujemy katalog debian/ do katalogu minitube/ i przechodzimy do tego katalogu. Poniżej jest zobrazowany schemat działania opisanego wyżej:

$ apt-get source minitube
Reading package lists... Done
Building dependency tree
Reading state information... Done
Selected version '2.0-1' (testing) for minitube
NOTICE: 'minitube' packaging is maintained in the 'Git' version control system at:
git://git.sur5r.net/minitube
Need to get 888 kB of source archives.
Get:1 http://ftp.pl.debian.org/debian/ sid/main minitube 2.0-1 (dsc) [1,833 B]
Get:2 http://ftp.pl.debian.org/debian/ sid/main minitube 2.0-1 (tar) [880 kB]
Get:3 http://ftp.pl.debian.org/debian/ sid/main minitube 2.0-1 (diff) [5,868 B]
Fetched 888 kB in 0s (1,222 kB/s)
gpgv: Signature made Sat 06 Sep 2014 09:30:43 PM CEST using RSA key ID F54DAE3D
gpgv: Can't check signature: public key not found
dpkg-source: warning: failed to verify signature on ./minitube_2.0-1.dsc
dpkg-source: info: extracting minitube in minitube-2.0
dpkg-source: info: unpacking minitube_2.0.orig.tar.gz
dpkg-source: info: unpacking minitube_2.0-1.debian.tar.xz
dpkg-source: info: applying disable-update-check
dpkg-source: info: applying proper-tempfiles
dpkg-source: info: applying assure-quit-keybinding

$ wget http://flavio.tordini.org/files/minitube/minitube.tar.gz
--2014-09-26 16:43:19--  http://flavio.tordini.org/files/minitube/minitube.tar.gz
Resolving flavio.tordini.org (flavio.tordini.org)... 85.17.133.22
Connecting to flavio.tordini.org (flavio.tordini.org)|85.17.133.22|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 878634 (858K) [application/x-gzip]
Saving to: ‘minitube.tar.gz’

100%[==============================>] 878,634     1.05MB/s   in 0.8s

2014-09-26 16:43:20 (1.05 MB/s) - ‘minitube.tar.gz’ saved [878634/878634]

$ mv minitube.tar.gz minitube_2.2.orig.tar.gz

$ tar xpf minitube_2.2.orig.tar.gz

$ tar xpf minitube_2.0-1.debian.tar.xz

$ cp -a debian/ minitube

By proces aktualizacji paczek przebiegał sprawnie, przydałoby się poznać trochę budowę katalogu debian/ . Pierwszym plikiem, na który musimy rzucić okiem, jest plik debian/control -- w nim są definiowane min. zależności potrzebne do zbudowania/instalacji pakietu. Poniżej przykładowy plik:

Source: minitube
Section: video
Priority: extra
Maintainer: Jakob Haufe <sur5r@sur5r.net>
Build-Depends: cdbs, debhelper (>= 9), libqt4-dev (>= 4:4.5), libphonon-dev, dpkg-dev (>= 1.16.1~)
Standards-Version: 3.9.5
Homepage: http://flavio.tordini.org/minitube
Vcs-Browser: http://git.sur5r.net/?p=minitube;a=summary
Vcs-Git: git://git.sur5r.net/minitube

Package: minitube
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, phonon-backend-gstreamer | phonon-backend, dbus-x11
Description: Native YouTube client
 Minitube is a native YouTube client. With it you can watch YouTube videos in
 a new way: you type a keyword, Minitube gives you an endless video stream.
 .
 Minitube does not require the Flash Player.
 .
 Minitube is not about cloning the original YouTube web interface, it aims to
 create a new TV-like experience.

Na stronie projektu danej aplikacji, zwykle przy nowszych wersjach, będą publikowane informacje na temat zależności, które muszą być spełnione by dany pakiet można było zbudować. Także jeśli podczas budowania pakietu, system narzeka na brak pewnych bibliotek, znaczy to, że musimy uaktualnić pole Build-Depends: . Zwykle też nie trzeba definiować zależności, które muszą być spełnione przy instalacji pakietu w systemie -- te powinny zostać wygenerowane automatycznie, w oparciu o ${shlibs:Depends}, ${misc:Depends}, . Więcej na temat samego pliku debian/control oraz opcji w nim użytych można znaleźć pod tym linkiem.

Kolejnym miejscem gdzie warto zajrzeć przy aktualizacji pakietu jest katalog debian/patches/ , który zawiera wszystkie modyfikacje źródeł wprowadzone przez opiekuna pakietu. Zwykle przy nowszej wersji, część z łatek zwyczajnie staje się zbędna lub też zbudowanie pakietu za ich sprawą może okazać się niemożliwe. Jeśli paczka ma problemy ze zbudowaniem się, w logu będzie informacja odnośnie łaty, która stwarza problemy. W takiej sytuacji najlepiej jest ją wyłączyć przez zakomentowanie odpowiedniej linijki w pliku debian/patches/series .

Przy aktualizacji paczki, dobrze jest też uzupełnić wpisy w changelogu odnośnie tego co zostało zmienione. Przy czy, nie musimy ręcznie edytować pliku debian/changelog -- są przeznaczone do tego odpowiednie narzędzia, w tym przypadku wykorzystamy dch -- zwykle będziemy korzystać z opcji -n , -i oraz -r . Jeśli byśmy dokonywali aktualizacji czyjejś paczki, wtedy posługujemy się parametrem -n oraz -r . W przypadku aktualizacji swojej, wykorzystujemy -i oraz -r. Opcja -n uzupełnia wpis w changelogu o Non-maintainer upload. , przykładowo:

 minitube (2.2-1.1) UNRELEASED; urgency=medium
 
  * Non-maintainer upload.
  *
 
  -- Mikhail Morfikov <morfik@nsa.com>  Fri, 26 Sep 2014 17:30:33 +0200

Tam gdzie są gwiazdki, definiujemy zmiany. Natomiast opcja -r zmienia UNRELEASED , widoczny wyżej, na unstable, przykład:

 minitube (2.2-1.1) unstable; urgency=medium
 
   * Non-maintainer upload.
   * New upsteram version.
 
  -- Mikhail Morfikov <morfik@nsa.com>  Fri, 26 Sep 2014 17:33:19 +0200

I to jest w zasadzie wszystko czego od nas wymaga proces przygotowywania źródeł, przynajmniej w przypadku aktualizowanych paczek.

Musimy teraz zbudować osobno źródła i paczkę .deb ale zanim przejdziemy do procesu budowania, dobrze jest wrzucić poniższe linijki do swojego pliku ~/.bashrc :

DEBEMAIL="morfik@nsa.com"
DEBFULLNAME="Mikhail Morfikov"
export DEBEMAIL DEBFULLNAME

W oparciu o te zmienne, narzędzia służące budowaniu pakietów będą uzupełniać odpowiednie pola, tak jak to np. można zauważyć w changelogu.

Przechodzimy do katalogu ze źródłami (tam gdzie jest katalog debian/) i wydajemy poniższe polecenie:

$ debuild -S -sa
 dpkg-buildpackage -rfakeroot -d -us -uc -S -sa
dpkg-buildpackage: source package minitube
dpkg-buildpackage: source version 2.2-1.1
dpkg-buildpackage: source distribution unstable
dpkg-buildpackage: source changed by Mikhail Morfikov <morfik@nsa.com>
 dpkg-source --before-build minitube
dpkg-source: info: using options from minitube/debian/source/options: --compression=xz --compression-level=7
dpkg-source: info: applying disable-update-check
dpkg-source: info: applying proper-tempfiles
dpkg-source: info: applying assure-quit-keybinding
 fakeroot debian/rules clean
test -x debian/rules
rm -f debian/stamp-makefile-build debian/stamp-makefile-install
/usr/bin/make  -C .  -k distclean
make[1]: Entering directory '/home/morfik/Desktop/debian_sources/minitube'
make[1]: *** No rule to make target 'distclean'.
make[1]: Leaving directory '/home/morfik/Desktop/debian_sources/minitube'
/usr/share/cdbs/1/class/makefile.mk:55: recipe for target 'makefile-clean' failed
make: [makefile-clean] Error 2 (ignored)
dh_clean
rm -f ./Makefile ./.qmake.internal.cache
 dpkg-source -b minitube
dpkg-source: info: using options from minitube/debian/source/options: --compression=xz --compression-level=7
dpkg-source: info: using source format `3.0 (quilt)'
dpkg-source: info: building minitube using existing ./minitube_2.2.orig.tar.gz
dpkg-source: info: building minitube in minitube_2.2-1.1.debian.tar.xz
dpkg-source: info: building minitube in minitube_2.2-1.1.dsc
 dpkg-genchanges -S -sa >../minitube_2.2-1.1_source.changes
dpkg-genchanges: including full source code in upload
 dpkg-source --after-build minitube
dpkg-source: info: using options from minitube/debian/source/options: --compression=xz --compression-level=7
dpkg-source: info: unapplying assure-quit-keybinding
dpkg-source: info: unapplying proper-tempfiles
dpkg-source: info: unapplying disable-update-check
dpkg-buildpackage: full upload (original source is included)
Now signing changes and any dsc files...
 signfile minitube_2.2-1.1.dsc 771B6520

You need a passphrase to unlock the secret key for
user: "Mikhail Morfikov (primary) <morfik@nsa.com>"
4096-bit RSA key, ID 0xCD046810771B6520, created 2013-11-13


 signfile minitube_2.2-1.1_source.changes 771B6520

You need a passphrase to unlock the secret key for
user: "Mikhail Morfikov (primary) <morfik@nsa.com>"
4096-bit RSA key, ID 0xCD046810771B6520, created 2013-11-13


Successfully signed dsc and changes files

Jak widzimy w logu wyżej, pliki .changes oraz .dsc zostały podpisane cyfrowo.

Przechodzimy do katalogu nadrzędnego cd .. i budujemy paczkę przy pomocy poniższego polecenia:

$ sudo pbuilder --build minitube_2.1.6-0.1.dsc
...
dpkg-deb: building package `minitube' in `../minitube_2.2-1.1_amd64.deb'.
 dpkg-genchanges -sa >../minitube_2.2-1.1_amd64.changes
dpkg-genchanges: including full source code in upload
 dpkg-source --after-build minitube-2.2
dpkg-source: info: using options from minitube-2.2/debian/source/options: --compression=xz --compression-level=7
dpkg-buildpackage: full upload (original source is included)

Podglądając plik .changes , dostrzeżemy, że nie jest on podpisany. Jeśli mamy własny klucz gpg, możemy podpisać sobie zbudowaną paczkę:

$ debsign /media/Server/pbuilder/result/minitube_2.2-1.1_amd64.changes
 signfile /media/Server/pbuilder/result/minitube_2.2-1.1.dsc 771B6520

You need a passphrase to unlock the secret key for
user: "Mikhail Morfikov (primary) <morfik@nsa.com>"
4096-bit RSA key, ID 0xCD046810771B6520, created 2013-11-13


 signfile /media/Server/pbuilder/result/minitube_2.2-1.1_amd64.changes 771B6520

You need a passphrase to unlock the secret key for
user: "Mikhail Morfikov (primary) <morfik@nsa.com>"
4096-bit RSA key, ID 0xCD046810771B6520, created 2013-11-13


Successfully signed dsc and changes files

Teraz zarówno plik .changes jak i .dsc są podpisane. Można to poznać po dołączonej sygnaturze w pliku i pierwszej linijce wiadomości: -----BEGIN PGP SIGNED MESSAGE----- . Tak stworzony pakiet można teraz dystrybuować, np. wrzucić do własnego repo, czy też posłać do repo debiana.

Przy czym, jeszcze taka uwaga -- konfiguracja debsign opiera się o devscripts i można w nim określić to jakiego klucza ma używać przy podpisywaniu pakietów. Te opcje można sprawdzić wydając polecenie:

$ debsign --help
...

Default settings modified by devscripts configuration files:
  DEBSIGN_PROGRAM=gpg
  DEBSIGN_KEYID=771B6520

Konfiguracja pakietu devscripts jest trzymana w /etc/devscripts.conf . Dobrze jest przejrzeć ten plik, choć objętościowo może nieco przytłoczyć. W każdym razie interesujące nas opcje to:

DEBSIGN_PROGRAM=gpg

DEBSIGN_SIGNLIKE=gpg

DEBSIGN_KEYID=771B6520

I to w zasadzie tyle na początek.

Makulatura

Pisane w oparciu o korespodencję z mati75 oraz o poniższe linki:

https://wiki.ubuntu.com/PbuilderHowto
http://pbuilder.alioth.debian.org/
https://www.debian.org/doc/manuals/maint-guide/build.en.html
http://manpages.debian.org/cgi-bin/man.cgi?query=dh_make&apropos=0&sektion=0&manpath=Debian+unstable+sid&format=html&locale=en

OSnews Wykop Blip Flaker Kciuk Śledzik Facebook Identi.ca Twitter del.icio.us Google Bookmarks