it-swarm.com.de

Wozu dient die "Soname" -Option zum Erstellen von gemeinsam genutzten Bibliotheken?

Ich habe die "Program Library HOWTO" gelernt. Erwähnen Sie, dass Sie mit soname die Version wie folgt verwalten.

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

Und ich erhalte die Information, dass soname nicht gesetzt ist. es wird gleich libfoo.so.1.0.0 sein, siehe Antwort von hier .

Und ich finde, dass es auch ohne Soname funktionieren kann, wie zum Beispiel 

 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

Ich denke, dass der einzige nützliche Punkt ist, dass die Option soname Ihnen die Version der gemeinsam genutzten Bibliothek mitteilen kann, wenn Sie den Befehl readelf -d libfoo.so verwenden, um sie zu überprüfen. 

Was kann es sonst noch tun?

39
Samuel

soname wird verwendet, um anzugeben, welche binären API-Kompatibilität Ihre Bibliothek unterstützt.

SONAME wird zur Übersetzungszeit vom Linker verwendet, um aus der Bibliotheksdatei zu bestimmen, welche Zielbibliotheksversion aktuell ist. gcc -lNAME sucht nach dem Link oder der Datei libNAME.so und erfasst dann dessen SONAME, der sicherlich genauer ist (ex libnuke.so verlinkt auf libnuke.so.0.1.4, die SONAME libnuke.so.0 enthält).

Zur Laufzeit wird der Link mit diesem Link in den ELF-dynamischen Abschnitt NEEDED gesetzt, dann sollte eine Bibliothek mit diesem Namen (oder einem Link dazu) vorhanden sein .. Zur Laufzeit wird SONAME ignoriert, also nur der Link oder die Datei Existenz ist genug.

Anmerkung: SONAME wird nur zur Link-/Build-Zeit und nicht zur Laufzeit erzwungen.

'SONAME' der Bibliothek kann mit 'objdump -p Datei | grep SONAME' ..__ gesehen werden. 'NEEDED' von Binärdateien kann mit 'objdump -p Datei | grep NEEDED' gesehen werden.

[BEARBEITEN] WARNUNG Es folgt eine allgemeine Bemerkung, nicht die in Linux eingesetzte. Siehe am Ende.

Nehmen wir an, Sie haben eine Bibliothek mit dem Namen libnuke.so.1.2 und entwickeln eine neue libnuke-Bibliothek:

  • wenn Ihre neue Bibliothek ein Update von vorigen ohne Änderung der API ist, sollten Sie einfach den gleichen Namen beibehalten und die Version von Dateiname erhöhen. Das heißt, die Datei wird libnuke.so.1.2.1 sein, aber Soname bleibt libnuke.so.1.2. 
  • wenn Sie eine neue Bibliothek haben, die nur neue Funktionen hinzugefügt hat, die Funktionalität jedoch nicht beeinträchtigt hat und noch mit der vorherigen kompatibel ist, möchten Sie denselben Sonamen wie in früheren Versionen und ein neues Suffix wie .1 verwenden. dh Datei und Soname werden libnuke.so.1.2.1 sein. Jedes Programm, das mit libnuke.1.2 verknüpft ist, funktioniert weiterhin mit diesem Programm. Neue Programme, die mit libnuke.1.2.1 verknüpft sind, funktionieren nur mit diesem Programm (bis neue Subversion wie libnuke.1.2.1.1 erscheint).
  • wenn Ihre neue Bibliothek nicht mit libnuke kompatibel ist: libnuke.so.2
  • wenn Ihre neue Bibliothek mit der alten Version kompatibel ist: libnuke.so.1.3 [dh noch kompatibel mit libnuke.so.1]

[BEARBEITEN] zum Abschließen: Linux-Fall.

In Linux im realen Leben ist SONAME eine bestimmte Form: Lib [NAME] [API-VERSION] .so. [Hauptversion] Die Hauptversion ist nur ein ganzzahliger Wert, der bei jeder größeren Bibliotheksänderung zunimmt API-VERSION ist standardmäßig leer

ex libnuke.so.0

Dann umfassen echte Dateinamen kleinere Versionen und Subversionen, z. B. libnuke.so.0.1.5

Ich denke, es ist eine schlechte Praxis, kein Soname bereitzustellen, da das Umbenennen der Datei ihr Verhalten ändert.

43
philippe lhardy

Sie haben eine dynamische Bibliothek mit dem Namen libx.1.0.0 unter dem Namen tradition libname erstellt. {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

Jetzt veröffentlichen Sie libx.1.2.0 und müssen erklären, dass libx.1.2.0 mit libx.1.0.0 kompatibel ist, da das Hinzufügen von Funktionen und der ausführbaren Datei von Personen nicht zum Absturz führen würde. Verknüpfen Sie sie einfach wie in der alten Zeit durch:

Legen Sie fest, dass libx.1.0.0 und libx.1.2.0 denselben Sonamen haben, z. B. libx.1

Das macht Soname.

2
igonejack

Angenommen, libA.so hängt von libB.so ab, und alle befinden sich in einem Verzeichnis (natürlich kann das Verzeichnis vom dynamischen Linker nicht gefunden werden). Wenn Sie nicht soname eingestellt haben, funktioniert dlopen nicht:

auto pB = dlopen("./libB.so", RTLD_LAZY | RTLD_GLOBAL);
auto pA = dlopen("./libA.so", RTLD_LAZY | RTLD_GLOBAL);

Da der Laufzeit-Linker libB.so nicht finden kann, wird pA auf NULL gesetzt. 

In diesem Fall rettet soname Sie vor der Hölle ...

1
Lw Cui

Ein weiterer Aspekt: ​​ Zumindest unter Linux gibt der SONAME-Eintrag einen Hinweis für das Laufzeit-Linker-System an, wie entsprechende Links in/lib,/lib64 usw. erstellt werden. Durch Ausführen des Befehls ldconfig wird versucht, einen symbolischen Link mit dem Namen zu erstellen mit SONAME, das auch in den Laufzeit-Linker-Cache aufgenommen wird. Die neueste Bibliothek, die mit demselben SONAME-Tag versehen ist, gewinnt das Link-Race. Wenn eine Software auf den jeweiligen SONAME-Speicher angewiesen ist und Sie eine Bibliothek erneuern möchten, müssen Sie diesen SONAME-Code angeben, damit ldconfig in dieser neuen Bibliothek gespeichert wird (falls vorhanden) ldconfig wird verwendet, um den Cache und die Links neu zu erstellen. Z.B. libssl.so.6 und libcrypto.so.6 sind solche Fälle.

0
Johann Klasek

Hier ist ein Beispiel, das die Antwort von Johann Klasek ..__ unterstützt.

In einem Word wird SONAME zur Laufzeit benötigt. Zur Kompilierungszeit wird nur linker name oder real name benötigt (z. B. g ++ main.cpp -L. -ladd oder g ++ main.cpp -L. -l:libadd.so.1.1). Die Definition von linker name und real name folgt Programmbibliothek HOWTO: 3. Shared Libraries

quellbaum:

├── 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}
0
BugKiller