wake-up-neo.com

Wie spezifiziere ich die Präferenz des Bibliothekspfades?

Ich kompiliere ein C++ - Programm mit g++ Und ld. Ich habe eine .so Bibliothek, die ich beim Verlinken verwenden möchte. In /usr/local/lib Ist jedoch eine Bibliothek mit demselben Namen vorhanden, und ld wählt diese Bibliothek über die Bibliothek aus, die ich direkt spezifiziere. Wie kann ich das beheben?

Für die folgenden Beispiele lautet meine Bibliotheksdatei /my/dir/libfoo.so.0. Dinge, die ich ausprobiert habe und die nicht funktionieren:

  • mein g ++ Befehl ist g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • hinzufügen von /my/dir zum Anfang oder Ende meiner $PATH en-Variablen
  • hinzufügen von /my/dir/libfoo.so.0 als Argument zu g ++

Fügen Sie den Pfad zu Ihrer neuen Bibliothek hinzu, um LD_LIBRARY_PATH (es hat einen etwas anderen Namen auf dem Mac ...)

Ihre Lösung sollte mit dem -L/my/dir -lfoo -Optionen verwenden Sie zur Laufzeit LD_LIBRARY_PATH, um auf den Speicherort Ihrer Bibliothek zu verweisen.

Vorsicht bei der Verwendung von LD_LIBRARY_PATH - kurz (von Link):

..implikationen ..:
Sicherheit : Denken Sie daran, dass die in LD_LIBRARY_PATH angegebenen Verzeichnisse vor (!) Den Standardverzeichnissen durchsucht werden? Auf diese Weise könnte eine böse Person Ihre Anwendung veranlassen, eine Version einer gemeinsam genutzten Bibliothek zu laden, die schädlichen Code enthält! Dies ist einer der Gründe, warum die ausführbaren Dateien von setuid/setgid diese Variable vernachlässigen!
Leistung : Der Linkloader muss alle angegebenen Verzeichnisse durchsuchen, bis er das Verzeichnis findet, in dem sich die gemeinsam genutzte Bibliothek befindet - für ALLE gemeinsam genutzten Bibliotheken, mit denen die Anwendung verknüpft ist! Dies bedeutet, dass viele Systemaufrufe von open () fehlschlagen, wenn ENOENT (keine solche Datei oder kein solches Verzeichnis) angegeben wird! Wenn der Pfad viele Verzeichnisse enthält, steigt die Anzahl der fehlgeschlagenen Anrufe linear an. Dies können Sie an der Startzeit der Anwendung ablesen. Wenn sich einige (oder alle) Verzeichnisse in einer NFS-Umgebung befinden, kann die Startzeit Ihrer Anwendungen sehr lang werden - und das gesamte System verlangsamen!
Inkonsistenz : Dies ist das häufigste Problem. LD_LIBRARY_PATH zwingt eine Anwendung, eine gemeinsam genutzte Bibliothek zu laden, mit der sie nicht verknüpft wurde. Dies ist sehr wahrscheinlich nicht mit der Originalversion kompatibel. Dies kann entweder sehr offensichtlich sein, d. H. Die Anwendung stürzt ab, oder es kann zu falschen Ergebnissen führen, wenn die aufgenommene Bibliothek nicht ganz das tut, was die Originalversion getan hätte. Vor allem letzteres ist manchmal schwer zu debuggen.

OR

Verwenden Sie die Option rpath über gcc, um den Suchpfad für die Laufzeitbibliothek zu verknüpfen. Diese Option wird verwendet, anstatt im Standardverzeichnis zu suchen (Option gcc):

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

Dies ist gut für eine vorübergehende Lösung. Der Linker durchsucht zuerst den LD_LIBRARY_PATH nach Bibliotheken, bevor er in Standardverzeichnissen sucht.

Wenn Sie LD_LIBRARY_PATH nicht permanent aktualisieren möchten, können Sie dies im Handumdrehen über die Befehlszeile tun:

LD_LIBRARY_PATH=/some/custom/dir ./fooo

Sie können überprüfen, was der Bibliothekslinker über die Verwendung von (Beispiel) weiß:

/sbin/ldconfig -p | grep libpthread
        libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0

Und Sie können überprüfen, welche Bibliothek Ihre Anwendung verwendet:

ldd foo
        linux-gate.so.1 =>  (0xffffe000)
        libpthread.so.0 => /lib/libpthread.so.0 (0xb7f9e000)
        libxml2.so.2 => /usr/lib/libxml2.so.2 (0xb7e6e000)
        librt.so.1 => /lib/librt.so.1 (0xb7e65000)
        libm.so.6 => /lib/libm.so.6 (0xb7d5b000)
        libc.so.6 => /lib/libc.so.6 (0xb7c2e000)
        /lib/ld-linux.so.2 (0xb7fc7000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7c2a000)
        libz.so.1 => /lib/libz.so.1 (0xb7c18000)
83
stefanB

Die Angabe des absoluten Pfads zur Bibliothek sollte problemlos funktionieren:

g++ /my/dir/libfoo.so.0  ...

Haben Sie daran gedacht, den -lfoo Zu entfernen, nachdem Sie den absoluten Pfad hinzugefügt haben?

20

Dies ist eine alte Frage, aber niemand scheint dies erwähnt zu haben.

Sie hatten Glück, dass das Ding überhaupt verknüpft war.

Du musstest dich ändern

g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp

dazu:

g++ -g -Wall -o my_binary -L/my/dir bar.cpp -lfoo

Ihr Linker verfolgt die Symbole, die aufgelöst werden müssen. Wenn die Bibliothek zuerst gelesen wird, sind keine erforderlichen Symbole vorhanden, sodass die darin enthaltenen Symbole ignoriert werden. Geben Sie die Bibliotheken nach den Dingen an, die mit ihnen verknüpft werden müssen, damit in Ihrem Linker Symbole zu finden sind.

Ebenfalls, -lfoo veranlasst die Suche speziell nach einer Datei mit dem Namen libfoo.a oder libfoo.so wie benötigt. Nicht libfoo.so.0. Also entweder ln den Namen oder benenne die Bibliothek entsprechend um.

So zitieren Sie die gcc-Manpage:

-l library
   ...
   It makes a difference where in the command you 
   write this option; the linker searches and processes 
   libraries and object files in the order they are 
   specified.  Thus, foo.o -lz bar.o searches library z 
   after file foo.o but before bar.o.  If bar.o refers 
   to functions in z, those functions may not be loaded.

Hinzufügen der Datei direkt zu g++s Kommandozeile hätte funktionieren sollen, es sei denn natürlich, Sie setzen sie vor bar.cpp, wodurch der Linker es ignoriert, weil alle benötigten Symbole fehlen, da noch keine Symbole benötigt wurden.

17
Michael Speer

Alternativ können Sie die Umgebungsvariablen LIBRARY_PATH und CPLUS_INCLUDE_PATH, die jeweils angeben, wo nach Bibliotheken und nach Headern gesucht werden soll (CPATH erledigt auch die Aufgabe), ohne die Optionen -L und -I anzugeben.

Bearbeiten: CPATH enthält Header mit -I und CPLUS_INCLUDE_PATH mit -isystem.

11
Alexandre Hamez

Wenn man mit DLL in Windows arbeitet und .so-Versionsnummern in Linux/QT überspringen möchte, werden durch Hinzufügen von CONFIG += plugin Versionsnummern entfernt. Um den absoluten Pfad zu verwenden zu .so, es Linker zu geben, funktioniert gut, wie Herr Klatchko erwähnte.

0