文章目录
1. 基本模板
# CMake 最低版本要求
cmake_minimum_required (VERSION 2.8)
# 项目名称
project (Demo1)
# 指定生成目标
add_executable(Demo main.cc)
编译命令如下:
$ camke . # 如果是编译上一层目录,则 cmake ..
$ make
先生成Makefile文件,再make编译!
2. 同一目录多个源文件
# 查找指定目录下的所有源文件
aux_source_directory(<dir> <variable>)
$ aux_source_directory(. DIR_SRCS)
$ add_executable(Demo ${DIR_SRCS})
3. 多目录多源文件
- 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS}) add_library(common STATIC util.cpp) # 生成静态库 add_library(common SHARED util.cpp) # 生成动态库或共享库
- 添加math子目录,这样就能同时处理math子目录下的CMakeLists.txt和源代码了
add_subdirectory(math)
- 添加链接库
target_link_libraries(test MathFunctions)
注意:如果是两个CMakeLists.txt文件,应该注意子目录下名称变量不能与主目录下重复,否则报错!
4. 自定义编译选项
CMakeLists.txt内容如下:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo4)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# 是否使用自己的 MathFunctions 库
option (USE_MYMATH
"Use provided math implementation" ON)
# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
# 是否加入 MathFunctions 库
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable (Demo ${DIR_SRCS})
target_link_libraries (Demo ${EXTRA_LIBS})
源代码中也要通过宏定义实现修改:
#ifdef USE_MYMATH
#include <MathFunctions.h>
#else
#include <math.h>
#endif
配置文件config.h.in
的内容如下,CMake会自动根据此内容生成config.h文件,如果选项为OFF,则config.h内容会自动生成为#undef USE_MYMATH
#cmakedefine USE_MYMATH
编译时,使用ccmake
进入交互式配置界面,通过选项c
进入修改配置界面,通过回车键进行配置修改,修改完后通过c
返回上层界面,然后选择g
选项生成Makefile,最后make
生成可执行文件即可。
5. 安装和测试
定义库的安装路径:
# 指定安装路径,默认安装在/usr/local/下
install (TARGETS Demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include)
如果自定义指定安装路径,则在install
之前添加:
# 设置上一层目录下的install_file文件夹为安装目录
set(CMAKE_INSTALL_PREFIX ../install_file)
安装指令为:
make install
添加测试:
# 启用测试
enable_testing()
# 测试程序是否成功运行
add_test(test_5_2 Demo 5 2)
# 测试是否能够正常打印
set_tests_properties(test_5_2 PROPERTIES PASS_REGULAR_EXPRESSION "is 25")
编写宏,简化测试:
# 定义宏
macro(do_test arg1 arg2 result)
add_test(test_${arg1}_${arg2} Demo ${arg1} ${arg2})
set_tests_properties(test_${arg1}_${arg2} PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro(do_test)
# 使用宏
do_test(5 2 "is 25")
do_test(10 2 "is 100")
do_test(2 10 "is 1024")
测试指令为:
make test
注意:必须make生成可执行文件后才能进行测试,测试生成的报告位于"编译目录/Testing/Temporary/"下
6. 支持gdb
如果没有设置支持gdb,则查看代码时会提示:
(gdb) l
没有符号表被读取。请使用 "file" 命令。
(gdb)
只需要指定Debug模式下开启-g
选项即可完成CMake支持gdb的设置:
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
7. 添加环境检查
在顶层 CMakeLists 文件中添加 CheckFunctionExists.cmake
宏,并调用 check_function_exists
命令测试链接器是否能
够在链接阶段找到pow
函数:
#检查系统是否支持 pow 函数
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (pow HAVE_POW)
注意:由于我们在代码中会通过一些宏定义来调用不同环境下的函数,因此我们要在
config.h.in
文件里定义#cmakedefine HAVE_POW
,因此,检查语句要放在configure_file
命令之前。
8. 添加版本号
#项目信息
project (Demo7)
set(Demo_VERSION_MAJOR 2) # 指定当前项目的主版本号
set(Demo_VERSION_MINOR 3) # 指定当前项目的副版本号
set(Demo_VERSION_PATCH 1) # 指定当前项目的补丁等级
为了在代码中能够获取版本信息,修改config.h.in
文件:
// the configured options and settings for Tutorial
#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@
#define Demo_VERSION_PATCH @Demo_VERSION_PATCH@
在代码中,即可通过打印宏定义实现版本获取。
9. 生成二进制安装包和源码安装包
在CMakeLists.txt
末尾添加:
#构建一个 CPack 安装包
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
include (CPack)
- 生成二进制安装包
cpack -C CPackConfig.cmake
- 生成源码安装包
cpack -C CPackSourceConfig.cmake
执行以后,会在执行目录下生成3个不同格式的二进制包文件:
- Demo8-1.0.1-Linux.sh
- Demo8-1.0.1-Linux.tar.gz
- Demo8-1.0.1-Linux.tar.Z
执行以后会提示安装在了Demo8-1.0.1-Linux
目录下,有bin、include、lib三个文件夹,即我们在CMakeLists.txt中设置的内容。
更多CPack的详细用法可通过man 1 cpack
或cpack --help
查看。
10. 将其他平台的项目迁移到CMake
- autotools
- am2cmake工具:将autotools系的项目转换到CMake
- Alternative Automake2CMake工具:可以转换使用automake的KDevelop工程项目
- qmake
- qmake converter:可以转换使用QT的qmake工程
- Visual Studio
- vcproj2cmake.rb:可以根据 Visual Studio 的工程文件(后缀名是 .vcproj或 .vcxproj)生成 CMakeLists.txt 文件。
- vcproj2cmake.ps1:vcproj2cmake 的 PowerShell 版本。
- folders4cmake:根据 Visual Studio 项目文件生成相应的 “source_group” 信息,这些信息可以很方便的在 CMake脚本中使用。支持 Visual Studio 9/10 工程文件。
- CMakeLists.txt自动推导
- gencmake根据现有文件推导 CMakeLists.txt 文件。
- CMakeListGenerator应用一套文件和目录分析创建出完整的 CMakeLists.txt 文件。仅支持 Win32 平台。
11. 完整Demo
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo8)
set (Demo_VERSION_MAJOR 1)
set (Demo_VERSION_MINOR 0)
set (CMAKE_INCLUDE_CURRENT_DIR ON)
# 检查系统是否支持 pow 函数
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (pow HAVE_POW)
# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
# 是否加入 MathFunctions 库
if (NOT HAVE_POW)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (NOT HAVE_POW)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
target_link_libraries (Demo ${EXTRA_LIBS})
# 指定安装路径
install (TARGETS Demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include)
# 启用测试
enable_testing()
# 测试程序是否成功运行
add_test (test_run Demo 5 2)
# 测试帮助信息是否可以正常提示
add_test (test_usage Demo)
set_tests_properties (test_usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")
# 定义一个宏,用来简化测试工作
macro (do_test arg1 arg2 result)
add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2})
set_tests_properties (test_${arg1}_${arg2}
PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)
# 利用 do_test 宏,测试一系列数据
do_test (5 2 "is 25")
do_test (10 5 "is 100000")
do_test (2 10 "is 1024")
# 构建一个 CPack 安装包
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
include (CPack)
参考文献:
- CMake入门实战_HaHack