cmake简介

CMake 是一个开源、跨平台的工具系列,旨在构建、测试和打包软件。CMake 用于使用简单的平台和编译器独立配置文件来控制软件编译过程,并生成可在您选择的编译器环境中使用的本机 makefile和工作区。

cmake 存在的意义

在介绍g++/gcc原理的文章中C++编译原理,我们用一个简单的例子讲解了C++编译的原理,以及g++的使用。对于生成可执行文件这项任务,我们需要包含相应的头文件,以确保我们写的源代码文件可以顺利的被编译为二进制文件。对于在代码中使用的,定义在其他库的函数和变量,我们需要通过链接,将其具体的二进制内容,加入到可执行文件中(动态库是运行时加载),这样可执行文件才能顺利执行。

但是对于大型项目来说,为了可读性和可维护性,源代码文件往往根据功能分散在不同层级的不同目录下,需要的第三方库和第三方头文件也是非常多的。这种情况下,如果直接用g++命令来进行项目构建,无疑是非常麻烦的。也许一些新手会说可以使用MakeFile,但其实MakeFile其实就是将g++命令对应的脚本文件。

cmake的出现就是为了帮助构建这种大型复杂项目。cmake为我们提供了简洁的接口,方便我们设置编译参数(如优化等级,报警设置等等),添加依赖(头文件和库),编译源代码等等。

需要注意的是cmake的任务并不是构建项目,而是生成构建项目的g++命令(更确切的来说就是MakeFile)。

cmake的一个简单的例子

例子的源代码在这里cmake例子。例子的目录结构如下:

.
├── CMakeLists.txt
├── include
│   └── header.h
├── library
├── main.cpp
└── src
    ├── add
    │   └── add.cpp
    ├── distinct
    │   └── distinct.cpp
    └── printer.cpp

CMakeLists.txt的内容如下:

# cmake 最低版本需求
cmake_minimum_required(VERSION 3.10)

# 工程名称
project(leak_example)

# 设置编译标准为C++11
set(CMAKE_CXX_STANDARD "11")
# 设置编译静态库的产出目录为项目根目录下的library文件夹
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/library/)
# 设置编译可执行文件的产出目录为项目根目录下
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/)

# 设置包含头文件路径
include_directories(include/)

# 编译源码生成目标

# 寻找src目录下所有的cpp文件(源代码文件)
file(GLOB_RECURSE SRC_LIST src/*.cpp)
# 将src目录下的cpp文件编译为静态库libcommon.a
add_library(common STATIC ${SRC_LIST})

# 设置链接库目录
link_directories(${CMAKE_SOURCE_DIR}/library/)
# 将main.cpp编译为可执行文件
add_executable(main main.cpp)
# 增加可执行文件需要链接的静态库。一定要放在add_executable后面,否则cmake会对main产生困惑。add_executable相当于声明了可执行文件main的存在。
target_link_libraries(main libcommon.a)

构建项目时,依次执行以下命令:

mkdir build
cd build && cmake ..

此时,就可以在build文件夹下看到MakeFile文件了,cmake也就正式完成了它的使命,接着执行make,就可以看到下面的目录结构,主文件已经出现了可执行文件main和生成的静态库libcommon.a:

├── CMakeLists.txt
├── include
│   └── header.h
├── library
│   └── libcommon.a
├── main
├── main.cpp
└── src
    ├── add
    │   └── add.cpp
    ├── distinct
    │   └── distinct.cpp
    └── printer.cpp

然而不幸的是,这个程序并不能正确执行,因为里面有一些内存泄露的问题,在下一篇文章中将会介绍如何利用一些工具来定位内存泄露问题。

03-05 21:02