2014-12-09 18 views
8

Mam program Linux Qt. Chciałbym, aby preferencyjnie używał (dynamicznych) bibliotek Qt w katalogu wykonywalnym, jeśli istnieją, w przeciwnym razie używał bibliotek Qt systemu. RPATH na ratunek.Ustawianie kolejności RPATH w QMake

dodać tę linię do qmake „s .pro plik:

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

i patrząc na wynikające wykonywalnego z readelf widzę:

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] 

wydaje się słuszne, ale ldd pokazuje, że używa wersji systemu:

libQt5Core.so.5 => /usr/local/Trolltech/Qt-5.2.0/lib/libQt5Core.so.5 (0x00007f2d2fe09000) 

Gdybym ręcznie edytować QMake wynikowym Makefile zamienić kolejność dwóch rpaths, więc $ ORIGIN przychodzi po/usr/local/..., ja uzyskać prawo zachowania:

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) 

mój problem jest z tym, jak qmake konstruuje końcową zmienną LFLAGS. Nie mogę wymyślić, jak umieścić mój dodatek ($ ORIGIN) po bibliotece systemu. Jakieś pomysły?

+0

Dlaczego wolisz preferować biblioteki lokalne nad bibliotekami systemowymi? W zwykłym scenariuszu wdrażania, w którym wysyłasz biblioteki z plikiem binarnym, masz tylko lokalny system lub lokalny. –

+0

Nie zrobiłbym tego dla produktu produkcyjnego, ale jest użyteczny do debugowania, gdzie biblioteka lokalna ma dodatkowe wyjście diagnostyczne (na przykład). Zdaję sobie sprawę, że mogę użyć czegoś podobnego do LD_LIBRARY_PATH w skrypcie wrappera, ale spieszyłem się z tym króliczym otworem QMAke/RPATH, a teraz jestem ciekawy jak zrobić QMake, co chcę ... –

Odpowiedz

0

Zgaduję, co się dzieje, ale opiera się na znajomości niektórych dziwnych zachowań ld.

sprawdź obecność zmiennej LD_LIBRARY_PATH, która wejdzie w życie przed przetworzeniem zmiennej RUNPATH. Z powodu obecności zarówno RPATH, jak i RUNPATH, zaczyna obowiązywać reguła LD_LIBRARY_PATH, więc jeśli jest ustawiona, usuń ją.

Po drugie, nigdy nie spodziewałem się zobaczyć:

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

na wyjściu ldd, to zawsze widzę ekspansję $ORIGIN do katalogu binarny (? Może skrócona), tak Liczyłam, że:

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

Co oznacza, że ​​to brzmi jak ekspansji LD_LIBRARY_PATH jest .:/usr/local/Trolltech/Qt-5.2.0/lib, co dla mnie brzmi jak masz nadpisania środowiskowe dzieje.

+0

To jest dosłowny wynik z LDD, bez skracania. LD_LIBRARY_PATH nie jest ustawiony w żadnym z tych przykładów. –

+0

Czy masz ustawione * dowolne zmienne środowiskowe '' LD_'? czy występuje takie samo zachowanie w przypadku 'env -i ldd '? Jakiej dystrybucji Linuksa używasz (próbując sprawdzić błędy)? – Petesh

1

O ile moje badania mogą powiedzieć, możesz dodać RPATH na początku listy za pomocą QMake.

Ale jeśli korzystasz z systemu Linux i możesz zainstalować chrpath, możesz to zmienić.

Dodaj ten blok na końcu pliku .pro

# 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

Nie do końca było to rozwiązanie, którego oczekiwałem, ale świetne hackowanie! –

+0

Można użyć 'patchelf --set-rpath' zamiast' chrpath -r'. Wygląda na to, że nie ma problemu z rozszerzeniem ścieżki rpath, więc nie ma potrzeby usuwania QMAKE_RPATHDIR. – user362515

8

Można dodać następujące do Twojego.pro plik zmusić dynamiczny linker patrzeć w tym samym katalogu, co Qt aplikacji w czasie wykonywania w Linuksie:

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\'" 
} 

Jeśli ma to wyglądać w podkatalogu wykonywalnego ścieżce, można użyć:

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

Należy pamiętać, że pliki .so powinny mieć dokładnie taką samą nazwę w katalogu aplikacji. Na przykład powinieneś skopiować libQt5Core.so.5.2.0 do swojego katalogu aplikacji o nazwie libQt5Core.so.5. Teraz ldd pokazuje katalog aplikacji.

Możesz również mieć libQt5Core.so.5.2.0 i link do niego o nazwie libQt5Core.so.5 w katalogu aplikacji.

+0

To jest blisko. Ustawienie 'QMAKE_FLAGS_RPATH =' w celu wyłączenia wartości domyślnej było kluczem. Wtedy mogę zrobić: 'QMAKE_FLAGS + =" -Wl, -rpath, \ '/ usr/local/Trolltech/Qt-5.2.0/libs \' -Wl, -rpath, \ '\ $$ ORIGIN \' " aby uzyskać właściwe elementy w RPATH w odpowiedniej kolejności. Prawdopodobnie istnieje pewna zmienna, która zawiera ścieżkę systemową, której mogłem użyć, ale nie mogłem jej znaleźć ... –

0

QMake zawsze dołączać QMAKE_RPATHDIR z QT_INSTALL_LIBS wewnętrznie określonym w $(QT_DIR)/mkspecs/features/qt.prf pliku:

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) 

Więc aby uniknąć aplikacji przy użyciu biblioteki QTod ścieżce systemowej, skomentuj linie powyżej którego dołączy QMAKE_RPATHDIR i dodaj QMAKE_RPATHDIR=$ORIGIN do swojego pliku .pro.

Powiązane problemy