- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
在使用cmake引用第三方库(比如OpenCV)时,我们总是使用find_package()这个指令来实现对包的查找(比如find_package(OpenCV))。调用完后就可以使用一些似乎凭空出现的变量如${OpenCV_INCLUDE_DIRS}以及${OpenCV_LIBS},分别指示了OpenCV库的头文件路径以及各个库文件位置.
find_package(OpenCV)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
# 这样就可以使用到OpenCV了
cmake官方文档对find_package()的解释是这样的:
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
[GLOBAL]
[NO_POLICY_SCOPE]
[BYPASS_PROVIDER])
其中[]中的内容表示为可选项。下面我们来解释find_package()是如何工作的.
实际上,find_package(<PackageName>)运行时,会去指定路径查找一些名字为 。
Find<PackageName>.cmake 。
<PackageName>Config.cmake 。
<lowercasePackageName>-config.cmake 。
<lowercasePackageName>-config-version.cmake # 指定版本信息 。
<PackageName>ConfigVersion.cmake # 指定版本信息 。
的文件,注意这里的命名格式是非常的固定的,基本都是FindXXX.cmake或者XXXConfig.cmake。这些后缀为.cmake的文件本质上也是使用cmake语言编写的脚本文件,它们会定义一些变量,比如<PackageName>_INCLUDE_DIRS和<PackageName>_LIBS等。当find_package()找到这些文件时,会执行这些文件并将其中定义的变量引入到当前的cmake环境中.
对于搜索这些后缀为.cmake的文件,find_package()采用两种策略来实现 。
这里引用官方文档的解释:
在这种模式下,CMake 搜索名为Find<PackageName>.cmake的文件,首先在 CMAKE_MODULE_PATH 中列出的位置中查找,然后在 CMake 提供的 Find Modules 中查找安装。如果找到该文件,CMake 将读取并处理该文件。它负责查找包、检查版本并生成任何需要的消息。一些 Find 模块对版本控制提供有限支持或不支持;检查查找模块的文档.
一般来说,FindXXX.cmake并非为包所提供,大多数包提供的是更为严谨的XXXConfig.cmake,这将在后面说到。也就是说,FindXXX.cmake是一个较为简单的查找模块,大多为用户或者cmake本身自行编写或者提供。查找时,cmake会优先查找cmake环境变量的CMAKE_MODULE_PATH中的路径(这个变量默认为空),然后再查找cmake自带的Find Modules中的路径,这部分可以使用cmake --help-module-list查看cmake自带的模块列表,可以看到很多FindXXX.cmake文件.
或者对于一些轻量级的包,本身并不提供XXXConfig.cmake或者FindXXX.cmake,而是使用其他包管理器(比如package-config,使用后缀为.pc的文件来管理),若想使用find_package()引用这些包,就需要自行编写FindXXX.cmake文件。(当然也可以直接使用cmake中的pkg_check_modules()来引用这些包)。下面给出一个FindXXX.cmake的例子,引用的是ffmpeg这个包.
#FindFFMEPG.cmake
set(FFMPEG_SOURCE /home/ruby/ffmpeg_loc) #指定ffmpeg位置
set(FFMPEG_INCLUDE_DIRS ${FFMPEG_SOURCE}/include)
set(FFMPEG_LIBDIRS_DIRS ${FFMPEG_SOURCE}/lib)
find_library(FFMPEG_AVCODEC_LIBRARY avcodec ${FFMPEG_LIBDIRS_DIR})
find_library(FFMPEG_AVFORMAT_LIBRARY avformat ${FFMPEG_LIBDIRS_DIR})
find_library(FFMPEG_AVUTIL_LIBRARY avutil ${FFMPEG_LIBDIRS_DIR})
find_library(FFMPEG_SWSCALE_LIBRARY swscale ${FFMPEG_LIBDIRS_DIR})
find_library(FFMPEG_SWRESAMPLE_LIBRARY swresample ${FFMPEG_LIBDIRS_DIR})
set(FFMPEG_LIBS ${FFMPEG_AVCODEC_LIBRARY} ${FFMPEG_AVFORMAT_LIBRARY} ${FFMPEG_AVUTIL_LIBRARY} ${FFMPEG_SWSCALE_LIBRARY} ${FFMPEG_SWRESAMPLE_LIBRARY})
可以看到,我们做到工作无非是设置一些变量,这些变量指向了ffmpeg的头文件路径以及库文件路径,然后使用find_library()来查找对应的库文件.
在使用时,我们可以使用set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} /path/to/FindFFMPEG.cmake)来指定FindFFMPEG.cmake的位置,然后使用find_package(FFMPEG)来引用ffmpeg这个包,然后就可以使用${FFMPEG_INCLUDE_DIRS}和${FFMPEG_LIBS}了。若这个脚本就在当前目录下,可以直接使用set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR})来指定.
这里引用官方文档的解释:
在这种模式下,CMake 搜索名为“<lowercasePackageName>-config.cmake”或“<PackageName>Config.cmake”的文件。如果指定了版本详细信息,它还将查找``<lowercasePackageName>-config-version.cmake`` 或``<PackageName>ConfigVersion.cmake``(请参阅:ref:version selection 以了解如何将它们分开使用版本文件)。
在配置模式下,可以为该命令提供一个名称列表,以作为包名称进行搜索。 CMake 搜索配置和版本文件的位置比模块模式复杂得多。
配置和版本文件通常作为包的一部分安装,因此它们往往比查找模块更可靠。它们通常包含包内容的直接知识,因此不需要在配置或版本文件本身中进行搜索或试探。
对于大多数的第三方包,都会提供XXXConfig.cmake文件,这个文件会定义一些变量,比如XXX_INCLUDE_DIRS和XXX_LIBS/XXX_LIBRARIS等。当模块模式搜索不到时,自动切换到配置模式进行搜索。配置模式的搜索非常繁琐,会尽一切可能去搜索。有一些我也看不懂,这里挑几个比较易懂且常用的来说.
XXX_DIR
指定的路径下搜索XXXConfig.cmake
文件,XXX_DIR
为变量或者环境变量,指定到配置文件所在路径CMAKE_PREFIX_PATH
指定的路径下搜索XXXConfig.cmake
文件PATH
下搜索XXXConfig.cmake
文件其中,第2和第3种方式提供了一种以前缀路径的方式来指定包的位置,当本级路径搜索不到时,cmake会将本级路径作为前缀去搜索该路径下其他文件中是否有配置文件。匹配规则如下:
其中的<prefix>或者<前缀>即为上述指定的根路径,以根路径为前缀,一直去搜索,直到找到配置文件为止。例如find_package(OpenCV),其中PATH指定有一个路径为/usr/lib/x86_64-linux-gnu/,查找时便会找 。
- /usr/lib/x86_64-linux-gnu/
- /usr/lib/x86_64-linux-gnu/cmake/
- /usr/lib/x86_64-linux-gnu/OpenCV(opencv)/
- /usr/lib/x86_64-linux-gnu/cmake/OpenCV(opencv)/ ....
等能匹配上的路径,注意,这里的<name>*中的name对应于find_package()中的参数,即find_package(OpenCV)中的OpenCV。但是在作为前缀路径时,name参数不区分大小写,且允许有后缀,如opencv4.5。规则中的|代表选其一,<arch>为系统架构,比如x86,64位架构下就会搜索/lib/x86_64-linux-gnu而arm64架构下则会搜索/lib/aarch64-linux-gnu等.
对于自己写的FindXXX.cmake,在使用时用 。
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR})
# or不在本级目录
set(MY_FINDXXX "path/to/FindXXX.cmake")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${MY_FINDXXX})
对于三方库,可以直接用find_package() 。
find_package(OpenCV)
倘若找不到,可以用locate命令查找一下,然后手动指定路径 。
locate OpenCVConfig.cmake
然后将配置文件所在路径赋值给XXX_DIR 。
set(OpenCV_DIR /path/to/opencv)
对于有多个配置文件的项目(如Qt),使用CMAKE_PREFIX_PATH来指定路径 。
set(CMAKE_PREFIX_PATH /path/to/qt)
给出一个例子 进入到可以匹配到路径的路径,我这里是/home/ruby/Qt5.14.0/5.14.0/gcc_64,里面的格式为 。
也就是最好找到带有lib字眼或者cmake字眼的那一级目录即可,然后将这个路径赋值给CMAKE_PREFIX_PATH 。
set(CMAKE_PREFIX_PATH /home/ruby/Qt5.14.0/5.14.0/gcc_64)
即可。使用这个方法可以简便的使用不同版本的Qt,比如我这里有5.14.0和5.15.0两个版本,只需要将CMAKE_PREFIX_PATH指定到对应的路径即可.
set(CMAKE_PREFIX_PATH /home/ruby/Qt5.15.0/5.15.0/gcc_64)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} /home/ruby/Qt5.14.0/5.14.0/gcc_64)
# 注意,这两个路径正常直接find是find不到的,只能加入CMAKE_PREFIX_PATH中
#find_package(Qt5 <version> COMPONENTS Core Widgets REQUIRED), version填版本号,如
find_package(Qt5 5.15.0 COMPONENTS Core Widgets REQUIRED)
# or
find_package(Qt5 5.14.0 COMPONENTS Core Widgets REQUIRED)
可以加入EXACT来精确匹配,当匹配不到时会报错
find_package(Qt5 5.14.0 EXACT COMPONENTS Core Widgets REQUIRED)
最后此篇关于find_package()使用指南的文章就讲到这里了,如果你想了解更多关于find_package()使用指南的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
关于find_package() 在使用cmake引用第三方库(比如OpenCV)时,我们总是使用find_package()这个指令来实现对包的查找(比如find_package(OpenCV))
我们有一个 CMakeLists.txt 链接(例如)opencv 到我们的各种二进制文件。这是按如下方式完成的: find_package(OpenCV REQUIRED core imgproc
我有一个名为 messages 的外部项目.我正在使用 ExternalProject_Add 来获取和构建项目。 如果我使用 find_package(messages REQUIRED)在顶级 C
我有一个带有配置文件支持组件的 cmake 包,例如 find_package(myPack REQUIRED COMPONENTS foo bar) 在 myPackConfig.cmake 中我通
是否有一个变量存储与包版本类似的找到的包的路径? find_package(name) message("name version: ${name_VERSION}") #something like
是否有一个变量存储与包版本类似的找到的包的路径? find_package(name) message("name version: ${name_VERSION}") #something like
我可以在哪里或如何获得 find_package 支持的软件包的完整列表? 我知道这些是模块,所以它们必须驻留在某个地方? 我正在为 C++/ROS 构建在线自动打包系统,我需要一份详细的可用内容列表
我需要使用 mangrove(基于 mongo-c-driver 和 mongo-cxx-driver 的 mongo ODM 库)并将其作为 CMake ExternalProject_Add 命令
这可能是一个新手错误,但我处于学习 python 的早期阶段。 运行 Win7 64 位 Python 是 2.7.2 64 位,python 在 CMD 提示符下运行良好。 I downloaded
我正在尝试将 OpenCv 包含在一个项目中,实际上我的计算机上有 2 倍于该库的相同版本。一种在/good/path 中使用额外的所需函数(Cuda 和 OpenGl 支持)编译,另一种在/old/
我目前正在尝试编写我的第一个重要的 CMake 项目,但我无法检查 FIND_PACKAGE() 的任何输出,因为它似乎没有将值赋予我期望的全局变量!例如,下面的代码: MESSAGE("CMake
CMake manual of Qt 5使用 find_package并说: Imported targets are created for each Qt module. Imported tar
在我的 CMake 项目中,我提供了用户可编辑的 Boost 的默认路径。 set(PATH_BOOST_DEFAULT "/softs/boost/${BOOST_VER}/${ARCH}/gcc/
在我的CMake包中,有一个对find_package的调用。这成功了,太好了!但是,事实证明这是该软件包的错误版本。我现在要删除该程序包。但是,我不知道它在系统上的什么位置,也不知道CMake必须在
当我尝试安装我的包时,它没有安装任何东西。当我手动执行 find_packages 时,它返回一个空列表。 这是我的 setup.py 文件: from setuptools import setup
在文件 CMakelists.txt 中我看到 find_packages 和 catkin_package: find_package(catkin REQUIRED COMPONENTS rosc
当我尝试安装我的包时,它没有安装任何东西。当我手动执行 find_packages 时,它返回一个空列表。 这是我的 setup.py 文件: from setuptools import setup
我正在创建一个 python 包(第一次)并且能够打包内容,但我在打包子目录中的一个数据文件时遇到问题。我的目录结构如下所示 ├── Jenkinsfile ├── MANIFEST.in ├── R
因此,我想创建一个 C 库,该库可以通过 cmake 中的 find_package 函数轻松地在其他项目中使用。具体来说,我想要一个名为 foo 的项目,可以像这样访问: find_package
确保 cmake 仅从特定根目录中查找库和 header 的最佳方法是什么。 假设: 我们只想查看特定目录(例如:/mysdkroot/) 我们要忽略所有不在特定目录中的文件(例如,不应使用/usr/
我是一名优秀的程序员,十分优秀!