How to link properly shared linux libraries in qt? - qt

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.

Related

Cannot open input file 'ANN.lib' in QT creator 4.21(community)

ANN: Approximate Nearest Neighbor Searching.
I am using QT creator in windows-10 64 bit system. I have compiled the source files from official site of ANN with visual studio 2015 and have successfully run the sample and test with the same environment. That is also the way how I get dll and lib files.
However, I tried to add the library to my QT creator but failed. I used both external library and internal library, even tried system library, but the problem of ' cannot open' always shows up. Meanwhile, I tried put all .h files, dll and lib file in the project's directory, still the same problem. All of other external libraries work fine after I configure them in my qmake file. Here is an example:
LIBS += -lopengl32
This is an internal lib I added (maybe system lib). And:
win32:CONFIG(release, debug|release): LIBS += -LC:/local/boost_1_63_0/lib64-msvc-14.0/ -lboost_filesystem-vc140-mt-gd-1_63
-llibboost_filesystem-vc140-mt-s-1_63
-llibboost_serialization-vc140-mt-s-1_63
-llibboost_system-vc140-mt-s-1_63
else:win32:CONFIG(debug, debug|release):
LIBS += -LC:/local/boost_1_63_0/lib64-msvc-14.0/
INCLUDEPATH += C:/local/boost_1_63_0
DEPENDPATH += C:/local/boost_1_63_0
As you can see, the two above libraries are working perfectly. Again, as I mentioned, my VS2015 can compile the sample by the library I put in the system directories. So how should I configure ANN lib in my QT?
I solved the main part of this problem by the suggestion made by the dude who commented above. Thanks a lot! The situation currently is that I can run the ANN.lib correctly in my QT creator with several other libraries (without compiling errors).
As I mentioned, I have already put all necessary files into the system directories, such as dll(system32), .lib(my visual studio 14/VC/lib), .h(my visual studio 14/VC/include). But that seemed not enough to run the ANN.lib successfully.
So I added a configuration of compilation, which is x64 release, to generate the newest dll and lib. Then I did the last step again, still not working. After that I put all files in single directory located in disk C and add this path to my qmake as external library. Now it works. Although I didn't delete the ones in my system's directories, it is running. Another thing I wonder to mention is that I also add this path to environment variables, so that I can just use += -lANN to run the lib without making it as external library. Both can work fine.

Can you specify the path to exe in qmake?

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.

How do I stop Qt Creator placing my executable in a "debug" subdirectory?

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.

Configuring Qt builds with Jenkins

I have several Qt projects that are dependent upon a Qt library that I've developed.
The project files (.pro) for projects which use the library define the LIBS and PRE_TARGETDEPS paths. For example: -
PRE_TARGETDEPS += ../ProjectLibrary_Qt_5_2_1_clang_64bit-Debug/projectlibrary.dylib
LIBS += -L../ProjectLibrary_Qt_5_2_1_clang_64bit-Debug -lProjectLibrary
As you can see, there is a defined path to the linked library and they have been building with Shadow Builds, via Qt Creator. The file hierarchy is like this: -
Projects
ProjectLibrary_Qt_5_2_1_clang_64bit-Debug
ProjectLib.dylib (the built library)
DependentProject
DependentProject.pro
(dylib is an OSX extension, but it could equally be .lib for Windows, or .so for linux)
However, Jenkins creates a different folder structure:-
jobs
ProjectLib
workspace
Project.dylib
DependentProject
workspace
DependentProject.pro
Now there is an extra directory (workspace), which would need this reflected in the .pro file and the names of the folders are different.
Obviously, If I just call qmake on the .pro with a Jenkins build, the path to the library is going to be wrong.
So, do I need to create a separate .pro just to be able to reflect the paths when building with Jenkins, or is there another way to handle specifying the location of libraries in the project file, for Jenkins, without having to change the directory structures?
Solution 1) Based on your current build configration
Modify your .pro file like this :
isEmpty(PROJECT_PATH) {
PROJECT_PATH=../ProjectLibrary_Qt_5_2_1_clang_64bit-Debug
}
LIBS += -L$${PROJECT_PATH} -lProjectLibrary
Then in Jenkins , you should pass PROJECT_PATH={path to your project} to qmake
Solution 2)
Using git submodule to fetch ProjectLibrary as a part of your building project. Then you don't need to build the ProjectLibrary by Qt Creator manually.

Qt: mingw compiled library does only work with both library.so and library.lib file present

I compiled a library using the MinGW toolchain provided with Qt 5.0.2 on Windows. As a result I received a library.so file. First I failed using the library in a Qt application, but now I found out that everything works fine when I make a copy of the liblibrary.so file and call it liblibrary.dll or liblibrary.lib (which is the only file ending supported by the add library wizard in QtCreator).
Now I wonder if this is normal or if I should change something in order not to have both files (which are exact copies). Leaving one away makes the application crash during start up. I added the library as follows to my Qt pro file:
LIBS += -L"../path/to/library" -llibrary
INCLUDEPATH += $$quote(../path/to/library)
EDIT: I compiled the library using the MinGW of Qt, not as Qt project but using mingw32-make and the provided Makefile. As a result I get the liblibrary.so.
EDIT: It seems to work also when renaming the copy to liblibrary.dll instead of .lib. But still, I need two files to make the application work -- the .so and the .dll.
Chris
That's weird, I think you should get a *.a and *.dll files when building a shared lib with MinGW on Windows, as said in the documentation:
In windows, MinGW will output .a and .dll, MSVC2010 will ouput .lib and .dll. In linux, MinGW will output .so, .so.1, .so.1.0 and .so.1.0.0 – .lib, .a and .so are import libraries.
You definitely shouldn't rename your file!
Be careful to:
not to include the "lib" prefix after "-l" in your project file.
put everything after after "-l" in lower case as you're on Windows
not adding any extension to your library name after "-l"
add and reference the .h file used in your library
A real example using QtWebsocket lib:
INCLUDEPATH += "$${PWD}/include/"
LIBS += -L"$${PWD}/libs/" -lqtwebsocket
...
HEADERS += ... \
$${PWD}/include/QWsSocket.h \
...
In my include/ folder, I have the following file:
QWsSocket.h (taken from original project - required)
In my libs/ folder, I have the following file:
libQtWebsocket.a
QtWebsocket.dll
Edit: I struggled with this too initially. Have you tried to build your lib as a static lib instead (CONFIG += staticlib in your library project)? This might help you getting you *.pro file right before switching to using the shared library.
Edit 2: Ok, the fact that you get a *.so file is still a bit odd. In this question
the user has the same issue as you and keep both files, which is just a workaround. According to a later answer it seems that you need to modify your makefile to generate a file with the proper extension. Maybe this will help: http://www.mingw.org/wiki/sampleDLL

Resources