Общие библиотеки¶
Общие библиотеки — это скомпилированный код, предназначенный для совместного использования несколькими различными программами. Они распространяются в виде файлов .so в /usr/lib/.
A library exports symbols which are the compiled versions of functions, classes and variables. A library has a name called an SONAME which includes a version number. This SONAME version does not necessarily match the public release version number. A program gets compiled against a given SONAME version of the library. If any of the symbols is removed or changes then the version number needs to be changed which forces any packages using that library to be recompiled against the new version. Version numbers are usually set by upstream and we follow them in our binary package names called an ABI number, but sometimes upstreams do not use sensible version numbers and packagers have to keep separate version numbers.
Библиотеки обычно распространяются апстримом в виде отдельных выпусков. Иногда они распространяются, как часть программы. В последнем случае они могут быть включены в двоичный пакет вместе с программой (это называется bundling), если вы не предполагаете использование этих библиотек другими программами, но чаще их всё же следует выделять в отдельные двоичные пакеты.
Сами библиотеки помещаются в двоичный пакет с именем libfoo1, где foo — имя библиотеки, а 1 — версия из SONAME. Файлы разработки из пакета, такие как заголовочные файлы, необходимые для компиляции программ с библиотекой, помещаются в пакет с именем libfoo-dev.
Пример¶
В качестве примера мы используем libnova:
$ bzr branch ubuntu:natty/libnova
$ sudo apt-get install libnova-dev
Чтобы найти SONAME библиотеки, выполните:
$ readelf -a /usr/lib/libnova-0.12.so.2 | grep SONAME
SONAME в данном случае libnova-0.12.so.2, что соответствует имени файла (как правило, но не всегда). Здесь апстрим поместил номер версии из апстрима, как часть SONAME, и задал ABI-версию 2. Имена библиотечных пакетов должны следовать SONAME библиотеки, которую они содержат. Двоичный библиотечный пакет называется libnova-0.12-2, где libnova-0.12 — имя библиотеки, а 2 — наш ABI-номер.
Если авторы из апстрима внесли несовместимые изменения в свою библиотеку, они должны изменить номер версии SONAME, а мы должны переименовать нашу библиотеку. Любые другие пакеты, использующие наш библиотечный пакет, нужно будет перекомпилировать с новой весрией, это называется переходом (transition) и требует некоторых усилий. Надо надеяться, наш ABI-номер продолжит соответствовать SONAME апстрима, но иногда они вносят несовместимости без изменения их номера версии, а нам нужно изменить наш.
Взглянув на debian/libnova-0.12-2.instal, мы увидим, что он включает в себя два файла:
usr/lib/libnova-0.12.so.2
usr/lib/libnova-0.12.so.2.0.0
The last one is the actual library, complete with minor and point version number. The first one is a symlink which points to the actual library. The symlink is what programs using the library will look for, the running programs do not care about the minor version number.
libnova-dev.install includes all the files needed to compile a program with this library. Header files, a config binary, the .la libtool file and libnova.so which is another symlink pointing at the library, programs compiling against the library do not care about the major version number (although the binary they compile into will).
Файлы .la (libtool) необходимы в некоторых не-Linux системах с плохой поддержкой библиотек, но в системах Debian они обычно вызывают больше проблем, чем решают. Текущая цель Debian — убрать файлы .la (Debian goal to remove .la files), и мы должны в этом помочь.
Статические библиотеки¶
Пакет -dev также содержит usr/lib/libnova.a. Это статическая библиотека, альтернатива общей библиотеке. Любая программа, скомпилированная со статической библиотекой, содержит её код непосредственно в себе. Это позволяет не беспокоиться о двоичной совместимости библиотеки. Однако это также означает, что любые ошибки, в том числе уязвимости в безопасности, не будут исправлены за счёт обновления библиотеки, пока программа не будет перекомпилирована. По этой причине использовать программы со статическими библиотеками не рекомендуется.
Символьные файлы¶
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.
To make the library dependencies more precise we keep .symbols files that list all the symbols in a library and the version they appeared in.
libnova не имеет символьного файла, так что мы можем создать его. Начните с компиляции пакета:
$ bzr builddeb -- -nc
Опция -nc указывает не удалять сборочные файлы после завершения компиляции. Перейдите в каталог сборки и выполните dpkg-gensymbols для пакета библиотеки:
$ cd ../build-area/libnova-0.12.2/
$ dpkg-gensymbols -plibnova-0.12-2 > symbols.diff
Это создаст diff-файл, который вы сможете применить самостоятельно:
$ 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
Теперь переместите файл туда, где он должен находиться, зафиксируйте изменения и выполните тестовую сборку:
$ 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
Если компиляция выполняется успешно, значит символьный файл не содержит ошибок. С выходом следующей апстрим-версии libnova вам придётся снова запустить dpkg-gensymbols, чтобы создать diff для обновления символьного файла.
C++ Library Symbols Files¶
C++ имеет ещё более строгие стандарты двоичной совместимости, чем C. Команда Debian Qt/KDE поддерживает несколько сценариев для работы с ними: посетите их страницу Working with symbols files, чтобы узнать как пользоваться этими сценариями.
Информация для дальнейшего чтения¶
В Debian Library Packaging Guide (автор: Junichi Uekawa) эта тема рассматривается более подробно.