Kapitel 3. Den Quellcode verändern

# Kapitel 3. Den Quellcode verändern

Die Überarbeitung dieser Anleitung mit aktualisierten Inhalten und weiteren praktischen Beispielen ist unter Guide for Debian Maintainers verfügbar. Bitte verwenden Sie diese neue Anleitung als primäre Anleitung.

Bitte beachten Sie, dass an dieser Stelle nicht auf alle Details eingegangen wird, wie die ursprünglichen Quellen korrigiert werden können, aber hier sind ein paar grundlegende Schritte und Probleme, auf die man häufig stößt.

## 3.1. Einrichten von quilt

Das Programm quilt bietet eine grundlegende Methode, um Änderungen an den ursprünglichen Quellen für das Debian-Paket aufzuzeichnen. Es ist sinnvoll, eine leicht geänderte Voreinstellung zu verwenden, daher sollte ein Alias dquilt für die Debian-Paketierung erstellt werden, indem folgendes zur `~/.bashrc` hinzugefügt wird; dabei stellt die zweite Zeile die gleiche Shell-Vervollständigungsfunktionalität wie der Befehl quilt für den Befehl dquilt bereit:

    alias dquilt="quilt --quiltrc=${HOME}/.quiltrc-dpkg"
    . /usr/share/bash-completion/completions/quilt
    complete -F _quilt_completion -o filenames dquilt

Dann erstellen Sie die `~/.quiltrc-dpkg` wie folgt:

    d=. ; while [ ! -d $d/debian -a $(readlink -e $d) != / ]; do d=$d/..; done
    if [ -d $d/debian ] && [ -z $QUILT_PATCHES ]; then
        # falls in Debian-Paketbaum mit ungesetztem $QUILT_PATCHES
        QUILT_PATCHES="debian/patches"
        QUILT_PATCH_OPTS="--reject-format=unified"
        QUILT_DIFF_ARGS="-p ab --no-timestamps --no-index --color=auto"
        QUILT_REFRESH_ARGS="-p ab --no-timestamps --no-index"
        QUILT_COLORS="diff_hdr=1;32:diff_add=1;34:diff_rem=1;31:diff_hunk=1;33:diff_ctx=35:diff_cctx=33"
        if ! [ -d $d/debian/patches ]; then mkdir $d/debian/patches; fi
    fi

Siehe quilt(1) und `/usr/share/doc/quilt/quilt.pdf.gz` für eine Anleitung, wie quilt benutzt wird.

## 3.2. Fehler in den ursprünglichen Quellen korrigieren

Nehmen wir an, Sie finden den folgenden Fehler in dem ursprünglichen `Makefile`, wo statt »`install: gentoo`« besser »`install: gentoo-target`« stehen sollte.

    install: gentoo
            install ./gentoo $(BIN)
            install icons/* $(ICONS)
            install gentoorc-example $(HOME)/.gentoorc

Wir beheben dies und speichern es mit dem Befehl quilt wie folgt als `fix-gentoo-target.patch`: [22]

    $ mkdir debian/patches
    $ dquilt new fix-gentoo-target.patch
    $ dquilt add Makefile

Sie können die Datei `Makefile` wie folgt ändern:

    install: gentoo-target
            install ./gentoo $(BIN)
            install icons/* $(ICONS)
            install gentoorc-example $(HOME)/.gentoorc

Jetzt muss dquilt noch mitgeteilt werden, dass der Patch erzeugt werden soll, so dass die Datei `debian/patches/fix-gentoo-target.patch` erstellt wird. Außerdem sollten Sie eine Beschreibung gemäß DEP-3: Patch Tagging Guidelines hinzufügen:

    $ dquilt refresh
    $ dquilt header -e
    ... Patch beschreiben

## 3.3. Installation von Dateien in ihr Zielverzeichnis

Die meisten Programme Dritter installieren sich in die Verzeichnishierachie `/usr/local`. Unter Debian ist diese für die private Benutzung durch den Systemadministrator reserviert, daher dürfen Pakete Verzeichnisse wie `/usr/local/bin` nicht verwenden, sondern sollten stattdessen Systemverzeichnisse wie `/usr/bin` verwenden und dem Filesystem Hierarchy Standard (FHS) folgen.

Normalerweise wird make(1) benutzt, um das Programm automatisch zu bauen. Der Aufruf von »`make install`« installiert das Programm dann direkt in das Ziel (gemäß dem `install`-Ziel des `Makefile`s). Damit Debian vorab erstellte installierbare Pakete bereitstellen kann, verändert es das Bausystem, um Programme in ein Dateisystem-Abbild, welches unter einem temporären Verzeichnis erstellt wurde, anstatt in das tatsächliche Ziel zu installieren.

Diese beiden Unterschiede zwischen einerseits der normalen Programminstallation und andererseits dem Paketieren für Debian können vom Paket `Debhelper` transparent adressiert werden. Es benutzt dazu die Befehle dh_auto_configure und dh_auto_install, sofern die folgenden Bedingungen erfüllt sind:

- Das `Makefile` muss den GNU-Konventionen folgen und die Variable `$(DESTDIR)` unterstützen. [23]

- Die Quelle muss dem »Filesystem Hierarchy Standard« (FHS) folgen.

Programme, die GNU autoconf einsetzen, folgen automatisch den GNU-Konventionen, so dass sie trivial zu paketieren sind. Aufgrund dieser Tatsache und weiterer Heuristik wird geschätzt, dass das Paket `debhelper` für ungefähr 90% aller Pakete richtig funktionieren wird, ohne dass irgendwelche tiefgreifenden Änderungen an deren Build-Systemen vorgenommen werden müssen. Daher ist das Paketieren nicht so kompliziert, wie es zunächst aussieht.

Falls Sie Änderungen an dem `Makefile` vornehmen müssen, sollten Sie vorsichtig sein, dass die Variable `$(DESTDIR)` unterstützt wird. Obwohl sie standardmäßig nicht gesetzt ist, wird die Variable `$(DESTDIR)` jedem Dateipfad vorangestellt, der für die Programminstallation verwendet wird. Das Skript für das Paketieren setzt `$(DESTDIR)` auf das temporäre Verzeichnis.

Bei einem Quellpaket, das ein einzelnes Binärpaket erstellt, wird das temporäre Verzeichnis, das vom Befehl dh_auto_install benutzt wird, auf `debian/`Paket`` gesetzt. [24] Alles, was im temporären Verzeichnis enthalten ist, wird auf dem System eines Benutzers installiert, wenn dieser Ihr Paket installiert. Der einzige Unterschied ist, dass dpkg die Dateien relativ zum Wurzelverzeichnis statt zu Ihrem Arbeitsverzeichnis installieren wird.

Vergessen Sie nicht, dass Ihr Programm zwar unter `debian/`Paket`` installiert wird, es sich aber trotzdem korrekt verhalten muss, wenn es aus dem `.deb`-Paket unter dem Wurzelverzeichnis installiert wird. Daher dürfen durch das Build-System keine fest eingestellten Zeichenketten wie `/home/ich/deb/`Paket`-`Version`/usr/share/`Paket`` für Dateien im Paket festgeschrieben werden.

Dies ist der relevante Abschnitt aus dem `Makefile`[25] von `gentoo`:

    # Where to put executable commands on 'make install'?
    BIN     = /usr/local/bin
    # Where to put icons on 'make install'?
    ICONS   = /usr/local/share/gentoo

Sie sehen, dass die Dateien unter `/usr/local` installiert werden sollen. Wie oben erklärt ist diese Verzeichnis-Hierarchie unter Debian für lokale Benutzung reserviert, ändern Sie daher diese Pfade wie folgt:

    # Where to put executable commands on 'make install'?
    BIN     = $(DESTDIR)/usr/bin
    # Where to put icons on 'make install'?
    ICONS   = $(DESTDIR)/usr/share/gentoo

Der genaue Ort, der für Programme, Icons, Dokumentation usw. verwandt werden sollte, ist im »Filesystem Hierarchy Standard« (FHS) spezifiziert. Sie sollten ihn durchblättern und die für Ihr Paket relevanten Abschnitte lesen.

Sie sollten also ausführbare Befehle in `/usr/bin/` statt `/usr/local/bin/` installieren, die Handbuchseiten in `/usr/share/man/man1/` statt `/usr/local/man/man1/` usw. Beachten Sie, dass im `Makefile` von `gentoo` keine Handbuchseite auftaucht. Da die Debian-Richtlinien aber verlangen, dass jedes Programm eine hat, schreiben Sie später eine und installieren sie unter `/usr/share/man/man1/`.

Manche Programme nutzen die `Makefile`-Variablen nicht, um solche Pfade zu definieren. Das bedeutet, dass Sie wahrscheinlich die C-Quelltexte direkt bearbeiten müssen, damit diese dann die richtigen Pfade benutzen. Aber wo soll man suchen, und wonach eigentlich genau? Sie können dies herausfinden, indem Sie folgendes eingeben:

    $ grep -nr --include='*.[c|h]' -e 'usr/local/lib' .

Grep durchsucht das Quellverzeichnis rekursiv und gibt Ihnen den Dateinamen und die Zeilennummer für alle Treffer aus.

Sie müssen diese Dateien nun bearbeiten und in den entsprechenden Zeilen `usr/local/lib` durch `usr/lib` ersetzen. Dies kann wie folgt automatisch erledigt werden:

    $ sed -i -e 's#usr/local/lib#usr/lib#g' \
            $(find . -type f -name '*.[c|h]')

Falls Sie stattdessen jede Ersetzung bestätigen möchten, kann dies wie folgt interaktiv durchgeführt werden:

    $ vim '+argdo %s#usr/local/lib#usr/lib#gce|update' +q \
            $(find . -type f -name '*.[c|h]')

Als nächstes sollten Sie das »install«-Ziel suchen (suchen Sie nach der Zeile, die mit `install:` beginnt, das funktioniert üblicherweise) und alle Verweise auf Verzeichnisse umbenennen, die nicht denen entsprechen, die Sie am Anfang des `Makefile`s definiert haben.

Ursprünglich sah das `install`-Ziel von `gentoo` wie folgt aus:

    install: gentoo-target
            install ./gentoo $(BIN)
            install icons/* $(ICONS)
            install gentoorc-example $(HOME)/.gentoorc

Wir beheben diesen Fehler der Originalautoren und speichern es mit dem Befehl dquilt als `debian/patches/install.patch`.

    $ dquilt new install.patch
    $ dquilt add Makefile

Wir ändern dies für das Debian-Paket im Editor wie folgt:

    install: gentoo-target
            install -d $(BIN) $(ICONS) $(DESTDIR)/etc
            install ./gentoo $(BIN)
            install -m644 icons/* $(ICONS)
            install -m644 gentoorc-example $(DESTDIR)/etc/gentoorc

Sie haben bemerkt, dass jetzt der Befehl »`install -d`« vor den anderen Befehlen in dieser Regel steht. Das ursprüngliche `Makefile` hatte das nicht, weil normalerweise `/usr/local/bin/` und andere Verzeichnisse schon auf dem System vorhanden sind, wenn Sie »`make install`« aufrufen. Weil wir aber in unseren frisch erstellten Verzeichnisbaum installieren, müssen wir jedes einzelne dieser Verzeichnisse anlegen.

Wir können am Ende der Regel noch weitere Dinge einfügen, wie beispielsweise die Installation zusätzlicher Dokumentation, die die Originalautoren manchmal weglassen:

            install -d $(DESTDIR)/usr/share/doc/gentoo/html
            cp -a docs/* $(DESTDIR)/usr/share/doc/gentoo/html

Überprüfen Sie alles sorgfältig und falls es in Ordnung ist, bitten Sie dquilt, den Patch zu erstellen und die Datei `debian/patches/install.patch` neu zu erstellen. Fügen Sie außerdem noch eine Beschreibung hinzu:

    $ dquilt refresh
    $ dquilt header -e
    ... Patch beschreiben

Jetzt haben Sie eine Reihenfolge von Patches.

1. Die Fehlerkorrektur der originalen Quellen: `debian/patches/fix-gentoo-target.patch`

2. Die Debian-spezifische Änderung für's Paketieren: `debian/patches/install.patch`

Wann immer Sie Änderungen machen, die nicht spezifisch für das Debian-Paket sind (so wie `debian/patches/fix-gentoo-target.patch`), sollten Sie diese dem Betreuer des Originalprogramms zukommen lassen, damit er sie in der nächsten Programmversion verwenden kann und sie für andere auch nützlich sind. Denken Sie auch daran, Ihre Patches nicht spezifisch für Debian oder Linux (oder sogar Unix!) zu gestalten, sondern sie portierbar zu erstellen. Dadurch können Ihre Änderungen wesentlich leichter übernommen werden.

Beachten Sie, dass Sie dem Originalautor die `debian/*`-Dateien nicht schicken müssen.

## 3.4. Unterschiedliche Bibliotheken

Es gibt ein anderes typisches Problem: Bibliotheken variieren oft von Plattform zu Plattform. Beispielsweise kann ein `Makefile` eine Referenz auf eine Bibliothek enthalten, die auf Debian-Systemen nicht existiert. In diesem Fall müssen wir sie auf eine Bibliothek ändern, die unter Debian existiert und den gleichen Zweck erfüllt.

Nehmen wir an, eine Datei in dem `Makefile` (oder `Makefile.in`) Ihres Programms lautet wie folgt:

    LIBS = -lfoo -lbar

Falls Ihr Programm nicht übersetzt, da die Bibliothek `foo` nicht existiert und auf Debian-Systemen ihr Äquivalent von der Bibliothek `foo2` bereitgestellt wird, können Sie dieses Bauproblem mittels `debian/patches/foo2.patch` beheben, indem Sie `foo` in `foo2` ändern: [26]

    $ dquilt new foo2.patch
    $ dquilt add Makefile
    $ sed -i -e 's/-lfoo/-lfoo2/g' Makefile
    $ dquilt refresh
    $ dquilt header -e
    … Patch beschreiben

[22] Das Verzeichnis `debian/patches` sollte inzwischen existieren, wenn Sie dh_make wie vorher beschrieben ausgeführt haben. In diesem Beispiel wird es sicherheitshalber erstellt, nur für den Fall, dass Sie ein existierendes Paket aktualisieren.

[23] Lesen Sie GNU Coding Standards: 7.2.4 DESTDIR: Support for Staged Installs.

[24] Bei einem Quellpaket, das mehrere Binärpakete erstellt, verwendet der Befehl dh_auto_install das temporäre Verzeichnis `debian/tmp`. Der Befehl dh_install teilt dann den Inhalt von `debian/tmp` mit Hilfe von `debian/`Paket-1`.install` und `debian/`Paket-2`.install` in die temporären Verzeichnisse `debian/`Paket-1`` und `debian/`Paket-2`` auf, um daraus die Binärpakete ``Paket-1`_*.deb` und ``Paket-2`_*.deb` zu erstellen.

[25] Dies ist nur ein Beispiel, wie ein `Makefile` aussehen sollte. Falls die `Makefile`-Datei durch den Befehl ./configure erstellt wird, ist die richtige Vorgehensweise, um diese Art `Makefile` zu korrigieren, ./configure durch den Befehl dh_auto_configure aufrufen zu lassen. Dabei kommen die voreingestellten Optionen zum Tragen, einschließlich der Option `--prefix=/usr`.

[26] Falls es API-Änderungen von der Bibliothek `foo` zu der Bibliothek `foo2` gibt, müssen die Quellen entsprechend angepasst werden, um zur neuen API zu passen.

Kapitel 2. Erste Schritte |  | Kapitel 4. Benötigte Dateien im Verzeichnis `debian`