PDA

View Full Version : LD_LIBRARY_PATH and QT



splinterz
2nd January 2013, 22:30
i'm trying to deploy a QT application to linux with shared libraries. i've never attempted this before, but i'm following this guide: http://www.qtcentre.org/wiki/index.php?title=Deploying_Qt_Applications

i have a directory structure as follows:

root dir

lib folder (contains libQtCore.so.4.8.1, and others)

DT (executable)

wrapper script


the wrapper script looks like this:



#!/bin/sh
export LD_LIBRARY_PATH=./lib
./DT $*


so after running the wrapper script, in a terminal i run "ldd DT | grep Qt", but it shows every qt library still pointing to /usr/lib.. for example: libQtCore.so.4 => /usr/lib/i386-linux-gnu/libQtCore.so.4

i've tried using chrpath -d DT as well, but there's no change. what's going on? :(

splinterz
3rd January 2013, 15:46
so the solution was two part: first i had to rename the shared library i copied from libQtCore.so.4.8.1 to libQtCore.so.4. secondly i had to add the following line in the .pro file:



QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN/lib

this results in ldd showing all Qt library dependencies pointing to the local ./lib folder when running the wrapper script now. still one more problem to solve, it now complains that it can't mix Qt library versions. however i think this is due to a few changes on my system, and shouldn't affect the solution to LD_LIBRARY_PATH not working alone.

wysota
4th January 2013, 09:57
It's enough to run your app like this:

$ LD_LIBRARY_PATH=lib ./DT

ldd won't show DT depend on your local lib directory because your changes to LD_LIBRARY_PATH are not propagated outside the sh script so ldd doesn't see them.

splinterz
4th January 2013, 18:53
that's the first thing i tried but unfortunately that wasn't enough. the QMAKE flags were necessary. in fact ldd does show that it's looking in the local directory for any libraries placed in the /lib folder now.

wysota
4th January 2013, 19:29
I used LD_LIBRARY_PATH many times and I assure you it works. Maybe your lib folder doesn't have the proper symlinks (e.g. libQtCore.so -> libQtCore.so.4.8.1)

sfcheng77
4th January 2013, 19:37
We didn't have to do the rpath thing on linux. When you set the LD_LIBRARY_PATH, set it to the absolute path instead of a relative path like ./lib since you don't know what is the current directory from which the shellscript is run from. As for mixed qt versions, add this line into the script:

export QT_PLUGIN_PATH=

We also put a qt.conf in the same folder as the exe indicating the plugins are located in ".\plugins".

Some linux distributions ship a preinstalled version of QT which might be different from the version of QT you are building against. If you don't clear this variable, you might end up mixing two versions of QT.



so the solution was two part: first i had to rename the shared library i copied from libQtCore.so.4.8.1 to libQtCore.so.4. secondly i had to add the following line in the .pro file:



QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN/lib

this results in ldd showing all Qt library dependencies pointing to the local ./lib folder when running the wrapper script now. still one more problem to solve, it now complains that it can't mix Qt library versions. however i think this is due to a few changes on my system, and shouldn't affect the solution to LD_LIBRARY_PATH not working alone.

ChrisW67
4th January 2013, 21:53
Why not use the generic wrapper script in the Qt docs and your application and libraries deployed in one folder? No special RPATH shenanigans required, works out the "correct" directory itself etc.
Creating The Application Package

splinterz
4th January 2013, 22:53
I used LD_LIBRARY_PATH many times and I assure you it works. Maybe your lib folder doesn't have the proper symlinks (e.g. libQtCore.so -> libQtCore.so.4.8.1)
i'm sure i tried with both the symlinks and the shared libraries in the lib folder, and as far as i could tell (via ldd) it still wouldn't look in the lib folder first. is there another way to check this without using ldd? i don't have any symlinks in the lib folder, why would i need a symlink rather than the actual shared library?


We didn't have to do the rpath thing on linux. When you set the LD_LIBRARY_PATH, set it to the absolute path instead of a relative path like ./lib since you don't know what is the current directory from which the shellscript is run from. As for mixed qt versions, add this line into the script: export QT_PLUGIN_PATH=
i don't have any plugins, so should i still add that line to the script? i tried removing the QMAKE_LFLAGS, setting the absolute path in the wrapper script, running chrpath -d DT, and ldd once again shows nothing pointing to the local lib folder...


Why not use the generic wrapper script in the Qt docs and your application and libraries deployed in one folder? No special RPATH shenanigans required, works out the "correct" directory itself etc.
Creating The Application Package

that's exactly what i did, but i then tested with ldd to see if it was actually using the local directory, and ldd reported it wasn't. believe me i'd really rather not mess around at all with this QMAKE_LFLAGS and RPATH crap at all, but it's the only thing i can verify via ldd actually works.

wysota
4th January 2013, 23:03
and as far as i could tell (via ldd) it still wouldn't look in the lib folder first
What exactly did you do step by step to verify with ldd that it wouldn't look in the lib folder?


is there another way to check this without using ldd?
Run the application and see if it can find the libraries :)

splinterz
4th January 2013, 23:21
What exactly did you do step by step to verify with ldd that it wouldn't look in the lib folder?
Run the application and see if it can find the libraries :)

haha well that doesn't help me because i have all the libraries! anyway, i think i've got this sorted. the entire issue was that i was testing under the assumption that ldd was somehow aware of the libraries being used regardless of whether or not it was launched from a script. after your hint about it not being able to perform such magic, i used lsof -P -T -p <pid here> after launching from the script. this does show that the local libraries are being grabbed first!

now i see a lot of other /Qt-4.8.1/plugins/imageformats/<shared lib name> files in lsof that ldd didn't report. am i safe just including everything ldd reports in the libs folder, or do i need to pick through all these lsof reported libraries as well?

wysota
4th January 2013, 23:29
Oh man...

$ ldd progname | grep QtCore
libQtCore.so.4 => /usr/lib/x86_64-linux-gnu/libQtCore.so.4 (0x00007f8e8ee8f000)
$ LD_LIBRARY_PATH=lib ldd progname | grep QtCore
libQtCore.so.4 => lib/libQtCore.so.4 (0x00007f4b4c59c000)

As you can see ldd picks up the proper library just fine.


now i see a lot of other /Qt-4.8.1/plugins/imageformats/<shared lib name> files in lsof that ldd didn't report. am i safe just including everything ldd reports in the libs folder, or do i need to pick through all these lsof reported libraries as well?

ldd will never report plugins because your application doesn't depend on them.

splinterz
4th January 2013, 23:44
Oh man...

$ ldd progname | grep QtCore
libQtCore.so.4 => /usr/lib/x86_64-linux-gnu/libQtCore.so.4 (0x00007f8e8ee8f000)
$ LD_LIBRARY_PATH=lib ldd progname | grep QtCore
libQtCore.so.4 => lib/libQtCore.so.4 (0x00007f4b4c59c000)

As you can see ldd picks up the proper library just fine.

ldd will never report plugins because your application doesn't depend on them.

bah, i guess instead of asking what i was doing wrong i should have been asking why my testing wasn't working :(

thanks for all the help though, i really appreciate it.

pkj
18th December 2013, 05:11
RPATH is set by qmake makefile generation if the qt is not in the default library. For anyone working on linux with a newer version of qt will probably have qt on a /opt/ folder or similar non default folder. Once rpath is set, the ld_library_path thing doesn't work as rpath has a higher priority over ld_library_path. Refer https://blog.qt.digia.com/blog/2011/10/28/rpath-and-runpath/
In such cases we need to remove the rpath by PatchElf or chrpath. Chrpath only works for 32 bit executables. Or the flags as op has entered is an option. Or modify the generated makefile by hand.
Once rpath dependencies go, the shell script mentioned in qt documentation works as ld_library_path gets higher precedence.
Am I wrong in my understanding somewhere. Guys??

wysota
18th December 2013, 07:04
This is true only if you wish to override one (existing in the system) version of Qt library with another one, assuming your application was built with RPATH pointing to the location of the wrong library.

pkj
19th December 2013, 03:09
This is true only if you wish to override one (existing in the system) version of Qt library with another one, assuming your application was built with RPATH pointing to the location of the wrong library.
Generally in at-office work environment, qt comes pre-installed in the distribution (RHEL) for example so that kde can use it. The new qt5 versions i download, are added in /opt/ or /home/ folders. So linking against these newer qt version and using qmake to generate makefiles causes the addition of a DT_RPATH variable in the executable/library. Is there a way to tell qmake to not do so. Does adding LD_LIBRARY_PATH in the runtime settings avoid this? I tried a few combinations, but had to finally remove it -rpath manually from the generated makefile. This I have to do everytime I build the executable/library or use a nix-patcher.
Is there any way to avoid all this and tell the qmake about not adding -rpath so that the shell which exports the new ld_library_path works as expected and ld loads the shared libraries of my choice?

wysota
19th December 2013, 08:56
Your system's Qt is Qt4 or Qt5? If Qt4 then I don't see what problem you are having -- you cannot replace Qt4 libs with Qt5 or vice versa.

pkj
20th December 2013, 13:19
system is rhel6. It contains qt 4 libraries. If i replace the libraries, then kde and qt dependent application will break as qt 4 and 5 are not binary compatible. Or so I think.

wysota
20th December 2013, 15:18
Qt5 apps links explicitly against Qt5 libraries (libQt5Core.so.5). There is no way you could mix Qt4 and Qt5 libs.