背景

如果我们在cmake某个程序的时候,经常会提示找不到某个所依赖的库,那么这是时候我们就需要检查我们引入依赖库的路径对不对了, Cmake中一个自动寻找函数find_package()可以帮我们实现这个功能。

使用方法

//以slam十四讲中的joinMap程序Cmake文件为例:
cmake_minimum_required( VERSION 2.8 )
project( joinMap )set( CMAKE_BUILD_TYPE Release )
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )# opencv
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )# eigen
include_directories( "/usr/include/eigen3/" )# pcl
find_package( PCL REQUIRED COMPONENT common io )
include_directories( ${PCL_INCLUDE_DIRS} )
add_definitions( ${PCL_DEFINITIONS} )list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
add_executable( joinMap joinMap.cpp )
target_link_libraries( joinMap ${OpenCV_LIBS} ${PCL_LIBRARIES} )

概括来说,以opencv为例:find_package()函数,如果找到了相关的头文件和库文件,则会相应保存在OpenCV_INCLUDE_DIRSOpenCV_LIBRARIES (OpenCV_LIBS) 中。
我们可以输出一下看看上面两个cmake变量是什么内容,在上述文件后面加如下代码:

message("!!!!!!!!OpenCV_INCLUDE_DIRS:" ${OpenCV_INCLUDE_DIRS})
message("!!!!!!!!OpenCV_LIBRARIES:" ${OpenCV_LIBRARIES} )

可以看出我们实际上拿到了所有这个依赖库的头文件路径和所有库文件。

关键字解释

下面我们说一说find_package()的语法:

  • versionEXACT: 都是可选的,version指定的是版本,如果指定就必须检查找到的包的版本是否和version兼容。如果指定EXACT则表示必须完全匹配的版本而不是兼容版本就可以。
    QUIET 可选字段,表示如果查找失败,不会在屏幕进行输出(但是如果指定了REQUIRED字段,则QUIET无效,仍然会输出查找失败提示语)。
  • MODULE可选字段。前面提到说“如果Module模式查找失败则回退到Config模式进行查找”,但是假如设定了MODULE选项,那么就只在Module模式查找,如果Module模式下查找失败并不回落到Config模式查找。
  • CONFIG可选字段。直接在Config模式中查找。下文会介绍什么是Moudule模式什么是Config模式。
  • REQUIRED可选字段。表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定REQUIRED则cmake会继续执行。
  • COMPONENTS:可选字段,表示查找的包中必须要找到的组件(components),如果有任何一个找不到就算失败,类似于REQUIRED,导致cmake停止执行。上面的例子中find_package( PCL REQUIRED COMPONENT common io )我们就利用了该关键字寻找了commonio包。
  • OPTIONAL_COMPONENTS:可选的模块,找不到也不会让cmake停止执行。

find_package原理

首先,cmake本身不提供任何搜索库的便捷方法,所有搜索库并给变量赋值的操作必须由cmake代码完成,比如FindXXX.cmake和XXXConfig.cmake。只不过,库的作者通常会提供这两个文件,以方便使用者调用。
find_package采用两种模式搜索库:

  • Module模式:搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件,执行该文件从而找到XXX库。其中,具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由FindXXX.cmake模块完成(先搜索当前项目里面的Module文件夹里面提供的FindXXX.cmake,然后再搜索系统路径/usr/local/share/cmake-x.y/Modules/FindXXX.cmake)
  • Config模式:搜索XXX_DIR指定路径下的XXXConfig.cmake文件,执行该文件从而找到XXX库。其中具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成。
  • 对于可能没有***.cmake和***Config.cmake的库文件,可以直接找到其头文件和库文件所在文件夹,直接进行路径赋值:
SET(LAPACK_DIR /usr/local/lib/)
SET(LAPACK_INCLUDE_DIRS /usr/local/include)
SET(LAPACK_LIBRARIES /usr/local/lib)

相关命令:pkg-config

pkg-config可用与列举出某个库的相关信息,比如此库的路径、相关头文件路径等,这在程序编译时将非常有用。例如,现在要编译一个依赖librtmp.so库的程序。去哪找librtmp.so相关的头文件呢?librtmp.so库又在哪呢?这是一个大问题,但有了pkg-config后这些都不是问题。先使用以下命令看看:

jeason@Mi-Jeason:~$ pkg-config --cflags librtmp
-I/usr/local/includejeason@Mi-Jeason:~$ pkg-config --libs librtmp
-L/usr/local/lib -lrtmp -lz -lssl -lcrypto

看到没,pkg-config能找出头文件的路径,也能找出库存放在哪,而且还能知道依赖的其它库。

有了pkg-config后,当我编译程序要使用librtmp.so库时,就可以这么写:

jeason@Mi-Jeason:~$ gcc sample.c -o sample `pkg-config --cflags --libs librtmp`

哈哈哈哈,有了pkg-config,妈妈再也不用担心我程序编译时找不到库了。

那么,问题也来了,pkg-config又是如何知道库存放路径及头文件路径等信息的呢?

答案就在.pc文件中。库文件编译完成后,会在{installed_home/lib/}下生成产生一个名为pkgconfig的目录,内含该链接库的.pc文件,此文件记录了改库的相关信息。为了能被查找读取到,需要将该.pc文件安装到 /usr/lib/pkgconfig/ 目录中,或在PKG_CONFIG_PATH环境变量中加入该.pc文件的安装路径。这样做的目的是为了使依赖此库的其它程序能够借助pkg-config自动链接该库,避免编译期错误。

  • pkg-config常用参数
    –-list-all 列出所有已安装的共享库
    -–cflags 列出指定共享库的预处理和编译flag。
    -–libs 列出指定共享库的链接flag。

环境变量 PKG_CONFIG_PATH 用于指定pkg-config查找.pc文件的路径。此外,pkg-config还会查找/usr/lib/pkgconfig/下的.pc文件。

像这样设置环境变量:

export PKG_CONFIG_PATH=/usr/local/lib

Cmake语句find_package()函数相关推荐

  1. oracle中执行动态sql语句吗,oracle中有没有可动态执行sql语句的函数

    oracle中有没有可动态执行sql语句的函数 关注:233  答案:2  手机版 解决时间 2021-03-05 15:53 提问者祗剩寂寞 2021-03-04 22:38 oracle中有没有可 ...

  2. python保留字分支结构_Python基础语法----缩进、注释、命名与保留字、数据类型、分支语句、函数...

    缩进 -严格明确:缩进是语法的一部分,缩进不正确程序运行错误 -所属关系:表达代码间包含和层次关系的唯一手段 -长度一致:程序内一致即可,一般用4个空格或1个TAB 注释 -用于提高代码可读性的辅助性 ...

  3. legend---十二、js中的js语句和函数和ready函数的关系是什么

    legend---十二.js中的js语句和函数和ready函数的关系是什么 一.总结 一句话总结: 函数和全局变量不必放到ready函数中 语句(调用函数和全局变量)的必须放到ready函数中 1.在 ...

  4. Oracle 10g数据库基础之基本查询语句-中-函数

    Oracle 10g数据库基础之基本查询语句-中-函数 --资料参考:张烈 张建中<数据库管理员培训讲义> 函数: 使用函数的目的是为了操作数据 将输入的变量处理,返回一个结果. 变量可以 ...

  5. GJM :Sql 各种语句 以及函数 [转载]

    版权声明:本文原创发表于 [请点击连接前往] ,未经作者同意必须保留此段声明!如有侵权请联系我删帖处理! 1.更改数据库的名称 2.表中有数据的情况下再添加列.删除列 3.在SQLServer 中各种 ...

  6. 标量函数,多语句表值函数,内嵌表值函数

    标量函数返回一个标量(单值)结果,可返回Timestamp,text,Ntext,Image,Table,Cursor 多语句表值函数,返回一条或多条Transact-sql语句建立的表,可在sele ...

  7. JavaScript中语句与函数的执行辨析

    文章出自个人博客https://knightyun.github.io/2018/05/23/js-anonymous-function,转载请申明. Javascript代码中,语句和函数以及匿名函 ...

  8. python没有return语句的函数将返回_为什么Python没有return返回值

    为什么Python没有return返回值 发布时间:2020-08-24 17:12:18 来源:亿速云 阅读:118 今天就跟大家聊聊有关为什么Python没有return返回值,可能很多人都不太了 ...

  9. sql多语句表值函数_构造一个特殊的多语句表函数来检查SQL Server的运行状况

    sql多语句表值函数 问题 ( The Problem ) Checking the many SQL Servers health conditions is one of the DBA basi ...

最新文章

  1. ML之多分类预测:以某个数据集为例从0到1深入理解科学预测之多分类问题的思路框架
  2. 10亿个数中求最大的10个数字
  3. 【linux】gcc命令
  4. 单列变双列css_css – 右对齐双列布局丢失水平滚动条
  5. linux运维要掌握哪些,学习Linux运维需要掌握哪些技能?Linux运维
  6. c语言程序32位,turbo c语言下载
  7. 关于计算机音乐编创的论文,有关浅谈少儿舞蹈音乐的编创论文
  8. 计算机毕业论文任务书模板,计算机毕业论文设计任务书范文计算机系毕业论文任务书上的方法写.doc...
  9. c++调用opencv库实现视频关键帧提取--灰度帧差法
  10. 新概念下兴起域名商机 云域名是神马浮云
  11. 十年磨一剑,奋进新征程!麒麟信安在上交所科创板成功上市
  12. “去哪儿”创始人兼总裁庄辰超专访实录
  13. 2、如何搭建百度离线地图服务
  14. 网易收购《底特律》《暴雨》开发商继续走向全球化
  15. win10用易语言需要C环境,win10系统易语言打开支持库配置就崩溃的具体教程
  16. 小程序拼团营销怎么做
  17. LMT and ASSM
  18. lin通讯从节点同步间隔场_LIN模块介绍
  19. 最新BlOS详解,及UEFi引导重装系统方法
  20. JavaScript捕获同时多个按键-非组合键

热门文章

  1. Appium+Eclipse+夜神模拟器 实现QQ打电话功能
  2. Carla-Scenario Runner 安装步骤与踩坑
  3. 轮播图的实现,点击按钮切换轮播图等功能
  4. 预失真算法matlab实现,2013-全国研究生数学建模B题-seleh模型预失真MATLAB仿真代码...
  5. 笔记本采取拨号上网有线连接校园网,开启热点的方法
  6. cydia java_使用Cydia Substrate 从Native Hook Android Java世界
  7. html视频怎么编辑倍速,浏览器flash/html5视频播放如何倍速(Enounce MySpeed)
  8. U盘制作Ubuntu系统启动盘的官方推荐软件
  9. php查询google pr值接口api介绍,最新 google pr值查询 接口 php版 示例
  10. 论文学习-NOVA:A log-structured File System for Hybrid Volatile/Non-volatile Main