2014-12-09 14 views
8

Ich habe ein Linux Qt-Programm. Ich möchte, dass es vorzugsweise die (dynamischen) Qt-Bibliotheken im Verzeichnis der ausführbaren Datei verwendet, falls sie existieren, andernfalls verwende die Qt-Bibliotheken des Systems. RPATH zur Rettung.Einstellung der RPATH-Reihenfolge in QMake

ich die folgende Zeile in der Qmake ‚s .proDatei:

QMAKE_LFLAGS += '-Wl,-rpath,\'\$$ORIGIN\'' 

und Blick auf die ausführbare Datei mit readelf Ich sehe:

0x000000000000000f (RPATH)    Library rpath: [$ORIGIN:/usr/local/Trolltech/Qt-5.2.0/lib] 
0x000000000000001d (RUNPATH)   Library runpath: [$ORIGIN:/usr/local/Trolltech/Qt-5.2.0/lib] 

rechts scheint, aber ldd zeigt, dass es die Systemversion verwendet:

qmake ist resultierende Makefile die Reihenfolge der beiden rpaths zu tauschen, so $ ORIGIN kommt nach/usr/local/..., ich das richtige Verhalten

Wenn ich manuell bearbeiten:

0x000000000000000f (RPATH)    Library rpath: [/usr/local/Trolltech/Qt-5.2.0/lib:$ORIGIN] 
0x000000000000001d (RUNPATH)   Library runpath: [/usr/local/Trolltech/Qt-5.2.0/lib:$ORIGIN] 

libQt5Core.so.5 => ./libQt5Core.so.5 (0x00007fb92aba9000) 

Mein Problem ist, mit wie qmake konstruiert die endgültige LFLAGS-Variable. Ich kann nicht herausfinden, wie ich meine Addition ($ ORIGIN) hinter die Systembibliothek stellen kann. Irgendwelche Ideen?

+0

Warum möchten Sie lokale Bibliotheken über Systembibliotheken bevorzugen? In einem normalen Bereitstellungsszenario, in dem Sie Bibliotheken mit der Binärdatei bereitstellen, haben Sie nur lokale oder lokale Systeme. –

+0

Ich würde dies nicht für ein Produktionsprodukt tun, aber es ist nützlich für das Debugging, wo die lokale Bibliothek eine zusätzliche Diagnoseausgabe hat (zum Beispiel). Ich weiß, dass ich in einem Wrapper-Skript einfach etwas in der Art von LD_LIBRARY_PATH verwenden kann, aber ich hastete dieses QMAke/RPATH-Hasenloch hinunter und jetzt bin ich neugierig, wie ich QMake machen kann, was ich will ... –

Antwort

0

Ich bin ein wenig raten, was passiert ist, aber es basiert auf einige der seltsamen Verhaltensweisen von LD kennen.

Überprüfen Sie, ob eine LD_LIBRARY_PATH Variable vorhanden ist, die vor der Verarbeitung einer RUNPATH-Variablen in Kraft tritt. Aufgrund der Anwesenheit von RPATH und RUNPATH tritt die LD_LIBRARY_PATH Regel in Kraft, also wenn sie gesetzt ist, dann lösche sie.

Zweitens würde ich nie sehen erwarten:

libQt5Core.so.5 => ./libQt5Core.so.5 (0x00007fb92aba9000) 

in der Ausgabe von ldd, würde ich immer den Ausbau der $ORIGIN in das Verzeichnis der binären sehen (? Vielleicht haben Sie es verkürzt), so ich hätte erwartet, dass:

libQt5Core.so.5 => /path/to/bin/./libQt5Core.so.5 (0x00007fb92aba9000) 

was bedeutet, dass es wie die LD_LIBRARY_PATH Expansion klingt, ist .:/usr/local/Trolltech/Qt-5.2.0/lib, das klingt für mich wie Sie Umweltüberschreibungen passiert haben.

+0

Das ist das wörtliche Ausgabe von ldd, keine Verkürzung. LD_LIBRARY_PATH wird in keinem dieser Beispiele festgelegt. –

+0

Haben Sie * any * 'LD_' Umgebungsvariablen gesetzt? erhalten Sie das gleiche Verhalten mit 'env -i ldd '? Welche Linux-Distribution benutzt du (um nach Fehlern zu suchen)? – Petesh

1

Soweit meine Forschung kann sagen, können Sie nur RPATH am Anfang der Liste mit QMake hinzufügen.

Aber wenn Sie auf Linux sind und chrpath installieren können, können Sie sich damit herumhacken.

Diesen Block am Ende Ihrer .proDatei

# Add spacing since chrpath cannot expand RPATH length 
QMAKE_RPATHDIR = \ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY1\ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY2\ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY3\ 
    /XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY4 
QMAKE_POST_LINK += 'chrpath -r \'/my/qt/installation:\$$ORIGIN\' $$OUT_PWD/mybinaryname;' 
+0

Nicht ganz die Lösung, die ich erwartet hatte, aber ein großartiger Hack dennoch! –

+0

Man könnte 'patchelf --set-rpath' anstelle von' chrpath -r' verwenden. Es scheint, dass es kein Problem hat, den rpath ebenfalls zu erweitern, also muss QMAKE_RPATHDIR nicht gelöscht werden. – user362515

8

Sie folgendes zu Ihrem hinzufügen können.Pro Datei, um den dynamischen Linker zu zwingen, im gleichen Verzeichnis wie die Qt-Anwendung zur Laufzeit in Linux zu suchen:

unix:{ 
    # suppress the default RPATH if you wish 
    QMAKE_LFLAGS_RPATH= 
    # add your own with quoting gyrations to make sure $ORIGIN gets to the command line unexpanded 
    QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\'" 
} 

Wenn Sie wollen, dass es in einem Unterverzeichnis des ausführbaren Pfades suchen, können Sie verwenden:

QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN/libs\'" 

Beachten Sie, dass Sie die .so-Dateien mit dem exakt gleichen Namen in Ihrem Anwendungsverzeichnis haben sollten. Zum Beispiel sollten Sie libQt5Core.so.5.2.0 in Ihr Anwendungsverzeichnis mit dem Namen libQt5Core.so.5 kopieren. Jetzt zeigt die ldd das Verzeichnis der Anwendung an.

Sie können auch libQt5Core.so.5.2.0 und einen Link mit dem Namen libQt5Core.so.5 im Anwendungsverzeichnis haben.

+0

Dies ist in der Nähe. Die Einstellung 'QMAKE_FLAGS_RPATH =' um den Standard zu unterdrücken war der Schlüssel. Dann kann ich tun: 'QMAKE_FLAGS + =" -Wl, -rpath, \ '/ usr/lokal/Trolltech/Qt-5.2.0/libs \' -Wl, -rpath, \ '\ $$ ORIGIN \' "' um die richtigen Elemente in RPATH in der richtigen Reihenfolge zu erhalten. Es gibt wahrscheinlich eine Variable, die den Systempfad enthält, den ich verwenden könnte, aber ich konnte ihn nicht finden ... –

0

Qmake würde hängen immer die QMAKE_RPATHDIR mit dem QT_INSTALL_LIBS intern in $(QT_DIR)/mkspecs/features/qt.prf-Datei definiert:

170: relative_qt_rpath:!isEmpty(QMAKE_REL_RPATH_BASE):contains(INSTALLS, target):\ 
173:  QMAKE_RPATHDIR += $$relative_path($$[QT_INSTALL_LIBS], $$qtRelativeRPathBase()) 
175:  QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS/dev] 
179:!isEmpty(QMAKE_LFLAGS_RPATHLINK):!contains(QT_CONFIG, static) { 
189: QMAKE_RPATHLINKDIR *= $$unique(rpaths) 

So Ihre Anwendung zu vermeiden, mit der QTBibliothek von Systempfad, kommentieren die Zeilen oberhalb derer anhängen, um die QMAKE_RPATHDIR und fügen Sie QMAKE_RPATHDIR=$ORIGIN in Ihre .pro Datei hinzu.