soname wird verwendet, um anzuzeigen, welche binäre API-Kompatibilität Ihre Bibliothek unterstützt.
SONAME
wird zur Kompilierungszeit vom Linker verwendet, um aus der Bibliotheksdatei zu bestimmen, welche tatsächliche Zielbibliotheksversion. gcc -lNAME
sucht nach libNAME
.so-Link oder -Datei erfassen dann ihren SONAME, der sicherlich spezifischer sein wird (z. B. libnuke.so-Links zu libnuke.so.0.1.4, der SONAME libnuke.so.0 enthält).
Zur Laufzeit wird es mit diesem verknüpft und dann in den dynamischen ELF-Abschnitt NEEDED
gesetzt , dann sollte eine Bibliothek mit diesem Namen ( oder ein Link darauf ) existieren. Zur Laufzeit SONAME
wird außer Acht gelassen, also reicht nur der Link oder die Dateiexistenz.
Bemerkung:SONAME wird nur zur Link-/Build-Zeit erzwungen und nicht zur Laufzeit.
'SONAME' der Bibliothek kann mit 'objdump -p file |grep SONAME' angezeigt werden. 'NEEDED' der Binärdateien kann mit 'objdump -p file |grep NEEDED' angezeigt werden.
[BEARBEITEN] WARNUNG Das Folgende ist eine allgemeine Bemerkung, nicht die, die in Linux verwendet wird. 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 Fix der vorherigen ohne API-Änderung ist, sollten Sie einfach den gleichen Sonamen beibehalten und die Version des Dateinamens erhöhen. dh die Datei wird libnuke.so.1.2.1 sein, aber soname wird immer noch libnuke.so.1.2 sein.
- Wenn Sie eine neue Bibliothek haben, die nur neue Funktionen hinzugefügt hat, aber die Funktionalität nicht beeinträchtigt hat und immer noch mit der vorherigen kompatibel ist, möchten Sie den gleichen Sonamen wie die vorherige plus 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. Neue Programme, die mit libnuke.1.2.1 gelinkt sind, funktionieren nur mit dieser (bis neue Subversionen wie libnuke.1.2.1.1 kommen).
- wenn Ihre neue Bibliothek mit keiner libnuke kompatibel ist:libnuke.so.2
- wenn Ihre neue Bibliothek mit der alten Version kompatibel ist:libnuke.so.1.3 [ dh immer noch kompatibel mit libnuke.so.1 ]
[BEARBEITEN] zum Abschließen:Linux-Fall.
Im wirklichen Leben unter Linux ist SONAME eine bestimmte Form:lib[NAME][API-VERSION].so.[Hauptversion]Hauptversion ist nur ein ganzzahliger Wert, der sich bei jeder größeren Bibliotheksänderung erhöht. API-VERSION ist standardmäßig leer
ex libnuke.so.0
Dann enthält der echte Dateiname Nebenversionen und Unterversionen, z. B.:libnuke.so.0.1.5
Ich denke, dass es eine schlechte Praxis ist, keinen Sonamen anzugeben, da das Umbenennen der Datei ihr Verhalten ändern wird.
Sie haben eine dynamische Bibliothek namens libx.1.0.0 in der Tradition der Namensgebung libname.{a}.{b}.{c}
erstellt{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 Sie müssen erklären, dass libx.1.2.0 mit libx.1.0.0 kompatibel ist, da nur das Hinzufügen von Funktionen und die ausführbare Datei der Leute nicht abstürzen würde, verknüpfen Sie sie einfach wie in der alten Zeit durch:
Festlegen, dass libx.1.0.0 und libx.1.2.0 den gleichen Sonamen haben, zum Beispiel libx.1
Das macht soname.
Hier ist ein Beispiel, das die Antwort von Johann Klasek unterstützt.
Kurz gesagt, SONAME wird zur Laufzeit benötigt. Zur Kompilierungszeit wird nur ein Linkername oder ein richtiger Name benötigt (z. B. g++ main.cpp -L. -ladd
oder g++ main.cpp -L. -l:libadd.so.1.1
). Die Definitionen des Linkernamens und des richtigen Namens folgen dem Program Library HOWTO:3. Shared Libraries.
Quellbaum:
├── 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}