# 10. Общие библиотеки

Общие библиотеки — это скомпилированный код, предназначенный для совместного использования несколькими различными программами. Они распространяются в виде файлов `.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`.

## 10.1. Пример

В качестве примера мы используем libnova:

    $ bzr branch ubuntu:trusty/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

Вторая строчка — настоящая библиотека, с полным номером версии. Первая — символическая ссылка, указывающая на настоящую библиотеку. Программы, использующие библиотеку, как правило, будут пользоваться символической ссылкой.

`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), и мы должны в этом помочь.

## 10.2. Статические библиотеки

Пакет -dev также содержит `usr/lib/libnova.a`. Это статическая библиотека, альтернатива общей библиотеке. Любая программа, скомпилированная со статической библиотекой, содержит её код непосредственно в себе. Это позволяет не беспокоиться о двоичной совместимости библиотеки. Однако это также означает, что любые ошибки, в том числе уязвимости в безопасности, не будут исправлены за счёт обновления библиотеки, пока программа не будет перекомпилирована. По этой причине использовать программы со статическими библиотеками не рекомендуется.

## 10.3. Символьные файлы

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 для обновления символьного файла.

## 10.4. Символьные файлы библиотек C++

C++ имеет ещё более строгие стандарты двоичной совместимости, чем C. Команда Debian Qt/KDE поддерживает несколько сценариев для работы с ними: посетите их страницу Working with symbols files, чтобы узнать как пользоваться этими сценариями.

## 10.5. Информация для дальнейшего чтения

В Debian Library Packaging Guide (автор: Junichi Uekawa) эта тема рассматривается более подробно.