1 CMake介绍
CMake允许开发者编写一种平台无关的 CMakeLists.txt
文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。
在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:
- 编写 CMake 配置文件 CMakeLists.txt 。
- 执行命令
cmake PATH
或者ccmake PATH
生成Makefile
。其中,PATH
是 CMakeLists.txt 所在的目录。- 使用
make
命令进行编译,得到可执行文件。
2 实用技巧
CMake手册见官网,可以查阅cmake命令,变量等各种资料。下面介绍一些常用的编写CMakeLists.txt
技巧:
2.1 单个源文件
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo1)
# 指定生成目标
add_executable(run main.cxx)
2.2 多个源文件
- 同一目录下多个源文件
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo2)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
- 多个目录
需要分别在项目根目录 Demo3 和 源文件目录里各编写一个CMakeLists.txt
文件。为了方便,我们可以先将 源文件 目录里的文件编译成静态库再由 main 函数调用。
举例:项目文件:
./Demo3
|
+--- main.cxx
|
+--- print/
|
+--- print.cxx
|
+--- print.h
Demo3 中有源文件main.cxx, main函数调用print()函数,print()函数在print目录下.
- print子目录中的
CMakeLists.txt
:
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
# 生成链接库
add_library (Prints ${DIR_LIB_SRCS})
- 项目根目录中的
CMakeLists.txt
:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo3)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# Prints lib
# 添加 print 子目录
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/print)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/print)
# 指定生成目标
add_executable(run ${DIR_SRCS})
# 添加链接库
target_link_libraries(run Prints)
2.3 自定义编译选项
CMake 允许为项目增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案。
如上述Demo3中设置两种print方式,分别为print,和print1:
./Demo4
|
+--- main.cxx
|
+--- print/
|
+--- print.cxx
|
+--- print.h
|
+--- print1/
|
+--- print1.cxx
|
+--- print1.h
子目录print 和 print1 中CMakeLists.txt
和Demo3中一样,以创建静态链接库。
第一步:修改根目录下CMakeLists.txt
:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo4)
# 使用print库还是print1库
option (PRINT_LIB
"Use print lib" ON)
# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file(
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_SOURCE_DIR}/config.h"
)
# 加入哪个库
if (PRINT_LIB)
include_directories (${PROJECT_SOURCE_DIR}/print)
# 添加 print 子目录
add_subdirectory(print)
set (PRINT_LIBS Prints)
else()
include_directories (${PROJECT_SOURCE_DIR}/print1)
# 添加 print1 子目录
add_subdirectory(print1)
set (PRINT_LIBS Prints)
endif (PRINT_LIB)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(run ${DIR_SRCS})
# 添加链接库
target_link_libraries(run ${PRINT_LIBS})
第二步:根目录下编写config.h.in
文件,编译时会生成config.h
文件(根目录下CMakeListx.txt
中configure_file
命令的结果)
#cmakedefine PRINT_LIB
#ifdef PRINT_LIB
#include <print.h>
#else
#include <print1.h>
#endif
第三步:main.cxx
文件加入#include "config.h"
注意:通过设定PRINT_LIB
为ON
或OFF
(根目录下CMakeListx.txt
中option
命令设置)
可以改变config.h
内容,为ON
时,首行为#define PRINT_LIB
为OFF
时,首行为/* #undef PRINT_LIB */
2.4 安装和测试
CMake 也可以指定安装规则,以及添加测试。这两个功能分别可以通过在产生 Makefile 后使用 make install
和 make test
来执行。
- 定制安装规则
首先先在print/CMakeLists.txt
文件里添加下面两行:
# 指定Prints 库的安装路径
install (TARGETS Prints
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
install (FILES "print.h"
DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
print1/CMakeLists.txt
中为"print1.h"
然后在修改根目录的 CMakeLists.txt
文件,在末尾添加下面几行:
# 指定安装路径
install (TARGETS run
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
install (FILES "${PROJECT_SOURCE_DIR}/config.h"
DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
编译、安装过程:
$ mkdir build & cd build #创建编译目录
$ cmake -D CMAKE_INSTALL_PREFIX=/home/ywq/Documents/ceshi .. # 指定安装目录
$ make
$ make install
- 为工程添加测试
CMake 提供了一个称为CTest
的测试工具。我们要做的只是在项目根目录的CMakeLists.txt
文件中调用一系列的add_test
命令。
# 启用测试
enable_testing()
# 测试程序是否成功运行
add_test (test_run run)
# 测试帮助信息是否可以正常提示
add_test (test_usage run)
set_tests_properties (test_usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")
2.5 添加版本号
给项目添加和维护版本号,修改顶层 CMakeLists.txt
文件,在 project
命令之后加入如下两行:
# 指定主版本号和副版本号
set (Run_VERSION_MAJOR 1)
set (Run_VERSION_MINOR 0)
还可以修改 config.h.in
文件,添加两个预定义变量:
#define Run_VERSION_MAJOR @Run_VERSION_MAJOR@
#define Run_VERSION_MINOR @Run_VERSION_MINOR@
以在代码中获取版本信息。
2.6 生成安装包
配置生成各种平台上的安装包,包括二进制安装包和源码安装包。为了完成这个任务,我们需要用到 CPack
,它同样也是由 CMake 提供的一个工具,专门用于打包。
首先在项目根目录的 CMakeLists.txt
文件尾部添加下面几行:
# 构建一个 CPack 安装包
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Run_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Run_VERSION_MINOR}")
include (CPack)
构建工程后,使用cpack
命令生成安装包:
- 生成二进制安装包:
$ cpack -C CPackConfig.cmake
- 生成源码安装包:
$ cpack -C CPackSourceConfig.cmake
2.7 gdb调试
在CMakeLists.txt
中增加:
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")
然后重新编译:
$ cmake -D CMAKE_BUILD_TYPE=Debug Path # Path 为CMakeLists.txt文件所在目录
$ make
之后就可以使用`gdb``调试生成的可执行文件:
$ gdb run # run 为生成的可执行文件