CMake 使用 OpenCV:从库中查找包含头文件

9 篇文章 0 订阅
8 篇文章 0 订阅

在这里插入图片描述

前言

       在开发使用 OpenCV 的项目时,正确配置 CMake 是确保项目顺利构建和运行的关键。开发过程经常存在各种各样的意外和偶然, 是困难也是收获. 比如一直好好的项目, include某个头文件, 编译突然出现:No such file or directory

CmakeTest/test_opencv.h:4: error: opencv2/highgui.hpp: No such file or directory
    4 | #include <opencv2/highgui.hpp>
      |          ^~~~~~~~~~~~~~~~~~~~~

find_package查找 OpenCV 库

CMakeLists.txt 文件中,使用 find_package(OpenCV REQUIRED) 来查找并引入 OpenCV 库。这行代码的作用如下:

  1. 查找 OpenCV 库:CMake 会在系统的标准位置以及环境变量中指定的位置查找 OpenCV 库。
  2. 设置相关变量:找到 OpenCV 后,CMake 会设置一些变量,如 OpenCV_INCLUDE_DIRS(头文件路径)和 OpenCV_LIBS(库文件)。
  3. 配置编译选项:CMake 使用这些变量配置项目,使代码能够包含 OpenCV 的头文件并链接到 OpenCV 库。

CMakeLists.txt 文件示例:

cmake_minimum_required(VERSION 3.4.1)
project(CMakeTest)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 配置OpenCV 路径
set(OpenCV_DIR /sdk/opencv-linux-aarch64/lib/cmake/opencv4)

# 查找 OpenCV 库
find_package(OpenCV REQUIRED)

#message(OpenCV_LIBS "=${OpenCV_LIBS}")
# 输出: OpenCV_LIBS=opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio

#message(OpenCV_INCLUDE_DIRS "=${OpenCV_INCLUDE_DIRS}")
# 输出: OpenCV_INCLUDE_DIRS=/sdk/opencv-linux-aarch64/include/opencv4

#target_include_directories(my_executable PRIVATE ${OpenCV_INCLUDE_DIRS})

#include_directories(${CMAKE_SOURCE_DIR}/include2)
# 添加可执行文件
add_executable(test_opencv
    test_opencv.cpp)
    
# 链接 OpenCV 库
target_link_libraries(test_opencv
  ${OpenCV_LIBS}
)

在这个示例中,CMake 首先查找 OpenCV 库,然后设置包含路径和库路径,最后将这些路径添加到编译选项中,以便在编译和链接时使用 OpenCV 库。

包含 OpenCV 头文件

假设项目目录结构如下:

CMakeTest/
├── CMakeLists.txt
├── test_opencv.cpp
├── main.cpp
└── test_opencv.h

test_opencv.htest_opencv.cpp 文件中,需要正确包含 OpenCV 的头文件:

test_opencv.h

#ifndef _TEST_OPENCV_H_
#define _TEST_OPENCV_H_

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

class ImageUtils{
public:
    void init(){
        cv::Mat img = cv::imread("/data/test.jpg");
    }
};

#endif

test_opencv.cpp

#include "test_opencv.h"
#include "stdio.h"
#include "stdlib.h"

int main()
{
    printf("[%s] start\n", __FUNCTION__);

    return 0;
}

通过上述设置,test_opencv.htest_opencv.cpp 文件都能正确包含 OpenCV 的头文件。

通常, 在正常情况下, 使用外部的动态库时, 只需要2步:

  1. 包含所需的头文件
  2. 链接所需的库.

在前面代码中, 并没有显式地使用 include_directoriestarget_include_directories 包含OpenCV的头文件.

为什么不需要显式设置 include_directories

      原因是在 CMake 中,find_package(OpenCV REQUIRED) 会引入 OpenCV 的目标(targets),这些目标包含了库文件和包含路径信息。当你链接 OpenCV 目标时,这些包含路径会自动应用于你的目标。

示例项目结构

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 查找 OpenCV 库
find_package(OpenCV REQUIRED)

# 添加可执行文件
add_executable(my_executable main.cpp mycpp.cpp)

# 链接 OpenCV 库
target_link_libraries(my_executable ${OpenCV_LIBS})

在这个配置中,target_link_libraries(my_executable ${OpenCV_LIBS}) 会自动将 OpenCV 的包含路径应用到 my_executable 目标的所有源文件(main.cppmycpp.cpp)。

全局范围与目标范围的 include_directories

虽然在现代 CMake 中不需要显式调用 include_directories(${OpenCV_INCLUDE_DIRS}),但为了确保兼容性和避免潜在问题,明确设置包含路径仍然是个好习惯:

  1. 全局范围:在项目的顶部调用 include_directories,会影响整个项目中的所有目标和源文件。

    include_directories(${OpenCV_INCLUDE_DIRS})
    
  2. 目标范围:使用 target_include_directories,只会影响特定目标。

    target_include_directories(my_executable PRIVATE ${OpenCV_INCLUDE_DIRS})
    

结论

  • CMake:依赖目标导入机制,target_link_libraries 会自动处理包含路径。
  • 兼容性:为了避免路径冲突或未找到头文件的问题,显式设置包含路径是个好习惯。

通过正确配置 CMake 和 OpenCV,确保项目顺利构建和运行。

问题解决

首先, 关于 include某个头文件, 编译突然出现:No such file or directory 这个问题是如何出现的:

cmake_minimum_required(VERSION 3.4.1)
project(CMakeTest)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 配置OpenCV 路径
set(OpenCV_DIR /sdk/opencv-linux-aarch64/lib/cmake/opencv4)

# 查找 OpenCV 库
find_package(OpenCV REQUIRED)

# 添加可执行文件
add_executable(test_opencv
    test_opencv.cpp)
    
# 链接 OpenCV 库
target_link_libraries(test_opencv
  ${OpenCV_LIBS}
)


### 分界线 ###
add_executable(test_main
    main.cpp)

配置输出两个可执行文件: test_opencv, test_main
问题就出在 test_main

main.cpp 源码内容和test_opencv.cpp是一样的

#include "test_opencv.h"
#include "stdio.h"
#include "stdlib.h"

int main()
{
    printf("[%s] start\n", __FUNCTION__);

    return 0;
}
CmakeTest/main.cpp:1: In file included from CmakeTest/main.cpp:1:
CmakeTest/test_opencv.h:4: error: opencv2/highgui.hpp: No such file or directory
    4 | #include <opencv2/highgui.hpp>
      |          ^~~~~~~~~~~~~~~~~~~~~

因为 test_main 没有链接OpenCV库, 解决方案有:

  1. 增加: target_link_libraries(test_main ${OpenCV_LIBS} )

  2. 全局增加include_directories(${OpenCV_INCLUDE_DIRS})

  3. 针对 test_main 增加 target_include_directories(test_main PRIVATE ${OpenCV_INCLUDE_DIRS})

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值