¿Por qué no puedo instalar varias versiones de una biblioteca compartida?

10

A menudo hay casos en los que un determinado programa dependerá de la versión de la biblioteca xy y otro de xz, pero, que yo sepa, ningún administrador de paquetes me permitirá instalar tanto xy como xz. A veces, permitirán ambas versiones principales (como qt4 y qt5, que se pueden instalar al mismo tiempo), pero (aparentemente) nunca versiones menores.

¿Por qué es esto? Como en, ¿cuál es el factor limitante que lo impide? Supongo que debe haber una buena razón para no permitir esta funcionalidad aparentemente útil. Por ejemplo, ¿no hay un campo para indicar qué versión cargar al cargar un objeto compartido y, por lo tanto, no hay forma de que Linux sepa cómo decidir qué cargar? ¿O realmente no hay razón para ello? ¿Como se supone que todas las versiones menores son compatibles de todos modos o algo así?

Tyler
fuente

Respuestas:

13

En realidad, puede instalar varias versiones de una biblioteca compartida si se realiza correctamente.

Las bibliotecas compartidas generalmente se nombran de la siguiente manera:

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

A continuación, hay enlaces simbólicos a la biblioteca con los siguientes nombres:

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

Cuando un desarrollador se vincula con la biblioteca para producir un binario, es el nombre de archivo que termina en el .soque encuentra el vinculador. De hecho, puede haber solo uno de los instalados a la vez para cualquier cosa, <name>pero eso solo significa que un desarrollador no puede apuntar a múltiples versiones diferentes de una biblioteca al mismo tiempo. Con los administradores de paquetes, este .soenlace simbólico es parte de un -devpaquete separado que solo los desarrolladores necesitan instalar.

Cuando el vinculador encuentra un archivo con un nombre que termina en .soy lo usa, busca dentro de esa biblioteca un campo llamado soname . El soname informa al vinculador qué nombre de archivo incrustar en el binario resultante y, por lo tanto, qué nombre de archivo se buscará en tiempo de ejecución. Se supone que el soname está establecido en lib<name>.so.<api-version>.

Por lo tanto, en tiempo de ejecución, el vinculador dinámico buscará lib<name>.so.<api-version>y usará eso.

La intención es que:

  • <minor>las actualizaciones no cambian la API de la biblioteca y, cuando se <minor>pasa a una versión superior, es seguro permitir que todos los binarios se actualicen a la nueva versión. Dado que todos los archivos binarios buscan la biblioteca con el lib<name>.so.<api-version>nombre, que es un enlace simbólico al último instalado lib<name>.so.<api-version>.<minor>, obtienen la actualización.
  • <api-version>las actualizaciones cambian la API de la biblioteca, y no es seguro permitir que las aplicaciones binarias existentes usen la nueva versión. En el caso de que <api-version>se cambie, dado que esas aplicaciones están buscando el nombre lib<name>.so.<api-version>pero con un valor diferente <api-version>, no elegirán la nueva versión.

Los gestores de paquetes a menudo no empaquetan más de una versión de la misma biblioteca dentro de la misma versión de distribución porque toda la distribución, incluidos todos los archivos binarios que hacen uso de la biblioteca, generalmente se compila para usar una versión coherente de cada biblioteca antes de que se distribuya liberado. Asegurarse de que todo sea consistente y que todo en una distribución sea compatible con todo lo demás es una gran parte de la carga de trabajo para los distribuidores.

Pero puede terminar fácilmente con varias versiones de una biblioteca si ha actualizado su sistema de una versión de su distribución a otra y aún tiene algunos paquetes más antiguos que requieren versiones de biblioteca más antiguas. Ejemplo:

  • libmysqlclient16 de un Debian anterior, contiene libmysqlclient.so.16.0.0y enlace simbólico libmysqlclient.so.16.
  • libmysqlclient18 de Debian actual, contiene libmysqlclient.so.18.0.0y enlace simbólico libmysqlclient.so.18.
Celada
fuente
4

Esta funcionalidad no está prohibida, simplemente no es muy común como resultado de la forma en que funciona la numeración de la mayoría de las bibliotecas y debido a la inconveniencia de los cambios en el nombre del paquete.

Si utiliza un esquema de número de versión punteado XYZ La versión "micro" Z a menudo cambia en las correcciones de errores, el número "menor" Y cambia en los cambios compatibles con versiones anteriores y el número de versión "mayor" X tiene que cambiar en los cambios de API (y a veces lo hace en mayor funcionalidad adicional).

Nunca debería haber una razón por la que no desea que se corrijan los errores más recientes, y los cambios compatibles con versiones anteriores tampoco deberían dañar su software.

Si la biblioteca se desarrolla de esa manera, siempre debería poder reemplazar XYZ por X. (Y + m). (Z + n). para cualquier m y n dado. Es decir, siempre debe poder reemplazar su biblioteca con la última de la misma serie de números principales. Y si los desarrolladores de la biblioteca son cuidadosos y el próximo número principal es compatible (por ejemplo, por el anuncio de desaprobar las cosas, pero no eliminarlas aún), incluso puede usar el siguiente número principal.

Para los desarrolladores de paquetes, esto significa que pueden usar el nombre con solo uno, o incluso sin nombre de número para darle la última versión simplemente actualizando el paquete. Si envían una biblioteca en un paquete, abc2entonces tienen que pasar por aros para mover su propio software que se basa en la abc2actualización para usar abc3, a veces con paquetes de transición. Es más conveniente omitir el número de versión principal de una biblioteca si eso funciona para la mayoría de los paquetes dependientes. Entonces, incluso si ambos abc2y abc3deberían estar disponibles en algún momento disponibles en una distribución, a abc3menudo se llama abc(tal como abc2se llamó cuando abc3aún no había), y tan pronto como ningún paquete depende de abc2la distribución, es posible descartarabc2 en total.

El esquema de numeración no se sigue de manera uniforme, pero solo puedo imaginar que con el advenimiento de Internet difundiendo información sobre cómo usar dicho esquema, y ​​la presión de los usuarios de la biblioteca (incluidos los desarrolladores de distribución) para aclarar cosas importantes como la compatibilidad con versiones anteriores sin tener que leer un archivo de CAMBIOS incluido en la biblioteca, ha contribuido a que esto se haya vuelto más común.

Un ejemplo de contador, pero no de una biblioteca es el intérprete de python, que no es compatible con sus objetos compartidos y el formato de decapado en un cambio de número menor. Por lo tanto, verá paquetes para python (el último en la serie 2.7) y python3 (el último en la serie actualmente python3.4), así como paquetes explícitos para python 2.6 (que no se vuelven menos comunes) y python 3.3.

Anthon
fuente