cmake find_package 原理简介以及使用说明

下面简单介绍Cmake 如何使用find_package命令对外部库进行查找:

cmake本身不提供任何关于搜索库的便捷方法,也不会对库本身的环境变量进行设置。它仅仅是按照优先级顺序在指定的搜索路径进行查找Findxxx.cmake文件和xxxConfig.cmake文件(其中xxx代表库的名字,特别注意的是有大小写之分),这两个文件大体上是没有区别的,cmake能够找到这两个文件中的任何一个,我们都能成功使用该库,也就是我们可以用库的内置好了Cmake变量。包含了库的头文件和库文件的路径信息,虽然库的作者一般会提供这两个文件,但是也会遇到安装完毕后找不到的情况。当我们在cmake..命令之后,Cmake 会读取执行CMakeLists.txt中的代码,当执行find_package()这条命令后,Cmake 就会从某些路径中找这Findxxx.cmake文件或者xxxConfig.cmake文件,Cmake找到任意一个之后就会执行这个文件,然后这个文件执行后就会设置好一些Cmake变量。比如下面的变量(NAME表示库的名字 比如可以用Opencv 代表Opencv库):

_FOUND
_INCLUDE_DIRS or _INCLUDES
_LIBRARIES or _LIBRARIES or _LIBS
_DEFINITIONS

一般常用的就是xxx_FOUND 、xxx_INCLUDE_DIRS、xxx_LIBS,分别代表是否找到库的标志、库的头文件路径、库文件路径。find_package()有两种模式:Module模式和Config模式,分别对应上面的Findxxx.cmake 和xxxConfig.cmake两个文件。cmake默认优先Module模式,而Config模式是备选项。

Module模式(仅仅查找Findxxx.cmake文件):
Cmake会优先搜索CMAKE_MODULE_PATH指定的路径,如果在CMakeLists.txt中没有设置CMAKE_MODULE_PATH为存储Findxxx.cmake的路径,也就是说没有下面的指令:
set(CMAKE_MODULE_PATH "Findxxx.cmake文件所在的路径")
那么Cmake不会搜索CMAKE_MODULE_PATH指定的路径,此时Cmake会搜索第二优先级的路径,也就是/share/cmake-x.y/Mdodules (注意:x.y表示版本号。我的是3.10)。其中CMAKE_ROOT是你在安装Cmake的时候的系统路径,因为我并没有指定安装路径,所以是系统默认的路径,在我的系统中(ubuntu16.04)系统的默认路径是/usr/loacl,如果你在安装的过程中使用了
cmake -DCMAKE_INSTALL_PREFIX=自己dir路径 ,那么此时CMAKE_ROOT就代表那个你写入的路径 。刚刚说道第一优先级的路径搜索没有找到Findxxx.cmake文件,就会到第二优先级的路径下搜索。如果Cmake在两个路径下都没有找到Findxxx.cmake文件。那么Cmake就会进入Config模式。

Config模式(仅仅查找xxxConfig.cmake文件):
Cmake会优先搜索xxx_DIR 指定的路径。如果在CMakeLists.txt中没有设置这个cmake变量。也就是说没有下面的指令:
set(xxx_DIR "xxxConfig.cmkae文件所在的路径")
那么Cmake就不会搜索xxx_DIR指定的路径,此时Cmake 就会自动到第二优先级的路径下搜索,也就是/usr/local/lib/cmake/xxx/中的xxxConfig.cmake文件。
上面主要讲了Cmake的搜索模式。如果Cmake在两种模式提供的路径中没有找到对应的Findxxx.cmake和xxxConfig.cmake文件,此时系统就会提示最上面的那些错误信息。

 

现以but_velodyne package查找为例:

​​​​​​​find_package(but_velodyne REQUIRED)

现在查找到: /usr/local/lib/cmake/but_velodyne-0.1/but_velodyne-config.cmake

cat but_velodyne-config.cmake:
 

# Users can set the following variables before calling the module:
# ButVELODYNE_DIR - The preferred installation prefix for searching for ButVELODYNE. Set by the user.
#
# ButVELODYNE_ROOT_DIR - the root directory where the installation can be found
# ButVELODYNE_CXX_FLAGS - extra flags for compilation
# ButVELODYNE_LINK_FLAGS - extra flags for linking
# ButVELODYNE_INCLUDE_DIRS - include directories
# ButVELODYNE_LIBRARY_DIRS - link directories
# ButVELODYNE_LIBRARIES - libraries to link plugins with
# ButVELODYNE_Boost_VERSION - the boost version but_velodyne was compiled with

get_filename_component(_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_PREFIX "${_PREFIX}" PATH)
get_filename_component(_PREFIX "${_PREFIX}" PATH)
get_filename_component(ButVELODYNE_ROOT_DIR "${_PREFIX}" PATH)

set( ButVELODYNE_CXX_FLAGS "-DBUT_VELODYNE_DLL  " )
set( ButVELODYNE_LINK_FLAGS "" )
set( ButVELODYNE_INCLUDE_DIRS "${ButVELODYNE_ROOT_DIR}/include/but_velodyne-0.1")
set( ButVELODYNE_LIBRARY_DIRS "${ButVELODYNE_ROOT_DIR}/lib")
set( ButVELODYNE_LIBRARIES but_velodyne${ButVELODYNE_LIBRARY_SUFFIX})

set( ButVELODYNE_Boost_VERSION "1.58")

mark_as_advanced(
  ButVELODYNE_ROOT_DIR
  ButVELODYNE_CXXFLAGS
  ButVELODYNE_CXX_FLAGS
  ButVELODYNE_LINK_FLAGS
  ButVELODYNE_INCLUDE_DIRS
  ButVELODYNE_LIBRARIES
  ButVELODYNE_Boost_VERSION
)

如何查看find_package()的结果:

find_package(but_velodyne REQUIRED)
if (but_velodyne_FOUND)
  MESSAGE (STATUS "@@@@@@dern: ${ButVELODYNE_DEFINITIONS}")
  MESSAGE (STATUS "@@@@@@dern: ${ButVELODYNE_INCLUDE_DIRS}")
  MESSAGE (STATUS "@@@@@@dern: ${ButVELODYNE_LIBRARY_DIRS}")
else()
  MESSAGE (STATUS "@@@@@@dern: but_velodyne not found")
endif(but_velodyne_FOUND)

OpenCV


安装在opt的文件中会有share文件夹,这里面就有咱们需要的OpenCV文件夹,所以如果要自己有选择的控制版本,则在find_package这句话前面去设置opencv的OpenCV文件夹在哪里,添加set(OpenCV_DIR /opt/opencv-2.4.11/share/OpenCV)这句话。这个可以根据你install的位置去变化。

你可能感兴趣的:(cmake)