Unable to link to OpenCV

I’m building a simple test program using OpenCV on ubuntu 20.04 with gcc 9.4.0. I downloaded and built OpenCV 4.6.0, but my test program refuses to link to OpenCV shared libraries.

main.cpp:(.text+0x70): undefined reference to `cv::Mat::Mat(int, int, int)'

My options to g++ include

-L../../libs/opencv/opencv-4.6.0/build/lib
-lopencv_core

The path is correct and libopencv_core.so is present there.
Any idea??
Thank you.

curious… can you show me a listing (ls -l) of that lib directory?

total 72092
lrwxrwxrwx 1 lazanik domainusers       24 Oct 14 14:26 libopencv_calib3d.so -> libopencv_calib3d.so.406
lrwxrwxrwx 1 lazanik domainusers       26 Oct 14 14:26 libopencv_calib3d.so.406 -> libopencv_calib3d.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers  2745480 Oct 14 14:26 libopencv_calib3d.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       21 Oct 14 14:24 libopencv_core.so -> libopencv_core.so.406
lrwxrwxrwx 1 lazanik domainusers       23 Oct 14 14:24 libopencv_core.so.406 -> libopencv_core.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers 18290592 Oct 14 14:24 libopencv_core.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       20 Oct 14 14:26 libopencv_dnn.so -> libopencv_dnn.so.406
lrwxrwxrwx 1 lazanik domainusers       22 Oct 14 14:26 libopencv_dnn.so.406 -> libopencv_dnn.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers  7173120 Oct 14 14:26 libopencv_dnn.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       27 Oct 14 14:25 libopencv_features2d.so -> libopencv_features2d.so.406
lrwxrwxrwx 1 lazanik domainusers       29 Oct 14 14:25 libopencv_features2d.so.406 -> libopencv_features2d.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers  1059944 Oct 14 14:25 libopencv_features2d.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       22 Oct 14 14:24 libopencv_flann.so -> libopencv_flann.so.406
lrwxrwxrwx 1 lazanik domainusers       24 Oct 14 14:24 libopencv_flann.so.406 -> libopencv_flann.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   691728 Oct 14 14:24 libopencv_flann.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       21 Oct 14 14:32 libopencv_gapi.so -> libopencv_gapi.so.406
lrwxrwxrwx 1 lazanik domainusers       23 Oct 14 14:32 libopencv_gapi.so.406 -> libopencv_gapi.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers  5742296 Oct 14 14:32 libopencv_gapi.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       24 Oct 14 14:26 libopencv_highgui.so -> libopencv_highgui.so.406
lrwxrwxrwx 1 lazanik domainusers       26 Oct 14 14:26 libopencv_highgui.so.406 -> libopencv_highgui.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   345768 Oct 14 14:26 libopencv_highgui.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       26 Oct 14 14:25 libopencv_imgcodecs.so -> libopencv_imgcodecs.so.406
lrwxrwxrwx 1 lazanik domainusers       28 Oct 14 14:25 libopencv_imgcodecs.so.406 -> libopencv_imgcodecs.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   506280 Oct 14 14:25 libopencv_imgcodecs.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       24 Oct 14 14:25 libopencv_imgproc.so -> libopencv_imgproc.so.406
lrwxrwxrwx 1 lazanik domainusers       26 Oct 14 14:25 libopencv_imgproc.so.406 -> libopencv_imgproc.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers 30630720 Oct 14 14:25 libopencv_imgproc.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       19 Oct 14 14:24 libopencv_ml.so -> libopencv_ml.so.406
lrwxrwxrwx 1 lazanik domainusers       21 Oct 14 14:24 libopencv_ml.so.406 -> libopencv_ml.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   687648 Oct 14 14:24 libopencv_ml.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       26 Oct 14 14:27 libopencv_objdetect.so -> libopencv_objdetect.so.406
lrwxrwxrwx 1 lazanik domainusers       28 Oct 14 14:27 libopencv_objdetect.so.406 -> libopencv_objdetect.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   727328 Oct 14 14:27 libopencv_objdetect.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       22 Oct 14 14:25 libopencv_photo.so -> libopencv_photo.so.406
lrwxrwxrwx 1 lazanik domainusers       24 Oct 14 14:25 libopencv_photo.so.406 -> libopencv_photo.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   770544 Oct 14 14:25 libopencv_photo.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       26 Oct 14 14:27 libopencv_stitching.so -> libopencv_stitching.so.406
lrwxrwxrwx 1 lazanik domainusers       28 Oct 14 14:27 libopencv_stitching.so.406 -> libopencv_stitching.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   854528 Oct 14 14:27 libopencv_stitching.so.4.6.0
-rw-rw-r-- 1 lazanik domainusers  2327408 Oct 14 14:27 libopencv_ts.a
lrwxrwxrwx 1 lazanik domainusers       24 Oct 14 14:26 libopencv_videoio.so -> libopencv_videoio.so.406
lrwxrwxrwx 1 lazanik domainusers       26 Oct 14 14:26 libopencv_videoio.so.406 -> libopencv_videoio.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   556264 Oct 14 14:26 libopencv_videoio.so.4.6.0
lrwxrwxrwx 1 lazanik domainusers       22 Oct 14 14:27 libopencv_video.so -> libopencv_video.so.406
lrwxrwxrwx 1 lazanik domainusers       24 Oct 14 14:27 libopencv_video.so.406 -> libopencv_video.so.4.6.0
-rwxrwxr-x 1 lazanik domainusers   675968 Oct 14 14:27 libopencv_video.so.4.6.0
drwxrwxr-x 2 lazanik domainusers     4096 Oct 14 14:34 python3

show the entire build process… better yet, what guides/tutorials are you following?

I don’t believe the linker sees those directives.

I’m using a very simple make file

INCLUDE := -I../../libs/opencv/opencv-4.6.0/include
INCLUDE += -I../../libs/opencv/opencv-4.6.0/build
INCLUDE += -I../../libs/opencv/opencv-4.6.0/modules/core/include
INCLUDE += -I../../libs/opencv/opencv-4.6.0/modules/imgcodecs/include 

LINK := -lstdc++
LINK += -lm
LINK += -L../../libs/opencv/opencv-4.6.0/build/lib
LINK += -lopencv_core 

CFLAGS := -Wno-narrowing 

default:
	g++ $(CFLAGS) $(INCLUDE)  $(LINK)  src/*.cpp

And this is the result:

$ make
g++ -Wno-narrowing  -I../../libs/opencv/opencv-4.6.0/include -I../../libs/opencv/opencv-4.6.0/build -I../../libs/opencv/opencv-4.6.0/modules/core/include -I../../libs/opencv/opencv-4.6.0/modules/imgcodecs/include   -lstdc++ -lm -L../../libs/opencv/opencv-4.6.0/build/lib -lopencv_core   src/*.cpp
/usr/bin/ld: /tmp/cc6wAumR.o: in function `Draw(int)':
main.cpp:(.text+0x61): undefined reference to `cv::Mat::Mat(int, int, int)'
/usr/bin/ld: main.cpp:(.text+0x6f0): undefined reference to `cv::imwrite(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&)'
/usr/bin/ld: main.cpp:(.text+0x738): undefined reference to `cv::Mat::~Mat()'
/usr/bin/ld: main.cpp:(.text+0x848): undefined reference to `cv::Mat::~Mat()'
collect2: error: ld returned 1 exit status
make: *** [makefile:14: default] Error 1

If i change the lib folder to something else it claims “cannot find -lopencv_core”, just as expected. So it finds the so, but for some strange reason cannot find the exported symbols??

The linker says it can’t find cv::Mat:::Mat(), which looks to me to have one Mat too many, so I would check the code

no, that’s just how the thing denotes the constructor of that class, with that specific signature

something is strange here.

those are .so files, they are for runtime, not for building.

you need to find .lib or .a files. those you need to tell the linker.

Hmmm, i followed the build tutorial as described here:
https://docs.opencv.org/4.x/d7/d9f/tutorial_linux_install.html

There are no *.a and *.lib files as output, only *.so. Tried with different versions, one and the same result, can’t find the symbols in the final *.so. I tried OpenCV under Windows with latest Visual Studio, it took me only 15 minutes, the lib was linked in one click build, under linux i’m trying for 2 days now…

I’m using Windows and Visual Studio for decades, now it is the first time i try gcc and linux, and my side rhetoric question is, is there anythin, just anything, that is working under linux at all???

where did you get those .so files from?

There are the output of the build as described in the linked tutorial, located in build/lib

that can’t be.

where did you look?

those different files are in different directories.

I searched in the whole tree:

~/libs/opencv/opencv-4.6.0$ find . -name "*.a"
./build/3rdparty/ippicv/ippicv_lnx/icv/lib/intel64/libippicv.a
./build/3rdparty/lib/libade.a
./build/3rdparty/lib/libippiw.a
./build/3rdparty/lib/libquirc.a
./build/3rdparty/lib/libittnotify.a
./build/3rdparty/lib/liblibprotobuf.a
./build/lib/libopencv_ts.a
~/libs/opencv/opencv-4.6.0$ find . -name "*.lib"
~/libs/opencv/opencv-4.6.0$ 

hello, @nik7012 , you’re supposed to run a

make install

from the opencv build folder, after building the libs.

this will copy all required headers to

/usr/local/include/opencv4

and the libs to

/usr/local/lib

you should not depend on the src tree for any of it later (it might no more be there !)
also, linux never uses .lib files, but .dll.a or .a files for libraries

Thanks berak, i have now the correct folders and my make file looks like

INCLUDE := -I/usr/local/include/opencv4

LINK := -lstdc++ -lm
LINK += -lopencv_core 
LINK += -lopencv_imgcodecs

CFLAGS := -Wno-narrowing

default:
	g++ $(CFLAGS) $(INCLUDE)  $(LINK)  src/*.cpp

But unfortunately this does not solve the linker problem:

~/_Projects/draw$ make
g++ -Wno-narrowing  -I/usr/local/include/opencv4  -lstdc++ -lm -lopencv_core  -lopencv_imgcodecs  src/*.cpp
/usr/bin/ld: /tmp/cc7kvFwr.o: in function `Draw(int)':
main.cpp:(.text+0x61): undefined reference to `cv::Mat::Mat(int, int, int)'
/usr/bin/ld: main.cpp:(.text+0x6f0): undefined reference to `cv::imwrite(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&)'
/usr/bin/ld: main.cpp:(.text+0x738): undefined reference to `cv::Mat::~Mat()'
/usr/bin/ld: main.cpp:(.text+0x848): undefined reference to `cv::Mat::~Mat()'
collect2: error: ld returned 1 exit status
make: *** [makefile:11: default] Error 1

Is there any way to check if these symbols are really exported in the *.so files? How to get there decorated names?

i tried

$ nm libopencv_imgcodecs.so | grep imwrite
000000000001c9c0 T _ZN2cv7imwriteERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_11_InputArrayERKSt6vectorIiSaIiEE
000000000000ff27 t _ZN2cv7imwriteERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_11_InputArrayERKSt6vectorIiSaIiEE.cold
0000000000060720 d _ZZN2cv7imwriteERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_11_InputArrayERKSt6vectorIiSaIiEEE25__cv_trace_location_fn799
0000000000063920 b _ZZN2cv7imwriteERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_11_InputArrayERKSt6vectorIiSaIiEEE31__cv_trace_location_extra_fn799

if this is the correct export of imwrite(), why g++ can not find it???