GNU/Linux >> Tutoriales Linux >  >> Linux

¿Para qué sirve la opción 'soname' para crear bibliotecas compartidas?

soname se usa para indicar qué compatibilidad de API binaria admite su biblioteca.

SONAME se utiliza en el momento de la compilación por el enlazador para determinar a partir del archivo de biblioteca qué versión de biblioteca de destino real. gcc -lNAME buscará libNAME .so enlace o archivo y luego capture su SONAME que sin duda será más específico (ex libnuke.so enlaces a libnuke.so.0.1.4 que contiene SONAME libnuke.so.0).

En tiempo de ejecución, se vinculará con esto y luego se establecerá en la sección dinámica ELF NEEDED , entonces debería existir una biblioteca con este nombre (o un enlace a ella). En tiempo de ejecución SONAME se ignora, por lo que solo el enlace o la existencia del archivo es suficiente.

Observación:SONAME solo se aplica en tiempo de enlace/compilación y no en tiempo de ejecución.

'SONAME' de la biblioteca se puede ver con 'objdump -p file |grep SONAME'. 'NEEDED' de binarios se puede ver con 'objdump -p file |grep NECESARIO'.

[EDITAR] ADVERTENCIA Lo siguiente es un comentario general, no el implementado en Linux. Ver al final.

Supongamos que tiene una biblioteca con el nombre libnuke.so.1.2 y desarrolla una nueva biblioteca libnuke:

  • si su nueva biblioteca es una corrección de la anterior sin cambio de API, debe mantener el mismo nombre de usuario y aumentar la versión del nombre de archivo. es decir, el archivo será libnuke.so.1.2.1 pero el soname seguirá siendo libnuke.so.1.2.
  • si tiene una nueva biblioteca que solo agregó una nueva función pero no interrumpió la funcionalidad y sigue siendo compatible con la anterior, le gustaría usar el mismo soname que la anterior más un nuevo sufijo como .1. es decir, el archivo y el soname serán libnuke.so.1.2.1. Cualquier programa vinculado con libnuke.1.2 seguirá funcionando con ese. Los nuevos programas vinculados con libnuke.1.2.1 solo funcionarán con ese (hasta que llegue una nueva subversión como libnuke.1.2.1.1).
  • si su nueva biblioteca no es compatible con ninguna libnuke:libnuke.so.2
  • si su nueva biblioteca es compatible con la versión anterior:libnuke.so.1.3 [es decir, sigue siendo compatible con libnuke.so.1]

[EDITAR] para completar:caso de Linux.

En la vida real de Linux, SONAME como una forma específica:lib[NOMBRE][API-VERSIÓN].así que.[versión-principal]versión-principal es solo un valor entero que aumenta con cada cambio importante en la biblioteca.API-VERSIÓN está vacía de forma predeterminada

ex libnuke.so.0

Luego, el nombre de archivo real incluye versiones menores y subversiones, por ejemplo:libnuke.so.0.1.5

Creo que no proporcionar un soname es una mala práctica ya que cambiar el nombre del archivo cambiará su comportamiento.


Ha creado una biblioteca dinámica llamada libx.1.0.0 al nombrar la tradición libname.{a}.{b}.{c}

{a} stand for primary version, should changes when APIs changes(which making things incompatible).
{b} stand for sub version, should changes by adding APIs.
{c} stand for mirror version, should changes by bug fixing or optimizing

Ahora está lanzando libx.1.2.0, y necesita declarar que libx.1.2.0 es compatible con libx.1.0.0 ya que solo agregar funciones y el ejecutable de las personas no fallaría, solo vincúlelo como en los viejos tiempos:

Configurar libx.1.0.0 y libx.1.2.0 para que tengan el mismo soname, por ejemplo, libx.1

Esto es lo que hace soname.


Aquí hay un ejemplo que respalda la respuesta de Johann Klasek.

En resumen, se necesita SONAME en tiempo de ejecución. En tiempo de compilación, solo se necesita un nombre de enlace o un nombre real (por ejemplo, g++ main.cpp -L. -ladd o g++ main.cpp -L. -l:libadd.so.1.1 ). Las definiciones de nombre del enlazador y nombre real siguen el CÓMO de la biblioteca de programas:3. Bibliotecas compartidas.

Árbol de fuentes:

├── add.cpp
├── add.h
├── main.cpp
└── Makefile

Makefile:

SOURCE_FILE=add.cpp
# main.cpp includes `add.h`, whose implementation is `add.cpp`
MAIN_FILE=main.cpp
SONAME=libadd.so.1
REAL_NAME=libadd.so.1.1
LINKER_NAME=libadd.so
OUTPUT_FILE=a.out

all:
   g++ -shared -fPIC -Wl,-soname,${SONAME} -o ${REAL_NAME} ${SOURCE_FILE}
   ln -s ${REAL_NAME} ${LINKER_NAME}
   g++ main.cpp -I. -L. -ladd -o ${OUTPUT_FILE} 
   # Same as `ldconfig -n .`, creates a symbolic link
   ln -s ${REAL_NAME} ${SONAME}
   #./a.out: error while loading shared libraries: libadd.so.1: cannot open 
   # shared object file: No such file or directory
   LD_LIBRARY_PATH=. ./${OUTPUT_FILE}
clean:
   rm ${SONAME} ${REAL_NAME} ${LINKER_NAME} ${OUTPUT_FILE}

Linux
  1. ¿Qué define el tamaño máximo para un solo argumento de comando?

  2. ¿"cuál" equivalente para bibliotecas compartidas?

  3. ¿Cómo verificar qué bibliotecas compartidas se cargan en tiempo de ejecución para un proceso determinado?

  4. ¿Cuál es la contraseña raíz predeterminada para MySQL 5.7?

  5. ¿Cuál es el equivalente del comando updatedb de Linux para Mac?

comprobando bibliotecas compartidas para cargadores no predeterminados

¿Cuál es la razón por la que rmdir(1) y rm(1) coexisten?

¿Para qué se utiliza el grupo `sombra`?

¿Qué constituye un 'campo' para el comando de corte?

¿Cuál es la ubicación correcta de la variable Shell de PS1?

¿Cuál es la instalación de syslog para registros auditados?