【问题标题】:undefined reference to opencv function when i compiled with Makefile使用 Makefile 编译时对 opencv 函数的未定义引用
【发布时间】:2019-02-09 10:40:46
【问题描述】:

我想用 Makefile 编译 opencv4.0 但出现未定义的引用错误。
我曾经在 Windows 中使用 opencv,代码只是简单的代码,仅在 ubuntu18.10 中显示用于测试的图像。

但如果我在 shell 上输入下面的行,它会起作用。

g++ -o simple main.cpp $(pkg-config opencv4 --libs --cflags)

我的 Makefile 在下面

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

下面是我的opencv4.pc。

# 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}

并且错误如下。

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

【问题讨论】:

  • 嗯?您的 Makefile 无法正常工作,因为它没有生成与您在 shell 中运行 g++ 时相同的命令 - OpenCV 开关全部丢失。
  • @MarkSetchell 这意味着什么openCV 开关全部丢失
  • 如果您查看您说 *"and error is below" 之后的行,您会看到执行的命令不包括您已经说过并且知道您需要的所有库。这也是弗洛里安在他的回答中告诉你的。

标签: opencv ubuntu makefile


【解决方案1】:

我假设您使用的是 GNU Make,因为您使用的是 Ubuntu Linux。

我还假设您发布的内容为:

$(TARGET):$(SRCS)
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)

在帖子中格式错误,并且您的 Makefile 确实包含:

$(TARGET):$(SRCS)
    (CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)

配方命令必须缩进制表符。

在您的 Makefile 中,您相信:

OPENCV = $(pkg-config opencv4 --libs --cflags)

是命令 pkg-config opencv4 --libs --cflags 的 shell 扩展 将命令的输出分配给 Make 变量 OPENCV。它不是。 它只是字符串 pkg-config opencv4 --libs --cflags 的 Make 扩展, 就像下一行一样:

LIBS = $(OPENCV)

$(OPENCV) 是 Make 变量 OPENCV 的 Make 扩展,而不是 shell 扩展一个shell命令OPENCV

字符串pkg-config opencv4 --libs --cflags 不是具有值的 Make 变量(显然)。

也不能调用GNU Make-function $(pkg-config ...),因为没有这样的 GNU Make 函数。

所以$(pkg-config opencv4 --libs --cflags) 扩展为nothing。因此:

LIBS = $(OPENCV)

使$(LIBS) 扩展为空,并且:

$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)

扩展为:

$(CC) $(CFLAGS) -o $(TARGET) $(SRCS)

这就是为什么链接中缺少 opencv 库并且链接失败的原因。

要将 shell 命令的输出分配给 Make 变量,请使用 $(shell ...) function

OPENCV := $(shell pkg-config opencv4 --libs --cflags)

那么$(OPENCV)$(LIBS) 将获得正确的值。

顺便说一句...

请注意,您的 clean 配方会尝试删除一个文件 core,该文件从未由您的 Makefile 创建。

还有..

注意配方:

$(TARGET):$(SRCS)
    (CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)

通常代表了最低效的自动化方法 用 Make 编译程序的构建过程,因为它会重新编译所有的 N $(SRCS) 中的源文件,只要您更改其中的一个。在你的特定 发布的情况下,没关系,因为 N = 1。但是当 N = 1 时,没有 需要制作。为了编写更多 N 较大的专业项目,您 可能想通过Chapter 2 An Introduction to Makefiles工作, 至少,在 GNU Make 手册中。

【讨论】:

    【解决方案2】:

    您的 makefile 的这一部分可能已损坏:

    $(TARGET):$(SRCS)
    $(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
    

    第二行似乎缺少前导制表符。

    未使用,因此 make 使用默认规则从.cpp 文件构建可执行文件,该规则不使用LIBS 变量(仅CFLAGS)。

    【讨论】:

    • 我可以编译简单的“.cpp”文件,但我想编译包含“opencv”api的“.cpp”文件,并且我从[gist.github.com/kevinhughes27/5311609]引用了Makefile。
    • 你确定你完全复制了吗?在您的问题中,缺少制表符。