CMake 手册
本文来源:http://www.cnblogs.com/coderfenghc/
目录:CMD#
CMake 用法导览
Preface : 本文是 CMake 官方文档 CMake Tutorial
(http://www.cmake.org/cmake/help/cmake_tutorial.html) 的翻译。通过一个样例
工程从简单到复杂的完善过程,文档介绍了 CMake 主要模块(cmake, ctest, cpack)的
功能和使用环境;从中可以一窥 cmake 的大体形貌。正文如下:
本文下述内容是一个手把手的使用指南;它涵盖了 CMake 需要解决的公共构建系统的
一些问题。这些主题中的许多主题已经在 Mastering CMake 一书中以单独的章节被介绍
过,但是通过一个样例工程看一看它们如何工作也是非常有帮助的。本指南可以在 CMake
源码树的 Tests/Tutorial 路径下找到。每一步都有它自己的子路径,其中包含该步骤的一
个完整的指南。
作为基础的起始点(步骤 1)
最基本的工程是一个从源代码文件中构建可执行文件的例子。对于简单工程,只要一个
两行的 CMakeLists 文件就足够了。这将会作为我们指南的起点。这份 CMakeLists 文件
看起来像是这样:
?
1
2
3
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
add_executable(Tutorial tutorial.cxx)
注意到这个例子在 CMakeLists 文件中使用了小写。CMake 支持大写、小写、混合大
小写的命令。tutorial.cxx 中的源代码用来计算一个数的平方根,并且它的第一版非常简单,
如下所示:
?
// A simple program that computes the square root of a number
// 计算一个数的平方根的简单程序
#include
#include
#include
int main (int argc, char *argv[])
{
}
if (argc < 2)
{
fprintf(stdout,"Usage: %s number\n",argv[0]);
return 1;
}
double inputValue = atof(argv[1]);
double outputValue = sqrt(inputValue);
fprintf(stdout,"The square root of %g is %g\n",
inputValue, outputValue);
return 0;
我们添加的第一个特性用来为工程和可执行文件指定一个版本号。虽然你可以在源代
码中唯一指定它,但是你在 CMakeLists 文件中指定它可以提供更好的灵活性。如下所示,
我么可以通过添加一个版本号来修改 CMakeLists 文件:
?
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# 版本号
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
# 配置一个头文件,通过它向源代码中传递一些 CMake 设置。
configure_file (
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# 将二进制文件树添加到包含文件的搜索路径中,这样我们可以找到 TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
# 添加可执行文件
add_executable(Tutorial tutorial.cxx)
由于配置过的文件将会被写到二进制文件目录下,我们必须把该目录添加到包含文件
的搜索路径清单中。然后,以下的代码就可以在源目录下创建一份 TotorialConfig.h.in 文
件:
?
1
2
3
// 与 tutorial 相关的配置好的选项与设置;
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
当 CMake 配置这份头文件时,@Tutorial_VERSION_MAJOR@和
@Tutorial_VERSION_MINOR@的值将会被从 CMakeLists 文件中传递过来的值替代。
下一步,我们要修改 tutorial.cxx 来包含 configured 头文件然后使用其中的版本号。修改
过的源代码展列于下:
?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
// 计算平方根的简单程序。
#include
#include
#include
#include "TutorialConfig.h"
int main (int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stdout,"%s Version %d.%d\n",
argv[0],
Tutorial_VERSION_MAJOR,
Tutorial_VERSION_MINOR);
fprintf(stdout,"Usage: %s number\n",argv[0]);
return 1;
}
double inputValue = atof(argv[1]);
double outputValue = sqrt(inputValue);
fprintf(stdout,"The square root of %g is %g\n",
inputValue, outputValue);
return 0;
}
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
引入库(步骤 2)
现在我们将会在我们的工程中引入一个库。这个库会包含我们自己实现的计算一个数的
平方根的函数。可执行文件随后可以使用这个库文件而不是编译器提供的标准开平方函数。
在本指南中,我们将会把库文件放到一个子目录 MathFunctions 中。它包含下述的单行
CMakeLists 文件:
?
1 add_library(MathFunctions mysqrt.cxx)
源文件 mysqrt.cxx 有一个叫做 mysqrt 的函数,它提供了与编译器的 sqrt 函数类似
的功能。为了使用新的库,我们在顶层的 CMakeLists 中增加一个 add_subrirectory 调
用,这样这个库也会被构建。我们也要向可执行文件中增加另一个头文件路径,这样就可以
从 MathFunctions/mysqrt.h 头文件中找到函数的原型。最后的一点更改是在向可执行文
件中引入新的库。顶层 CMakeLists 文件的最后几行现在看起来像是这样:
?
1
2
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
3
4
5
# 引入可执行文件
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial MathFunctions)
现在,让我们考虑下让 MathFunctions 库变为可选的。在本指南中,确实没有必要这
样画蛇添足;但是对于更大型的库或者依赖于第三方代码的库,你可能需要这种可选择性。
第一步是为顶层的 CMakeLists 文件添加一个选项:
?
1
2
3
# 我们应该使用我们自己的数学函数吗?
option (USE_MYMATH
"Use tutorial provided math implementation" ON)
这将会在 CMake 的 GUI 中显示一个默认的 ON 值,并且用户可以随需改变这个设置。
这个设置会被存储在 cache 中,那么用户将不需要在 cmake 该工程时,每次都设置这个
选项。第二处改变是,让链接 MathFunctions 库变为可选的。要实现这一点,我们修改顶
层 CMakeLists 文件的结尾部分:
?
1
2
3
4
5
6
7
8
9
# 添加 MathFunctions 库吗?
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# 添加可执行文件
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial
${EXTRA_LIBS})
这里用 USE_MYMATH 设置来决定是否 MathFunctions 应该被编译和执行。注意到,
要用一个变量(在这里是 EXTRA_LIBS)来收集所有以后会被连接到可执行文件中的可选
的库。这是保持带有许多可选部件的较大型工程干净清爽的一种通用的方法。源代码对应的
改变相当直白,如下所示:
?
1 // 计算一个数平方根的简单程序
#include
#include
#include
#include "TutorialConfig.h"
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
int main (int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stdout,"%s Version %d.%d\n", argv[0],
Tutorial_VERSION_MAJOR,
Tutorial_VERSION_MINOR);
fprintf(stdout,"Usage: %s number\n",argv[0]);
return 1;
}
double inputValue = atof(argv[1]);
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
#endif
fprintf(stdout,"The square root of %g is %g\n",
inputValue, outputValue);
return 0;
}
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
3
2
在源代码中,我们也使用了 USE_MYMATH。这个宏是由 CMake 通过
TutorialConfig.h.in 配置文件中的下述语句行提供给源代码的:
+ View Code?
1 #cmakedefine USE_MYMATH
安装与测试(步骤 3)
下一步我们会为我们的工程引入安装规则以及测试支持。安装规则相当直白,对于
MathFunctions 库,我们通过向 MathFunctions 的 CMakeLists 文件添加如下两条语句
来设置要安装的库以及头文件:
?
1
2
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)
对于应用程序,在顶层 CMakeLists 文件中添加下面几行,它们用来安装可执行文件
以及配置头文件:
?
1
2
3
4
# 添加安装目标
install (TARGETS Tutorial DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include)
这就是要做的全部;现在你应该可以构建 tutorial 工程了。然后,敲入命令 make install
(或者从 IDE 中构建 INSTALL 目标)然后它就会安装需要的头文件,库以及可执行文件
CMake 的变量 CMAKE_INSTALL_PREFIX 用来确定这些文件被安装的根目录。添加测试
同样也只需要相当浅显的过程。在顶层 CMakeLists 文件的的尾部补充许多基本的测试代
码来确认应用程序可以正确工作。
+ View Code?
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
# 应用程序是否运行?
add_test (TutorialRuns Tutorial 25)
# 它是否对 25 做了开平方运算
add_test (TutorialComp25 Tutorial 25)
set_tests_properties (TutorialComp25
PROPERTIES PASS_REGULAR_EXPRESSION "25 is 5")
# 它是否能处理是负数作为输入的情况
add_test (TutorialNegative Tutorial -25)
set_tests_properties (TutorialNegative
PROPERTIES PASS_REGULAR_EXPRESSION "-25 is 0")
# 它是否可以处理较小的数字。
add_test (TutorialSmall Tutorial 0.0001)
set_tests_properties (TutorialSmall
PROPERTIES PASS_REGULAR_EXPRESSION "0.0001 is 0.01")
# 用法信息是否可用?
add_test (TutorialUsage Tutorial)
set_tests_properties (TutorialUsage
PROPERTIES