前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入浅出CMake(三):find_package 添加依赖库

深入浅出CMake(三):find_package 添加依赖库

作者头像
Frank909
发布2019-06-16 10:24:51
11K0
发布2019-06-16 10:24:51
举报
文章被收录于专栏:Frank909Frank909

深入浅出CMake(一):基础篇

深入浅出CMake(二):基础语法及实现九九乘法表

有了前面两篇博文的基础,相信我们已经能够用 CMake 去编译比较简单的工程了,但是我们还差一步就可以应付大多数开发编译场景。

目前我们还不知道怎么样处理在工程中引入第三方库。

以 Unix 环境下的 c++ 代码工程为例。

加入工程要引入一个 libtest.so 动态库,源码是 hello.cpp。

如果用 g++ 编译的话,大概是这样

代码语言:javascript
复制
g++ hello.cpp -ltest -o hello -I include

引入库文件时,我们必须知道头文件的路径还有库文件的路径

如果我们工程引入的不止一个库文件,而是 20 个的话,用最原始的 g++ 命令行方式就比较痛苦,也容易出错,所以我们大多会编写 Makefile 来利用 make 编译。

但是 Makefile 的编写有时候也是一件痛苦的事情,用 CMake 可以比较轻松实现同样的目的,所以这篇博文我们讲解如何用 cmake 处理库文件的引入情况。

package

在 cmake 的编译体系中,package 用来指代一个依赖库,包括一些头文件、动态库、静态库等等,在 CMakeFileLists.txt 中通过 find_package()命令可以很轻易实现。

比如很多同学可能会用 OpenCV 进行图像开发,它是个非常有名的开源库,它有 10 来个库文件、几十个头文件,因此如何正确引用它就是一件值得小心翼翼的事情,但好在 cmake 可以轻松搞定这件事情。

前提条件,你的 PC 上已经完全安装好了 OpenCV

DisplayImage.cpp

代码语言:javascript
复制
#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
int main(int argc, char** argv )
{
    if ( argc != 2 )
    {
        printf("usage: DisplayImage.out <Image_Path>\n");
        return -1;
    }
    Mat image;
    image = imread( argv[1], 1 );
    if ( !image.data )
    {
        printf("No image data \n");
        return -1;
    }
    namedWindow("Display Image", WINDOW_AUTOSIZE );
    imshow("Display Image", image);
    waitKey(0);
    return 0;
}

下面是 CMakeFileLists.txt

代码语言:javascript
复制
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage DisplayImage.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )

然后就可以编译了。

代码语言:javascript
复制
mkdir build
cd build
cmake ..
make 
./DisplayImage  ../lena.jpg

程序就可以运行。

这个例子是 OpenCV 的官方示例。

下面需要说明的是,find_package(OpenCV REQUIRED)执行成功后,它的头文件路径,库文件路径都会被赋值。

代码语言:javascript
复制
OpenCV_INCLUDE_DIRS 是头文件路径

OpenCV_LIBS 是库文件地址

有了头文件和库文件,自然而然可以正常引用 OpenCV 了。

package 的通用套路

实际上,通过 find_package() 可以顺利查找任何符合 cmake package 标准的外部工程。

find_pacage()方法签名如下:

代码语言:javascript
复制
find_package(<package> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])

QUITE 参数指代,当查找出错时,屏蔽 message() 的输出。

REQUIRED 参数指代,当找不到 package 时,终止过程。

现在用 XXX 代表要查找的 package 名字

find_pacakge(XXX REQUIRED)会设置一系列变量。

代码语言:javascript
复制
XXX_FOUND 代表库是否查找成功
XXX_INCLUDE_DIRS 代表头文件的路径
XXX_LIBRARIES 代表库文件的路径

比如,cmake 可以很轻松引入 bzip2

代码语言:javascript
复制
find_package (BZip2)
if (BZIP2_FOUND)
    include_directories(${BZIP_INCLUDE_DIRS})
    target_link_libraries (test ${BZIP2_LIBRARIES})
endif (BZIP2_FOUND)

BZIP2 定义了一系列变量,含义如下

代码语言:javascript
复制
BZIP2_FOUND - system has BZip2
BZIP2_INCLUDE_DIR - the BZip2 include directory
BZIP2_LIBRARIES - Link these to use BZip2
BZIP2_NEED_PREFIX - this is set if the functions are prefixed with BZ2_
BZIP2_VERSION_STRING 

到这里,我们已经掌握了 find_package()到这里,我们才真正可以应付大多数情况下cmake 编译了。

当然,一个库可能由好多个组件构成,cmake 可以单独引入这些组件

代码语言:javascript
复制
find_package(Qt5 5.1.0 COMPONENTS Widgets Xml Sql)

引入了 Qt5 中的 Widgets Xml Sql 组件。

可能有同学好奇,cmake 怎么就人工智能一般能够自动找到依赖库呢?

这个,我下一篇详细讲解一下。

参考:

https://cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年06月13日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • package
  • package 的通用套路
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档