cmake find_package
【转载】
cmake find_package
cmake find_package基本原理
当编译一个需要使用第三方库的软件时,我们需要知道去哪寻找头文件,则CMakeLists.txt需要指定头文件目录和库文件:
include_directories(/usr/include/curl)
target_link_libraries(myprogram path/curl.so)
借助cmake提供的finder。使用cmake的Modules目录下的FindCURL.cmake,则CMakeLists.txt:
find_package(CURL REQUIRED)
include_directories($CURL_INCLUDE_DIR)
target_link_libraries(myprogram path/curl.so)
那么cmake是怎么查找的呢?
find_package()命令首先会在模块路径中寻找Find.cmake,这是查找库的一个典型方式。具体查找路径依次为CMake:变量${CMAKE_MODULE_PATH}中的所有目录。如果没有,然后在查看它自己的模块目录/share/cmake-x.y/Modules/($CMAKE_ROOT的具体值可以通过CMake中的message命令输出)。这称为模块模式。
为了能支持各种常见的库和包,CMake自带了很多模块。可以通过cmake -help-module-list得到支持的模块的列表:直接查看模块路径
如何编写自己的cmake module模块
目录结构示例如下
├── cmake
│ └── FindDEMO9LIB.cmake
├── CMakeLists.txt
├── demo9.cpp
├── demo9.h
└── demo9_main.cpp
对于系统预定义的Find.cmake模块,使用方法一般如上例所示:
每一个模块都会定义以下几个变量
• _FOUND
• _INCLUDE_DIR or _INCLUDES
• _LIBRARY or _LIBRARIES
你可以通过_FOUND来判断模块是否被找到,如果没有找到,按照工程的需要关闭某些特性、给出提醒或者中止编译,上面的例子就是报出致命错误并终止构建。
系统信息
1, CMAKE_MAJOR_VERSION,CMAKE主版本号,比如2.4.6中的2
2, CMAKE_MINOR_VERSION,CMAKE次版本号,比如2.4.6中的4
3, CMAKE_PATCH_VERSION,CMAKE补丁等级,比如2.4.6 中的6
4, CMAKE_SYSTEM,系统名称,比如Linux-2.6.22
5, CMAKE_SYSTEM_NAME,不包含版本的系统名,比如Linux
6, CMAKE_SYSTEM_VERSION,系统版本,比如2.6.22
7, CMAKE_SYSTEM_PROCESSOR,处理器名称,比如i686.
8, UNIX,在所有的类UNIX平台为TRUE,包括OS X和cygwin
9, WIN32,在所有的win32平台为TRUE,包括cygwin
主要开关选项
1,CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS,用来控制IF ELSE语句的书写方式,在下一节语法部分会讲到。
2,BUILD_SHARED_LIBS
这个开关用来控制默认的库编译方式,如果不进行设置,使用ADD_LIBRARY并没有指定库类型的情况下,默认编译生成的库都是静态库。如果SET(BUILD_SHARED_LIBS ON)后,默认生成的为动态库。
3,CMAKE_C_FLAGS
设置C编译选项,也可以通过指令ADD_DEFINITIONS()添加。
4,CMAKE_CXX_FLAGS
设置C++编译选项,也可以通过指令ADD_DEFINITIONS()添加。
关于cmake的一些知识
具体的说,这里是把项目根目录(CMakeLists.txt在项目根目录,${PROJECT_SOURCE_DIR}表示CMakeLists.txt所在目录)下的cmake/Modules子目录对应的路径值,追加到CMAKE_MODULE_PATH中;CMAKE_MODULE_PATH后续可能被include()和find_package()等命令所使用
- include()命令的作用:
- 包含文件
- 例如:include(utils.cmake)
- 基本等同于C/C++中的#include
- 需要.cmake后缀
- 包含模块
- 例如:include(xxx)
- 是说在CMAKE_MODULE_PATH变量对应的目录,或者CMake安装包自带的Module目录里寻找xxx.cmake文件
- 不需要.cmake后缀
具体的说,这里是把CMake安装包提供的ExternalProject.cmake
(例如我的是/usr/local/share/cmake/Modules/ExternalProject.cmake
)文件包含进来。ExternalProject,顾名思义,引入外部工程,各种第三方库什么的都可以考虑用它来弄
-
也就是说,只有这3种情况下才是Config模式:
-
find_package()
中指定CONFIG
关键字 -
find_package()
中指定NO_MODULE
关键字 -
find_package()
中使用了不在"basic signature"(也就是Module模式下所有支持的配置)关键字
find_package()中指定
NO_MODULE`关键字
find_package()
中使用了不在"basic signature"(也就是Module模式下所有支持的配置)关键字
换句话说,只要我不指定"CONFIG",不指定“NO_MODULE",也不使用"full signature"中的关键字,那我就是在Module模式