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?
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:
[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.
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.
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 ...
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.
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}