Frage Kann .so nicht im selben Verzeichnis wie die ausführbare Datei gefunden werden?


Ich habe eine ausführbare Datei, mit der ich verlinken muss libtest.so dynamisch, also lege ich sie in das gleiche Verzeichnis, dann:

cd path_to_dir
./binary

Aber hab das:

error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

Wie kann es nicht finden libtest.so welches ist bereits im selben Verzeichnis wie die ausführbare Datei selbst?


36
2018-06-10 08:54


Ursprung




Antworten:


Der Loader überprüft das aktuelle Verzeichnis niemals auf gemeinsam genutzte Objekte, es sei denn, es wird explizit auf via verwiesen $LD_LIBRARY_PATH. Siehe die ld.so(8) Man-Seite für weitere Details.


22
2018-06-10 08:56



echo $LD_LIBRARY_PATH ist leer auf meiner Maschine :( - linuxer
Es ist normalerweise. - Ignacio Vazquez-Abrams
Es gibt zusätzliche Verzeichnisse an, in denen der Loader nach Bibliotheken suchen kann. - Ignacio Vazquez-Abrams
Pfade in * nix sind durch einen Doppelpunkt getrennt (:), kein Semikolon. - Ignacio Vazquez-Abrams
LD_LIBRARY_PATH ist generell eine schlechte Wahl in der Produktion. Es ist gut für schnelle Hacks, und Dinge wie deinstallierte Binärdateien helfen, ihre gemeinsam genutzten Bibliotheken zu finden, wenn Unit-Tests ausgeführt werden (denke an ./configure; make; make check). Wenn Sie Ihre Binärdatei erstellen, können Sie entweder Ihre Bibliothek an einem Standardspeicherort (aufgelistet in /etc/ld.so.conf) ablegen oder das Flag -R an den Linker übergeben, damit die Binärdatei weiß, wo sie suchen soll. - automatthias


Während Sie LD_LIBRARY_PATH so einstellen können, dass der dynamische Linker weiß, wo er aussehen soll, gibt es bessere Möglichkeiten. Sie können Ihre freigegebene Bibliothek in einen der Standard-Orte stellen, siehe /etc/ld.so.conf (auf Linux) und /usr/bin/crle (unter Solaris) für die Liste dieser Orte

Sie können durch -R <path> an den Linker beim Erstellen Ihrer Binärdatei, die hinzufügen wird <path> zu der Liste der Verzeichnisse, die nach Ihrer gemeinsamen Bibliothek durchsucht wurden. Hier ist ein Beispiel. Zuerst zeigt das Problem:

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 (Registerkarten müssen verwendet werden):

all: hello
hello: libtest.so.0
%.o: %.c
        $(CC) $(CFLAGS) -fPIC -c -o $@ $<
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 $< $@
clean:
        rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0

Lass es uns laufen:

$ 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? Hinzufügen -R <path> zu den Linker-Flags (hier, durch Einstellung 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 das Binärprogramm betrachten, können Sie sehen, dass es benötigt wird libtest.so.0:

$ objdump -p hello | grep NEEDED
  NEEDED               libtest.so.0
  NEEDED               libc.so.6

Die Binärdatei sucht nach ihren Bibliotheken, abgesehen von den Standardplätzen, im angegebenen Verzeichnis:

$ objdump -p hello | grep RPATH
  RPATH                /home/maciej/src/tmp

Wenn Sie möchten, dass die Binärdatei im aktuellen Verzeichnis angezeigt wird, können Sie RPATH auf festlegen $ORIGIN. Dies ist ein bisschen schwierig, weil Sie sicherstellen müssen, dass das Dollarzeichen nicht von make interpretiert wird. Hier ist ein Weg, es zu tun:

$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
  RPATH                $ORIGIN
$ ./hello 
Hello world, I'm a library!

53
2018-06-18 09:14



Wenn nicht verwendet makewie beim manuellen Aufruf g++, Versuchen -Wl,-rpath='$ORIGIN' (beachten Sie die einfachen Anführungszeichen) zu verhindern $ORIGINvom Erweitern zu einer leeren Zeichenfolge. - Morpork


Um die freigegebenen Objekte aus demselben Verzeichnis wie Ihre ausführbare Datei zu laden, führen Sie einfach Folgendes aus:

$ LD_LIBRARY_PATH=. ./binary

Hinweis: Die LD_LIBRARY_PATH-Variable Ihres Systems wird nicht geändert. Die Änderung betrifft nur diese und nur die Ausführung Ihres Programms.


9
2017-08-29 00:06





Für jeden, der immer noch ohne Antwort kämpft, habe ich selbst einen mit folgendem Vorschlag gefunden:

Sie könnten versuchen, die ld.so.cache zu aktualisieren mit: sudo ldconfig -v

Arbeitete für mich.


3
2017-08-12 23:24





Für jeden, der es benutzt CMake Für ihre Erstellung können Sie die festlegen CMAKE_EXE_LINKER_FLAGS Zu dem 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.


0