Por que não consigo instalar várias versões de uma biblioteca compartilhada?

10

Geralmente, há casos em que um determinado programa depende da versão da biblioteca xy e outro no xz, mas, até onde eu sei, nenhum gerenciador de pacotes me permite instalar o xy e o xz Às vezes, eles permitem as duas versões principais (como qt4 e qt5, que podem ser instalados ao mesmo tempo), mas (aparentemente) nunca versões menores.

Por que é isso? Como, qual é o fator limitante que o impede? Suponho que deve haver uma boa razão para não permitir essa funcionalidade aparentemente útil. Por exemplo, não há um campo para indicar qual versão carregar ao carregar um objeto compartilhado e, portanto, não há como o Linux saber como decidir qual carregar? Ou realmente não há razão para isso? Como todas as versões secundárias devem ser compatíveis de qualquer maneira ou algo assim?

Tyler
fonte

Respostas:

13

Na verdade, você pode instalar várias versões de uma biblioteca compartilhada, se isso for feito corretamente.

Bibliotecas compartilhadas geralmente são nomeadas da seguinte maneira:

lib<name>.so.<api-version>.<minor>

Em seguida, há links simbólicos para a biblioteca com os seguintes nomes:

lib<name>.so
lib<name>.so.<api-version>

Quando um desenvolvedor é vinculado à biblioteca para produzir um binário, é o nome do arquivo que termina no local em .soque o vinculador encontra. De fato, pode haver apenas um daqueles instalados de cada vez, <name>mas isso significa apenas que um desenvolvedor não pode segmentar várias versões diferentes de uma biblioteca ao mesmo tempo. Com os gerenciadores de pacotes, esse .solink simbólico faz parte de um -devpacote separado que somente os desenvolvedores precisam instalar.

Quando o vinculador encontra um arquivo com um nome terminado em .soe o usa, ele procura dentro da biblioteca um campo chamado soname . O soname informa ao vinculador qual nome de arquivo deve ser incorporado no binário resultante e, portanto, qual nome de arquivo será procurado em tempo de execução. O soname deve estar definido como lib<name>.so.<api-version>.

Portanto, no tempo de execução, o vinculador dinâmico buscará lib<name>.so.<api-version>e usará isso.

A intenção é que:

  • <minor>as atualizações não alteram a API da biblioteca e, quando <minor>elas são transferidas para uma versão superior, é seguro permitir que todos os binários sejam atualizados para a nova versão. Como todos os binários estão procurando a biblioteca com o lib<name>.so.<api-version>nome, que é um link simbólico para a instalação mais recente lib<name>.so.<api-version>.<minor>, eles obtêm a atualização.
  • <api-version>as atualizações alteram a API da biblioteca e não é seguro permitir que aplicativos binários existentes usem a nova versão. No caso de a <api-version>alteração ser alterada, pois esses aplicativos procuram o nome, lib<name>.so.<api-version>mas com um valor diferente <api-version>, eles não receberão a nova versão.

Os gerenciadores de pacotes geralmente não empacotam mais de uma versão da mesma biblioteca na mesma versão de distribuição, porque a distribuição inteira, incluindo todos os binários que fazem uso da biblioteca, geralmente é compilada para usar uma versão consistente de todas as bibliotecas antes da distribuição. liberado. Garantir que tudo seja consistente e que tudo em uma distribuição seja compatível com todo o resto é uma grande parte da carga de trabalho dos distribuidores.

Mas você pode facilmente terminar com várias versões de uma biblioteca se tiver atualizado seu sistema de uma versão para outra e ainda tiver alguns pacotes mais antigos que exigem versões mais antigas da biblioteca. Exemplo:

  • libmysqlclient16 de um Debian antigo, contém libmysqlclient.so.16.0.0e link simbólico libmysqlclient.so.16.
  • libmysqlclient18 do Debian atual, contém libmysqlclient.so.18.0.0e link simbólico libmysqlclient.so.18.
Celada
fonte
4

Essa funcionalidade não é permitida, apenas não é muito comum como resultado da maneira como a numeração de bibliotecas funciona e devido ao inconveniente das alterações no nome do pacote.

Se o uso de um esquema de número de versão pontilhada XYZ A versão "micro" Z muda frequentemente em correções de erros, o número "menor" Y muda em alterações compatíveis com versões anteriores e o número da versão "principal" X precisa mudar nas alterações da API (e às vezes muda maior funcionalidade extra).

Nunca deve haver um motivo para você não querer corrigir os bugs mais recentes, e as alterações compatíveis com versões anteriores também não devem prejudicar o software.

Se a biblioteca for desenvolvida dessa maneira, você sempre poderá substituir XYZ por X. (Y + m). (Z + n). para qualquer dado m e n. Ou seja, você sempre deve poder substituir sua biblioteca pelas últimas da mesma série de números principais. E se os desenvolvedores da biblioteca forem cuidadosos e o próximo número principal for compatível (por exemplo, com o anúncio de descontinuar as coisas, mas ainda não as remover), você poderá usar o próximo número principal.

Para desenvolvedores de pacotes, isso significa que eles podem usar o nome com apenas um, ou mesmo sem nome numérico, para fornecer a versão mais recente atualizando o pacote. Se eles entregam uma biblioteca em um pacote abc2, precisam passar por dificuldades para mover seu próprio software que contava com abc2a atualização para uso abc3, às vezes com pacotes de transição. É mais conveniente deixar de fora o número da versão principal de uma biblioteca, se isso funcionar para a maioria dos pacotes que dependem. Portanto, mesmo que ambos abc2e abc3devam estar disponíveis em algum momento disponível em uma distribuição, abc3seja chamado com frequência abc(assim como abc2foi chamado quando abc3ainda não existia) e, assim que nenhum pacote depende abc2da distribuição, é possível descartarabc2 completamente.

O esquema de numeração não é seguido de maneira uniforme, mas só posso imaginar que, com o advento da Internet, divulgue informações sobre como usar esse esquema e a pressão dos usuários da biblioteca (incluindo desenvolvedores de distribuição) para deixar claro coisas importantes, como compatibilidade com versões anteriores, sem ter que ler um arquivo CHANGES incluído na biblioteca, contribuiu para que isso se tornasse mais comum.

Um exemplo contrário, mas não de uma biblioteca, é o intérprete python, que não é compatível com seus objetos compartilhados e com o formato de decapagem em uma pequena alteração no número. Portanto, você verá pacotes para python (o mais recente da série 2.7) e python3 (o mais recente da série python3.4), bem como pacotes explícitos para o python 2.6 (não ficando menos comum) e para o python 3.3.

Anthon
fonte