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_PATH

    PATH_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.0

    Kompiliere 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.0

    Nun 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


  • Mod

    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?


  • Mod

    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_important

    Anschließ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


  • Mod

    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:

    test.cc

    #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:

    boost.cc

    #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. Daher

    g++ -print-search-dirs
    

    und 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.


Anmelden zum Antworten