CMake简介

Author Avatar
sunT 5月 13, 2018
  • 在其它设备中阅读本文章

CMake

什么是 CMake

由于存在各种各样不同的平台,所以就产生了各种各样的 makefile 文件。当我们想使软件可以跨平台,那么我们不得不对每个平台编写一个 Makefile。

这时候 cmake 就应运而生,它允许开发者只编写一个名为 CMakelists.txt的文件,就可以执行 cmake 后自动生成对应平台的 Makefile 文件。

执行起来也非常简单,只需要 cmake PATH 即可,其中 PATH 就是 CMakeLists.txt 的路径。

如何编写 CMakeLists.txt文件

有上述可知,编写 CMakeLists.txt 成了使用 cmake 的关键。

一个简单的例子

#CMake 最低版本的要求
cmake_minimum_required (VERSION 2.8)

#项目信息
project(Demo)

#指定生成的目标
add_executable(Demo main.c)

#号是用来注释的。

多个目录及源文件

我们在实际的生产环境中一般都是有多个目录和源文件的项目。所以如何利用 CMakeLists.txt 来构建整个项目才是学习的重点。

假如我们的项目目前有main.c、libfunc.c、libfunc.h三个文件。那么我们的 CMakeLists.txt 就可以这么写。

#CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

#项目信息
project (Demo2)

#指定生成目标
add_executable(Demo main.c libfunc.c)

如上我们只是在生成目标时,将 libfunc.c 加入而已。那么当我们有很多源文件那么一条一条的加入一定不是一个明智的做法。幸好我可以使用aux_source_directory(<dir> <variable>)来定义一个需要加入源文件的目录,所以我们可以将上面的 CMakeLists.txt 修改为。

#CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
#项目信息
project (Demo2)
#创建 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
#指定生成目标
add_executable(Demo ${DIR_SRCS})

利用了 aux_source_directory 来定义了一个名为DIR_SRCS的变量,他的值为’.’。这样在生成目标的时候就可以不当前目录的所有源文件包含。

如果我们的目录结构是 main.c 在根目录,而函数库定义的源文件libfunc.c 在 lib 目录下那又该如何编写 CMakeLists.txt 呢?
这时就该为每个目录编写一个 CMakeLists.txt 了。

所以首先根目录的CMakeLists.txt:

#CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
#项目信息
project (Demo3)
#创建 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
#添加  lib 子目录
add_subdirectory(lib)
#指定生成目标
add_executable(Demo main.cc)
#添加链接库
target_link_libraries(Demo lib)

我们看到了添加 lib 子目录add_subdirectory(lib)的命令。
然后就是 target_link_libraries(Demo lib)将 lib 库链接到最终生成的目标中。

接下来我们在就可以在 lib 目录下编写CMakeLists.txt 了。

#创建 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
#生成链接库
add_library ( lib ${DIR_LIB_SRCS})

可以看到的是我们使用了 add_library 将lib 生成静态链接库。

掌握上述的知识点基本上就可以满足一般的需求了。但是 cmake 还是提供了一些更自由的方式。

配置文件

设置版本号

set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)

configure_file(
                                "${PROJECT_SOURCE_DIR}/Config.h.in"
                                "${PROJECT_SOURCE_DIR}/Config.h"
                                )

在 Config.h.in 中定义:
在 Config.h.in 中定义:

#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @ Tutorial_VERSION_MINOR@

这样 cmake 就会自动生成一个 Config.h 文件。
但是需要将 Config.h包含在要使用版本号的地方。然后就可以在源代码中使用Tutorial_VERSION_MAJOR和Tutorial_VERSION_MINOR了。

还可使用 include_directories(...)指定头文件目录。

设置选项:

option(USE_MYLIB
                "Use my own lib function" ON)
if (USE_MYLIB)
  include_directories ("${PROJECT_SOURCE_DIR}/lib")
  add_subdirectory (lib)
  set (EXTRA_LIBS ${EXTRA_LIBS} lib)
endif (USE_MYLIB)

在源代码中添加:

#ifdef USE_MYLIB
  #include "lib/libfunc.h"
#else

gdb 相关设置

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 能做的还有很多诸如安装、测试、打包等操作。而且可以在 cmake 中定义函数和宏定义。你可以在cmake 官方网站学习更多。