Linking OpenCV to a shared library "mylib", `undefined reference to ...` errors - c++

I am trying to use OpenCV-2.4.13 shared objects (libopencv_core.so,libopencv_imgproc.so etc.) in mylib.so.
These OpenCV shared objects are compiled and installed with standard build procedure (make, make install) and I confirmed that they are located in /usr/local/lib, they can be used directly with an application without any problem.
I am using Qt 5.8 on Ubuntu 16.04 for building process.
In mylib.so, I use common cv::Mat functions. Looking at the similar questions, I have already skimmed this article, it suggests either using -rpath or -rpath-link options during linking mylib.so with an application. I also did read this article from Qt and applied the suggested method when building mylib.so: adding a a_global.h and defining an export symbol as Q_DECL_EXPORT.
I am providing .pro file for mylib.so below.
QT -= gui
CONFIG += c++11
TARGET = mylib
TEMPLATE = lib
DEFINES += MYLIB_LIBRARY
SOURCES += a.cpp
HEADERS += a.h external_libraries.h a_global.h
unix {
target.path = /usr/lib
INSTALLS += target
}
INCLUDEPATH += "/usr/local/include"
LIBS += -L/usr/local/lib -lopencv_calib3d -lopencv_contrib -lopencv_core\
-lopencv_features2d -lopencv_flann -lopencv_highgui -lopencv_imgproc\
-lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_ocl\
-lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_video\
-lopencv_videostab
Also, here is the .pro file for a dummy test application.
QT += core
QT -= gui
CONFIG += c++11
TARGET = apptest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
INCLUDEPATH += "/home/foo/mylib/" #this is where `a.h` is
LIBS += "/home/foo/mylib/build/mylib.so.1.0.0"
QMAKE_CXXFLAGS += "-Wall"
QMAKE_LFLAGS += "-Wl,-rpath-link,/usr/local/lib"
QMAKE_LFLAGS += "-Wl,--unresolved-symbols=ignore-in-shared-libs"
You can see that I am providing /usr/local/lib as the -rpath-link where OpenCV shared objects reside. I am also instructing the linker to ignore unresolved symbols from shared libraries, which is suggested in this question and documented here.
The "right way" according to many sources is not to link OpenCV (or any dependency) in application, because this causes overlinking. In apptest, when I don't link OpenCV, I get the following linker error:
undefined reference to cv::Mat::deallocate()
undefined reference to cv::fastFree(void)
collect2: error: ld returned 1 exit status
Looking at the error, my intuition is, somehow -rpath-link is not doing what it is supposed to do.
I was not able to resolve this, I decided to deliberately link OpenCV with apptest just to see what happens. What happens is awkward: it compiles and links without errors (whether I provide --unresolved-symbols=ignore-in-shared-libs option or not). But when I run the app, it crashes without any exceptions from OpenCV; cv::imread operation does not work as expected, rows and cols of image is zero.
I checked both apptest and mylib.so with readelf -d. Nothing strange occured to me,
mylib.so depends on libQt5Core and libopencv_* and it has the right SONAME entry.
apptest depends on mylib.so,libQt5Core and also libopencv_* when I did the deliberate linking.
I also tried to debug apptest with gdb. Output was not very helpful...
(gdb) r
Starting program:
/home/foo/apptest/build/apptest
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffc9b0 in ?? ()
I assume linking is not done properly, but why? How can I resolve this without having to link OpenCV libs directly in app?

Related

Qt 5.14.2 does not file .so file when building

I struggle for cross compiling for Raspberry pi 4. My OS is Ubuntu 20.04. I builded cross compile platform and I have been run simple quick application. (I created project on PC and I could see output window on Raspberry pi screen).
I want run more big project on Raspberry pi4 with cross compile. I want edit code on my PC and I want see output on Raspberry pi 4. I have been worked this project on Raspberry pi 4 without Qt.
I tried run qmake for .pro file and I compiled the resulting makefile file. It's working. I want do same process with cross compile but I have errors this place. Qt does not find some .so files but I checked and this files are exist on the specified path. I tried add external library,I tried add external library and I tried editing path of LIBS and INCLUDEPATH but result did not change.
P.S. I used this commands when I building cross compile. https://github.com/PhysicsX/QTonRaspberryPi/blob/main/qt5.14.2onRaspberrypi
My .pro file is:
QT += quick widgets serialport multimedia
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
INCLUDEPATH += -I/opt/qt5pi/sysroot/usr/include/opencv2
LIBS += -L/opt/qt5pi/sysroot/usr/lib -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_videostab -lopencv_features2d
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
file.cpp \
gcodesender.cpp \
movementmanager.cpp \
usbmanager.cpp \
imageresizer.cpp \
serialcommunicator.cpp \
frameprocessor.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /home/pi/dev/$${TARGET}/
!isEmpty(target.path): INSTALLS += target
HEADERS += \
file.h \
gcodesender.h \
movementmanager.h \
usbmanager.h \
imageresizer.h \
serialcommunicator.h \
frameprocessor.h
DISTFILES += \
theme/DarkTheme_copy.qml \
theme/WhiteTheme.qml
Part of the error is below:
linux-gnueabihf/libavformat.so.58, not found (try using -rpath or -rpath-link)
/opt/qt5pi/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/7.5.0/../../../../arm-linux-gnueabihf/bin/ld: warning: libvcos.so, needed by /opt/qt5pi/sysroot/usr/lib/arm-linux-gnueabihf/libavformat.so.58, not found (try using -rpath or -rpath-link)
/opt/qt5pi/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/7.5.0/../../../../arm-linux-gnueabihf/bin/ld: warning: libblas.so.3, needed by /opt/qt5pi/sysroot/lib/libarmadillo.so.9, not found (try using -rpath or -rpath-link)
/opt/qt5pi/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/7.5.0/../../../../arm-linux-gnueabihf/bin/ld: warning: liblapack.so.3, needed by /opt/qt5pi/sysroot/lib/libarmadillo.so.9, not found (try using -rpath or -rpath-link)
/opt/qt5pi/sysroot/lib/libarmadillo.so.9: undefined reference to `zgemm_'
/opt/qt5pi/sysroot/usr/lib/arm-linux-gnueabihf/libarpack.so.2: undefined reference to `clahqr_'
/opt/qt5pi/sysroot/lib/libarmadillo.so.9: undefined reference to `sdot_'
/opt/qt5pi/sysroot/usr/lib/arm-linux-gnueabihf/libavcodec.so.58: undefined reference to `vcsm_malloc_cache'
/opt/qt5pi/sysroot/lib/libarmadillo.so.9: undefined reference to `dgehrd_'
/opt/qt5pi/sysroot/lib/libarmadillo.so.9: undefined reference to `zgetrf_'
/opt/qt5pi/sysroot/lib/libarmadillo.so.9: undefined reference to `zggev_'
And my compiled output all errors(I'm stuck on the character limit ): https://pastebin.pl/view/cbeede8a
How can I fix error ?
Thanks

Undefined reference to symbol 'gzclose'

I guess this is a linker error, but I've spent a lot of time and haven't find a working answer. I have an OpenCV C++ program, when I try to compile something of the style cv::Mat newMatObject; it gives me the error /usr/local/lib/libopencv_core.a(persistence.cpp.o): undefined reference to symbol 'gzclose'.
The .pro file contains the following lines:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = QtTest
TEMPLATE = app
INCLUDEPATH += /usr/local/include/opencv
LIBS += -L/usr/local/lib -lopencv_core -lopencv_highgui -lz -ltbb -ltiff
SOURCES += main.cpp\
qttest.cpp
HEADERS += qttest.h
FORMS += qttest.ui
Am I forgetting something/doing something wrong?
Some Info:
Kubuntu 16.04 LTS 64 Bits
Qt Creator 4.0.2, based on Qt 5.7.0
OpenCV 2.4.13
Addendum:
I had the program working properly with OpenCV 2.4.9, no other changes. I decided to move on to 2.4.13 because of the extended gui, which didn't work on 2.4.9. I downloaded OpenCV 2.4.13 from the official website, and installed it with this script (except for the wget and unzip, which were made manually), initially didn't autoremove the previous library, but I did after the issue came up and rerun the previous script again, to ensure proper installation.
Edit 1:
Running
g++ -o opencvtest opencvtest.cpp `pkg-config opencv --cflags --libs`
with similar lines of code provides the desired result without a problem.
Add -lz to your LIBS:
LIBS += -L/usr/local/lib -lopencv_core -lopencv_highgui -lz

ft2build.h: No such file or directory - Freetype 2.6

I am trying to build from Linux cause I decided to start using Jenkins, my personal work but, even with freetype installed: v.2.6.3, it doens't recognize this ft2build.h.
This is the QT Pro with freetype loaded. I'm now running on UBuntu 16.04:
linux {
message("Build for Linux")
DEFINES += LINUX
DEFINES += BOOST_LOG_DYN_LINK
LIBS += -lGLU
LIBS += -lfreetype
LIBS += -L/usr/lib/x86_64-linux-gnu/-libboost_timer.so -libboost_log.so -libboost_log_setup.so -libboost_system.so -libboost_thread.so -libboost_filesystem.so
}
So i tried to change also the lib pointer doing manually as:
LIBS *= -L/usr/local/lib/ -lfreetype
but still nothing going properly. The error I get is from lGLU
In file included from displays/display.cpp:3:0:
displays/./../oglft/oglft.h:50:22: fatal error: ft2build.h: No such file or directory
compilation terminated.
Makefile:1093: recipe for target 'display.o' failed
I do always run 'qmake make clean' then /usr/lib/x86_64-linux-gnu/qt5/bin/qmake && make && make check to be sure it starts properly. Can someone help me solving the bug?
I've checked where freetype lib is located by doing:
pkg-config --cflags --libs freetype2
and this is what I get
-I/usr/local/include/freetype2 -L/usr/local/lib -lfreetype
PROBLEM SOLVED!
I have had to set FREETYPE in the environment variables as BOOST too and everything is now working properly!
Here is how is mine:
export BOOST=/var/lib/jenkins/workspace/boost_1_59_0
export FREETYPE=/var/lib/jenkins/workspace/freetype-2.6.3
I preferred to move those two libs under Jenkins to avoid permissions problems.
;-)

Adding libusb library to a Qt project in osx

I've been attempting for the past 16 hours to attach the libusb library to a Qt project without much success. I would appreciate any input on the matter, it's getting frustrating.
The .pro file is this:
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp
INCLUDEPATH +=/usr/local/include/libusb-1.0
LIBS += -L/usr/local/lib -libusb-1.0.a
LIBS += -L<libusb.h>
Source code:
#include <iostream>
#include <libusb.h>
using namespace std;
int main()
{
cout << "Hello World!" << endl;
return 0;
}
Compiler output:
13:01:50: Running steps for project lallala...
13:01:50: Configuration unchanged, skipping qmake step.
13:01:50: Starting: "/usr/bin/make" -w
make: Entering directory `/Users/MAXIMUS/Documents/workspace/lallala-build-Desktop_Qt_5_0_0_clang_64bit_SDK-Debug'
/Users/MAXIMUS/Qt5.0.0/5.0.0/clang_64/bin/qmake -spec macx-g++42 CONFIG+=debug CONFIG+=x86_64 CONFIG+=declarative_debug CONFIG+=qml_debug -o Makefile ../lallala/lallala.pro
make: Leaving directory `/Users/MAXIMUS/Documents/workspace/lallala-build-Desktop_Qt_5_0_0_clang_64bit_SDK-Debug'
make: Entering directory `/Users/MAXIMUS/Documents/workspace/lallala-build-Desktop_Qt_5_0_0_clang_64bit_SDK-Debug'
g++-4.2 -headerpad_max_install_names -mmacosx-version-min=10.6 -o lallala main.o -L/usr/local/lib -libusb-1.0.a -L<libusb.h>
/bin/sh: -c: line 0: syntax error near unexpected token `newline'
/bin/sh: -c: line 0: `g++-4.2 -headerpad_max_install_names -mmacosx-version-min=10.6 -o lallala main.o -L/usr/local/lib -libusb-1.0.a -L<libusb.h> '
make: *** [lallala] Error 2
make: Leaving directory `/Users/MAXIMUS/Documents/workspace/lallala-build-Desktop_Qt_5_0_0_clang_64bit_SDK-Debug'
13:01:50: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project lallala (kit: Desktop Qt 5.0.0 clang 64bit (SDK))
When executing step 'Make'
Forming my comment into a proper answer; this is not the correct syntax to use:
LIBS += -L/usr/local/lib -libusb-1.0.a
LIBS += -L<libusb.h>
The proper one would be this:
LIBS += -L/usr/local/lib -lusb-1.0
or
LIBS += -l/full/path/to/libusb-1.0.a
You can drop the second LIBS line in your initial attempt because you have already specified the path in the former, and putting an "include" statement in there would not be reasonable anyhow. So, this is what you could write for your complete .pro file:
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp
INCLUDEPATH +=/usr/local/include/libusb-1.0
LIBS += -L/usr/local/lib -lusb-1.0
This is not Qt specific, just generic linkage issue: -lfoo extends to $(prefix)foo$(suffix), where the prefix and suffix are figured out automatically based on the platform. That is, the prefix would be lib in your case, and suffix would be either .a or .so on Unix, probably .dylib on Mac, etc.
You may wish to look into pkg-config support if it is possible to establish. In that case, you would write something like this what we did in QtSerialPort:
CONFIG += link_pkgconfig
PKGCONFIG += libudev
Yet another option is to add the GUI through the QtCreator IDE or similar IDE that you may be using. There is an option usually in the "Linker" section to add a library. Here are two screenshots from my QtCreator:
Click on the project name on the left in the project source tree navigator, and select Add Library. Then the first screenshot will come up, and you can select the external option, and then you can see the second.
It is needless to say that you would need to run qmake after these changes to generate the corresponding Makefile on your desired platform.
Syntax is the following:
-L%LIBRARY_PATH% to make a specific path visible and
-l%LIBRARY_NAME% to link a specific library that is located in a visible path
so I guess this should work (I don't think you need the .a extension):
LIBS += -L/usr/local/lib -llibusb-1.0
and I have no idea what this would do:
LIBS += -L
so I guess I'd remove it.
Once fixed run qmake then build...
Hope it helps...

shared library in Qt Creator with mingw gives undefined reference error

Resolved. When I add my library as a normal internal library everything is fine. What I had failed to do was use the MY_LIBRARY_EXPORT macro on some free functions defined in a namespace. Somehow I had manipulated the library import in such a way to get those functions working, but it broke in other ways as described here.
I have not been able to use a shared library using the Qt Creator wizard. I have tried with dynamic linkage, and have failed, and cannot use as a static lib either. In both cases I get an 'undefined reference to `IMP_*' error.
Here are my pro files. They are both in the same SUB_DIR parent project and the paths are correct.
Relevant parts of the library pro file:
TARGET = Prospec
TEMPLATE = lib
CONFIG += staticlib
QMAKE_CXXFLAGS += -std=c++11
DEFINES += PROSPEC_LIBRARY
The entirety of the user .pro file. (ProspecTest is a unit test project for Prospec).
#-------------------------------------------------
#
# Project created by QtCreator 2013-12-12T15:04:30
#
#-------------------------------------------------
QT += testlib
QT -= gui
TARGET = prospectest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
QMAKE_CXXFLAGS += -std=c++11
SOURCES += prospectest.cpp \
mltest.cpp \
convertertest.cpp \
numericitemtest.cpp
DEFINES += SRCDIR=\\\"$$PWD/\\\"
HEADERS += \
utilities.h \
mltest.h \
convertertest.h \
numericitemtest.h
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../Prospec/release/ -lProspec
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../Prospec/debug/ -lProspec
INCLUDEPATH += $$PWD/../Prospec/debug
DEPENDPATH += $$PWD/../Prospec/debug
win32:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/../Prospec/release/libProspec.a
else:win32:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/../Prospec/debug/libProspec.a
# Boost
INCLUDEPATH += C:/boost/boost_1_55_0/
LIBS += "-LC:/boost/boost_1_55_0/stage/lib/"
EDIT: the undefined reference errors happen only where I invoke functionality in a source file. For instance, if I construct a library object I get the error, but if I move that objects constructor into a header file, then compile is OK. Right now I'm not sure if the problem is due to the Qt environment, or me not understanding shared libraries in general.
The error you describe points to a linker error. It happens when a necessary object/lib file is not specified. The most likely scenario is this: you include a header and use a function from that header, but don't specify in which library that function is defined.
Small example:
//test.c
#include <winsock.h>
int main() { gethostbyname("localhost"); }
'undefined reference' linker error:
>gcc test.c
cczICEqq.o:test.c:(.text+0x1e): undefined refer ence to `gethostbyname#4'
collect2.exe: error: ld returned 1 exit status
In this case you would have to specify libwsock32.a like this:
gcc test.c -lwsock32
Also, note that a libsomething.a is not the only place where a reference can be resolved. You might have missed an object file.
Unfortunately without more details I am not able to tell you the exact problem.
You probably forgot to export your symbols, as described here on MSDN and in various questions on this website. It's a pain in general, and there are a few ways to handle this, none much better than the other.
This makes it so that the DLL and import library actually contain a reference to the symbols you compiled into it. You can compare it partially to GCC's symbol visibility, although that only works in Linux, and GCC also supports the stuff described on MSDN for Windows.
Had the same problem just now. Build was working fine on macOS/OSX but not on Windows with the same codebase. Thanks to rubenvb, who pointed me in the right direction. Here the full solution, how to do it for Qt:
Use Q_DECL_EXPORT on functions when building the lib. And use Q_DECL_IMPORT when using the functions from the lib.
Example how to do this here: https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application#Creating_a_shared_library
Solved the problem in my case, hope it helps!