Dieser Artikel wurde von darthdespotism erstellt.


Folgende Themen werden von diesem Artikel berührt:


Druckversion des Artikels


Inhalt
  1. Einleitung
    1. Das Debian-System
    2. Paketmanager

  2. Auf geht's
    1. Voraussetzungen
    2. Das Programm
    3. Die Umgebung

  3. Zum ersten Debian-Paket
    1. Grundstruktur
    2. Erste Anpassungen
    3. Bauen
    4. Das Menü
    5. Ein Test

  4. Feinschliff
    1. lintian & linda
    2. pbuilder

  5. Tipps, Tricks & Sonstiges
  6. Schlusswort


1 Einleitung

1.1 Das Debian System

Linuxdistributionen gibt es viele und die Paketsysteme sind nahezu ebenso vielfältig. Allerdings haben sich bei den großen Distributionen in Sachen Paketmanager zwei große Fraktionen gebildet. Einige, unter ihnen die großen kommerziellen Distributionen Red Hat (+ Fedora) und SuSE Linux verwenden den «Red Hat Package Manager» kurz rpm und Debian mit seinen «Kindern», dessen bekanntester, aber bei weitem nicht einziger Vertreter Ubuntu ist, verwenden libapt mit den .deb-Paketen. Und Debian an sich ist mehr als nur Linux! Es existieren auch Gnu/Hurd- und BSD-Releases.

Interessierte können einen bestimmt nicht vollständigen Stammbaum von Debian unter http://www.debian.org/misc/children-distros.de.html nachschlagen.

Und um die Pakete für genau diese Debian-Familie geht es in diesem Artikel.

1.2 Paketmanager

Doch was machen diese Paketmanager? Zu den Aufgaben der Paketmanager gehört neben der Installation von Software auch die Deinstallation, das Auflösen von Abhängigkeiten, die dafür sorgt, dass die Software nicht alle benötigten Bibliotheken mitbringen muss und sich trotzdem darauf verlassen kann, dass die benötigten Bibliotheken vorhanden sind.

2 Auf geht's

2.1 Voraussetzungen

Für den ersten Teil des Artikels wird neben dem Buildsystem, ich werde nur g++ verwenden, und der -dev-Version von libgtkmm die Debian-Tools benötigt.


2.2 Das Programm

Als zu Software verwende ich das Beispielprogramm, das schon im Artikel zur «Softwareinstallation unter Linux» von joomoo verwendet wurde:

C++:
1
2
3
4
5
6
7
8
9
10
11
#include <gtkmm.h>
 
int main(int argc, char** argv)
{
    Gtk::Main kit(argc, argv);
    Gtk::Window win;
    Gtk::Image img("/usr/share/hallowelt/hallowelt.png");
    win.add(img);
    win.show_all();
    kit.run(win);
}


2.3 Die Umgebung

Die Debian-Tools erwarten, dass sich die Software, die wir packen wollen in einem Verzeichnis nach dem Muster <paketname>-<version> befindet. Auch wenn man dies umgehen kann, halten wir uns erst einmal an diese Vorgaben und erstellen das Verzeichnis hallowelt-1.0.0/ und legen das obige C++-Programm dort ab.

Auch das Bild legen wir hier ab. Wer will, kann sich überzeugen, dass er das Programm jetzt mit g++ kompilieren kann. Allerdings sollte am Ende das Verzeichnis nur

enthalten, im Allgemeinen ein sauberes Sourcearchiv ohne Überreste von Builds oder ähnlichem.

3 Zum ersten Debian-Paket

3.1 Die Grundstruktur

Die Grundstruktur eines Debian-Paketes wird mit dem Tool dh_make erstellt:

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ ls -lh
insgesamt 12K
-rw-r--r-- 1 christoph christoph 2,4K 2008-02-15 21:07 hallowelt.png
-rw-r--r-- 1 christoph christoph  175 2008-02-15 21:06 hallowelticon.png
-rw-r--r-- 1 christoph christoph  210 2008-02-15 20:56 main.cpp
$ dh_make --createorig -e christoph@coders-nemesis.eu
 
Type of package: single binary, multiple binary, library, kernel module or cdbs?
 [s/m/l/k/b] s
 
Maintainer name : Christoph Egger
Email-Address   : christoph@coders-nemesis.eu
Date            : Fri, 15 Feb 2008 21:08:59 +0100
Package Name    : hallowelt
Version         : 1.0.0
License         : blank
Type of Package : Single
Hit <enter> to confirm:
Currently there is no top level Makefile. This may require additional tuning.
Done. Please edit the files in the debian/ subdirectory now. You should also
check that the hallowelt Makefiles install into $DESTDIR and not in / .


Mit dem Schalter --createorig (-r) teilen wir mit, dass noch kein Tarball mit allen Dateien besteht (dieser wird normalerweise verwendet um die Modifikationen des Paketbaus von der Software selbst zu trennen). dh_make erstellt dann einen solchen im Verzeichnis, in dem sich auch das Verzeichnis hallowelt-1.0.0 befindet.

Mit der Option -e E-Mail-Adresse geben wir unsere E-Mail-Adresse an, da dh_make sonst username@computername annimmt, was in unserem Fall wenig Sinn macht.

Code:
$ ls .. -lh
insgesamt 12K
drwxr-xr-x 3 christoph christoph 4,0K 2008-02-15 21:09 hallowelt-1.0.0
drwxr-xr-x 2 christoph christoph 4,0K 2008-02-15 21:07 hallowelt-1.0.0.orig


Danach fragt dh_make welcher Art die Software ist, die wir packen wollen. Ich habe hier single binary gewählt. Dann gibt es einen Überblick über die Paketdaten - wir können diese später jederzeit ändern.

Zum Schluss werden wir noch darauf hingewiesen, dass dh_make kein Makefile gefunden hat und wir uns selbst um die Erstellung der Software kümmern müssen.

Wenn alles glatt gelaufen ist, sollte sich jetzt in unserem Projektverzeichnis (hallowelt-1.0.0) ein Unterverzeichnis debian befinden, das in etwa so aussieht:

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ ls -lh debian
insgesamt 116K
-rw-r--r-- 1 christoph christoph  193 2008-02-15 21:09 changelog
-rw-r--r-- 1 christoph christoph    2 2008-02-15 21:09 compat
-rw-r--r-- 1 christoph christoph  337 2008-02-15 21:09 control
-rw-r--r-- 1 christoph christoph  672 2008-02-15 21:09 copyright
-rw-r--r-- 1 christoph christoph   87 2008-02-15 21:09 cron.d.ex
-rw-r--r-- 1 christoph christoph   17 2008-02-15 21:09 dirs
-rw-r--r-- 1 christoph christoph    0 2008-02-15 21:09 docs
-rw-r--r-- 1 christoph christoph 1,3K 2008-02-15 21:09 emacsen-install.ex
-rw-r--r-- 1 christoph christoph  477 2008-02-15 21:09 emacsen-remove.ex
-rw-r--r-- 1 christoph christoph 1,2K 2008-02-15 21:09 emacsen-startup.ex
-rw-r--r-- 1 christoph christoph  241 2008-02-15 21:09 hallowelt-default.ex
-rw-r--r-- 1 christoph christoph  541 2008-02-15 21:09 hallowelt.doc-base.EX
-rw-r--r-- 1 christoph christoph 4,1K 2008-02-15 21:09 init.d.ex
-rw-r--r-- 1 christoph christoph 8,4K 2008-02-15 21:09 init.d.lsb.ex
-rw-r--r-- 1 christoph christoph 1,8K 2008-02-15 21:09 manpage.1.ex
-rw-r--r-- 1 christoph christoph 4,6K 2008-02-15 21:09 manpage.sgml.ex
-rw-r--r-- 1 christoph christoph 4,5K 2008-02-15 21:09 manpage.xml.ex
-rw-r--r-- 1 christoph christoph  132 2008-02-15 21:09 menu.ex
-rw-r--r-- 1 christoph christoph  961 2008-02-15 21:09 postinst.ex
-rw-r--r-- 1 christoph christoph  934 2008-02-15 21:09 postrm.ex
-rw-r--r-- 1 christoph christoph  694 2008-02-15 21:09 preinst.ex
-rw-r--r-- 1 christoph christoph  881 2008-02-15 21:09 prerm.ex
-rw-r--r-- 1 christoph christoph  186 2008-02-15 21:09 README.Debian
-rwxr-xr-x 1 christoph christoph 1,8K 2008-02-15 21:09 rules
-rw-r--r-- 1 christoph christoph  684 2008-02-15 21:09 watch.ex


3.2 Erste Anpassungen

Im debian Verzeichnis sind jetzt jede Menge Dateien von denen wir eine ganze Menge nicht benötigen.

Da wir sie für dieses Programm nicht benötigen, können wir sie gleich löschen. Sehen wir uns an, was übriggeblieben ist.

3.2.1 debian/control

Die debian/control sollte in etwa so aussehen:

Code:
1
2
3
4
5
6
7
8
9
10
11
12
Source: hallowelt
Section: unknown
Priority: extra
Maintainer: Christoph Egger <christoph@coders-nemesis.eu>
Build-Depends: debhelper (>= 5)
Standards-Version: 3.7.2
 
Package: hallowelt
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>


<insert up to 60 chars description> ersetzen wir mit einer Kurzbeschreibung für das Programm, beispielsweise Grußprogramm,

<insert long description, indented with spaces> gibt uns Platz, etwas ausführlicher zu werden:
Code:
 hallowelt ist ein kleines Programm, das die Welt auf Deutsch grüßt.
 .
 hallowelt verwendet GTKmm als GUI-Toolkit

Dieser Text muss in jeder neuen Zeile mit einem Leerzeichen beginnen. Einen neuen Absatz erhält man mit einer Zeile, die nur ein Leerzeichen und einen Punkt enthält.

3.2.2 debian/copyright

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
This package was debianized by Christoph Egger <christoph@coders-nemesis.eu> on
Fri, 15 Feb 2008 21:08:59 +0100.
 
It was downloaded from <url://example.com>
 
Upstream Author(s):
 
    <put author's name and email here>
    <likewise for another author>
 
Copyright:
 
    <Copyright (C) YYYY Name OfAuthor>
    <likewise for another author>
 
License:
 
    <Put the license of the package here indented by 4 spaces>
 
The Debian packaging is (C) 2008, Christoph Egger <christoph@coders-nemesis.eu> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
 
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.


Wieder müssen wir anpassen, was in den spitzen Klammern steht (Ausnahme ist die E-Mail-Adresse)

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
This package was debianized by Christoph Egger <christoph@coders-nemesis.eu> on
Fri, 15 Feb 2008 21:08:59 +0100.
 
It was downloaded from http://magazin.c-plusplus.de/
 
Upstream Author(s):
 
    joomoo <jhasse@gmail.com>
 
Copyright:
 
    Copyright (C) 2008 joomoo
 
License:
 
    Veröffentlicht unter der GNU GPL v3, siehe auch /usr/share/common-licenses/GPL-3
 
The Debian packaging is (C) 2008, Christoph Egger <christoph@coders-nemesis.eu> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
 
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.


3.2.3 debian/rules

Das Herzstück der Paketierung. Es handelt sich hierbei um ein GNU-Makefile, das die Regeln für die einzelnen Schritte enthält.

Code:
1
2
3
4
5
6
7
8
build-stamp: configure-stamp
    dh_testdir
 
# Add here commands to compile the package.
    $(MAKE)
#docbook-to-man debian/hallowelt.sgml > hallowelt.1
 
    touch $@

In diesem Ausschnitt müssen wir angeben, wie die Software gebaut wird.

Ersetzen wir $(MAKE) mit g++ main.cpp -o hallowelt `pkg-config gtkmm-2.4 --cflags --libs`

Code:
1
2
3
4
5
6
7
8
install: build
    dh_testdir
    dh_testroot
    dh_clean -k
    dh_installdirs
 
# Add here commands to install the package into debian/hallowelt.
    $(MAKE) DESTDIR=$(CURDIR)/debian/hallowelt install


Hier ersetzen wir $(MAKE) DESTDIR=$(CURDIR)/debian/hallowelt install mit
Code:
    mv hallowelt debian/hallowelt/usr/bin/
    cp hallowelt.png debian/hallowelt/usr/share/hallowelt/
    cp hallowelticon.png debian/hallowelt/usr/share/icons/hallowelticon.png


Code:
1
2
3
4
5
6
7
8
9
clean:
    dh_testdir
    dh_testroot
    rm -f build-stamp configure-stamp
 
# Add here commands to clean up after the build process.
    $(MAKE) clean
 
    dh_clean

$(MAKE) clean können wir entfernen, da die ausführbare Datei bereits in das debian/hallowelt Verzeichnis verschoben wird, das von dh_clean aufgeräumt wird, und sonst keine Reste bleiben.

3.3 Bauen

Mit dpkg-buildpackage wird das Paket dann gebaut:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ dpkg-buildpackage
dpkg-buildpackage: Quellpaket hallowelt
dpkg-buildpackage: Quellversion 1.0.0-1
dpkg-buildpackage: Quellen geändert durch Christoph Egger <christoph@coders-nemesis.eu>
dpkg-buildpackage: Host-Architektur i386
 fakeroot debian/rules clean
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
# /usr/bin/make clean
dh_clean
 dpkg-source -b hallowelt-1.0.0
dpkg-source: baue hallowelt in hallowelt_1.0.0.orig.tar.gz
dpkg-source: baue hallowelt in hallowelt_1.0.0-1.diff.gz
dpkg-source: Warnung: newly created empty file 'debian/docs' will not be represented in diff
dpkg-source: baue hallowelt in hallowelt_1.0.0-1.dsc
 debian/rules build
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
dh_testdir
# Add here commands to compile the package.
g++ main.cpp -o hallowelt `pkg-config gtkmm-2.4 --cflags --libs`
#docbook-to-man debian/hallowelt.sgml > hallowelt.1
touch build-stamp
 fakeroot debian/rules binary
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/hallowelt.
mv hallowelt debian/hallowelt/usr/bin/
cp *.png debian/hallowelt/usr/share/hallowelt/
cp: angegebenes Ziel "debian/hallowelt/usr/share/hallowelt/" ist kein Verzeichnis: Datei oder Verzeichnis nicht gefunden
make: *** [install] Fehler 1
dpkg-buildpackage: Fehlschlag: fakeroot debian/rules binary gab Fehler-Exitstatus 2


Wir versuchen also, eine Datei in ein nicht existentes Verzeichnis zu kopieren. Um den Fehler zu vermeiden, teilen wir dpkg mit, welche Verzeichnisse benötigt werden. Dies geschieht in der Datei debian/dirs. Dort fügen wir jetzt folgende Einträge hinzu:
Code:
usr/share
usr/share/hallowelt
usr/share/icons

Die Verzeichnisse müssen rekursiv hinzugefügt werden, da das Erstellen von usr/share/hallowelt fehlschlagen muss, wenn usr/share nicht existiert.

Jetzt läuft dpkg-buildpackage erfolgreich durch:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
$ dpkg-buildpackage
dpkg-buildpackage: Quellpaket hallowelt
dpkg-buildpackage: Quellversion 1.0.0-1
dpkg-buildpackage: Quellen geändert durch Christoph Egger <christoph@coders-nemesis.eu>
dpkg-buildpackage: Host-Architektur i386
 fakeroot debian/rules clean
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
# /usr/bin/make clean
dh_clean
 dpkg-source -b hallowelt-1.0.0
dpkg-source: building hallowelt using existing hallowelt_1.0.0.orig.tar.gz
dpkg-source: baue hallowelt in hallowelt_1.0.0-1.diff.gz
dpkg-source: Warnung: file debian/dirs has no final newline (either original or modified version)
dpkg-source: Warnung: newly created empty file 'debian/docs' will not be represented in diff
dpkg-source: baue hallowelt in hallowelt_1.0.0-1.dsc
 debian/rules build
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
dh_testdir
# Add here commands to compile the package.
g++ main.cpp -o hallowelt `pkg-config gtkmm-2.4 --cflags --libs`
#docbook-to-man debian/hallowelt.sgml > hallowelt.1
touch build-stamp
 fakeroot debian/rules binary
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/hallowelt.
mv hallowelt debian/hallowelt/usr/bin/
cp *.png debian/hallowelt/usr/share/hallowelt/
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
dh_installdeb
dh_shlibdeps
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libgdkmm-2.4.so.1 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libatkmm-1.6.so.1 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libgtk-x11-2.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libpangomm-1.4.so.1 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libcairomm-1.0.so.1 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libsigc-2.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libgdk-x11-2.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libatk-1.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libgdk_pixbuf-2.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libpangocairo-1.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libpango-1.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libcairo.so.2 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libgobject-2.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libgmodule-2.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libdl.so.2 gelinkt werden (es verwendet keine seiner Symbole).
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libglib-2.0.so.0 gelinkt werden (es verwendet keine seiner Symbole).
dh_gencontrol
dpkg-gencontrol: Warnung: unbekannte Substitutionsvariable ${misc:Depends}
dh_md5sums
dh_builddeb
dpkg-deb: Baue Paket »hallowelt« in »../hallowelt_1.0.0-1_i386.deb«.
 signfile hallowelt_1.0.0-1.dsc
gpg: »Christoph Egger <christoph@coders-nemesis.eu>« übersprungen: Geheimer Schlüssel ist nicht vorhanden
gpg: [stdin]: clearsign failed: Geheimer Schlüssel ist nicht vorhanden
 
 dpkg-genchanges  >../hallowelt_1.0.0-1_i386.changes
dpkg-genchanges: füge kompletten Quellcode beim Hochladen hinzu
dpkg-buildpackage: Alles hochzuladen (Originalquellen enthalten)
dpkg-buildpackage: Warnung: Konnte .dsc- und .changes-Datei nicht signieren


Gehen wir die Warnungen der Reihe nach durch:
Code:
dpkg-source: Warnung: file debian/dirs has no final newline (either original or modified version)

Das ist relativ eindeutig. Ich habe vergessen, die Textdatei debian/dirs mit einem Newline-Zeichen abzuschließen. Das ist ziemlich schnell repariert also weiter zur nächsten Warnung:
Code:
dpkg-source: Warnung: newly created empty file 'debian/docs' will not be represented in diff

Die Datei debian/docs enthält eine mit Newline separierte Liste an Dateien, die die Dokumentation des Programms bilden und später unter /usr/share/doc/hallowelt/ abgelegt werden.
Diese Warnung können wir ignorieren oder eine Dokumentation erstellen und in die Datei eintragen. Kommen wir zu den nächsten Warnungen:
Code:
dpkg-shlibdeps: Warnung: debian/hallowelt/usr/bin/hallowelt sollte nicht gegen
 libgdkmm-2.4.so.1 gelinkt werden (es verwendet keine seiner Symbole).

Durch die Verwendung von `pkg-config gtkmm-2.4 --libs` haben wir einige libs mitgelinkt, die von unserem kleinen Programm gar nicht verwendet werden. Wir können uns jetzt entscheiden, die benötigten libs einzeln aufzulisten oder die Warnung ebenfalls ignorieren. Da die gtkmm von diesen Bibliotheken abhängt, bekommen wir durch ihre Verwendung keine zusätzlichen Abhängigkeiten und die libs werden auch nur dynamisch geladen, sodass dies keinen allzu großen Einfluss auf die Größe des Programms hat. Bleibt noch eine Warnung:

Code:
gpg: skipped "Christoph Egger <christoph@coders-nemesis.eu>": secret key not available


Der GPG-Fehler weist darauf hin, dass wir für die verwendete E-Mail-Adresse keinen privaten GPG-Schlüssel besitzen. GPG wird bei den Debian-Paketen dazu verwendet, den Ersteller zu identifizieren und dient nebenbei als Checksumme. Der Schlüssel wird mit gpg --gen-key erstellt. Für Näheres sei hier auf man gpg(1) verwiesen.

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$dpkg-buildpackage
[...]
dh_md5sums
dh_builddeb
dpkg-deb: Baue Paket »hallowelt« in »../hallowelt_1.0.0-1_i386.deb«.
 signfile hallowelt_1.0.0-1.dsc
 
You need a passphrase to unlock the secret key for
user: "Christoph Egger <christoph@coders-nemesis.eu>"
1024-bit DSA key, ID 8DCFF142, created 2007-12-29
 
 
 dpkg-genchanges  >../hallowelt_1.0.0-1_i386.changes
dpkg-genchanges: füge kompletten Quellcode beim Hochladen hinzu
 signfile hallowelt_1.0.0-1_i386.changes
 
You need a passphrase to unlock the secret key for
user: "Christoph Egger <christoph@coders-nemesis.eu>"
1024-bit DSA key, ID 8DCFF142, created 2007-12-29
 
 
dpkg-buildpackage: Alles hochzuladen (Originalquellen enthalten)


3.4 Das Menü

Was uns jetzt noch fehlt ist der Menüeintrag. In der debian/rules fällt hierzu der Eintrag dh_installmenu auf. Die man-Page zu diesem Befehl verrät, was wir machen müssen: Wir legen die Datei debian/hallowelt.menu an:
Code:
?package(hallowelt):needs="X11" section="Applications/Graphics"\
title="hallowelt" command="/usr/bin/hallowelt"\
icon="/usr/share/icons/helloworldicon.png"


und entfernen das '#' vor dem dh_installmenu, sodass der Befehl ausgeführt wird.

Wobei Applications/Graphics nur eine «Notlösung» ist, da ich keine bessere Kategorie gefunden habe. Eine Auflistung aller Kategorien findet man unter man 5 menufile, dort befinden sich auch weitere Informationen und optionale Argumente für den Aufbau des Menüs.

3.5 Ein Test

Jetzt ist es an der Zeit, einmal auszuprobieren, was wir bisher erreicht haben. Das Paket befindet sich in .. und kann z.B. mit sudo dpkg -i ../hallowelt_1.0.0-1_i386.deb installiert werden (i386 ist die Architektur, bei mir steht hier i386 weil ich einen Intel-kompatiblen Prozessor und ein 32bit-Linux verwende).

Wenn man jetzt sein Menü öffnet, sollte sich in der Sektion Grafik ein Eintrag Hallowelt mit dem Icon befinden. Das Programm lässt sich auch ausführen. "du" durch "man" ersetzt

Wenn man dpkg -r wieder entfernt, sollte der Menüeintrag wieder verschwunden sein und ein Starten aus einem Terminal heraus ebenfalls fehlschlagen:

Code:
$ hallowelt
bash: hallowelt: command not found


4 Der Feinschliff

4.1 lintian

Bei lintian handelt es sich um ein Programm, das die Struktur von Debian-Paketen auf Fehler überprüft. Sehen wir uns also einmal an, was sie zu unserem Hallowelt-Programm zu sagen haben:

Code:
1
2
3
4
5
6
7
8
9
10
11
12
$ cd ..
$ lintian `ls . | grep deb`
W: hallowelt: binary-without-manpage usr/bin/hallowelt
W: hallowelt: package-contains-empty-directory usr/sbin/
W: hallowelt: readme-debian-contains-debmake-template
W: hallowelt: copyright-lists-upstream-authors-with-dh_make-boilerplate
W: hallowelt: copyright-contains-dh_make-todo-boilerplate
E: hallowelt: menu-icon-not-in-xpm-format /usr/share/icons/helloworldicon.png
W: hallowelt: spelling-error-in-description programm program
E: hallowelt: section-is-dh_make-template
W: hallowelt: new-package-should-close-itp-bug
W: hallowelt: wrong-bug-number-in-closes l3:#nnnn


Von oben nach unten:


  1. Die Debian-Policy fordert, dass für jedes Programm eine Man-Page existiert. Da aber hallowelt keinerlei Optionen anbietet und keinerlei Nutzen hat, können wir das wohl getrost ignorieren.
  2. Die Datei debian/dirs enthält noch eine Zeile usr/sbin (sbin steht für System Binary), aber wir legen nichts in diesem Verzeichnis ab. Diese Warnung können wir also mit dem Entfernen der entsprechenden Zeile aus der debian/dirs beheben.
  3. Die debian/README.Debian enthält noch «Template-Text». Sehen wir uns die Datei an:
    Code:
    hallowelt for Debian
    --------------------
     
    <possible notes regarding this package - if none, delete this file>
     
     -- Christoph Egger <christoph@coders-nemesis.eu>  Fri, 15 Feb 2008 21:08:59 +0100

    Schreiben wir also etwas Sinnvolles hinein und ersetzen den Text in den spitzigen Klammern (einschließlich der Klammern).

    Das gleiche können wir für die anderen «Template-Fehler» machen.
  4. copyright-lists-upstream-authors-with-dh_make-boilerplate - Wenn wir in unsere debian/copyright sehen, stellen wir fest, dass dort Upstream Author(s) steht. Da wir nur einen Upstream Author haben entfernen wir das (s) einfach (sollten es mehrere Upstream Authors sein müssen die Klammern entfernt werden)
  5. Ebenfalls in der debian/copyright befindet sich noch folgende Anmerkung:
    Code:
    # Please also look if there are files or directories which have a
    # different copyright/license attached and list them here.
    Auch diese können wir (nachdem wir den Hinweis beachtet haben) herauslöschen.
  6. Das Icon ist nicht im xpm-Format. Auch hierbei handelt es sich um einen Bestandteil der Debian-Policy, das Paket funktioniert aber auch, wie wir gesehen haben, mit dem png-Icon.
  7. Hier sehen wir etwas Interessantes: lintian prüft die Rechtschreibung (allerdings nur die englische, Paketbeschreibungen sollten an sich immer Englisch sein)
  8. Die Section «unknown» (jetzt geht es nicht um Menü-Sektionen, sondern um die Anwendung selbst) existiert nicht. Wir entscheiden uns für die Sektion «devel», da das Paket ja als «Hilfe» zum Entwickeln gedacht ist (dies orientiert sich auch an dem Beispielpaket hello, das bereits im Repository ist und denselben Zweck hat wie unser Paket).
  9. Wenn für die Debian-Distribution gepackt wird, erstellt der Packager einen «Fehlerbericht», in dem er seine Absichten ankündigt. Dies geschieht als Fehler des «Pakets» wnpp, das ausschließlich für diesen Zweck existiert. Dieser Fehlerbericht wird natürlich hinfällig, wenn das Paket fertig ist, daher sollte das Paket den Fehlerbericht schließen. Da wir keinen WNPP-Fehlerbericht erstellt haben, müssen wir den Fehler wohl ignorieren. In der debian/changelog entfernen wir außerdem den Rest der Zeile, die mit « * initial Release» beginnt.


Sehen wir uns an, was wir erreicht haben:
Code:
$ ( cd hallo* ; dpkg-buildpackage -uc -us) ; lintian `ls . | grep deb`
[..]
W: hallowelt: binary-without-manpage usr/bin/hallowelt
E: hallowelt: menu-icon-not-in-xpm-format /usr/share/icons/helloworldicon.png
W: hallowelt: new-package-should-close-itp-bug


Sieht schon deutlich besser aus.

4.2 pbuilder

Bis jetzt haben wir das Paket mit dpkg-buildpackage gebaut. Man kann dies als den «schnellen Weg» bezeichnen, allerdings empfiehlt es sich, sollte man das Paket später veröffentlichen wollen, dem Umweg über pbuilder zu nehmen. pbuilder stellt sicher, dass alle Abhängigkeiten des Pakets erfüllt sind und nicht gegen neuere Bibliotheken gelinkt wird, die man sich auf seinem Arbeitssystem installiert hat, die aber für die Zieldistribution noch nicht vorhanden sind.

Außerdem ist es mit pbuilder möglich, das Paket für verschiedene Distributionen zu bauen, auch für verschiedene Debian-Erben, ohne sich jedes dieser Systeme installieren zu müssen.

4.2.1 Setup

Als erstes muss, nachdem pbuilder installiert wurde, eine Umgebung errichtet werden. Dies geschiet mit dem Kommando
Code:
sudo pbuilder --create [--distribution NAME]

Wird keine Distribution angegeben, so wird ein pbuilder für die aktuell verwendete Distribution errichtet. pbuilder initialisiert hier eine base.tgz, die alle wichtigen Dateien enthält. Wenn man mit --basetgz ein Ort angegeben hat, kann man auch pbuilder-Umgebungen für verschiedene Distributionen errichten.

4.3.2 Der erste Durchlauf

Zum Bauen mit pbuilder wird ein sogenanntes Source-Paket benötigt. dpkg-buildpackage baut ein solches gleich mit (man kann das durch die Option -b abschalten), sodass wir gleich anfangen können. Später können wir uns das Kompilieren beim dpkg-buildpackage sparen, indem wir die Option -S verwenden, kompiliert wird das Ganze ja im pbuilder.

Der Aufruf erfolgt über
Code:
sudo pbuilder --build *.dsc


Und schon wieder gibt es einige Fehler zu beheben:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
$ sudo pbuilder --build `ls . | grep dsc`
[sudo] password for christoph:
W: /home/christoph/.pbuilderrc does not exist
I: using fakeroot in build.
Current time: Mon Mar 17 14:40:54 CET 2008
pbuilder-time-stamp: 1205761254
Building the build Environment
 -> extracting base tarball [[b][/b]/var/cache/pbuilder/base.tgz]
 -> creating local configuration
 -> copying local configuration
 -> mounting /proc filesystem
 -> mounting /dev/pts filesystem
 -> policy-rc.d already exists
Obtaining the cached apt archive contents
Installing the build-deps
dpkg-architecture: warning: no utmp entry available and LOGNAME not defined; using uid of process (0)
 -> Attempting to satisfy build-dependencies
 -> Creating pbuilder-satisfydepends-dummy package
Package: pbuilder-satisfydepends-dummy
Version: 0.invalid.0
Architecture: i386
Maintainer: Debian Pbuilder Team <pbuilder-maint@lists.alioth.debian.org>
Description: Dummy package to satisfy dependencies with aptitude - created by pbuilder
 This package was created automatically by pbuilder and should
Depends: debhelper (>= 5)
dpkg-deb: building package `pbuilder-satisfydepends-dummy' in `/tmp/satisfydepends-aptitude/pbuilder-satisfydepends-dummy.deb'.
Reading package lists... Done
Building dependency tree... Done
aptitude is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Selecting previously deselected package pbuilder-satisfydepends-dummy.
(Reading database ... 9699 files and directories currently installed.)
Unpacking pbuilder-satisfydepends-dummy (from .../pbuilder-satisfydepends-dummy.deb) ...
dpkg: dependency problems prevent configuration of pbuilder-satisfydepends-dummy:
 pbuilder-satisfydepends-dummy depends on debhelper (>= 5); however:
  Package debhelper is not installed.
dpkg: error processing pbuilder-satisfydepends-dummy (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 pbuilder-satisfydepends-dummy
Reading package lists... Done
Building dependency tree... Done
Initializing package states... Done
Building tag database... Done
The following NEW packages will be automatically installed:
  debhelper file gettext gettext-base html2text intltool-debian libmagic1 po-debconf
The following NEW packages will be installed:
  debhelper file gettext gettext-base html2text intltool-debian libmagic1 po-debconf
The following packages are RECOMMENDED but will NOT be installed:
  curl libcompress-zlib-perl libmail-sendmail-perl lynx lynx-cur wget
0 packages upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
Need to get 0B/3370kB of archives. After unpacking 11.3MB will be used.
Writing extended state information... Done
Selecting previously deselected package libmagic1.
(Reading database ... 9699 files and directories currently installed.)
Unpacking libmagic1 (from .../libmagic1_4.17-5etch2_i386.deb) ...
Selecting previously deselected package file.
Unpacking file (from .../file_4.17-5etch2_i386.deb) ...
Selecting previously deselected package html2text.
Unpacking html2text (from .../html2text_1.3.2a-3_i386.deb) ...
Selecting previously deselected package gettext-base.
Unpacking gettext-base (from .../gettext-base_0.16.1-1_i386.deb) ...
Selecting previously deselected package gettext.
Unpacking gettext (from .../gettext_0.16.1-1_i386.deb) ...
Selecting previously deselected package intltool-debian.
Unpacking intltool-debian (from .../intltool-debian_0.35.0+20060710.1_all.deb) ...
Selecting previously deselected package po-debconf.
Unpacking po-debconf (from .../po-debconf_1.0.8_all.deb) ...
Selecting previously deselected package debhelper.
Unpacking debhelper (from .../debhelper_5.0.42_all.deb) ...
Setting up libmagic1 (4.17-5etch2) ...
 
Setting up file (4.17-5etch2) ...
Setting up html2text (1.3.2a-3) ...
 
Setting up gettext-base (0.16.1-1) ...
 
Setting up gettext (0.16.1-1) ...
 
Setting up intltool-debian (0.35.0+20060710.1) ...
Setting up po-debconf (1.0.8) ...
Setting up debhelper (5.0.42) ...
Setting up pbuilder-satisfydepends-dummy (0.invalid.0) ...
 -> Finished parsing the build-deps
Reading package lists... Done
Building dependency tree... Done
fakeroot is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Copying back the cached apt archive contents
Copying source file
    -> copying [hallowelt_1.0.0-1.dsc]
    -> copying [./hallowelt_1.0.0.orig.tar.gz]
    -> copying [./hallowelt_1.0.0-1.diff.gz]
Extracting source
dpkg-source: extracting hallowelt in hallowelt-1.0.0
dpkg-source: unpacking hallowelt_1.0.0.orig.tar.gz
dpkg-source: applying ./hallowelt_1.0.0-1.diff.gz
 -> Building the package
dpkg-buildpackage: source package is hallowelt
dpkg-buildpackage: source version is 1.0.0-1
dpkg-buildpackage: source changed by Christoph Egger <christoph@coders-nemesis.eu>
dpkg-buildpackage: host architecture i386
dpkg-buildpackage: source version without epoch 1.0.0-1
 fakeroot debian/rules clean
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
# /usr/bin/make clean
dh_clean
 dpkg-source -b hallowelt-1.0.0
dpkg-source: building hallowelt using existing hallowelt_1.0.0.orig.tar.gz
dpkg-source: building hallowelt in hallowelt_1.0.0-1.diff.gz
dpkg-source: building hallowelt in hallowelt_1.0.0-1.dsc
 debian/rules build
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
dh_testdir
# Add here commands to compile the package.
g++ main.cpp -o hallowelt `pkg-config gtkmm-2.4 --cflags --libs`
/bin/sh: pkg-config: command not found
main.cpp:1:20: error: gtkmm.h: No such file or directory
main.cpp: In function 'int main(int, char**)':
main.cpp:5: error: 'Gtk' has not been declared
main.cpp:5: error: expected `;' before 'kit'
main.cpp:6: error: 'Gtk' has not been declared
main.cpp:6: error: expected `;' before 'win'
main.cpp:7: error: 'Gtk' has not been declared
main.cpp:7: error: expected `;' before 'img'
main.cpp:8: error: 'win' was not declared in this scope
main.cpp:8: error: 'img' was not declared in this scope
main.cpp:10: error: 'kit' was not declared in this scope
make: *** [build-stamp] Error 1
pbuilder: Failed autobuilding of package
 -> Aborting with an error
 -> unmounting dev/pts filesystem
 -> unmounting proc filesystem
 -> cleaning the build env
    -> removing directory /var/cache/pbuilder/build//7581 and its subdirectories


Zuerst «installiert» pbuilder einige Pakete in seiner Umgebung, dann versucht er, das Paket zu bauen. Allerdings kann pbuilder weder das Programm pkg-config noch die gtkmm-Header finden. Dies ist auch logisch, wenn man sich die debian/control ansieht. Fügen wir dort also bei den Build-Depends (mit einem Komma abgetrennt) das Paket «libgtkmm-2.4-dev» hinzu. Das ganze sieht dann in etwa so aus:

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Source: hallowelt
Section: devel
Priority: extra
Maintainer: Christoph Egger <christoph@coders-nemesis.eu>
Build-Depends: debhelper (>= 5), libgtkmm-2.4-dev
Standards-Version: 3.7.2
 
Package: hallowelt
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Grußprogramm
 hallowelt ist ein kleines Programm, das die Welt auf Deutsch grüßt.
 .
 hallowelt verwendet GTKmm als GUI-Toolkit


Jetzt sollte der Build fehlerfrei durchlaufen (Neubau des Source-Pakets nicht vergessen bevor der pbuilder aufgerufen wird!) und das Ergebnis unserer Arbeit unter /var/cache/pbuilder/result zu finden sein:

Code:
$ ls -lh /var/cache/pbuilder/result
insgesamt 35M
-rw-r--r-- 1 christoph christoph 2,5K 2008-03-17 14:55 hallowelt_1.0.0-1.diff.gz
-rw-r--r-- 1 christoph christoph  356 2008-03-17 14:55 hallowelt_1.0.0-1.dsc
-rw-r--r-- 1 christoph christoph  732 2008-03-17 14:56 hallowelt_1.0.0-1_i386.changes
-rw-r--r-- 1 christoph christoph 7,4K 2008-03-17 14:56 hallowelt_1.0.0-1_i386.deb
-rw-r--r-- 1 christoph christoph 2,9K 2008-02-15 21:56 hallowelt_1.0.0.orig.tar.gz


Nachdem dieses Paket installiert wurde, kann man mit aptitude show hallowelt noch einmal betrachten, was zu unserem Paket zu sagen ist:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ aptitude show hallowelt
Kann kein Archiv »testing« für das Paket »hallowelt« finden
Paket: hallowelt
Neu: ja
Zustand: Installiert
Automatisch installiert: ja
Version: 1.0.0-1
Priorität: extra
Bereich: devel
Verwalter: Christoph Egger <christoph@coders-nemesis.eu>
Unkomprimierte Größe: 81,9k
Hängt ab von: libatk1.0-0 (>= 1.12.2), libc6 (>= 2.3.6-6), libcairo2 (>= 1.2.4),
          libfontconfig1 (>= 2.4.0), libgcc1 (>= 1:4.1.1-12), libglib2.0-0 (>=
               2.12.0),
          libglibmm-2.4-1c2a, libgtk2.0-0 (>= 2.8.0), libgtkmm-2.4-1c2a,
          libpango1.0-0 (>= 1.14.8), libsigc++-2.0-0c2a (>= 2.0.2),
               libstdc++6 (>= 4.1.1-12),
          libx11-6, libxcursor1 (> 1.1.2), libxext6,
          libxfixes3 (>= 1:4.0.1), libxi6, libxinerama1, libxrandr2,
          libxrender1
Beschreibung: Application greeting the world
 hallowelt ist ein kleines Program, das die Welt auf Deutsch grüßt.
 
 hallowelt uses the gtkmm library as it's graphics toolkit.


Da wir als build-Abhängigkeit libgtkmm-2.4-dev angegeben haben, hat pbuilder (und auch dpkg-buildpackage) bereits einiges an Abhängigkeiten hinzugefügt, ohne dass wir uns darum kümmern müssen. Hier zeigt sich, warum das Verwenden von pbuilder so hilfreich ist, um korrekte Pakete zu erstellen.

5 Tipps, Tricks & Sonstiges

An dieser Stelle möchte ich noch ein paar Tipps loswerden.

Manchmal ist es nicht so einfach, die richtigen Abhängigkeiten zu finden, um das Paket zu bauen. Insbesondere wenn diese Pakete alle bereits installiert waren und für das Entwickeln nicht installiert werden mussten oder wenn man Fremdsoftware packt. Hier hilft das tool apt-file, mit dem man die Paketquellen nach Dateinamen durchsuchen kann.

Beim Gegentesten des Artikels auf meinem alten PC mit Ubuntu 7.10 ist mir aufgefallen, dass sich das Verhalten bei einigen Details von dem meines Notebooks mit Debian lenny unterscheidet. So war z.B. unter Ubuntu die explizite Angabe von -rfakeroot nötig, während Debian fakeroot gleich mitinstalliert und verwendet hatte. Auch scheint der Menüeintrag im GNOME-Menü nicht zu erscheinen. Das fluxbox meines Notebooks hat hier keine Probleme gemacht.

Alle wichtigen Informationen sind auf der Debian-Website im Entwicklerbereich vorhanden:
http://www.debian.org/devel/
Und zum Paketbau direkt:
http://www.debian.org/doc/manuals/maint-guide/index.de.html

6 Schlusswort

Ich hoffe, ich konnte in diesem Artikel einen kleinen Einblick in den Paketbau für Debian-Systeme geben und dem einen oder anderen hier weiterhelfen.

Natürlich ist hier bei weitem noch nicht alles abgedeckt; das Verfahren, eine Bibliothek zu packen, unterscheidet sich deutlich, man-pages müssen normalerweise vorhanden sein und bei komplexeren Programmen müssen mehr und komplexere Abhängigkeiten betrachtet werden.

Ich wünsche viel Spaß beim Packen und vielleicht wird hier ja noch der eine oder andere irgendwann Debian-Maintainer ;).

Sie können Kommentare zu diesem Artikel im Forum schreiben. (Eine Registrierung ist nicht notwendig.)

Logo-Design: MastaMind Webdesign