execute Qt5 program
-
Hi. I am Linux user.
I installed a new Qt5.5 and uninstall previous installed Qts. I install Qt inside /opt/Qt.
I have set some environment variables inside "~/.bashrc", so now i can run Qt5 programs from a console (bash),
but if i want to execute directly a Qt5 program with a double click, it not run. I suppose he not found some library.
Somebody can help me ? I need to set some environment variables, and where ?
Daniel -
Hi, on Linux when you have installed Qt 5.5, you should be able to run Qt programs directly both from Terminal (bash) or by double-clicking them.
When Qt Creator builds your program, it writes the path to your Qt installation on your PC in your program. It's called the RPATH.To check the RPATH, you can download and install a utility:
sudo apt-get install chrpath
Then to check your program:
chrpath myprogram
-
Thanks. But i need to tell you that it not adjust directly my environment variables.
After doing a chrpath :
chino/VocabularyMem: RPATH=/home/daniel/Qt5.5/5.5/gcc_64:/home/daniel/Qt5.5/5.5/gcc_64/lib
But not is
/home/daniel/Qt5.5/...
its
/home/daniel/Qt
Previously i have installed Qt on path ..Qt5.5, but i uninstall it, and install again on ...Qt (this is default) for have a cleaner system (i have previously directories as Qt5.2, Qt5.3, ...)
How to set now RPATH permanently ?
Thanks. Daniel -
Dynamic linking / shared libraries are a pain. At the end of the day, you'll have to work out a way to determine which shared libraries your executable needs and how to locate them. This will be specific to your system. I've had to deal with this a bit, so I'll post some of my thoughts.
Determine required shared libraries
To figure out which shared libraries that your executable needs, you can use
readelf
:$ readelf -d <executable> | grep -i qt 0x00000001 (NEEDED) Shared library: [libQtGui.so.4] 0x00000001 (NEEDED) Shared library: [libQtCore.so.4]
Replace
<executable>
with the name of your executable...is yours calledchino/VocabularyMem
?Use loader diagnostics (ldd)
ldd
can show you where loader (ld) will find libraries at runtime:$ ldd <executable> | grep -i qt # sample output: the Qt libraries are in /usr/lib64 libQtGui.so.4 => /usr/lib64/libQtGui.so.4 (0x00007fcac241b000) libQtCore.so.4 => /usr/lib64/libQtCore.so.4 (0x00007fcac1f33000)
If a required shared library can't be found, you see something like this:
liblog4cplus-1.2.so.5 => not found
Many shared libraries use symbolic links
The loader diagnostics only show part of the story, as the listed libraries might actually reference more specific versions:
$ /sbin/ldconfig -v 2>/dev/null | egrep -i "libqt(gui|core)" libQtGui.so.4 -> libQtGui.so.4.8.5 libQtCore.so.4 -> libQtCore.so.4.8.5
Note:
2>/dev/null
gets rid of the annoying "Cannot stat...No such file or directory" messages that often clutter the output.In the output above, you'll see that what looks like version 4 is really 4.8.5; so you can tell that in this case, the executable is using Qt 4, specifically Qt 4.8.5.
Depending on what you're doing, you might be able to use symlinks to help solve your issue.
System default location for shared libraries
One way (but not the only way) that the system locates shared libraries is by looking in the paths specified in
ld.so.conf
:$ cat /etc/ld.so.conf /usr/local/lib64 /usr/local/lib64 include /etc/ld.so.conf.d/*.conf
Installing into non-standard locations (like /home) means that the system might not find the shared libraries it needs, in which case you'll have to find another way.
rpath or runpath in binaries
When an executable is loaded, it will search the
RPATH
for shared libraries. You can see what this is:chrpath <executable> <executable>: no rpath or runpath tag found.
So in the example I gave above, there was no
RPATH
set. However, you can embed this information into the executable at compile (linking) time. Passing-Wl,-rpath,<paths>
to g++ embeds info on where to find the shared library into the executable. For example:g++ ... -Wl,-rpath,.:/test/test
This would tell the system to look in these places:
.
the current/working directorytest/test
a relative path to the current directory
When I specified
RPATH
at compile time, this is whatchrpath
says:chrpath <executable> <executable>: RPATH=.:test/test
RPATH
can be changed after the fact using this option withchrpath
:-r <path>|--replace <path>
QtCreator: case study
How does an application find its shared libraries? Let's use QtCreator as an example.
You'll notice that QtCreator sets
RPATH
to search relative directories:$ chrpath qtcreator qtcreator: RPATH=$ORIGIN/../lib/qtcreator:$ORIGIN/../lib/qtcreator/plugins
QtCreator is heavily dependent on the specific version of Qt that it was compiled against. As a result, QtCreator ships with the specific libraries it needs to run, which are located in the paths you see above. This has a few consequences:
- You can use a different version of Qt than QtCreator was compiled against
- You can have multiple versions of QtCreator on the same system
In my view, these are good properties for a program to have. Here's what I usually do:
- Determine the shared libraries that the executable needs.
- Copy the libraries into a directory relative to the executable, say
lib/
. - During the linking phase, set
RPATH
tolib/
.
Sometimes you will not want to do this, but instead you will indeed want to use the shared libraries on the system--that's a key idea behind shared libraries. However, there are situations where that might not be desired.
QtCreator is probably different from most Qt applications that most of us write. QtCreator uses private headers and relies on non-public parts of Qt, which are subject to change from one Qt release to the next. You might not need to take the same measures that QtCreator does to locate shared libraries.
Determine for yourself what is appropriate.
LD_LIBRARY_PATH
There is another technique that I see developers use all the time. You can set the
LD_LIBRARY_PATH
environment variable before the program is run. As a developer I do this often, although the user of an installed program isn't expected to have to do this. Some people will advise against doing this, but before anyone gawks at this method, let's take a look at what QtCreator 3.5.0 does:$ cat qtcreator-3.5.0/bin/qtcreator.sh ... bindir=`dirname "$me"` libdir=`cd "$bindir/../lib" ; pwd` LD_LIBRARY_PATH=$libdir:$libdir/qtcreator${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} export LD_LIBRARY_PATH exec "$bindir/qtcreator" ${1+"$@"}
I've listed the last few lines of the
qtcreator.sh
launcher script. I'm using KDE, and this is the script that I run when I want to use QtCreator. I have (at least) three versions of QtCreator installed, and this script tells you exactly what's going on. Notice thatLD_LIBRARY_PATH
is modified.Akin to how
qtcreator.sh
works, you can write your own "launcher" script that you can run from your desktop, something similar to this:#!/bin/bash LD_LIBRARY_PATH=/home/daniel/Qt/5.5/gcc_64/lib export LD_LIBRARY_PATH ./<executable>
Put this in the same directory as the executable. Then run this launcher shell script instead of the executable.