C++学习笔记—find原理—以opencv为例子的实操
更新
locate
数据库 (必做!)- 操作: 打开终端,运行
sudo updatedb
。 - 原因: 确保
locate
的数据库包含你刚刚安装的新库的文件信息。否则后续步骤可能什么也找不到。
- 操作: 打开终端,运行
初步定位:查找核心配置文件 (
Config.cmake
)操作: 运行以下命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30locate -i 'config.cmake' | grep -i 'opencv'
# 结果为
~ ❯ locate -i 'config.cmake' | grep -i 'opencv'
/home/xfy/opencv_versions/4.5.5/build/3rdparty/ade/ade-0.1.1f/sources/ade/cmake/adeConfig.cmake.in
/home/xfy/opencv_versions/4.5.5/build/CPackConfig.cmake
/home/xfy/opencv_versions/4.5.5/build/CPackSourceConfig.cmake
/home/xfy/opencv_versions/4.5.5/build/OpenCVConfig.cmake
/home/xfy/opencv_versions/4.5.5/build/opencv_python_config.cmake
/home/xfy/opencv_versions/4.5.5/build/unix-install/OpenCVConfig.cmake
/home/xfy/opencv_versions/4.5.5/opencv/cmake/OpenCVGenConfig.cmake
/home/xfy/opencv_versions/4.5.5/opencv/cmake/OpenCVGenPkgconfig.cmake
/home/xfy/opencv_versions/4.5.5/opencv/cmake/templates/OpenCVConfig.cmake.in
/home/xfy/opencv_versions/4.5.5/opencv/samples/hal/c_hal/config.cmake
/home/xfy/opencv_versions/4.5.5/opencv/samples/hal/slow_hal/config.cmake
/usr/lib/x86_64-linux-gnu/cmake/opencv4/OpenCVConfig.cmake
/usr/local/opencv/4.5.5/lib/cmake/opencv4/OpenCVConfig.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/build/3rdparty/ade/ade-0.1.1f/sources/ade/cmake/adeConfig.cmake.in
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/build/CPackConfig.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/build/CPackSourceConfig.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/build/OpenCVConfig.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/build/opencv_python_config.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/build/unix-install/OpenCVConfig.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/cmake/OpenCVGenConfig.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/cmake/OpenCVGenPkgconfig.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/cmake/templates/OpenCVConfig.cmake.in
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/samples/hal/c_hal/config.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/home/myslam/3d/opencv-4.2.0/samples/hal/slow_hal/config.cmake
/var/lib/docker/overlay2/0809ea31aa8a06f4c911b20f04526b19005bfabdd262f23d6bb3a4ee464f4dbb/diff/usr/local/lib/cmake/opencv4/OpenCVConfig.cmake
/var/lib/docker/overlay2/1f605c5b588ec93f0f1947a29092b374d5fd184eedbfea41eba42bc85f33b932/diff/usr/lib/x86_64-linux-gnu/cmake/opencv4/OpenCVConfig.cmake可以看到有很多,但是我知道我是安装到/usr/local/的所以看/usr/local/opencv/4.5.5/lib/cmake/opencv4/OpenCVConfig.cmake
这一个
确定
find_package
名称由OpenCVConfig.cmake可以知道这里的名称大小写是OpenCV,所以应该是find_package(OpenCV REQUIRED)
这里可以指定模块,也可以不指定,没有太大影响的。之前文章的例子里指定了模块的写法是find_package(OpenCV REQUIRED COMPONENTS core imgcodecs highgui)
然后通过gedit或者vim等等查看这个文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40# The OpenCV CMake configuration file
#
# ** File generated automatically, do not modify **
#
# Usage from an external project:
# In your CMakeLists.txt, add these lines:
#
# find_package(OpenCV REQUIRED)
# include_directories(${OpenCV_INCLUDE_DIRS}) # Not needed for CMake >= 2.8.11
# target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})
#
# Or you can search for specific OpenCV modules:
#
# find_package(OpenCV REQUIRED core videoio)
#
# You can also mark OpenCV components as optional:
# find_package(OpenCV REQUIRED core OPTIONAL_COMPONENTS viz)
#
# If the module is found then OPENCV_<MODULE>_FOUND is set to TRUE.
#
# This file will define the following variables:
# - OpenCV_LIBS : The list of all imported targets for OpenCV modules.
# - OpenCV_INCLUDE_DIRS : The OpenCV include directories.
# - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability.
# - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API.
# - OpenCV_VERSION : The version of this OpenCV build: "4.5.5"
# - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "4"
# - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "5"
# - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION: "5"
# - OpenCV_VERSION_STATUS : Development status of this build: ""
#
# Advanced variables:
# - OpenCV_SHARED : Use OpenCV as shared library
# - OpenCV_INSTALL_PATH : OpenCV location
# - OpenCV_LIB_COMPONENTS : Present OpenCV modules list
# - OpenCV_USE_MANGLED_PATHS : Mangled OpenCV path flag
#
# Deprecated variables:
# - OpenCV_VERSION_TWEAK : Always "0"翻译一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40# ===================================================================================
# OpenCV CMake 配置文件
#
# ** 文件自动生成,请勿修改 **
#
# 从外部项目使用:
# 在你的 CMakeLists.txt 中,添加这些行:
#
# find_package(OpenCV REQUIRED)
# include_directories(${OpenCV_INCLUDE_DIRS}) # 对于 CMake >= 2.8.11 已不再需要
# target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})
#
# 或者你可以搜索特定的 OpenCV 模块:
#
# find_package(OpenCV REQUIRED core videoio)
#
# 你也可以将 OpenCV 组件标记为可选:
# find_package(OpenCV REQUIRED core OPTIONAL_COMPONENTS viz)
#
# 如果找到了模块,那么 OPENCV_<MODULE>_FOUND 会被设置为 TRUE。
#
# 该文件将定义以下变量:
# - OpenCV_LIBS : OpenCV 模块的所有导入目标 (imported targets) 的列表。
# - OpenCV_INCLUDE_DIRS : OpenCV 的包含目录。
# - OpenCV_COMPUTE_CAPABILITIES : 计算能力 (Compute Capability) 的版本。
# - OpenCV_ANDROID_NATIVE_API_LEVEL : 最低要求的 Android API 级别。
# - OpenCV_VERSION : 此 OpenCV 构建的版本:"4.5.5"
# - OpenCV_VERSION_MAJOR : OpenCV_VERSION 的主版本号:"4"
# - OpenCV_VERSION_MINOR : OpenCV_VERSION 的次版本号:"5"
# - OpenCV_VERSION_PATCH : OpenCV_VERSION 的修订版本号:"5"
# - OpenCV_VERSION_STATUS : 此构建的开发状态:""
#
# 高级变量:
# - OpenCV_SHARED : 将 OpenCV 作为共享库使用
# - OpenCV_INSTALL_PATH : OpenCV 的位置
# - OpenCV_LIB_COMPONENTS : 当前存在的 OpenCV 模块列表
# - OpenCV_USE_MANGLED_PATHS : Mangled OpenCV 路径标志
#
# 已弃用变量:
# - OpenCV_VERSION_TWEAK : 始终为 "0"可以看到这里说明了执行findpackage之后给哪些变量赋予了哪些值,也写了用法
1
2
3
4
5
6# 从外部项目使用:
# 在你的 CMakeLists.txt 中,添加这些行:
#
# find_package(OpenCV REQUIRED)
# include_directories(${OpenCV_INCLUDE_DIRS}) # 对于 CMake >= 2.8.11 已不再需要
# target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})这段注释虽然目的是指导用户,但它本身混合了新旧两种风格的痕迹,我们需要仔细解读:
- 旧方式 (Variable-Based) 的体现:
明确的指令: 注释中明确给出了以下使用步骤:
1
2include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})这是典型的旧式 CMake 用法。它依赖于
find_package
执行后设置的两个变量:${OpenCV_INCLUDE_DIRS}
: 包含了需要添加到编译器搜索路径的头文件目录。你需要手动调用include_directories()
(或现代的target_include_directories()
) 来使用它。${OpenCV_LIBS}
: 包含了需要链接的库文件列表(可能是库文件的绝对路径,也可能在旧 CMake 中是链接器标志)。你需要手动将这个变量传递给target_link_libraries()
。
- 新方式 (Target-Based) 的线索和提示:
关键注释:
include_directories(${OpenCV_INCLUDE_DIRS}) # Not needed for CMake >= 2.8.11
- 这是最强烈的暗示。它告诉你,对于较新版本的 CMake (2.8.11 及以后,实际上现代 CMake 实践通常指 3.x 系列),手动添加
OpenCV_INCLUDE_DIRS
是不必要的。为什么?因为现代 CMake 的核心是目标 (Target)。当你链接到一个设计良好的导入目标 (Imported Target) 时,这个目标本身就封装了它所需的包含目录、链接库、编译定义等信息。CMake 会自动将这些信息传递给链接它的目标。
- 这是最强烈的暗示。它告诉你,对于较新版本的 CMake (2.8.11 及以后,实际上现代 CMake 实践通常指 3.x 系列),手动添加
变量
OpenCV_LIBS
的描述:OpenCV_LIBS : The list of all **imported targets** for OpenCV modules.
- 这一点非常重要!虽然旧方式的使用示例中是
target_link_libraries(... ${OpenCV_LIBS})
,但这里对OpenCV_LIBS
变量内容的描述明确指出了它包含的是 “imported targets”。这意味着${OpenCV_LIBS}
变量里存放的不再仅仅是库文件名或路径,而是 CMake 能理解的、代表了 OpenCV 各个模块的目标名称列表(例如OpenCV::core
,OpenCV::imgproc
等)。
- 这一点非常重要!虽然旧方式的使用示例中是
结合以上两点,可以推断出新方式的用法(尽管这段注释没有直接写出来)
1
2
3
4
5
6
7
8
9
10
11find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui) # 假设需要这三个
target_link_libraries(MY_TARGET_NAME PRIVATE OpenCV::core OpenCV::imgproc OpenCV::highgui)
这里find_package可以不指定具体哪个模块而是用
find_package(OpenCV REQUIRED)
区别不大
target_link_libraries推荐指定模块,不然就会把所有模块全都链接到项目上
说是这样说,但是我指定模块运行失败,不知道是因为名字不对还是啥
target_include_directories(my_app PUBLIC include)才成功的
- 旧方式 (Variable-Based) 的体现:
总结:还是用文档里说的吧
1 | # 从外部项目使用: |