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.cmake这种格式),并执行FindCURL.cmake里的代码。
实际上,find_package寻找.cmake文件的搜索规则为${CMAKE_MODULE_PATH},该变量是CMake默认自带的一个路径,也可以通过语句添加自己的CMake的模块搜索路径,如:set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") # CMAKE_SOURCE_DIR是项目根目录
/share/cmake-x.y/Modules/
如果Find.cmake文件未找到,它将会尝试在系统路径中查找 Config.cmake 或 -config.cmake 文件。这两个文件是库文件安装时自己安装的,将自己的路径硬编码到其中。前者称为 module 模式,后者称为 config 模式。
通常FindCURL.cmake文件会提供以下几个变量:_FOUND => 表明是否查找到
_INCLUDE_DIR 或 _INCLUDES => 表示头文件位置
_LIBRARY 或 _LIBRARIES 或 _LIBS => 表示库文件路径+名称
_DEFINITIONS
编写Find.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( name1 [path1 path2 ...]) # 是查找的路径存储到变量, 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(
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里的话来解释该命令该命令用于给定名字文件所在的路径。一条名为的cache条目会被创建,并存储该命令的执行结果。如果在某个路径下发现了该文件,该结果会被存储到该变量中;除非该变量被清除,该次搜索不会继续进行。如果没有找到,存储的结果将会是-NOTFOUND,并且当下一次以相同的变量名调用find_path命令时,该命令会再一次尝试搜索该文件。需要搜索的文件名通过在NAMES选项后面的列出来的参数来确定。附加的搜索位置可以在PATHS选项之后指定。如果在PATHS或者HINTS命令中还指定了ENV var选项,环境变量var将会被读取并从一个系统环境变量转换为一个cmake风格的路径list。比如,ENV PATH是列出系统path变量的一种方法。参数DOC将用来作为该变量在cache中的注释。PATH_SUFFIXES指定了在每个搜索路径下的附加子路径。
find_library
实际上,find_library同find_path等价,见参考【6】的内容
参考