it-swarm.com.de

Sie können .so nicht im selben Verzeichnis wie die ausführbare Datei finden?

Ich habe eine ausführbare Datei, die dynamisch mit libtest.so Verknüpft werden muss, also lege ich sie in dasselbe Verzeichnis und 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 möglich sein, libtest.so Zu finden, das sich bereits im selben Verzeichnis wie die ausführbare Datei selbst befindet?

47
linuxer

Der Loader überprüft das aktuelle Verzeichnis niemals auf freigegebene Objekte, es sei denn, es wird explizit über $LD_LIBRARY_PATH Weitergeleitet. Weitere Informationen finden Sie in der Manpage ld.so(8).

Sie können LD_LIBRARY_PATH so einstellen, dass der dynamische Linker weiß, wo er suchen muss. Es gibt jedoch bessere Optionen. Sie können Ihre gemeinsam genutzte Bibliothek an einem der Standardorte ablegen. Die Liste dieser Orte finden Sie unter /etc/ld.so.conf (Unter Linux) und /usr/bin/crle (Unter Solaris)

Sie können -R <path> Beim Erstellen Ihrer Binärdatei an den Linker übergeben, wodurch <path> Zur Liste der für Ihre gemeinsam genutzte Bibliothek gescannten Verzeichnisse hinzugefügt wird. Hier ist ein Beispiel. Zeigen Sie zunächst 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 (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 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? Fügen Sie -R <path> Zu den Linker-Flags hinzu (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, sehen Sie, dass sie libtest.so.0 Benötigt:

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

Die Binärdatei sucht neben den Standardplätzen im angegebenen Verzeichnis nach ihren Bibliotheken:

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

Wenn die Binärdatei im aktuellen Verzeichnis angezeigt werden soll, können Sie RPATH auf $Origin Setzen. Dies ist etwas schwierig, da 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!
59
automatthias

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

$ LD_LIBRARY_PATH=. ./binary

Hinweis: Die Variable LD_LIBRARY_PATH Ihres Systems wird nicht geändert. Die Änderung wirkt sich nur auf diese und nur auf diese Ausführung Ihres Programms aus.

18
SwanS

Für alle, die immer noch ohne Antwort kämpfen, habe ich selbst einen mit folgendem Vorschlag gefunden:

Sie können versuchen, den ld.so.cache zu aktualisieren, indem Sie Folgendes verwenden: Sudo ldconfig -v

Hat für mich gearbeitet.

4
Ian Frisbie

Für jeden, der CMake für seinen Build verwendet, können Sie CMAKE_EXE_LINKER_FLAGS Auf Folgendes setzen:

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 im aktuellen Arbeitsverzeichnis nach .so-Dateien zu suchen.

4

Der dynamische Linker entscheidet, wo nach Bibliotheken gesucht wird. Unter Linux ist der dynamische Linker normalerweise GNU ld.so (Oder eine Alternative, die sich aus Kompatibilitätsgründen normalerweise identisch verhält.

Zu Zitaten aus der Wikipedia:

Der dynamische Linker der GNU C-Bibliothek sucht an folgenden Speicherorten nach gemeinsam genutzten Bibliotheken:

  1. Die (durch Doppelpunkte getrennten) Pfade im dynamischen Abschnittsattribut DT_RPATH Der Binärdatei, falls vorhanden, und im Attribut DT_RUNPATH Sind nicht vorhanden.
  2. Die (durch Doppelpunkte getrennten) Pfade in der Umgebungsvariablen LD_LIBRARY_PATH, Es sei denn, die ausführbare Datei ist eine Binärdatei setuid/setgid. In diesem Fall wird sie ignoriert. LD_LIBRARY_PATH Kann durch Aufrufen des dynamischen Linkers mit der Option --library-path (z. B. /lib/ld-linux.so.2 --library-path $ HOME/mylibs myprogram) überschrieben werden.
  3. Die (durch Doppelpunkte getrennten) Pfade im dynamischen Abschnittsattribut DT_RUNPATH Der Binärdatei, falls vorhanden.
  4. Die Suche basiert auf der ldconfig-Cache-Datei (häufig unter /etc/ld.so.cache), Die eine kompilierte Liste von Kandidatenbibliotheken enthält, die zuvor in der erweiterten Bibliothek gefunden wurden Pfad (festgelegt durch /etc/ld.so.conf). Wenn die Binärdatei jedoch mit der Linkeroption -z nodefaultlib Verknüpft wurde, werden Bibliotheken in den Standardbibliothekspfaden übersprungen.
  5. Im vertrauenswürdigen Standardpfad /lib Und dann /usr/lib. Wenn die Binärdatei mit der Linkeroption -z nodefaultlib verknüpft wurde, wird dieser Schritt übersprungen.

Quelle: https://en.wikipedia.org/wiki/Rpath

0
Mecki