J'ai appris le "Programme Library HOWTO". Il est mentionné que l'utilisation de soname
pour gérer la version est la suivante.
gcc -shared -fPIC -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0.0 foo.c
ln -s libfoo.so.1.0.0 libfoo.so.1
ln -s libfoo.so.1 libfoo.so
Et je reçois l'information que si la soname
n'est pas définie. ce sera égal à libfoo.so.1.0.0, voir la réponse de ici .
Et je trouve que ça peut aussi marcher sans soname, comme suivre
gcc -shared -fPIC -o libfoo.so.1.0.0 foo.c
ln -s libfoo.so.1.0.0 libfoo.so.1
ln -s libfoo.so.1 libfoo.so
Je pense donc que le seul point utile est que l'option soname
peut vous indiquer la version de la bibliothèque partagée lorsque vous utilisez la commande readelf -d libfoo.so
pour la vérifier.
Que puis-je faire d'autre?
soname est utilisé pour indiquer quelle compatibilité 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 quelle version de bibliothèque cible réelle. gcc -lNAME
cherchera un lien ou un fichier libNAME
.so, puis capturera son nom SONAME, qui sera certainement plus spécifique (ex libnuke.so renvoie à libnuke.so.0.1.4 contenant SONAME libnuke.so.0).
Au moment de l'exécution, le lien avec celui-ci est défini dans la section dynamique ELF NEEDED
, puis une bibliothèque portant ce nom (ou un lien vers celui-ci) doit exister . À l'exécution, la variable SONAME
est ignorée. Par conséquent, seul le lien ou le fichier l'existence suffit.
Remarque: SONAME est appliqué uniquement au moment de la création du lien et non au moment de l'exécution.
'SONAME' de la bibliothèque peut être vu avec 'objdump -p fichier | grep SONAME' . 'BESOIN' des fichiers binaires peut être vu avec 'objdump -p fichier | grep NEEDED'.
[EDIT] WARNING Voici une remarque d'ordre général, pas celle déployée sous Linux. Voir à la fin.
Supposons que vous avez une bibliothèque avec le nom libnuke.so.1.2 et que vous développez une nouvelle bibliothèque libnuke:
[EDIT] à compléter: cas linux.
Dans Linux real life, SONAME sous une forme spécifique: Lib [NOM] [API-VERSION] .so. [Version majeure] Version majeure 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
Ensuite, le nom de fichier réel inclut les versions mineures et les subversions ex: libnuke.so.0.1.5
Je pense que ne pas fournir de nom de fichier est une mauvaise pratique car renommer un fichier changera son comportement.
Supposons que libA.so dépend de libB.so et qu'ils se trouvent tous dans un répertoire (bien entendu, le répertoire ne peut pas être trouvé par l'éditeur de liens dynamique). Si vous n'avez pas défini soname
, alors dlopen
ne fonctionne pas:
auto pB = dlopen("./libB.so", RTLD_LAZY | RTLD_GLOBAL);
auto pA = dlopen("./libA.so", RTLD_LAZY | RTLD_GLOBAL);
Comme l'éditeur de liens au moment de l'exécution ne peut pas trouver libB.so
, donc pA
est défini sur NULL
.
Dans ce cas, soname
vous sauvera de l'enfer ...
Un autre aspect: Au moins sous Linux, l’entrée SONAME fournit un indice pour le système d’éditeur de liens à la compilation sur la manière de créer les liens appropriés dans/lib,/lib64, etc L’exécution de la commande ldconfig tente de créer un lien symbolique nommé avec SONAME qui est également pris dans le cache de l'éditeur de liens au moment de l'exécution. La plus récente des librairies marquant le même SONAME remporte la course par la liaison . Si certains logiciels reposent sur un SONAME spécifique et que vous souhaitez renouveler une bibliothèque, vous devez fournir à ce SONAME le nom de ldconfig stick sur cette nouvelle bibliothèque (si ldconfig est utilisé pour reconstruire le cache et les liens). Par exemple. libssl.so.6 et libcrypto.so.6 sont de tels cas.
Voici un exemple à l'appui de La réponse de Johann Klasek .
Dans un mot, SONAME est nécessaire au moment de l'exécution. au moment de la compilation, seuls linker name
ou real name
sont nécessaires (par exemple, g ++ main.cpp -L. -ladd
ou g ++ main.cpp -L. -l:libadd.so.1.1
). Les définitions de linker name
et real name
suivent Bibliothèque de programmes HOWTO: 3. Bibliothèques partagées
arbre source:
├── add.cpp
├── add.h
├── main.cpp
└── Makefile
Makefile:
SOURCE_FILE=add.cpp
# main.cpp include `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 with `ldconfig -n .` create a soft 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}