2014-12-09 2 views
6

Ich möchte gcc 4.8.1 für meine Anwendung verwenden (benötigt libstdC++. So.6.0.18), aber Kunden haben nur libstdC++. So.6.0.13. Ich habe -static-libgcc -static-stdlibc++ für eine Weile verwendet, aber meine Anwendung besteht aus mehreren dynamisch verknüpften Bibliotheken und einer Hauptanwendung. Dies bedeutet, dass sie beim Kompilieren jeder dynamischen Bibliothek die Standardbibliothek, die redundant und verschwenderisch ist, statisch kompilieren müssen. Ich möchte nur die Standardbibliothek meiner Wahl mit meinem Produkt ausliefern, aber jedes Mal, wenn ich meine Anwendung in einer Umgebung wie dieser austrage, lädt sie immer die falsche Standardbibliothek. Es bevorzugt die /usr/lib64/ Version, egal was ich zu tun scheint (es scheint Vorrang vor LD_LIBRARY_PATH zu haben).Versand libstdC++.so.6 mit Anwendung

Constraints:

  1. ich sie nicht erlaubt zu zwingen, zu einer neuen Standard-Bibliothek zu aktualisieren.

  2. Ich möchte die dynamischen Bibliotheken nicht statisch machen. (Ich wäre in der Lage, alles einmal statisch in die Haupt-App zu kompilieren, aber es gibt einige logistische Barrieren, die mich daran hindern, einige Bibliotheken in statische zu kompilieren).

-Wl,-rpath=$(path_to_directory) ist ein bisschen gefährlich, aber es ist legal, weil die Kunden einige Einstellungen tun beziehen, die mir erlauben Pfadvariablen zu setzen. Der rpath meines neuen stdlibC++ scheint jedoch die Standardversion /usr/lib64 nicht zu überschreiben. Ich bekomme immer noch GLIBCXX Fehler, weil es nicht die richtige Bibliothek verwenden wird.

Sicher gibt es eine elegante Lösung dafür?

Vielleicht gibt es nur einen Fehler in meinem Verfahren. Hier ist ein Beispiel (sorry über die Zensur, aber es ist nur username Sachen):

~/example$ pwd 
/home/username/example 
~/example$ echo $LD_LIBRARY_PATH 

~/example$ ls 
Makefile libstdc++.so.6.0.18 test.cpp 
~/example$ make 
g++ -std=c++11 -Wall -Werror test.cpp -o test 
~/example$ ldd test 
./test: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./test) 
    linux-vdso.so.1 => (0x00007fffe5919000) 
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x000000390b800000) 
    libm.so.6 => /lib64/libm.so.6 (0x0000003904800000) 
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000390b400000) 
    libc.so.6 => /lib64/libc.so.6 (0x0000003904400000) 
    /lib64/ld-linux-x86-64.so.2 (0x0000003904000000) 
~/example$ setenv LD_LIBRARY_PATH /home/username/example 
~/example$ echo $LD_LIBRARY_PATH 
/home/username/example 
~/example$ ldd test 
./test: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./test) 
    linux-vdso.so.1 => (0x00007fff2d3ff000) 
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x000000390b800000) 
    libm.so.6 => /lib64/libm.so.6 (0x0000003904800000) 
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000390b400000) 
    libc.so.6 => /lib64/libc.so.6 (0x0000003904400000) 
    /lib64/ld-linux-x86-64.so.2 (0x0000003904000000) 

Sorry Leute, ich habe einen ziemlich dummen Fehler gemacht ...

~/example$ file libstdc++.so.6.0.18 
libstdc++.so.6.0.18: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped 

Einige dweeb gebaut, um die falsche Version der Bibliothek, und ein anderer Dweeb (nämlich ich selbst) versuchte es auf einer 64-Bit-Maschine zu benutzen. Die Verwendung LD_LIBRARY_PATH funktionierte die ganze Zeit ...

+0

Ich hätte LD_LIBRARY_PATH erwartet zu arbeiten: Haben Sie versucht, Ihre Binärdatei sowohl mit als auch ohne LD_LIBRARY_PATH gesetzt? Denken Sie auch daran, dass LD_LIBRARY_PATH niemals durch Erhebungen bestehen bleibt. –

+0

Zeigen Sie, wie Sie LD_LIBRARY_PATH und auch die Ausgabe von 'ldd $ x | fgrep ++ 'wo' $ x' sich auf alle von Ihnen gelieferten Binaries erstreckt, mit LD_LIBRARY_PATH gesetzt und/oder '-Wl, -rpath =' in Kraft. –

+0

Okay, 'LD_LIBRARY_PATH' soll Vorrang haben? Meine Anwendung wird im Benutzermodus ausgeführt, sodass keine erhöhten Berechtigungen vorhanden sind. Hier ist, was ich im Grunde genommen habe: Kompiliere mit gcc 4.8.1 (seine Konfiguration löst Links mit der richtigen Bibliothek auf), setze 'setenv LD_LIBRARY_PATH/home/myusername /: $ {LD_LIBRARY_PATH}' und versuche dann/'ldd' das Programm auszuführen . Die Stdlib, die ich in diesem Beispiel haben möchte, ist in meinem Home-Verzeichnis. Dies soll Vorrang vor Systempfaden haben? – Suedocode

Antwort

4

Ihr Problem ist, dass die ausführbare Datei mit dem Soname libstdc++.so.6 nicht mit dem vollständigen Bibliotheksdateinamen libstdc++.so.6.0.16 verknüpft ist. Der dynamische Linker sucht an den üblichen Stellen nach libstdc++.so.6 (d. H. LD_LIBRARY_PATH, DT_RPATH, ldconfig dirs usw.). Um sicherzustellen, dass die Version 6.0.18 gefunden wird, benötigen Sie einen symbolischen Link namens libstdc++.so.6, der darauf verweist.

Anstelle der Verwendung von LD_LIBRARY_PATH (die auf Maschinen zerbrechlich ist, dass Sie nicht kontrollieren, da die Benutzer ihre Umgebung verändern könnte) Ich ziehe die Verknüpfung mit '-Wl,-rpath,$ORIGIN' (NB die Anführungszeichen sind notwendig, um die Schale zu stoppen Erweiterung $ORIGIN)

Ein RPATH von $ORIGIN teilt dem dynamischen Linker mit, nach gemeinsam genutzten Bibliotheken im selben Verzeichnis wie die ausführbare Datei zu suchen, also wenn Sie libstdC++. Wenn Sie die ausführbare Datei in ein Verzeichnis bin versenden und die Bibliothek in einem Verzeichnis lib haben möchten, können Sie '-Wl,-rpath,$ORIGIN/../lib' oder andere Pfade relativ zum Speicherort der ausführbaren Datei verwenden.

+0

Ahh Ich habe das ORIGIN-Ding schon einmal gesehen, aber ich habe nicht bemerkt, dass es ein Schlüsselwort für den Linker war; Ich dachte, es wäre nur eine häufig verwendete Shell-Variable (was völlig kontraproduktiv wäre). – Suedocode