LD_LIBRARY_PATH
-
In welcher Reihenfolge werden die Suchpfade für shared-Objects unter Verwendung von gnu Tools (gcc, ld, ...) abgearbeitet?
Ich habe das Problem, dass auf meinem System schon eine Boost-Bibliothek (Version 1.36) installiert ist.
Ich habe den Pfad zu meiner neu kompilierten Boost-Bibliothek (Version 1.47)
zum LD_LIBRARY_PATH vorne hinzugefügt, so dass echo LD_LIBRARY_PATHPATH_TO_NEW_BOOST:other_stuff
ist.
Kompiliere ich nun aber ein Hello-World und überprüfe mit ldd die Abhängigkeiten, so zeigt sich:
ldd a.out
libboost_thread.so.1.36.0 => /usr/lib64/libboost_thread.so.1.36.0Kompiliere ich das Programm, indem ich den Pfad mittels -L explizit angebe, sieht das anders aus:
ldd a.out
libboost_thread.so.1.47.0 => PATH_TO_NEW_BOOST/libboost_thread.so.1.47.0Nun möchte ich ein größeres Programm kompilieren, welches speziell von der Boost-Version 1.47 abhängt.
Wie kann ich erreichen, dass meine Boost-Version genutzt wird?
Das Makefile ist ein wenig zu kompliziert, da kann ich wohl wenig ändern.
Ein Alias für gcc / g++ fände ich ebenfalls sehr hässlich.Ich denke, es müsste irgendwie mit LD_LIBRARY_PATH gehen, zumindest hoffe ich das
-
Das soll doch nur und nur für dieses eine Programm gelten, oder? Wenn ja, dann ist LD_LIBRARY_PATH falsch, denn das gilt ja für alle Programme, die irgendwie Boost nutzen. In dem Fall böte sich LD_RUN_PATH an. Das ist ungefähr das gleiche wie der -L Parameter beim Linken, bloß kann man es als Umgebungsvariable setzen, bevor man sein Programm baut (und hinterher wieder aufheben!)
-
Man kann natürlich LD_LIBRARY_PATH in einem script direkt vor dem Start der Anwendung setzen.Wobei das eher was für Programme ist die man nicht selber zusammenlinkt.
Also es sind der Wege viele.
-
Der LD_LIBRARY_PATH wird tatsächlich für das Programm speziell gesetzt.
Es braucht sowieso einige Umgebungsvariablen, so dass sich das angeboten hat.Der Punkt ist aber immer noch:
Anstatt der im LIBRARY_PATH und LD_LIBRARY_PATH angegebenen Bibliotheken verwendet gcc immer systemeigene.
Wenn ich -L verwende, nutzt er die Bibliotheken, die ich möchte.
Wie kann ich ihn OHNE der -L Angabe, also durch setzen einer Umgebungsvariablen dazu bringen, zuerst an den von mir gewünschten Ordnern zu suchen?
-
Liest du die Antworten? LD_RUN_PATH!
LD_LIBRARY_PATH -> Laufzeit
LD_RUN_PATH -> Linkzeit (und wird dann für die Laufzeit gemerkt)
-
Ich vergaß zu erwähnen, dass LD_RUN_PATH auch nicht zum gewünschten Ergebnis geführt hat.
Mein Fehler
-
Bevor das ganze noch eskaliert:
Vlt verwende ich das auch falsch?
Ich mache das so:
export LD_RUN_PATH=PATH_TO_MY_BOOST
g++ application.cpp -lboost_importantAnschließend schau ich mit ldd nach, welche Boost-Version genutzt wurde.
In dem Fall die systemeigene und nicht die in PATH_TO_MY_BOOST.
Das würde ich gerne ändern
-
Zwei Punkte:
1. Ich habe was vergessen: LD_RUN_PATH setzt keinen Suchpfad. Man muss noch LIBRARY_PATH angeben. Dann sollte es theoretisch funktionieren.
Also vor dem Linken LD_RUN_PATH und LIBRARY_PATH setzen (absolute Pfade!), danach sollte die Executable für alle Ewigkeit dort zuerst ihre Libraries suchen.2. Obiges funktioniert bei mir nicht :p
Wenn ich einen Pfad /foo/my_boost setze, dann ergibt gcc -print-search-dirs so etwas wie[...] libraries: =/foo/my_boost/x86_64-linux-gnu/4.8/:/foo/my_boost/x86_64-linux-gnu/:/foo/my_boost/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/4.8/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/4.8/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/foo/my_boost/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/Ich weiß nicht warum. aber ich vermute, bei dir wird es ähnlich sein. Sprich: Zuerst werden allerlei Pfade ausgehend von /foo/my_boost durchsucht, aber nie /foo/my_boost selber! Erst nachdem ein paar Pfade in /usr/... durchsucht wurden kommt /foo/my_boost dran, aber dann ist es zu spät, weil die in /usr installierten Boostbibliotheken schon gefunden wurden.
Was bei mir funktioniert:
Die eigene Boost-Bibliothek in einen Pfad packen, der in der obigen Liste früh auftaucht, also zum Beispiel /foo/my_boost/x86_64-linux-gnu/4.8/. Dann LIBRARY_PATH auf /foo/my_boost/ setzen und LD_RUNPATH auf /foo/my_boost/x86_64-linux-gnu/4.8/. Dann Programm übersetzen/linken. Dann funktioniert alles wie gewünscht.Ich habe ein kleines Beispiel programmiert, damit man nicht immer ein fettes Programm übersetzen muss, wenn man ein wenig experimentiert. Es benötigt die optionalen Binaries von Boost Random irgendwo im System installiert:
#include <boost/random/random_device.hpp> using namespace boost::random; int main() { random_device foo; }$> g++ test.cc -lboost_random $> ldd a.out [...] libboost_random.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_random.so.1.54.0 (0x00007fdd3ae83000) [...]Dann mache ich mir ein Verzeichnis /foo/my_boost mit meiner eigenen Implementierung:
#include <string> namespace boost { namespace random { class random_device { public: // types typedef unsigned int result_type; // construct/copy/destruct random_device(); explicit random_device(const std::string &); ~random_device(); // public static functions static result_type min(); static result_type max(); // public member functions double entropy() const; unsigned int operator()(); template<typename Iter> void generate(Iter, Iter); // public data members static const bool has_fixed_range; }; random_device::random_device() {} random_device::random_device(const std::string &) {} random_device::~random_device() {} const bool random_device::has_fixed_range = false; } }Übersetzt mit
g++ -shared boost.cc -o libboost_random.so -fPIC(Man kann nun fix ausprobieren, ob alles funktioniert, wenn man beim Testprogramm einen Linkpfad mit -L angibt)
Dann LIBRARY_PATH auf /foo/my_boost gesetzt. Laut Dokumentation sollte der GCC nun /foo/my_boost zuerst durchsuchen, aber wie oben gesagt, ist das bei mir nicht der Fall. Daherg++ -print-search-dirsund gucken, was wirklich durchsucht wird. Irgendwas mit /foo/my_boost/... sollte ganz am Anfang stehen. Dieses Verzeichnis erstellen wir (vermutlich reicht auch ein Link, aber das überlasse ich Leuten, die damit experimentieren wollen), kopieren die selbst erstellte so-Datei dort hin und setzen LD_RUN_PATH auf das Verzeichnis.
Dann übersetzen wir das Ursprungsprogramm und siehe da!$> g++ test.cc -lboost_random $> ldd a.out [...] libboost_random.so => /foo/my_boost/x86_64-linux-gnu/4.8/libboost_random.so (0x00007f26ad868000 [...]Das bleibt auch persistent, nachdem die Umgebungsvariablen nicht mehr gesetzt sind.