undefined reference to opencv function when i compiled with Makefile - opencv

i want to compile opencv4.0 with Makefile but undefined reference error occur.
i have used to opencv in Windows and code is just simple code that only show image for test in ubuntu18.10.
but it work if i typing line below on shell.
g++ -o simple main.cpp $(pkg-config opencv4 --libs --cflags)
my Makefile is below
CC = g++
CFLAGS = -W -Wall
SRCS = main.cpp
TARGET = simple
OPENCV = $(pkg-config opencv4 --libs --cflags)
LIBS = $(OPENCV)
$(TARGET):$(SRCS)
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
clean:
rm -f $(OBJECTS) $(TARGET) core
and my opencv4.pc is below.
# Package Information for pkg-config
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/opencv4
Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.0.0
Libs: -L${exec_prefix}/lib -lopencv_gapi -lopencv_stitching -lopencv_aruco -lopencv_bgsegm -lopencv_b
Libs.private: -ldl -lm -lpthread -lrt -L/usr/lib/x86_64-linux-gnu -lGL -lGLU
Cflags: -I${includedir}
and error is below.
g++ -W -Wall -o simple main.cpp
/usr/bin/ld: /tmp/cciHsvhP.o: in function `main':
main.cpp:(.text+0x70): undefined reference to `cv::imread(cv::String const&, int)'
/usr/bin/ld: main.cpp:(.text+0xc4): undefined reference to `cv::imshow(cv::String const&, cv::_InputArray const&)'
....
collect2: error: ld returned 1 exit status
make: *** [Makefile:11: simple] Error 1

I assume you're using GNU Make, since you are working on Ubuntu Linux.
I also assume what you have posted as:
$(TARGET):$(SRCS)
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
is mis-formatted in the posting and that your Makefile really contains:
$(TARGET):$(SRCS)
(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
with the recipe command tab-indented as it must be.
In your Makefile you believe that:
OPENCV = $(pkg-config opencv4 --libs --cflags)
is a shell-expansion of the command pkg-config opencv4 --libs --cflags that
assigns the output of the command to the Make variable OPENCV. It is not.
It is simply a Make expansion of the string pkg-config opencv4 --libs --cflags,
just as in the next line:
LIBS = $(OPENCV)
$(OPENCV) is the Make expansion of the Make variable OPENCV and not the shell
expansion of a shell command OPENCV.
The string pkg-config opencv4 --libs --cflags is not a Make variable that has a value (obviously).
Neither can it be an invocation of a GNU Make-function
$(pkg-config ...), as there is no such GNU Make function.
So $(pkg-config opencv4 --libs --cflags) expands to nothing. Hence:
LIBS = $(OPENCV)
makes $(LIBS) expand to nothing, and:
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
expands to the same as:
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS)
which is why the opencv libraries are missing from your linkage and the linkage fails.
To assign the output of a shell command to a Make variable, using the $(shell ...) function:
OPENCV := $(shell pkg-config opencv4 --libs --cflags)
Then $(OPENCV) and $(LIBS) will acquire the correct value.
BTW...
Note that your clean recipe attempts to delete a file, core, that is never created by your Makefile.
And..
Be aware that the recipe:
$(TARGET):$(SRCS)
(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
represents in general the most inefficient possible way of automating a
program's build process with Make, because it will recompile all of the N
source files in $(SRCS) whenever you change even 1 of them. In your particular
case as posted, it doesn't matter because N = 1. But when N = 1 there is no
need for Make. In anticipation of writing more professional projects where N is large, you
might like to work through Chapter 2 An Introduction to Makefiles,
at least, in the GNU Make manual.

This part of your makefile is likely broken:
$(TARGET):$(SRCS)
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
It looks like a leading tab character is missing on the second line.
It is not used, so make uses the default rule for building executables from .cpp files, which does not use the LIBS variable (only CFLAGS).

Related

Linking to Qt4 library

I am trying to compile a short test program that requires Qt4, but have trouble properly linking to the Qt4 library. I have installed Qt4 via
sudo apt-get install qt4-dev-tools
The program code looks like this
#include <QtCore>
#include <iostream>
int main() {
std::cout << "Qt version: " << qVersion() << std::endl;
}
The shared library libQtCore.so is at /usr/lib/x86_64-linux-gnu but trying to compile the following way
g++ -L/usr/lib/x86_64-linux-gnu -Wall -o test.exe test.cpp -lQtCore
returns an error message that there is no file or directory called QtCore.
I have also tried to directly use the QtCore source code, but have received the following error message:
/tmp/ccljEHOY.o: In function main':
test.cpp:(.text+0xa): undefined reference toqVersion()'
collect2: error: ld returned 1 exit status
What am I doing wrong here?
Thanks
Ips
The compiler was not able to find QtCore file because you need to add path with Qt to the list of directories to be searched for header files.
You can use the pkg-config to get proper flags:
$:pkg-config QtCore --cflags
-DQT_SHARED -I/usr/include/qt4 -I/usr/include/qt4/QtCore
For linking:
$:pkg-config QtCore --libs
-lQtCore
You can use pkg-config when calling the compiler:
g++ test.cpp `pkg-config QtCore --cflags --libs`
or
g++ `pkg-config QtCore --cflags` test.cpp `pkg-config QtCore --libs`
Note that the following way won't work:
g++ `pkg-config QtCore --cflags --libs` test.cpp

Met undefined reference when use glib in ubuntu

I've searched about this a lot. And tried a lot. Just don't know where I go wrong.
Here is my code, it's very simple:
#include <glib.h>
int main()
{
int *ip=g_new(int,1);
*ip=42;
return *ip;
}
First I try apt-get libglib2.0-dev in my Ubuntu and Mint, when it's done, compile with:
gcc `pkg-config --cflags --libs glib-2.0` -o main main.c
/tmp/ccYFljQD.o: In function `main':
main.c:(.text+0x13): undefined reference to `g_malloc_n'
collect2: error: ld returned 1 exit status
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1
And the output of pkg-config:
$ pkg-config --cflags --libs glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0
So it's not working, then I try to compile from source and install one by my own.
I've apt-get libffi-dev, autogen and configure, make, make install, that's all okay.
$ pkg-config --cflags --libs glib-2.0
-I/home/donpope/software/include/glib-2.0 -I/home/donpope/software/lib/glib-2.0/include -L/home/donpope/software/lib -lglib-2.0
Yet compile with the same error:
gcc `pkg-config --cflags --libs glib-2.0` -o main main.c
/tmp/cctR3iEq.o: In function `main':
main.c:(.text+0x13): undefined reference to `g_malloc_n'
collect2: error: ld returned 1 exit status
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1
So I need some help here. Thank you!
Update:
Later I try this in a RedHat with older gcc. And it's just okay.
I have this Makefile in my glib sandbox:
PKGS=glib-2.0
CFLAGS+=$(shell pkg-config --cflags $(PKGS))
LDFLAGS+=$(shell pkg-config --libs $(PKGS))
%: %.c
$(CC) $(CFLAGS) $< -o $# $(LIBS) $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) $< -c -o $#
%: %.o
$(CC) $< -o $# $(LIBS) $(LDFLAGS)
Starting from this and tweaking, you should be able to figure out the exact commandline and compile your program.
Also, you should make sure that your PKG_CONFIG_PATH is properly updated to contain the path where you installed glib (typically in PREFIX/lib/pkgconfig).
Ubuntu 18.04 here. I had to place all my glib flags at the end of the compile statement, even after the source .c file. So this compiles fine:
gcc -Wall -o bfs bfs.c `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0`
but this does not :
gcc -Wall -o bfs `pkg-config --cflags glib-2.0` `pkg-config --libs glib-2.0` bfs.c
/tmp/ccvWsLk3.o: In function `newGraph':
bfs.c:(.text+0x58): undefined reference to `g_hash_table_new'
collect2: error: ld returned 1 exit status
Which drove me nuts for a while as I was taught that it's always good style to place the source file at the end of the compile statement. :p

pkg-config not working when compiling an OpenCV program with two objects

I have written an OpenCV program which contains both main.cpp and pedestrian.cpp. I wanted to compile them, so I did the following:
g++ -c -Wall `pkg-config --cflags opencv` main.cpp -o main.o
g++ -c -Wall `pkg-config --cflags opencv` pedestrian.cpp -o pedestrian.o
g++ `pkg-config --libs opencv` pedestrian.o main.o -o detect
After the third statement, every OpenCV command I use is considered an undefined reference. I have no idea why this is happening since other single object programs work just fine with pkg-config. I checked to see if it was a namespace problem and it wasn't either. Any help would be greatly appreciated.
Try changing the order int the last line to:
g++ -o detect pedestrian.o main.o `pkg-config --libs opencv`
This should work. Order matters when linking the .o files. When the linker finds and unknown OpenCV symbol in any of the .o, it looks for its definition in the following linked elements (i.e. in the elements to the right).

pkg-config --cflags opencv: No such file or directory

I'm writing a basic example of opencv, but make command give me message
g++-4.7.real: error: pkg-config --cflags opencv: No such file or directory
g++-4.7.real: error: pkg-config --libs opencv: No such file or directory
issue command pkg-config --cflag opencv give me result as:
-I/usr/local/include/opencv -I/usr/local/include
and pkg-config --libs opencv give me:
-I/usr/local/include/opencv -I/usr/local/include
vudao#vudaopc:~/work/nmath/ntrainer$ pkg-config --libs opencv
/usr/local/lib/libopencv_contrib.a /usr/local/lib/libopencv_stitching.a /usr/local/lib/libopencv_nonfree.a /usr/local/lib/libopencv_superres.a /usr/local/lib/libopencv_ocl.a /usr/local/lib/libopencv_ts.a /usr/local/lib/libopencv_videostab.a /usr/local/lib/libopencv_gpu.a /usr/local/lib/libopencv_photo.a /usr/local/lib/libopencv_objdetect.a /usr/local/lib/libopencv_legacy.a /usr/local/lib/libopencv_video.a /usr/local/lib/libopencv_ml.a /usr/local/lib/libopencv_calib3d.a /usr/local/lib/libopencv_features2d.a /usr/local/lib/libopencv_highgui.a /usr/local/share/OpenCV/3rdparty/lib/libIlmImf.a /usr/local/share/OpenCV/3rdparty/lib/liblibjasper.a /usr/local/share/OpenCV/3rdparty/lib/liblibtiff.a /usr/local/lib/libopencv_imgproc.a /usr/local/lib/libopencv_flann.a /usr/local/lib/libopencv_core.a /usr/lib/i386-linux-gnu/libbz2.so /usr/lib/i386-linux-gnu/libpng.so /usr/lib/i386-linux-gnu/libjpeg.so /usr/lib/i386-linux-gnu/libz.so -lswscale -lavformat -lavutil -lz -lSDL -lasound -lavcodec -lgthread-2.0 -lglib-2.0 -lgobject-2.0 -lfontconfig -lfreetype -lpango-1.0 -lcairo -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lpangoft2-1.0 -lgio-2.0 -latk-1.0 -lgdk-x11-2.0 -lgtk-x11-2.0 -lrt -lpthread -lm -ldl -lstdc++
Below is my Makefile:
CC=g++
CFLAGS=-O2 -g 'pkg-config --cflags opencv'
LDFLAGS='pkg-config --libs opencv'
BIN=ntrainer
ntrainer : ntrainer.cpp
$(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) ntrainer.cpp
My system is Ubuntu 12.10. I have installed opencv-2.4.7 successfully (I think) following instructions here http://www.samontab.com/web/2011/06/installing-opencv-2-2-in-ubuntu-11-04/
I also have configured and exported PKG_CONFIG_PATH into /etc/bash.bashrc, I'v also ran ldconfig
Please someone tell me what I'm missing? And how to correct it.
Thanks too much.
You used incorrect quotes. You should use ` instead of ':
CC=g++
CFLAGS=-O2 -g `pkg-config --cflags opencv`
LDFLAGS=`pkg-config --libs opencv`
For me, the file was there but the path was wrong:
I had to look for the opencv.pc file, make sure it is in the path for the pkgconfig program to find (i.e. in one of the pkgconfig folders) and then make sure the prefix path in there is right.
In my case it was wrong because it was not installed via make install but i made a make package package because it was cross-compiled, and the path I had installed it at didn't match the CMAKE path.
running
pkg-config --cflags opencv
or
pkg-config --libs opencv
tells you where it is looking for the files, so you can make sure they match.

Makefile to Compile OpenCV Code in C++ on Ubuntu/Linux

I am learning OpenCV using Learning OpenCV book.
One problem I am facing while compiling the code is that I have to write a long command to compile and get the executable.
This is the command I am using
g++ `pkg-config –cflags opencv` file_name.cpp -o output_file `pkg-config –libs opencv`
I am no Make expert but I think I can eliminate writing that long command using make.
Before that I should explain my work flow. I have created a directory called opencv in my home directory (~/opencv/). I am reading the book section by section and coding the examples or exercises into new cpp source code files in that directory. So I don't know the names of the files before hand.
Now what I want make to do is,
Suppose I have coded a new file named facedetect.cpp in my opencv directory, and if I call make like this
make facedetect
then I want make to execute the following command for me
g++ `pkg-config --cflags opencv` facedetect.cpp -o facedetect `pkg-config --libs opencv`
so that whenever I make a new file named abc.cpp, I will execute make abc
so that I can run
$ ./abc
at my command line to test my abc.cpp
Please give that make file so that I can save the frustration of typing that long command each time.
PS: I have Googled for help on this and found this on using CMake but I could not understand what that does. Kindly also explain how can I use CMake for the same task.
You can create a file called Makefile in you working directory like this:
CFLAGS = `pkg-config --cflags opencv`
LIBS = `pkg-config --libs opencv`
% : %.cpp
g++ $(CFLAGS) $(LIBS) -o $# $<
then you can use this file for all your single-file programms. Just call make with the basename of the file you want to compile. For facedetect.cpp that would be
make facedetect
Here some more details:
The general format of a makefile is like this:
target : dependecy1 dependenc2 ...
command that generates the target
So for your example you could write:
facedetect : facedetect.cpp
g++ $(CFLAGS) $(LIBS) -o facedetect facedetect.cpp
For each new example you can now create a new target. But you can also make it more general:
% : %.cpp
g++ $(CFLAGS) $(LIBS) -o $# $<
Here % matches any nonempty substring. The automatic variables $# and $< substitute the names of the target file and the source file.
For more information you can consult the make documentation.
GNU Make is pretty smart and the Makefile you need for this doesn't need to be as verbose as in the other answers given so far. Here is a simple Makefile which you can use to compile the OpenCV examples:
CPPFLAGS = $(shell pkg-config --cflags opencv)
LDLIBS = $(shell pkg-config --libs opencv)
That's it. The Makefile can be this short thanks to Make's implicit rules.
Then run make as usual:
make facedetect
This assumes there is a facedetect.c or facedetect.cpp in the same directory.
I recommend the following (free!) book if you want to learn Make: http://oreilly.com/catalog/make3/book/index.csp
Create a file named makefile in your working directory that contains the following:
CFLAGS = $SHELL(pkg-config --cflags opencv)
LIBS = $SHELL(pkg-config --libs opencv)
facedetect : facedetect.cpp
g++ $(CFLAGS) $(LIBS) -o $# $<
Then when you want to compile you just type:
$ make
(To answer your PS - note that CMake is very different from make - for now you should probaby just use make.)

Resources