# 10. Bibliotecas compartilhadas

Bibliotecas compartilhadas são códigos compilados para serem compartilhados entre diversos programas diferentes. Eles são distribuídos como arquivos ”.so” em “/usr/lib/”.

Uma biblioteca exporta símbolos que são versões compiladas de funções, classes e variáveis. Uma biblioteca tem nome chamado de SONAME que inclui o número de versão. Esta versão SONAME não corresponde necessariamente ao número de versão de lançamento público. Um programa é compilado com uma versão SONAME da biblioteca. Se qualquer dos símbolos for removido ou alterado, então o número da versão precisa ser alterado, o que força todos os pacotes que usam aquela biblioteca a serem recompilados com a nova versão. A numeração de versão é geralmente definida pelo uspstream e nós a seguimos em nossos nomes de pacotes binários chamados numeração ABI. Mas às vezes o upstream não utiliza uma numeração de versão prática e os empacotadores têm que manter uma numeração de versão separada.

As bibliotecas são normalmente distribuídas pelo upstream como versões independentes. Às vezes elas são distribuídas como parte de um programa. Neste caso elas podem ser incluídas no pacote binário junto com o programa se você não espera que outros programas utilizem a biblioteca. Geralmente, elas devem ser divididas em pacotes binários separados.

As bibliotecas em si são colocadas em um pacote binário chamado “libfoo1” onde “foo” é o nome da biblioteca e “1” é a versão do SONAME. Arquivos de desenvolvimento do pacote, como os arquivos de cabeçalhos, necessários para compilar programas com a biblioteca, serão colocados em um pacote chamado “libfoo-dev”.

## 10.1. Um exemplo

Vamos usar libnova como um exemplo:

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

Para encontra o SONAME de uma biblioteca, execute:

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

O SONAME é “libnova-0.12.so.2”, que corresponde ao nome do arquivo (geralmente é o caso, mas nem sempre). Aqui o upstream colocou o número da versão upstream como parte do SONAME e deu a ele a versão ABI “2”. Nomes de pacotes de bibliotecas devem seguir de acordo como SONAME das bibliotecas que contêm. O pacote binário de biblioteca “libnova-0.12-2” onde “libnova-0.12” é o nome da biblioteca e “2” é o nosso número ABI.

Se o upstream fizer alterações incompatíveis às suas bibliotecas, eles terão que reversionar o SONAME e nós teremos que renomear nossa biblioteca. Quaisquer outros pacotes usando o nosso pacote de biblioteca terão que ser recompilados com a nova versão, o que é chamado “transição” e pode exigir algum trabalho. Com sorte, nosso número ABI continuará a corresponder ao SONAME do uspstream, mas algumas vezes eles introduzem incompatibilidades sem alterar o seu número de versão e nós teremos que alterar o nosso.

Olhando em debian/libnova-0.12-2.install, vemos que inclui dos arquivos:

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

A última é a biblioteca real, completa com numeração de versão. A primeira é um link simbólico que aponta para a verdadeira biblioteca. O link simbólico é o que os programas que utilizam a biblioteca irão procurar, os programas em execução não se importam com alterações de versão menores.

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

## 10.2. Bibliotecas estáticas

The -dev package also ships `usr/lib/libnova.a`. This is a static library, an alternative to the shared library. Any program compiled against the static library will include the code directory into itself. This gets round worrying about binary compatibility of the library. However it also means that any bugs, including security issues, will not be updated along with the library until the program is recompiled. For this reason programs using static libraries are discouraged.

## 10.3. Arquivos de símbolos

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.

Para fazer as dependências de uma biblioteca mais precisas, nós mantemos os arquivos ”.symbols” que listam todos os símbolos em uma biblioteca e a versão em que eles aparecem.

libnova não tem arquivo de símbolos, então podemos criar um. Inicie compilando o pacote:

    $ bzr builddeb -- -nc

O “-nc” irá fazer terminar no final da compilação sem remover os arquivos de compilação. Vá para o diretório de compilação e execute “dpkg-gensymbols” para o pacote de biblioteca:

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

Isto gera um arquivo diff que você pode auto-aplicar:

    $ 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

Agora mova o arquivo para a seu novo local, submeta e faça uma construção de teste:

    $ 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

Se a compilação for bem-sucedida, o arquivo de símbolos está correto. Com a próxima versão usptream do libnova, se você executar dpkg-gensymbols novamente ele irá gerar um diff para atualizar o arquivo de símbolos.

## 10.4. Arquivos de símbolos de bibliotecas C++

O C++ tem padrões ainda mais exigentes de compatibilidade binária que o C. O Time de Qt/KDE do Debian mantém alguns scripts para manipular isto, consulte a página Working with symbols files para ver como usá-los.

## 10.5. Leitura adicional

Debian Library Packaging Guide, de Junichi Uekawa entra em mais detalhes deste tópico.