Let's talk about it in linux terms. I have a ".so" file. I want to make the executable dependent on it, look for it in the same directory. How do you do it through qmake? Or can this only be achieved through the use of QLibrary?
For example, when you have a ".so" file and want to use it in your project, in qmake you write:
LIBS += -L"path to the folder that contains your .so" -lSoName
But the path is hardcoded, as you can see, and I'm wondering what to write there to make the executable look for the ".so" in the same directory.
You use RPATH
You can configure your binary or library to find shared library (or dll) in current directory using RPATH directive that is emedded in the binary itself which the loader respects at runtime
1- Add the following in your .pro file
unix {
message("Adding RPATH to the app")
QMAKE_LFLAGS += -Wl,-rpath=\'\$$ORIGIN/\'
QMAKE_RPATH =
}
This will set RPATH of executable to current directory and your executable will first try to look for that .so in your current directory and then in standard directory (this process is explained here)
2- After you compile and create binary VERIFY that RPATH is set correctly
objdump -x <path/to/binary> |grep RPATH
it should say $ORIGIN
Compile time configuration:
CXXFLAGS += -L"/path/to/libmarylin.so/file" -lmarylin
There are a few ways to do it.
If the executable is going in the current directory, just do LIBS += -L$$(PWD) -lSoName.
If you're putting the executable into some other sub-directory, specified by some qmake variable like DESTDIR, use LIBS += -L$$(DESTDIR) (or whatever variable holds that directory).
Alternatively, you can add the directory with the executable to the runtime path of the executable, which gives the dynamic linker a list of directories to search for any unresolved libraries at runtime. This can be done with QMAKE_RPATHDIR += -L$$(PWD) and LIBS += -lSoName, which will tell the linker to look for unresolved libraries in the current directory where qmake is run.
Some operating systems may also include the current directory in the runtime search path for libraries by default, in which case just doing LIBS += -lSoName should be sufficient. That is platform-dependent, though, while the above solutions are not.
Related
I'd like to run my program on different computer which doesn't have any installed libs. I build my program in QT with openCV and copied all needed .so libs to folder with all my files. Next I changed paths in QT .pro to
INCLUDEPATH += ../
LIBS += -L../ -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_core.
I compiled that on my computer (linux) and it worked but I want it to work on another computer without compilation. On my friend's computer, binary doesnt work. I get error:
./displayImage: error while loading shared libraries: libopencv_highgui.so.3.1: cannot open shared object file: No such file or directory
Set the LD_LIBRARY_PATH environment variable to the directory that you're running it from.
If your files are located in /home/abc/cool/program/displayImage (and that folder contains all the .so files that your program needs to run)
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/abc/cool/program/
$ ./displayImage
You can also add a file <whatever>.conf in /etc/ld.so.conf.d and put one or more rows with the pathnames of your libraries.
Then run ldconfig. This is needed only once.
I have a project setup with a couple of Apps with a shared library, this is all built nicely using a SUBDIRS project, where the apps depend on the shared library.
TEMPLATE = subdirs
SUBDIRS = app1 app2 sharedLib
app1.depends = sharedLib
app2.depends = sharedLib
Each app also contains a number of tests, with CONFIG += testcase set.
This creates a check target so we can run all unit test from the top level .pro using make check.
The problem is that some of the app tests require the presence of the code within the sharedLib, therefore it needs to be discoverable according to each platforms library lookup rules.
On Windows one option is to have the sharedLib location on the PATH, on linux we can add the sharedLib location to LD_LIBRARY_PATH, on mac DYLD_LIBRARY_PATH.
One solution is to just set the location of the built shared lib before running make check:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:build/sharedDll/
make check
and this works, but it seems a little redundant as it is the build scripts themselves that are building the shared library so they know the path to the sharedLib binary location, which can be referenced from within .pro/pri files at:
$$TOP_BUILDDIR/sharedLib/release
So, is there anyway to set the PATH/LD_LIBRARY_PATH/DYLD_LIBRARY_PATH from within the project files for the purposes of the make check command?
If you are using gcc, you can use rpath parameter of gcc.
-rpath=dir
Add a directory to the runtime library search path. This is used
when linking an ELF executable with shared objects. All -rpath
arguments are concatenated and passed to the runtime linker, which
uses them to locate shared objects at runtime.
QMAKE_CXXFLAGS += -rpath=/the/absolute/path
If you use that technique, it will not be necessary to edit LD_LIBRARY_PATH
In Qt 5.5, the following qmake statement prepends the path $$TOP_BUILDDIR/sharedLib/release to LD_LIBRARY_PATH for the target check:
check.commands = LD_LIBRARY_PATH=$$TOP_BUILDDIR/sharedLib/release:\$$LD_LIBRARY_PATH $$check.commands
I drew inspiration for this solution from the files testcast.prf and qt_functions.prf (especially the functions qtAddTargetEnv() and qtAddToolEnv()), both located in $$[QT_INSTALL_PREFIX]/mkspecs/features.
I learned that qmake has a variable for searching for libs in a custom dir, it's called QMAKE_LIBDIR.
Instead of manually adding a lib path to LD_LIBRARY_PATH, you can set this in your .pro file, and then link the libraries you need with:
QMAKE_LIBDIR = /path_to_your_libs
-L/path_to_your_libs -l<whatever_lib_you_need>
I'm building a project in Qt Creator, and while I don't care where the intermediate .obj files go it's important that the final executable be put in (and run from) a particular directory where the many dependency DLLs etc. are to be found.
So, in Qt Creator, I select the 'Shadow Build' option and specify the path to this directory.
What I always find, however, is that instead of being put into this directory, the final executable is always placed into
the_Directory_I_Actually_Want/debug
... which is no use to me because, when I then try to run or debug the program from within Qt Creator, it won't start because the DLLs that it depends on are all in the_Directory_I_Actually_Want and not in the /debug subdirectory.
I've tried setting DESTDIR within my .pro file to the the_Directory_I_Actually_Want, and I've tried setting TARGET within my .pro file to the_Directory_I_Actually_Want/projectName, and I've tried faddling around with the various options that are part of the 'kit' configuration, and nothing seems to let me have any control over this.
Is there a way of doing this, or am I going to have to change the rest of my build system around just for Qt Creator's benefit?
Three years later...
Just use:
CONFIG -= \
copy_dir_files \
debug_and_release \
debug_and_release_target
On Windows you can use DLLDESTDIR variable which specifies where to copy the target dll or exe. Just add this to your .pro :
CONFIG(release, debug|release): DLLDESTDIR += $$PWD/../exec
On Linux you can use QMAKE_POST_LINK variable which contains the command to execute after linking the TARGET together. So it is like:
CONFIG(release, debug|release): QMAKE_POST_LINK += $$quote(cp project $$PWD/../exec)
Here project is the name of the target file which you provide by TARGET = project
These will copy the executable binary to a directory named exec one level upper than the program working directory. You can have your arbitrary path.
is there a way to define the path to the qt directory in a .pro file?
I've tried INCLUDEPATH += and LIB += but after qmake in the makefile always stands /usr/share/qt4 and /usr/include/qt4/ for the path to the directory where qt is installed... Maybe I could say I want to replace /usr/ with /home/ubuntu/Qt5.2.1/5.2.1/gcc or some other stuff.
What #Linville says is right. Use the correct qmake and those paths will be what you want.
Generally you should not need to set QTDIR and just running the correct qmake should work.
eg
export PATH=/home/ubuntu/Qt5.2.1/5.2.1/gcc/bin:$PATH
mkdir -p $HOME/build/myapp && cd $HOME/build/myapp
# check you have the right qmake
which qmake && qmake -query
# shadow build so as to not pollute your source tree
qmake $HOME/source/myapp/myapp.pro
If for some reason you want to refer to the paths listed by qmake -query you can use $$[QT_INSTALL_DATA] for example.
I have issue with header file not found, so I used export path before qmake which solved my problem.
I would like to include libQtGui.so.4 libQtNetwork.so.4 and libQtCore.so.4 in the same directory as where my app resides. How would I make Qt understand this? y purpose is to have a standalone app that uses shared libraries
Setting the LD_LIBRARY_PATH environment variable is one option. For example:
export LD_LIBRARY_PATH=/path/to/dir/with/libs:$LD_LIBRARY_PATH
Another option is to set the RPATH of your Qt application during linking. Setting the RPATH to the value "$ORIGIN" will cause the dynamic linker to look in the same directory as your Qt application at runtime. For example, if using qmake, add the following snippet to your project file:
unix:!mac{
QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN
QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN/lib
QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN/libs
QMAKE_RPATH=
}
This will set the RPATH to "$ORIGIN:$ORIGIN/lib:$ORIGIN/libs", meaning that the dynamic linker will first look in the location of your Qt application, then in a lib subdirectory at its location, then in a libs subdirectory at its location, and finally in any system defined locations.
UNIX / Linux is going to look in LD_LIBRARY_PATH (if set) first before looking in the system standard libs. So if you set that, you can indeed override. Just like setting the PATH on Windows. Same effect. The ordering matters.
You can add ./ or . to LD_LIBRARY_PATH as well.
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
LD_LIBRARY_PATH and QMAKE_RPATH never worked for me. Instead, I set QMAKE_RPATHDIR in my .pro file. For example after having built and installed (make install) Qt, it has been placed in /usr/local/Trolltech/Qt-4.8.5/lib/. I then write the following in my .pro file:
QMAKE_RPATHDIR += /usr/local/Trolltech/Qt-4.8.5/lib/
Note 1: Relative paths seem not to work. Prefer absolute paths.
Note 2: When you then make, you can see that the following option is given to the linker: -Wl,-rpath,/usr/local/Trolltech/Qt-4.8.5/lib/
Note 3: To be sure that the binary links dynamically to the correct library, you can display the version of Qt at runtime delivered by qVersion().