2014-12-09 5 views
8

У меня есть программа Linux Qt. Я бы хотел, чтобы они преимущественно использовали (динамические) библиотеки Qt в каталоге исполняемого файла, если они существуют, в противном случае используйте Qt libs системы. RPATH на помощь.Настройка порядка RPATH в QMake

добавить эту строку в QMAKE «s .pro файл:

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

и глядя на получившийся исполняемый файл с readelf Я вижу:

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] 

кажется правильным, но ldd показывает, что он использует системную версию:

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

Если я вручную редактировать QMAKE, влекущего Makefile, чтобы поменять порядок двух rpaths, так что $ ORIGIN приходит после того, как/USR/местные/..., я получаю правильное поведение:

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) 

Моя проблема заключается с как qmake создает конечную переменную LFLAGS. Я не могу понять, как заставить его добавить ($ ORIGIN) после системной библиотеки. Есть идеи?

+0

Почему вы предпочитаете местные библиотеки поверх системных библиотек? В обычном сценарии развертывания, когда вы отправляете библиотеки с двоичным кодом, у вас есть локальная или локальная система. –

+0

Я бы не сделал этого для производственного продукта, но он полезен для отладки, где в локальной библиотеке есть дополнительный диагностический результат (например). Я понимаю, что могу просто использовать что-то в строках LD_LIBRARY_PATH в сценарии оболочки, но я сбежал от этой кроличьей дыры QMAke/RPATH, и теперь мне интересно, как заставить QMake делать то, что я хочу ... –

ответ

0

Я немного задумываюсь о том, что происходит, но оно основано на знании некоторых странных поведений ld.

проверить наличие переменной LD_LIBRARY_PATH, которая вступит в силу до обработки переменной RUNPATH. Из-за наличия как RPATH, так и RUNPATH, правило LD_LIBRARY_PATH вступает в силу, поэтому, если оно установлено, то отключите его.

Во-вторых, я никогда не ожидал увидеть:

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

на выходе ldd, я бы всегда видеть расширение $ORIGIN в каталог бинарная (? Может быть, вы укоротить его), так Я бы ожидал:

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

это означает, что это звучит как LD_LIBRARY_PATH экспансии .:/usr/local/Trolltech/Qt-5.2.0/lib, что мне кажется, что у вас есть экологические переопределение происходит.

+0

Это verbatim output from ldd, без сокращения. LD_LIBRARY_PATH не задан ни в одном из этих примеров. –

+0

У вас есть * любые * переменные окружения LD_'? вы получаете то же поведение с 'env -i ldd '? Какой дистрибутив linux вы используете (пытаясь проверить наличие ошибок)? – Petesh

1

Насколько я могу сказать, вы можете добавить RPATH только в начале списка с помощью QMake.

Но если вы находитесь на Linux и можете установить chrpath, вы можете взломать этот путь.

Добавить этот блок в конце вашего .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

Не совсем решение, которое я ожидал, но отличный хак, тем не менее! –

+0

Вместо 'chrpath -r' можно использовать' patchelf -set-rpath'. Кажется, у него нет проблем с расширением rpath, поэтому нет необходимости очищать QMAKE_RPATHDIR. – user362515

8

Вы можете добавить следующие строки в ваш.про файл, чтобы заставить динамический компоновщик искать в том же каталоге, что и Qt приложения во время выполнения в Linux:

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

Если вы хотите, чтобы посмотреть в подкаталоге исполняемому пути, вы можете использовать:

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

Обратите внимание, что у вас должны быть файлы .so с таким же именем в каталоге приложения. Например, вы должны скопировать libQt5Core.so.5.2.0 в каталог вашего приложения с именем libQt5Core.so.5. Теперь ldd показывает каталог приложения.

Вы также можете указать libQt5Core.so.5.2.0 и ссылку на него с именем libQt5Core.so.5 в каталоге приложений.

+0

Это близко. Установка 'QMAKE_FLAGS_RPATH =' для подавления значения по умолчанию была ключом. Тогда я могу сделать: 'QMAKE_FLAGS + =" -Wl, -rpath, \ '/ usr/local/Trolltech/Qt-5.2.0/libs \' -Wl, -rpath, \ '\ $$ ORIGIN \' "' чтобы получить правильные элементы в RPATH в правильном порядке. Вероятно, есть какая-то переменная, которая содержит системный путь, который я мог бы использовать, но я не мог найти его ... –

0

QMAKE всегда будет добавить к QMAKE_RPATHDIR с QT_INSTALL_LIBS внутренне определенной в $(QT_DIR)/mkspecs/features/qt.prf файле:

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) 

Таким образом, чтобы избежать приложений, используя QTбиблиотеки из системного пути, закомментируйте строки, выше которой добавьте QMAKE_RPATHDIR и добавьте QMAKE_RPATHDIR=$ORIGIN в ваш файл .pro.