CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。
在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:
- 写 CMake 配置文件 CMakeLists.txt 。
- 执行命令
cmake PATH
或者ccmake PATH
生成 Makefile(ccmake
和cmake
的区别在于前者提供了一个交互式的界面)。其中,PATH
是 CMakeLists.txt 所在的目录。 - 使用
make
命令进行编译。
入门案例:
同一目录,多个源文件
假设现在我们的项目中只有一个源文件 main.cc ,该程序的用途是计算一个数的指数幂。
#include <stdio.h>
#include <stdlib.h>/*** power - Calculate the power of number.* @param base: Base value.* @param exponent: Exponent value.** @return base raised to the power exponent.*/
double power(double base, int exponent)
{int result = base;int i;if (exponent == 0) {return 1;}for(i = 1; i < exponent; ++i){result = result * base;}return result;
}int main(int argc, char *argv[])
{if (argc < 3){printf("Usage: %s base exponent \n", argv[0]);return 1;}double base = atof(argv[1]);int exponent = atoi(argv[2]);double result = power(base, exponent);printf("%g ^ %d is %g\n", base, exponent, result);return 0;
}
假设工程代码是如下形式:
./Demo2|+--- main.cc|+--- MathFunctions.cc|+--- MathFunctions.h
CMakeLists.txt 可以写成如下的形式:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)# 项目信息
project (Demo2)# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)# 指定生成目标
add_executable(Demo ${DIR_SRCS})
CMakeLists.txt 的语法比较简单,由命令、注释和空格组成,其中命令是不区分大小写的。符号 #
后面的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。对于上面的 CMakeLists.txt 文件,依次出现了几个命令:
cmake_minimum_required
:指定运行此配置文件所需的 CMake 的最低版本;project
:参数值是Demo1
,该命令表示项目的名称是Demo1
。aux_source_directory
:查找指定目录下的所有源文件,然后将结果存进指定变量名add_executable
:将名为 main.cc 的源文件编译成一个名称为 Demo 的可执行文件。
多个目录,多个源文件
假设工程代码是如下形式:
./Demo3|+--- main.cc|+--- math/|+--- MathFunctions.cc|+--- MathFunctions.h
CMakeLists.txt 可以写成如下的形式:
先将 math 目录里的文件编译成静态库再由 main 函数调用。
根目录中的 CMakeLists.txt :
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)# 项目信息
project (Demo3)# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)# 添加 math 子目录
add_subdirectory(math)# 指定生成目标
add_executable(Demo main.cc)# 添加链接库
target_link_libraries(Demo MathFunctions)
使用命令 add_subdirectory
指明本项目包含一个子目录 math,这样 math 目录下的 CMakeLists.txt 文件和源代码也会被处理 。使用命令 target_link_libraries
指明可执行文件 main 需要连接一个名为 MathFunctions 的链接库 。
子目录中的 CMakeLists.txt:
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)# 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS})
使用命令 add_library
将 src 目录中的源文件编译为静态链接库。
执行:
cmake 路径(CMakeList.txt所在的路径)
make
./Demo 参数
为工程添加测试
CMake 提供了一个称为 CTest 的测试工具。我们要做的只是在项目根目录的 CMakeLists 文件中调用一系列的 add_test
命令。
# 启用测试
enable_testing()# 测试程序是否成功运行
add_test (test_run Demo 5 2)# 测试帮助信息是否可以正常提示
add_test (test_usage Demo)
set_tests_properties (test_usagePROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")# 测试 5 的平方
add_test (test_5_2 Demo 5 2)set_tests_properties (test_5_2PROPERTIES PASS_REGULAR_EXPRESSION "is 25")# 测试 10 的 5 次方
add_test (test_10_5 Demo 10 5)set_tests_properties (test_10_5PROPERTIES PASS_REGULAR_EXPRESSION "is 100000")# 测试 2 的 10 次方
add_test (test_2_10 Demo 2 10)set_tests_properties (test_2_10PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")
第一个测试 test_run
用来测试程序是否成功运行并返回 0 值。
剩下的三个测试分别用来测试 5 的 平方、10 的 5 次方、2 的 10 次方是否都能得到正确的结果。其中 PASS_REGULAR_EXPRESSION
用来测试输出是否包含后面跟着的字符串。
测试结果:
[ehome@xman Demo5]$ make test
Running tests...
Test project /home/ehome/Documents/programming/C/power/Demo5Start 1: test_run
1/4 Test #1: test_run ......................... Passed 0.00 secStart 2: test_5_2
2/4 Test #2: test_5_2 ......................... Passed 0.00 secStart 3: test_10_5
3/4 Test #3: test_10_5 ........................ Passed 0.00 secStart 4: test_2_10
4/4 Test #4: test_2_10 ........................ Passed 0.00 sec100% tests passed, 0 tests failed out of 4Total Test time (real) = 0.01 sec
如果要测试更多的输入数据,像上面那样一个个写测试用例未免太繁琐。这时可以通过编写宏来实现:
# 定义一个宏,用来简化测试工作
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 5 "is 100000")
do_test (2 10 "is 1024")
关于 CTest 的更详细的用法可以通过 man 1 ctest
参考 CTest 的文档。
支持 gdb
让 CMake 支持 gdb 的设置也很容易,只需要指定 Debug
模式下开启 -g
选项:
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")
之后可以直接对生成的程序使用 gdb 来调试。
参考:全网最细的CMake教程!(强烈建议收藏) - 知乎