Ubuntu logo

Packaging Guide

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

Bibliotheken werden normalerweise von Upstream als Einzelreleases verteilt. Manchmal werden sie auch als Teil einen Programms herausgegeben. In diesem Fall können sie einfach mit in das Programm-Paket integriert werden (wenn zu erwarten ist, dass kein anderes Programm diese Bibliothek benutzt). Meistens sollten sie jedoch getrennt werden und in gesonderte Pakete gepackt werden.

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.

8.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 files are needed on some non-Linux systems with poor library support but usually cause more problems than they solve on Debian systems. It is a current Debian goal to remove .la files and we should help with this.

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

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

8.4. C++-Bibliothek-Symboldateien

C++ has even more exacting standards of binary compatibility than C. The Debian Qt/KDE Team maintain some scripts to handle this, see their Working with symbols files page for how to use them.

8.5. Weiterführende Literatur

Junichi Uekawa’s Debian Library Packaging Guide goes into this topic in more detail.