GNU开发工具——CMake快速入门

Posted 悦码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GNU开发工具——CMake快速入门相关的知识,希望对你有一定的参考价值。

一、CMake简介

不同Make工具,如GNU Make、QT的qmake、微软的MS nmake、BSD Make(pmake)等,遵循着不同的规范和标准,所执行的Makefile格式也不同。如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用Make工具,必须为不同的Make工具编写不同的Makefile。

CMake是一个比Make工具更高级的编译配置工具,是一个跨平台的、开源的构建系统(BuildSystem)。CMake允许开发者编写一种平台无关的CMakeList.txt文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化Makefile和工程文件,如:为Unix平台生成Makefile文件(使用GCC编译),为Windows MSVC生成projects/workspaces(使用VS IDE编译)或Makefile文件(使用nmake编译)。使用CMake作为项目架构系统的知名开源项目有VTK、ITK、KDE、OpenCV、OSG等。

二、CMake管理工程

在Linux平台下使用CMake生成Makefile并编译的流程如下:

A、编写CMake配置文件CMakeLists.txt

B、执行命令cmake PATH生成Makefile,PATH是CMakeLists.txt所在的目录。

C、使用make命令进行编译。

三、单个源文件工程

1、源文件编写

假设项目test中只有一个main.cpp源文件,程序用途是计算一个数的指数幂。

GNU开发工具——CMake快速入门

2、编写CMakeLists.txt

在main.cpp源文件目录test下编写CMakeLists.txt文件。

GNU开发工具——CMake快速入门

CMakeLists.txt由命令、注释和空格组成,其中命令是不区分大小写。符号#后的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。

本例中CMakeLists.txt文件的命令如下:

cmake_minimum_required:指定运行本配置文件所需的CMake的最低版本;

project:参数值是demo,表示项目的名称是demo。

add_executable:将名为main.cpp的源文件编译成一个名称为demo的可执行文件。

3、编译工程

在源码根目录下创建一个build目录,进入build目录,执行cmake ..,生成Makefile,再使用make命令编译得到demo可执行文件。

通常,建议在源码根目录下创建一个独立的build构建编译目录,将构建过程产生的临时文件等文件与源码隔离,避免源码被污染。

四、单目录多源文件工程

1、源文件编写

假如把power函数单独写进一个名为MathFunctions.cpp的源文件里,使得这个工程变成如下的形式:

GNU开发工具——CMake快速入门

MathFunctions.h文件:

GNU开发工具——CMake快速入门

MathFunctions.cpp文件:

GNU开发工具——CMake快速入门

main.cpp文件:

GNU开发工具——CMake快速入门

2、编写CMakeLists.txt

GNU开发工具——CMake快速入门

add_executable命令中增加了一个MathFunctions.cpp源文件,但如果源文件很多,可以使用aux_source_directory命令,aux_source_directory命令会查找指定目录下的所有源文件,然后将结果存进指定变量名。其语法如下:

aux_source_directory(dir variable)

修改后CMakeLists.txt如下:

GNU开发工具——CMake快速入门

CMake会将当前目录所有源文件的文件名赋值给变量DIR_SRCS ,再指示变量DIR_SRCS中的源文件需要编译成一个名称为demo的可执行文件。

五、多文件多目录工程

1、源码文件编写

创建一个math目录,将MathFunctions.h和MathFunctions.cpp文件移动到math目录下。在工程目录根目录test和子目录math里各编写一个CMakeLists.txt文件,可以先将math目录里的文件编译成静态库再由main函数调用。

GNU开发工具——CMake快速入门

math子目录:

MathFunctions.h文件:

GNU开发工具——CMake快速入门

MathFunctions.cpp文件:

GNU开发工具——CMake快速入门

根目录源文件:

GNU开发工具——CMake快速入门

2、CMakeLists.txt文件编写

根目录的CMakeLists.txt文件:

GNU开发工具——CMake快速入门

add_subdirectory命令指明本工程包含一个子目录math,math目录下的 CMakeLists.txt文件和源代码也会被处理 。target_link_libraries命令指明可执行文件demo需要连接一个名为MathFunctions的链接库 。

math子目录的CMakeLists.txt文件:

GNU开发工具——CMake快速入门

add_library命令将math目录中的源文件编译为静态链接库。

六、自定义编译选项

1、自定义编译选项简介

CMake允许为工程增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案。

例如,可以将MathFunctions库设为一个可选的库,如果该选项为ON ,就使用MathFunctions库定义的数学函数来进行运算,否则就调用标准库中的数学函数库。

2、CMakeLists 文件编写

在根目录的CMakeLists.txt文件指定自定义编译选项:

GNU开发工具——CMake快速入门

configure_file命令用于加入一个配置头文件config.h,config.h文件由CMake从config.h.in生成,通过预定义一些参数和变量来控制代码的生成。

option命令添加了一个USE_MYMATH选项,并且默认值为ON。

根据USE_MYMATH变量的值来决定是否使用自己编写的MathFunctions库。

3、修改源文件的调用

修改main.cpp文件,让其根据USE_MYMATH的预定义值来决定是否调用标准库还是MathFunctions库。

GNU开发工具——CMake快速入门

4、编写config.h.in文件

main.cpp文件包含了一个config.h文件,config.h文件预定义了USE_MYMATH 的值。但不会直接编写config.h文件,为了方便从CMakeLists.txt中导入配置,通常编写一个config.h.in文件,内容如下:

#cmakedefine USE_MYMATH

CMake会自动根据CMakeLists.txt配置文件中的设置自动生成config.h文件。

5、编译工程

修改CMakeLists.txt文件,USE_MYMATH为OFF,使用标准库。

# 是否使用自己的MathFunctions库
option (USE_MYMATH
"Use provided math implementation" OFF)

在build目录下cmake ..,make,执行程序:

GNU开发工具——CMake快速入门

七、安装和测试

1、定制安装规则

在math/CMakeLists.txt文件指定MathFunctions库的安装规则:

#指定MathFunctions库的安装路径
install(TARGETS MathFunctions DESTINATION bin)
install(FILES MathFunctions.h DESTINATION include)

修改根目录的CMakeLists.txt文件指定目标文件的安装规则:

#指定安装路径
install(TARGETS test DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include)

通过对安装规则的定制,生成的目标文件和MathFunctions函数库 libMathFunctions.o文件将会被拷贝到/usr/local/bin中,而MathFunctions.h和生成的config.h文件则会被复制到/usr/local/include中。

/usr/local是默认安装到的根目录,可以通过修改 CMAKE_INSTALL_PREFIX 变量的值来指定文件应该拷贝到哪个根目录。

2、为工程添加测试

CMake提供了一个CTest测试工具。在项目根目录的CMakeLists.txt文件中调用一系列的add_test 命令。

GNU开发工具——CMake快速入门

GNU开发工具——CMake快速入门

第一个测试test_run用来测试程序是否成功运行并返回0值。剩下的三个测试分别用来测试 5 的 平方、10 的 5 次方、2 的 10 次方是否都能得到正确的结果。其中PASS_REGULAR_EXPRESSION用来测试输出是否包含后面跟着的字符串。

如果要测试更多的输入数据,可以通过编写宏来实现:

GNU开发工具——CMake快速入门

GNU开发工具——CMake快速入门

八、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来调试。

九、添加环境检查

使用平台相关的特性时,需要对系统环境做检查。检查系统是否自带pow函数,如果有pow函数,就使用;否则使用自定义的power函数。

1、添加 CheckFunctionExists 宏

首先在顶层CMakeLists.txt文件中添加CheckFunctionExists.cmake 宏,并调用check_function_exists命令测试链接器是否能够在链接阶段找到 pow函数。

#检查系统是否支持 pow 函数
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
check_function_exists (pow HAVE_POW)
check_function_exists需要放在configure_file命令前。

2、预定义相关宏变量

修改 config.h.in 文件,预定义相关的宏变量。

// does the platform provide pow function?
#cmakedefine HAVE_POW

3、在代码中使用宏和函数

修改 main.cpp文件 ,在代码中使用宏和函数。

GNU开发工具——CMake快速入门

十、添加版本号

修改顶层CMakeLists.txt文件,在project命令后分别指定当前的项目的主版本号和副版本号。

GNU开发工具——CMake快速入门

GNU开发工具——CMake快速入门

分别指定当前的项目的主版本号和副版本号。

为了在代码中获取版本信息,可以修改 config.h.in 文件,添加两个预定义变量:

// the configured options and settings for Tutorial
#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@
// does the platform provide pow function?
#cmakedefine HAVE_POW

直接在源码中使用:

GNU开发工具——CMake快速入门

GNU开发工具——CMake快速入门

十一、生成安装包

1、增加CPack模块

CMake提供了一个专门用于打包的工具CPack,用于配置生成各种平台上的安装包,包括二进制安装包和源码安装包。

首先在顶层的CMakeLists.txt文件尾部添加下面几行:

GNU开发工具——CMake快速入门

导入InstallRequiredSystemLibraries模块,便于导入CPack模块;

设置一些CPack相关变量,包括版权信息和版本信息

导入CPack模块。

在顶层目录下创建License.txt文件内如如下:

2、生成安装包

生成二进制安装包:

cpack -C CPackConfig.cmake

生成源码安装包:

cpack -C CPackSourceConfig.cmake

上述两个命令都会在目录下创建3个不同格式的二进制包文件:

demo-1.0.1-Linux.tar.gz

demo-1.0.1-Linux.tar.Z

demo-1.0.1-Linux.sh

3个二进制包文件所包含的内容是完全相同的。

以上是关于GNU开发工具——CMake快速入门的主要内容,如果未能解决你的问题,请参考以下文章

GNU开发工具——CMake快速入门

GNU开发工具——GNU Binutils快速入门

GNU开发工具——GDB快速入门

GNU开发工具——CMake进阶

GNU ARM汇编快速入门

GNU开发工具——CMake工程实践