# 10. Gemeinsame Bibliotheken

Gemeinsame Bibliotheken sind kompilierter Code, der von vielen verschiedenen Programmen gemeinsam genutzt wird. Sie werden als `.so`-Dateien unter `/usr/lib/` zur Verfügung gestellt.

Eine Bibliothek exportiert Symbole, welche die kompilierten Versionen von Funktion, Klassen und Variablen sind. Eine Bibliothek wird als SONAME bezeichnet und beinhaltet eine Versionsnummer. Dieser SONAME entspricht nicht zwingend der öffentlichen Versionsbezeichnung. Ein Programm wird gegen eine gegebene SONAME-Version der Bibliothek kompiliert. Wenn eines der Symbole entfernt oder geändert wird, muss die Versionsnummer angepasst werden, was dazu führt, dass jedes Paket welches die Bibliothek benutzt, wieder gegen die neue Version kompiliert werden musss. Versionsnummern werden normalerweise vom Upstream festgelegt und wir folgen ihnen mit unseren Binärpaketnamen, auch ABI-Nummer genannt. Aber manchmal benutzt der Upstream keine vernünftigen Versionsnummern und die Paketierer müssen einer getrennten Nummerierung folgen.

Libraries are usually distributed by upstream as standalone releases. Sometimes they are distributed as part of a program. In this case they can be included in the binary package along with the program (this is called bundling) if you do not expect any other programs to use the library, more often they should be split out into separate binary packages.

Die Bibliotheken selbst werden in einem Binärpaket mit dem Namen `libfoo1` abgelegt, wobei `foo` der Name der Bibliothek und `1` die SONAME-Version ist. Entwicklungsdateien aus dem Paket, beispielsweise Kopfdateien, die benötigt werden, um Programme gegen die Bibliothek zu übersetzen, werden in einem Paket mit dem Namen `libfoo-dev` abgelegt.

## 10.1. Ein Beispiel

Wir werden libnova als Beispiel verwenden:

    $ bzr branch ubuntu:trusty/libnova
    $ sudo apt-get install libnova-dev

Um den SONAME der Bibliothek herauszufinden, starte:

    $ readelf -a /usr/lib/libnova-0.12.so.2 | grep SONAME

The SONAME is `libnova-0.12.so.2`, which matches the file name (usually the case but not always). Here upstream has put the upstream version number as part of the SONAME and given it an ABI version of `2`. Library package names should follow the SONAME of the library they contain. The library binary package is called `libnova-0.12-2` where `libnova-0.12` is the name of the library and `2` is our ABI number.

Wenn im Upstream inkompatible Änderungen an den Bibliotheken durchgeführt werden, müssen sie eine neue Revision des SONAME erstellen und wir werden unsere Bibliothek umbenennen müssen. Jedes andere Paket welches unsere Bibliothek verwendet, muss dann wieder gegen die neue Version kompiliert werden; das nennt man Transition und kann einigen Aufwand verursachen. Im besten Fall bleibt unsere ABI-Nummer passend zu SONAME des Upstreams, aber manchmal führen sie Inkompatibilitäten ein ohne ihre Versionsnummer zu ändern und so müssen wir unsere anpassen.

Wenn wir uns debian/libnova-0.12-2.install ansehen, stellen wir fest, dass dort zwei Dateien eingebunden werden:

    usr/lib/libnova-0.12.so.2
    usr/lib/libnova-0.12.so.2.0.0

Das letzte is die eigentliche Bibliothek, komplett mit Unter- und Punkversionsnummer. Das erste ist ein Symlink welcher auf die eigentliche Bibliothek verweist. Der Symlink ist das, nach dem die Programme welche Bibliothek benutzen suchen, sie kümmern sich nicht um die Unterversionsnummern.

`libnova-dev.install` beinhaltet alle benötigten Dateien um das Programm mit dieser Bibliothek zu kompilieren. Kopfdateien, eine Konfigurationsbinärdatei, die libtool Datei `.la` und `libnova.so`, welche als weiterer Symlink zu der Bibliothek führt; Programme die gegen die Bibliothek kompiliert werden kümmern sich nicht um die Hauptversionsnummer (jedoch wird das die Binärdatei in die sie kompilieren berücksichtigen).

`.la` libtool Dateien werden für manche nicht-Linux Systeme mit beschränkter Bibliotheksunterstützung benötigt. Sie bringen aber im Normalfall auf Debian basierenden Systemen mehr Probleme mit, als sie lösen. Es ist daher eines der derzeit wichtigsten Ziele alle .la Dateien auf Debian-Systemen zu entfernen und daran sollte jeder mitarbeiten.

## 10.2. Statische Bibliotheken

Das -dev Paket stellt außerdem `usr/lib/libnova.a` bereit. Dies ist eine statische Bibliothek, eine Alternative zu gemeinsamen Bibliotheken. Jedes gegen diese statische Bibliothek kompilierte Programm beinhaltet diesen Quelltext. Damit entfällt das Problem, die Bibliothek könnte als Binärdatei inkompatibel sein. Allerdings bedeutet dies auch, dass alle Fehler, die Sicherheitsprobleme inbegriffen, nicht behoben werden, solange das Programm nicht erneut kompiliert wird. Aus diesem Grund sind Programme, die statische Bibliotheken verwenden, zu vermeiden.

## 10.3. Symbol-Dateien

When a package builds against a library the `shlibs` mechanism will add a package dependency on that library. This is why most programs will have `Depends: ${shlibs:Depends}` in `debian/control`. That gets replaced with the library dependencies at build time. However shlibs can only make it depend on the major ABI version number, `2` in our libnova example, so if new symbols get added in libnova 2.1 a program using these symbols could still be installed against libnova ABI 2.0 which would then crash.

Um die Bibliotheksabhängigkeiten präzise zu halten, verwenden wir `.symbols`-Dateien, die alle Symbole in einer Bibliothek auflisten und in welcher Version sie zuerst auftauchten.

libnova hat keine Symboldatei, also können wir eine erstellen. Beginne damit das Paket zu kompilieren:

    $ bzr builddeb -- -nc

Die Option `-nc` sorgt dafür, dass nach dem Kompilieren die Dateien des Programms, die währenddessen erzeugten wurden, nicht entfernt werden. Wechseln Sie in das Verzeichnis des Kompilierungsprozesses und führen Sie `dpkg-gensymbols` für das Bibliothekspaket aus:

    $ cd ../build-area/libnova-0.12.2/
    $ dpkg-gensymbols -plibnova-0.12-2 > symbols.diff

Dies erstellt eine Diff-Datei welche du selbst anwenden kannst:

    $ patch -p0 < symbols.diff

Which will create a file named similar to `dpkg-gensymbolsnY_WWI` that lists all the symbols. It also lists the current package version. We can remove the packaging version from that listed in the symbols file because new symbols are not generally added by new packaging versions, but by the upstream developers:

    $ sed -i s,-0ubuntu2,, dpkg-gensymbolsnY_WWI

Nun verschiebe die Datei an ihren Ort, comitte und mache eine Testlauf:

    $ mv dpkg-gensymbolsnY_WWI ../../libnova/debian/libnova-0.12-2.symbols
    $ cd ../../libnova
    $ bzr add debian/libnova-0.12-2.symbols
    $ bzr commit -m "add symbols file"
    $ bzr builddeb

Wenn es erfolgreich kompiliert ist die Symboldatei in Ordnung. Mit der nächsten Upstream-Version von libnova würdest du erneut dpkg-gensymbols ausführen und es liefert eine Auflistung der Unterschiede um die Symboldatei zu aktualisieren.

## 10.4. C++-Bibliothek-Symboldateien

C++ hat noch genauere Standards für das Kompilieren als Binärdatei als C. Das Debian Qt/KDE Projekt betreut einige Scripte um dies zu vereinfachen. Lesen Sie die Seite »Arbeiten mit Symboldateien«_ um zu erfahren, wie diese zu benutzen sind.

## 10.5. Weiterführende Literatur

Junichi Uekawa’s Debian Library Packaging Guide erklärt das Thema detaillierter.