Softwareinstallation für das Debian System



  • Inhalt

    1. Einleitung

    2. Das Debian-System

    3. Paketmanager

    4. Auf geht's

    5. Voraussetzungen

    6. Das Programm

    7. Die Umgebung

    8. Zum ersten Debian-Paket

    9. Grundstruktur

    10. Erste Anpassungen

    11. Bauen

    12. Das Menü

    13. Ein Test

    14. Feinschliff

    15. lintian & linda

    16. pbuilder

    17. Tipps, Tricks & Sonstiges

    18. 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.

    • debhelper - Tools zum Erstellen von Paketen.
    • dh-make - Tool um Pakete zu initiieren
    • lintian - Tool, das die fertigen Pakete überprüft.
    • fakeroot - damit man nicht jedes Mal zum Bauen Superuser-Rechte 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:

    #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

    • main.cpp
    • hallowelt.png
    • hallowelticon.png

    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:

    $ 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.

    $ 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:

    $ 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.

    • cron.d dient zum Eintragen von Cronjobs unseres Programms,
    • init.d.ex falls unser Programm beim Systemstart mitgeladen werden soll,
    • manpage.*.ex für manpage Einträge
    • pre/post inst/rm für Skripte, die vor/nach dem Installieren/Deinstallieren ausgeführt werden sollen
    • emacsen* falls sich unser Programm in Emacs integrieren soll

    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:

    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:

    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

    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)

    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.net/
    
    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.

    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 halloweltpkg-config gtkmm-2.4 --cflags --libs``

    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

    mv hallowelt debian/hallowelt/usr/bin/
    	cp hallowelt.png debian/hallowelt/usr/share/hallowelt/
    	cp hallowelticon.png debian/hallowelt/usr/share/icons/hallowelticon.png
    
    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:

    $ 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:

    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:

    $ 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:

    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:

    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:

    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:

    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.

    $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:

    ?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:

    $ 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:

    $ 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:
    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.

    1. 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)
    2. Ebenfalls in der debian/copyright befindet sich noch folgende Anmerkung:
    # 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.

    1. 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.
    2. Hier sehen wir etwas Interessantes: lintian prüft die Rechtschreibung (allerdings nur die englische, Paketbeschreibungen sollten an sich immer Englisch sein)
    3. 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).
    4. 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:

    $ ( 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

    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

    sudo pbuilder --build *.dsc
    

    Und schon wieder gibt es einige Fehler zu beheben:

    $ 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:

    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:

    $ 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:

    $ 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 ;).



  • Ohne den Artikel bereits komplett gelesen zu haben:

    Danke, ganz sauberes Timing, ich bin gerade gestern in die Situation gelangt, Debian-Pakete schnüren zu müssen. 😃



  • LordJaxom schrieb:

    Ohne den Artikel bereits komplett gelesen zu haben:

    Danke, ganz sauberes Timing, ich bin gerade gestern in die Situation gelangt, Debian-Pakete schnüren zu müssen. 😃

    Darf man fragen an was für Packeten du arbeitest?



  • Jetzt gerade brauche ich das xcfe4-modemlights-plugin für Ubuntu 7.10, für meinen eeePC. Das Paket ist übrigens fertig und funktioniert bereits. Es gibt aber artigerweise cdbs-rules für xfce4-plugins.



  • cdbs wäre interessant gewesen, aber der Artikel war fertig als ich mit cdbs angefangen habe 🙂



  • Nach dem Artikel ist vor dem Artikel 😉


Anmelden zum Antworten