KJS_999
KJS_999

Reputation: 35

undefined reference to opencv function when i compiled with Makefile

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

Upvotes: 1

Views: 693

Answers (2)

Mike Kinghan
Mike Kinghan

Reputation: 61575

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.

Upvotes: 2

Florian Weimer
Florian Weimer

Reputation: 33727

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).

Upvotes: 0

Related Questions