find_package的作用
发布于 2018-03-05   4522人围观  0条评论
发表于 2018-03-05   4522人围观  0条评论

find_package的作用

在CMakeLists.txt如果需要使用第三方库,那么需要知道三个东西

去哪里找头文件(.h等)
对应于GCC的参数 -I
去哪里找库文件(.so/.lib/.ddl等)对应于GCC的参数 -L
需要链接的库文件名称
对应于GCC的参数 -l

 

比如我需要链接第三方库curl,那么在CMakeLists.txt中可以书写如下:

include_directories(/usr/include) # 对应于-I
target_link_libraries(target curl) # 对应于 -L和-l

find_package的作用就是去寻找该库的头文件位置、库文件位置以及库文件名称,并将其设为变量,返回提供给CMakeLists.txt其他部分使用。

例如:

find_package(curl)
include_directories(${CURL_INCLUDE_DIR})
target_link_libraries(curltest ${CURL_LIBRARY})

或者

find_package(CURL)
if(CURL_FOUND)
include_directories(${CURL_INCLUDE_DIR})
target_link_libraries(curltest ${CURL_LIBRARY})
else(CURL_FOUND)
message(FATAL_ERROR "curl not found!")
endif(CURL_FOUND)​

 那么find_package会去 ${CMAKE_MODULE_PATH}的所有路径中去寻找FindCURL.cmake(是的,一般会去查找Find<name>.cmake这种格式),并执行FindCURL.cmake里的代码。

实际上,find_package寻找.cmake文件的搜索规则为

  1. ${CMAKE_MODULE_PATH},该变量是CMake默认自带的一个路径,也可以通过语句添加自己的CMake的模块搜索路径,如:
    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") # CMAKE_SOURCE_DIR是项目根目录
  2. <CMAKE_ROOT>/share/cmake-x.y/Modules/
  3. 如果Find<name>.cmake文件未找到,它将会尝试在系统路径中查找 <Name>Config.cmake 或 <lower-case-name>-config.cmake 文件。这两个文件是库文件安装时自己安装的,将自己的路径硬编码到其中。前者称为 module 模式,后者称为 config 模式。

通常FindCURL.cmake文件会提供以下几个变量:

  • <name>_FOUND => 表明是否查找到

  • <name>_INCLUDE_DIR 或 <name>_INCLUDES => 表示头文件位置

  • <name>_LIBRARY 或 <name>_LIBRARIES 或 <name>_LIBS => 表示库文件路径+名称

  • <name>_DEFINITIONS

编写Find<Name>.cmake文件

这里主要有两个函数,find_path和find_library.

find_path

find_path函数用法有两种,举例说明,例子如下,其中cmake_example的绝对路径为 /home/ruiy/cmake_example/

├─cmake_example            % 用例根目录
   └─find_path             
      ├─CMakeLists.txt 
      └─test.h             

第一种

第一种用法是精简的命令格式,如下

   find_path(<VAR> name1 [path1 path2 ...])​ # <VAR>是查找的路径存储到变量, names是需要查找的文件名, path1等是搜索路径

例如

find_path(test_path find_path/test.h /home/ruiy/cmake_example)
message(${test_path}) # ${test_path}的值为 /home/ruiy/cmake_example

结果:
// Path to a file
test_path:PATH=/home/ruiy/cmake_example

再比如

find_path(test_path test.h /home/ruiy/cmake_example/find_path)
message(${test_path})

结果:
// Path to a file
test_path:PATH=/home/ruiy/cmake_example/find_path

第二种

 find_path(
             <VAR>
             name | NAMES name1 [name2 ...]
             [HINTS path1 [path2 ... ENV var]]
             [PATHS path1 [path2 ... ENV var]]
             [PATH_SUFFIXES suffix1 [suffix2 ...]]
             [DOC "cache documentation string"]
             [NO_DEFAULT_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_CMAKE_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_SYSTEM_PATH]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH]
            )

例如

find_path(test_path NAMES test.h PATHS /home/ruiy/cmake_example/find_path DOC "this is a test for find_path")
message(${test})

结果:
//this is a test for find_path
test_path:PATH=/home/ruiy/cmake_example/find_path

这里用参考6里的话来解释该命令

  该命令用于给定名字文件所在的路径。一条名为<VAR>的cache条目会被创建,并存储该命令的执行结果。如果在某个路径下发现了该文件,该结果会被存储到该变量中;除非该变量被清除,该次搜索不会继续进行。如果没有找到,存储的结果将会是<VAR>-NOTFOUND,并且当下一次以相同的变量名调用find_path命令时,该命令会再一次尝试搜索该文件。需要搜索的文件名通过在NAMES选项后面的列出来的参数来确定。附加的搜索位置可以在PATHS选项之后指定。如果在PATHS或者HINTS命令中还指定了ENV var选项,环境变量var将会被读取并从一个系统环境变量转换为一个cmake风格的路径list。比如,ENV PATH是列出系统path变量的一种方法。参数DOC将用来作为该变量在cache中的注释。PATH_SUFFIXES指定了在每个搜索路径下的附加子路径。

find_library

实际上,find_libraryfind_path等价,见参考【6】的内容

参考

  1. CMake:How To Find Libraries
  2. cmake 学习笔记(三)
  3. CMake之find_package
  4. CMake--find_path()
  5. CMake手册详解 (十四)
  6. CMake手册详解 (十二)
  7. Cmake 实践 

上一篇: ubuntu 16.04 烧写usrp固件和FPGA

下一篇: CLion编译QtCreator的CMakeLists.txt

立即登录,发表评论
没有帐号?立即注册
0 条评论