Gibt es einen R-Pfad für dynamisch verknüpfte Bibliotheken?

Gibt es einen R-Pfad für dynamisch verknüpfte Bibliotheken?

Das Projekt, an dem ich arbeite, verwendet ein Nicht-Systemverzeichnis, um einige DLLs zu speichern, die der Code verwendet. Ich möchte sie nicht in Systemverzeichnissen ablegen, daher haben die ausführbaren Dateien einen Rpath, um die DLLs zu finden. Da jedoch immer mehr Bibliotheken hinzugefügt werden, gibt es jetzt DLLs, die von anderen DLLs in diesem Verzeichnis abhängen.

Diese Bibliotheken können die DLLs, von denen sie abhängen, nicht finden, da sie sich nicht in einem Verzeichnis befinden, nach dem der Linker sucht, z. B. einem Systemverzeichnis.

Gibt es eine Möglichkeit, die DLLs dazu zu bringen, dieses bestimmte Nicht-Systemverzeichnis zu durchsuchen? Zum Beispiel einen Rpath? Und wie geht das mit einer Bibliothek? Das für das Projekt verwendete Build-System ist CMake, falls das bei der Antwort hilft.

Diese Antwort funktioniert nicht, da in der Bibliothek kein rPath-Tag vorhanden ist:https://unix.stackexchange.com/a/272286/4193

Ich habe überlegt, es zu verwenden LD_LIBRARY_PATH, und das funktioniert, aber es ist nervig, es einzutippen, und es rPathist auch nicht so toll, andere Leute dazu zu bringen, die App zu verwenden. Wenn es eine Möglichkeit gibt, das Tag zur Bibliothek hinzuzufügen, wäre das die beste Option.

Hinweise auf frühere relevante Fragen und Antworten sind willkommen.

Antwort1

Gibt es einen R-Pfad für dynamisch verknüpfte Bibliotheken?

Ja, das gibt es. Sie können -Wl,-rpathmit ELF-Shared Objects genauso arbeiten wie mit ELF-Executables. Klonen Sie ein kleines Beispiel, das ich hier hochgeladen habe. Hier:

git clone https://gist.github.com/ardrabczyk/6aeb8545c9b754d6b15be390af4bdff0

Zum Kompilieren ausführen make. Überprüfen Sie, welche Bibliotheken von der ausführbaren ELF-Datei benötigt werden main :

$ readelf -d ./main

Dynamic section at offset 0xe30 contains 22 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libtwo.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [.]
(...)

Und prüfen Sie, welche Bibliotheken benötigt werden von libtwo.so:

$ readelf -d ./libtwo.so

Dynamic section at offset 0xe38 contains 22 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libone.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [libs]
 (...)

Wie Sie sehen, benötigen beide maineinige libtwo.sogemeinsam genutzte Objekte und beide haben rpath festgelegt. Sie müssen LD_LIBRARY_PATH nicht festlegen, um ./main auszuführen:

$ ./main
I'm in bar()

main sucht immer nach seiner libtwo.so-Abhängigkeit im .aktuellen Verzeichnis und libtwo.so sucht wiederum immer nach seiner libone.so-Abhängigkeit im libsVerzeichnis. Wenn libsdiese fehlt, wird ./main nicht gestartet:

$ mv libs libs.bak
$ ./main
./main: error while loading shared libraries: libone.so: cannot open shared object file: No such file or directory

Stellen Sie es wieder her:

$ mv libs.bak libs
$ ./main
I'm in bar()

Antwort2

Da Sie es nicht als Teil des Systems betrachten möchten, verwenden Sie es als das, was es ist: eine Benutzeranwendung!

Wenn Sie ~/.local/lib/zu Ihrem hinzufügen LD_LIBRARY_PATH, können Sie alles dort ablegen. Erstellen Sie einfach eine teilweise FHS-Struktur unter ~/.local/wieBehälter,usw,BibliothekUndAktie. Auf diese Weise müssen Sie das Programm nicht mit einer vorangestellten Umgebungsvariable aufrufen. Alle anderen Systeme müssten diesem Verzeichnis einfach ihre Umgebungsvariable für den Bibliothekspfad anhängen. Sehr übersichtlich und unixartig.

Lehnt man auch diese Lösung ab, bleibt nur noch eine Möglichkeit. Entweder man verwendet einen festen Pfad, der auf jedem System erwartet wird oder eine Umgebungsvariable, die einen Pfad enthält und ebenfalls erwartet wird.

verwandte Informationen