find_packakge

1、find_packakge命令基本介绍
在我们实际开发过程中,经常不可避免会使用到第三方开源库,这些开源库可能是通过apt-get install命令自动安装到系统目录中,也可能是由我们自己下载库的源码然后通过编译安装到指令目录下的。

不管哪种方式安装的库文件,如果我们需要自己的项目中使用这些库,首先面临的第一个问题就是如何找到这些库。所谓“找到”这些库,其实是根据我们的需要找到指定版本的库头文件包含路径、链接库路径等,从而能够满足我们开发项目的编译链接需要。

在没有CMake的时代,这种库查找链接的工作都需要借助MakeFile中的各种命令来完成,非常的繁琐,而且不方便移植,到了CMake时代,CMake给我们提供了find_package()命令用来查找依赖包,理想情况下,一句find_package()命令就能把一整个依赖包的头文件包含路径、库路径、库名字、版本号等情况都获取到,后续只管用就好了。但实际使用过程可能会出现这样那样的问题,因此需要我们对find_package这个强大的命令有个大概的理解。

本篇文章先从一个find_package的例子出发,然后逐渐引出对find_package命令搜包过程的介绍,然后深入理解find_package的具体操作原理,帮助大家理解和消化。

2、一个使用find_package命令的例子
为了能够帮助大家理解find_package命令的用法,此处首先用OpenCV库举例子,示范如何通过find_pakcage命令找到OpenCV库并配置,从而能够在我们自己的项目中调用OpenCV库,实现特定的功能。

下面的代码主要实现了利用OpenCV载入一张图片并显示的简单功能:

注: 此处假设你已经安装了OpenCV库, 并对OpenCV有稍许的了解即可。

具体代码项目下载地址:Github:find_package_learning

opencv_test.cpp:

#include <cstdio>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;

int main() {
  Mat image;
  image = imread("../opencv_test.jpg");

  if (!image.data) {
    printf("No image data\n");
    return -1;
  }

  namedWindow("Display Image", CV_WINDOW_AUTOSIZE);
  imshow("Display Image", image);
  waitKey(0);
  return 0;
}


CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
project(find_package_learning)
find_package(OpenCV 3 REQUIRED)

message(STATUS "OpenCV_DIR = ${OpenCV_DIR}")
message(STATUS "OpenCV_INCLUDE_DIRS = ${OpenCV_INCLUDE_DIRS}")
message(STATUS "OpenCV_LIBS = ${OpenCV_LIBS}")

include_directories(${OPENCV_INCLUDE_DIRS})  
add_executable(opencv_test opencv_test.cpp)  
target_link_libraries(opencv_test ${OpenCV_LIBS})

2.1 编译运行
在源码路径打开终端,执行:

mkdir build
cd build
cmake ..
make -j4

在源码路径下放置一张图片并命名为opencv_test.jpg,运行:

./opencv_test

就可以看到显示的图片了。

2.2 编译输出与分析
我的Ubuntu18.04系统在usr/local路径下安装了OpencCV3.4.4,在执行上述cmake ..命令时输出为:

-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenCV: /usr/local (found suitable version "3.4.4", minimum required is "3") 
-- OpenCV_DIR = /usr/local/share/OpenCV
-- OpenCV_INCLUDE_DIRS = /usr/local/include;/usr/local/include/opencv
-- OpenCV_LIBS = opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_shape;opencv_stitching;opencv_superres;opencv_video;opencv_videoio;opencv_videostab;opencv_viz;opencv_aruco;opencv_bgsegm;opencv_bioinspired;opencv_ccalib;opencv_cvv;opencv_datasets;opencv_dnn_objdetect;opencv_dpm;opencv_face;opencv_freetype;opencv_fuzzy;opencv_hdf;opencv_hfs;opencv_img_hash;opencv_line_descriptor;opencv_optflow;opencv_phase_unwrapping;opencv_plot;opencv_reg;opencv_rgbd;opencv_saliency;opencv_stereo;opencv_structured_light;opencv_surface_matching;opencv_text;opencv_tracking;opencv_xfeatures2d;opencv_ximgproc;opencv_xobjdetect;opencv_xphoto
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zhanghm/Programming/programming-learning-examples/cmake_learning/learn_cmake_easily/find_package_learning/build

重点看下其中OpenCV_DIR、OpenCV_INCLUDE_DIRS和OpenCV_LIBS打印的结果,这是我在CMakeLists.txt中用message命令输出这三个变量的值的结果。

可以看到在执行find_package(OpenCV 3 REQUIRED)命令后,CMake找到了我们安装的位于/usr/local下的OpenCV库,并设置了CMake变量OpenCV_DIR为OpenCV库的配置文件所在路径,正是通过载入这个路径下的OpenCVConfig.cmake配置文件才能配置好OpenCV库,然后在OpenCVConfig.cmake配置文件中定义了变量OpenCV_INCLUDE_DIRS为OpenCV库头文件包含路径,这样我们才能才在代码中使用#include <opencv2/opencv.hpp>而不会出现编译错误,同时定义了变量OpenCV_LIBS为OpenCV链接库路径,这样我们才能正确链接到OpenCV中的库文件,而不会出现类似未定义的引用这样的链接错误。

所以整个过程总结为:

通过这个例子就可以看出find_package本质上就是一个搜包的命令,通过一些特定的规则找到<package_name>Config.cmake包配置文件,通过执行该配置文件,从而定义了一系列的变量,通过这些变量就可以准确定位到OpenCV库的头文件和库文件,完成编译。

那么关键的问题来了,find_package命令是怎么能够定位并载入指定库的配置文件的呢?这就需要梳理一下find_package命令的搜包过程。

3、find_package命令搜包过程
首先我们需要明确一点,CMake本身不提供任何搜索库的便捷方法,所有搜索库并给变量赋值的操作必须由CMake代码完成,也就是上述中的XXXConfig.cmake以及下面将要提到的FindXXX.cmake配置文件。只不过,库的作者通常会提供这两个文件,以方便使用者调用。

4、总结
通过前面的描述,我相信大家已经能够基本掌握find_package命令的各种用法了,也能够在出现各种问题时自己进行问题定位。但还有一个我们需要注意的点是我们能够在自己的项目中使用find_package命令便捷进行依赖包配置的前提是这个包的开发者也是用CMake配置好了这个包,并提供了<PackageName>Config.cmake或Find<PackageName>.cmake的配置文件。

那如果这个依赖包是我们自己开发的,应该如何配置这个包生成这些配置文件,从而能够被其他项目利用find_package命令来配置我们自定义的包呢?

这就需要学习如何使用CMake封装自己的软件包,我打算在另一篇博文中详细讲解,敬请期待。

【参考】
1、find_package官网介绍
2、深入理解CMake:find_package()的使用
3、cmake find_package路径详解
4、CMake find_package 使用
5、find_package与CMake如何查找链接库详解
6、How To Find Libraries
————————————————
版权声明:本文为CSDN博主「zhanghm1995」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhanghm1995/article/details/105466372

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值