CMake是一个跨平台的自动化建构系统,它使用一个名为 CMakeLists.txt 的文件来描述构建过程,可以产生标准的构建文件.

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

  1. 安装cmake,sudo apt-get install cmake
  2. 编写 CmakeLists.txt
  3. 执行命令“cmake PATH”生成 Makefile ( PATH是CMakeLists.txt 所在的目录 )
  4. 使用 make 命令进行编译

下面我们以例子来快速入门:

mkdir -p ~/workspace/cmake_prj

单层目录结构例子

创建目录及C代码文件

cd ~/workspace/cmake_prj
mkdir prj1 & cd prj1
gedit helloworld.c
// helloworld.c
#include <stdio.h>

int main(void){
  printf("hello world!!\r\n");
  return 0;
}

创建CMakeLists.txt文件

PROJECT(helloworld) #该命令表示项目的名称是 helloworld
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) #该命令限定了 CMake 的版本
AUX_SOURCE_DIRECTORY(. DIR_SRCS) #该命令会把参数 `.`当前目录 中所有的源文件名称赋值给参数 `DIR_SRCS`
ADD_EXECUTABLE(helloworld ${DIR_SRCS}) #指示变量 DIR_SRCS 中的源文件需要编译成一个名称为 main 的可执行文件
  • CMakeLists.txt 的语法比较简单,由命令、注释和空格组成,其中命令是不区分大小写的。符号”#”后面的内容被认为是注释
  • 命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔

编译运行

cd ~/workspace/cmake_prj/prj1
cmake .
make
./helloworld 

多层目录结构例子

以上的例子是单层目录结构, 但在项目中普遍是多层的目录结构. 下面我们来看看两层的目录结构:

├── prj2
│   ├── CMakeLists.txt
│   ├── hellolib.c
│   └── src
│       ├── CMakeLists.txt
│       ├── testlib.c
│       └── testlib.h

该例子中我们将会定义一个lib,并且该lib的代码在src文件夹下,prj2目录下的代码hellolib.c会用到定义的lib.

先编写简单lib代码

cd ~/workspace/cmake_prj & mkdir prj2 & cd prj2 & mkdir src & cd src

gedit testlib.h
gedit testlib.c
// testlib.h

#include <stdio.h>

int add(int a,int b);
// testlib.c

#include "testlib.h"

int add(int a,int b){
  return (a+b);
}

在lib目录下创建CMakeList.txt文件

AUX_SOURCE_DIRECTORY(. DIR_LIB_SRCS)
ADD_LIBRARY(testlib ${DIR_LIB_SRCS}) #将src目录中的源文件编译为共享库testlib 

prj2目录下创建主函数代码

cd ~/workspace/cmake_prj/prj2

gedit hellolib.c
// hellolib.c
#include "src/testlib.h"

int main(void){
  int a=11,b=12;
  int sum = add(a,b);
  printf("%d + %d = %d\r\n",a,b,sum);

}

再创建整个工程的CMakeLists.txt

PROJECT(hellolib)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
ADD_SUBDIRECTORY(src) # 指明本项目包含一个子目录 src
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_EXECUTABLE(hellolib ${DIR_SRCS})
TARGET_LINK_LIBRARIES(hellolib testlib) #指明可执行文件 hellolib 需要连接一个名为testlib的链接库

编译执行

cd ~/workspace/cmake_prj/prj2
make .
make
./hellolib 

外部构建例子

以上两个例子其实都为内部构建, 你会发现构建后会生成很多临时文件,与CMakeLists.txt或者源代码混杂在一起.
这对于版本管理比如git不是很友好,需要重新编辑.gitignore文件,比较麻烦.
此时,若使用外部构建将会方便很多,我们以上面的例子2为基础来演示.

拷贝prj2工程到prj3, 并删除多余的文件,若有的话.

cd ~/worksapce/cmake_prj
cp -R prj2 prj3

在prj3下创建build目录,并在build目录下执行cmake

cd ~/worksapce/cmake_prj/prj3
mkdir build & cd build
cmake ../  ## cmake的path是父目录

此时,在build目录下生成了编译需要的Makefile以及其它的临时文件.
这样对于原有的工程没有任何影响,所有动作全部发生在编译目录build内.

编译执行

cd ~/worksapce/cmake_prj/prj3/build
make
./hellolib