GNU/Linux >> Tutoriels Linux >  >> Linux

À quoi sert l'option 'soname' pour créer des bibliothèques partagées ?

soname est utilisé pour indiquer quelle compatibilité d'api binaire votre bibliothèque prend en charge.

SONAME est utilisé au moment de la compilation par l'éditeur de liens pour déterminer à partir du fichier de bibliothèque la version réelle de la bibliothèque cible. gcc -lNAME cherchera libNAME Le lien ou le fichier .so capture alors son SONAME qui sera certainement plus précis ( ex libnuke.so liens vers libnuke.so.0.1.4 qui contient le SONAME libnuke.so.0 ).

Au moment de l'exécution, il sera lié à ceci est ensuite défini dans la section dynamique ELF NEEDED , alors une bibliothèque portant ce nom (ou un lien vers celle-ci) devrait exister. Au moment de l'exécution SONAME est ignoré, donc seul le lien ou l'existence du fichier suffit.

Remarque :SONAME n'est appliqué qu'au moment du lien/de la construction et non au moment de l'exécution.

'SONAME' de la bibliothèque peut être vu avec 'objdump -p file |grep SONAME'. 'NEEDED' des binaires peut être vu avec 'objdump -p file |grep NEEDED'.

[EDIT] AVERTISSEMENT Voici une remarque générale, pas celle déployée sous Linux. Voir à la fin.

Supposons que vous ayez une bibliothèque avec le nom libnuke.so.1.2 et que vous développiez une nouvelle bibliothèque libnuke :

  • si votre nouvelle bibliothèque est un correctif de la précédente sans modification de l'API, vous devez simplement conserver le même soname, augmenter la version du nom de fichier. c'est-à-dire que le fichier sera libnuke.so.1.2.1 mais que soname sera toujours libnuke.so.1.2.
  • si vous avez une nouvelle bibliothèque qui n'a ajouté qu'une nouvelle fonction mais n'a pas cassé la fonctionnalité et est toujours compatible avec la précédente, vous souhaitez utiliser le même soname que la précédente plus un nouveau suffixe comme .1. c'est-à-dire que le fichier et le soname seront libnuke.so.1.2.1. Tout programme lié à libnuke.1.2 fonctionnera toujours avec celui-ci. Les nouveaux programmes liés à libnuke.1.2.1 ne fonctionneront qu'avec celui-ci (jusqu'à ce qu'une nouvelle subversion vienne comme libnuke.1.2.1.1).
  • si votre nouvelle bibliothèque n'est compatible avec aucune libnuke :libnuke.so.2
  • si votre nouvelle bibliothèque est compatible avec l'ancienne version nue :libnuke.so.1.3 [c'est-à-dire toujours compatible avec libnuke.so.1]

[EDIT] à compléter :cas linux.

Dans la vie réelle de Linux, SONAME sous une forme spécifique :lib[NAME][API-VERSION].so.[major-version]major-version n'est qu'une valeur entière qui augmente à chaque changement majeur de bibliothèque.API-VERSION est vide par défaut

ex libnuke.so.0

Alors le vrai nom de fichier inclut les versions mineures et les sous-versions ex :libnuke.so.0.1.5

Je pense que ne pas fournir de soname est une mauvaise pratique car renommer le fichier changera son comportement.


Vous avez créé une bibliothèque dynamique nommée libx.1.0.0 dans la tradition de dénomination 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

Maintenant, vous publiez libx.1.2.0 et vous devez déclarer que libx.1.2.0 est compatible avec libx.1.0.0 car le simple fait d'ajouter des fonctions et l'exécutable des utilisateurs ne planterait pas, il suffit de le lier comme autrefois en :

Définir libx.1.0.0 et libx.1.2.0 pour qu'ils aient le même soname, par exemple libx.1

C'est ce que fait soname.


Voici un exemple étayant la réponse de Johann Klasek.

En bref, SONAME est nécessaire au moment de l'exécution. Au moment de la compilation, seul un nom de lien ou un nom réel est nécessaire (par exemple, g++ main.cpp -L. -ladd ou g++ main.cpp -L. -l:libadd.so.1.1 ). Les définitions du nom de l'éditeur de liens et du nom réel suivent le programme HOWTO de la bibliothèque :3. Bibliothèques partagées.

Arborescence des sources :

├── 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. Quel est l'équivalent C++ d'AutoResetEvent sous Linux ?

  2. Quel est le mot de passe root par défaut pour MySQL 5.7

  3. Quel est l'équivalent de la commande updatedb de Linux pour Mac ?

  4. Quel est l'équivalent de la commande Linux File pour Windows ?

  5. Quel est l'ID de partition/le type de système de fichiers pour UDF ?

vérification des bibliothèques partagées pour les chargeurs non par défaut

Quelle est la raison pour laquelle rmdir(1) et rm(1) coexistent ?

A quoi sert le groupe "shadow" ?

Qu'est-ce qui constitue un 'champ' pour la commande cut ?

A quoi sert l'option -o dans la commande useradd ?

Quel est le fichier par défaut pour `hostname` ?