8.1 KiB
layout | title | subtitle | description | excerpt | date | author | tags | categories | published | ||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post | CMake 基本语法 | CMake 的简明语法。 | 通过简明的方式对 CMake 构建系统基本语法进行说明。 | 2020-01-20 15:17:00 | Rick Chan |
|
|
true |
CMake 支持大写、小写、混合大小写的命令。
1.最小版本号
cmake_minimum_required(VERSION 2.8)
2.工程名
project(<Project Name>)
3.Include 路径
需要出现在 add_executable 和 add_library 等之前。
include_directories(
<Path 1>
<Path 2>
...
<Path N>
)
4.添加库路径
需要出现在 add_executable 和 add_library 等之前。
link_directories(
<Path 1>
<Path 2>
...
<Path N>
)
5.添加库文件
已经被废弃了,需要出现在 add_executable 和 add_library 等之前。
link_libraries(
<Library 1>
<Library 2>
...
<Library N>
)
支持直接全路径的写法。
6.可执行文件目标和源码
add_executable(
<Executable Name>
<Source 1>
<Source 2>
...
<Source N>
)
7.库文件目标和源码
add_library(
<Library>
<SHARED/STATIC>
<Source 1>
<Source 2>
...
<Source N>
)
8.为目标添加库文件
可添加的动态库或静态库,可以在 add_executable 和 add_library 等之后。
target_link_libraries(
<Target Name>
<Library 1>
<Library 2>
...
<Library N>
)
9.添加依赖工程
add_dependencies(
<Target Name>
<Depend Target 1>
<Depend Target 2>
...
<Depend Target N>
)
10.添加子目录
添加的子目录下的 CMakeLists.txt 和源码将被处理。
add_subdirectory(
<sub dir 1>
<sub dir 2>
...
<sub dir N>
)
11.自定义编译选项
CMake 允许为项目增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案。
option (USE_MYMATH
"Use provided math implementation" ON)
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
12.Config File
configure_file 命令用于加入一个配置头文件(如 config.h),这个文件由 CMake(从 config.h.in)生成,通过这样的机制,将可以通过预定义一些参数和变量来控制代码的生成。
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
编写一个 config.h.in 文件,内容如下:
#cmakedefine USE_MYMATH
13.编译项目
通常会创建一个 build 目录为 cmake 的工作目录,用于存放 cmake 临时文件:
mkdir build && cd build
cmake ..
make
make install
为了便于交互式的选择该变量的值,可以使用:
ccmake
# 或
cmake -i
该命令会提供一个会话式的交互式配置界面。
14.CMake 标准宏
14.1.CMAKE_INSTALL_PREFIX
用于指定 make install 的安装根目录,默认值为:/usr/local/。
15.CTest
CMake 提供了一个称为 CTest 的测试工具。我们要做的只是在项目根目录的 CMakeLists 文件中调用一系列的 add_test 命令。
# 启用测试
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")
# 测试 5 的平方
add_test (test_5_2 Demo 5 2)
set_tests_properties (test_5_2
PROPERTIES PASS_REGULAR_EXPRESSION "is 25")
# 测试 10 的 5 次方
add_test (test_10_5 Demo 10 5)
set_tests_properties (test_10_5
PROPERTIES PASS_REGULAR_EXPRESSION "is 100000")
# 测试 2 的 10 次方
add_test (test_2_10 Demo 2 10)
set_tests_properties (test_2_10
PROPERTIES 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/Demo5
Start 1: test_run
1/4 Test #1: test_run ......................... Passed 0.00 sec
Start 2: test_5_2
2/4 Test #2: test_5_2 ......................... Passed 0.00 sec
Start 3: test_10_5
3/4 Test #3: test_10_5 ........................ Passed 0.00 sec
Start 4: test_2_10
4/4 Test #4: test_2_10 ........................ Passed 0.00 sec
100% tests passed, 0 tests failed out of 4
Total 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 的文档。
16.支持 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")
17.添加版本号
首先修改顶层 CMakeLists 文件,在 project 命令之后加入如下两行:
set (Demo_VERSION_MAJOR 1)
set (Demo_VERSION_MINOR 0)
分别指定当前的项目的主版本号和副版本号。
之后,为了在代码中获取版本信息,我们可以修改 config.h.in 文件,添加两个预定义变量:
// the configured options and settings for Tutorial
#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@
这样就可以直接在代码中打印版本信息了:
int main(void)
{
printf("Version %d.%d\n",
Demo_VERSION_MAJOR,
Demo_VERSION_MINOR);
return 0;
}
18.生成安装包
首先在顶层的 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)
上面的代码做了以下几个工作:
- 导入 InstallRequiredSystemLibraries 模块,以便之后导入 CPack 模块;
- 设置一些 CPack 相关变量,包括版权信息和版本信息,其中版本信息用了上一节定义的版本号;
- 导入 CPack 模块。
接下来的工作是像往常一样构建工程,并执行 cpack 命令。
- 生成二进制安装包:
cpack -C CPackConfig.cmake
- 生成源码安装包
cpack -C CPackSourceConfig.cmake
在生成项目后,执行 cpack -C CPackConfig.cmake 命令,此时会在该目录下创建:Demo8-1.0.1-Linux.sh、Demo8-1.0.1-Linux.tar.gz、Demo8-1.0.1-Linux.tar.Z,3 个不同格式的二进制包文件。
关于 CPack 的更详细的用法可以通过 man 1 cpack 参考 CPack 的文档。