Lösung 1:
Sie können LD_LIBRARY_PATH zwar so einstellen, dass der dynamische Linker weiß, wo er suchen soll, aber es gibt bessere Optionen. Sie können Ihre gemeinsam genutzte Bibliothek an einem der Standardorte ablegen, siehe /etc/ld.so.conf
(unter Linux) und /usr/bin/crle
(auf Solaris) für die Liste dieser Orte
Sie können -R <path>
passieren zum Linker, wenn Sie Ihre Binärdatei erstellen, wodurch <path>
hinzugefügt wird zur Liste der Verzeichnisse, die nach Ihrer gemeinsam genutzten Bibliothek durchsucht wurden. Hier ist ein Beispiel. Zuerst das Problem zeigen:
libtest.h:
void hello_world(void);
libtest.c:
#include <stdio.h>
void hello_world(void) {
printf("Hello world, I'm a library!\n");
}
hallo.c:
#include "libtest.h"
int main(int argc, char **argv) {
hello_world();
}
Makefile (Tabs müssen verwendet werden):
all: hello
hello: libtest.so.0
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o [email protected] $<
libtest.so.0.0.1: libtest.o
$(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
libtest.so.0: libtest.so.0.0.1
ln -s $< [email protected]
clean:
rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0
Lassen Sie es uns ausführen:
$ make
cc -fPIC -c -o libtest.o libtest.c
cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
ln -s libtest.so.0.0.1 libtest.so.0
cc hello.c libtest.so.0 -o hello
$ ./hello
./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory
Wie man es repariert? Fügen Sie -R <path>
hinzu zu den Linker-Flags (hier durch Setzen von LDFLAGS
).
$ make clean
(...)
$ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp"
(...)
cc -Wl,-R -Wl,/home/maciej/src/tmp hello.c libtest.so.0 -o hello
$ ./hello
Hello world, I'm a library!
Wenn Sie sich die Binärdatei ansehen, können Sie sehen, dass sie libtest.so.0
benötigt :
$ objdump -p hello | grep NEEDED
NEEDED libtest.so.0
NEEDED libc.so.6
Die Binärdatei sucht ihre Bibliotheken, abgesehen von den Standardorten, im angegebenen Verzeichnis:
$ objdump -p hello | grep RPATH
RPATH /home/maciej/src/tmp
Wenn Sie möchten, dass die Binärdatei im aktuellen Verzeichnis sucht, können Sie den RPATH auf $ORIGIN
setzen . Das ist ein bisschen knifflig, weil Sie sicherstellen müssen, dass das Dollarzeichen nicht von make interpretiert wird. Hier ist eine Möglichkeit, dies zu tun:
$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
RPATH $ORIGIN
$ ./hello
Hello world, I'm a library!
Lösung 2:
Der Loader überprüft niemals das aktuelle Verzeichnis auf gemeinsam genutzte Objekte, es sei denn, es wird ausdrücklich über $LD_LIBRARY_PATH
darauf verwiesen . Siehe ld.so(8)
Manpage für weitere Details.
Lösung 3:
Um die gemeinsam genutzten Objekte aus demselben Verzeichnis wie Ihre ausführbare Datei zu laden, führen Sie einfach Folgendes aus:
$ LD_LIBRARY_PATH=. ./binary
Hinweis:Die Variable LD_LIBRARY_PATH Ihres Systems wird dadurch nicht geändert. Die Änderung betrifft nur diese und nur diese Ausführung Ihres Programms.
Lösung 4:
Für alle, die CMake für ihren Build verwenden, können Sie den CMAKE_EXE_LINKER_FLAGS
festlegen zu Folgendem:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
Dadurch werden die Linker-Flags für alle Build-Typen (z. B. Debug, Release usw.) ordnungsgemäß weitergegeben, um zuerst nach .so-Dateien im aktuellen Arbeitsverzeichnis zu suchen.
Lösung 5:
Für alle, die immer noch ohne Antwort kämpfen, habe ich selbst eine mit folgendem Vorschlag gefunden:
Sie könnten versuchen, den ld.so.cache zu aktualisieren mit:sudo ldconfig -v
Hat bei mir funktioniert.