CMake基础篇(二)——编写CMakeLists

前言:
  CMake的编译规则由开发者指定,通过编写CMakeLists完成规则编写。

1 CMake简介

  CMake是一种跨平台的编译工具,它语法简单,可以输出各种各样的makefile或project文件。CMake用于产生标准的构建档,使得开发者可以在不同的平台用标准的方式构建软件,实现一次编写编译规则,多个平台相同编译。

2 编写CMakeLists

  在工程根目录创建一个名为 CMakeLists.txt 的文件。假设工程根目录结构如下。

  在Ubuntu下终端输入指令 tree 查看目录结构,如果为安装过tree,需要先执行指令 sudo apt-get install tree 进行安装。

1
2
3
.
├── CMakeLists.txt
└── main.c

  main.c文件内容如下:

1
2
3
4
5
6
7
8
#include <stdio.h>

int main(void)
{
printf("Hello World!\n");

return 0u;
}

&emsp;&emsp;对此,要将main.c编译为可执行文件可在CMakeLists.txt中编写如下编译规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#生成目标。
add_executable(Run main.c)

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

&emsp;&emsp;上面的代码指定了c编译器为 clang ,c++编译器为 clang++ 。在Ubuntu中需要安装clang,执行以下指令安装。

1
sudo apt-get install clang

&emsp;&emsp;也可以指定GCC编译,则CMakeLists.txt需要做以下修改。

1
2
3
4
#指定c编译器为gcc。
Set(CMAKE_C_COMPILER "/usr/bin/gcc")
#指定c++编译器为g++。
Set(CMAKE_CXX_COMPILER "/usr/bin/g++")

&emsp;&emsp;Ubuntu下需要安装GCC,执行以下指令安装。

1
2
sudo apt-get install gcc
sudo apt-get install g++

&emsp;&emsp; set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 使能产生compile_command.json文件,非必须,根据需要添加这样代码。

&emsp;&emsp;CMakeLists.txt的语法规则非常简单,也是函数调用的形式,命令不区分大小写。函数参数之间使用空白字符分割(注意:不是 , )。CMakeLists的行注释标识符为 #

  • cmake_minimum_required(VERSION 3.0): 限制了执行CMakeLists配置文件时所需的CMake最低版本要求;
  • project(Proj): 指定所编译工程的项目名;
  • add_executable(Run main.c): 指定编译输出的可执行文件名(Run),并且指定编译所以来的源文件(main.c)。

2 CMake编译

2.1 编译单个源文件

&emsp;&emsp;为了防止CMake编译出来的产物污染工程,我们在根目录下创建一个名为 build 的目录,并在该目录下执行CMake编译指令,这样产物就会生成在这个目录中。
&emsp;&emsp;Ubuntu下在工程根目录执行以下指令创建build目录。

1
mkdir build

&emsp;&emps;此时工程目录结构如下。

1
2
3
4
.
├── CMakeLists.txt
├── build
└── main.c

&emsp;&emsp;通过 cd build 指令进入到build目录中。在build目录下执行以下指令开始CMake编译。

1
cmake <path>

&emsp;&emsp; <path> 为CMakeLists.txt的目录路径,可以写相对路径,按上面的工程目录结构指令应该为 cmake .... 表示上一级目录。

CMake基础篇(二)——编写CMakeLists

前言:
&emsp;&emsp;CMake的编译规则由开发者指定,通过编写CMakeLists完成规则编写。

1 CMake简介

&emsp;&emsp;CMake是一种跨平台的编译工具,它语法简单,可以输出各种各样的makefile或project文件。CMake用于产生标准的构建档,使得开发者可以在不同的平台用标准的方式构建软件,实现一次编写编译规则,多个平台相同编译。

2 编写CMakeLists

&emsp;&emsp;在工程根目录创建一个名为 CMakeLists.txt 的文件。假设工程根目录结构如下。

&emsp;&emsp;在Ubuntu下终端输入指令 tree 查看目录结构,如果为安装过tree,需要先执行指令 sudo apt-get install tree 进行安装。

1
2
3
.
├── CMakeLists.txt
└── main.c

&emsp;&emsp;main.c文件内容如下:

1
2
3
4
5
6
7
8
#include <stdio.h>

int main(void)
{
printf("Hello World!\n");

return 0u;
}

&emsp;&emsp;对此,要将main.c编译为可执行文件可在CMakeLists.txt中编写如下编译规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#生成目标。
add_executable(Run main.c)

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

&emsp;&emsp;上面的代码指定了c编译器为 clang ,c++编译器为 clang++ 。在Ubuntu中需要安装clang,执行以下指令安装。

1
sudo apt-get install clang

&emsp;&emsp;也可以指定GCC编译,则CMakeLists.txt需要做以下修改。

1
2
3
4
#指定c编译器为gcc。
Set(CMAKE_C_COMPILER "/usr/bin/gcc")
#指定c++编译器为g++。
Set(CMAKE_CXX_COMPILER "/usr/bin/g++")

&emsp;&emsp;Ubuntu下需要安装GCC,执行以下指令安装。

1
2
sudo apt-get install gcc
sudo apt-get install g++

&emsp;&emsp; set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 使能产生compile_command.json文件,非必须,根据需要添加这样代码。

&emsp;&emsp;CMakeLists.txt的语法规则非常简单,也是函数调用的形式,命令不区分大小写。函数参数之间使用空白字符分割(注意:不是 , )。CMakeLists的行注释标识符为 #

  • cmake_minimum_required(VERSION 3.0): 限制了执行CMakeLists配置文件时所需的CMake最低版本要求;
  • project(Proj): 指定所编译工程的项目名;
  • add_executable(Run main.c): 指定编译输出的可执行文件名(Run),并且指定编译所以来的源文件(main.c)。

2 CMake编译

2.1 编译单个源文件

&emsp;&emsp;为了防止CMake编译出来的产物污染工程,我们在根目录下创建一个名为 build 的目录,并在该目录下执行CMake编译指令,这样产物就会生成在这个目录中。
&emsp;&emsp;Ubuntu下在工程根目录执行以下指令创建build目录。

1
mkdir build

&emsp;&emps;此时工程目录结构如下。

1
2
3
4
.
├── CMakeLists.txt
├── build
└── main.c

&emsp;&emsp;通过 cd build 指令进入到build目录中。在build目录下执行以下指令开始CMake编译。

1
cmake <path>

&emsp;&emsp; <path> 为CMakeLists.txt的目录路径,可以写相对路径,按上面的工程目录结构指令应该为 cmake .... 表示上一级目录。

cmake.png

&emsp;&emsp;接着执行以下指令生成可执行文件。

1
make

make.png

2.2 编译多个源文件

&emsp;&emsp;当工程有多个源文件时,只需将相关的源文件都添加到 add_executable 函数的参数中。

1
2
#生成目标,指定依赖的源文件。
add_executable(Run <file.c>)

&emsp;&emsp; <file.c> 为编译生成可执行文件Run时所需的依赖源文件,多个文件时用空白字符分隔。

&emsp;&emsp;若有如下目录结构,则指令为 add_executable(Run main.c file1.c)

1
2
3
4
5
6
.
├── CMakeLists.txt
├── build
├── file1.c
├── file1.h
└── main.c

&emsp;&emsp;更规范的方法可以定义变量,该变量的值为所有源文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#定义源文件变量。
Set(SRC
./main.c
./file1.c
)

#生成目标。
add_executable(Run ${SRC})

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

2.3 更复杂的目录结构

&emsp;&emsp;上面讲到的例子,代码都在根目录中,实际项目开发中稍微复杂点的项目都会有多级目录,IDE中需要添加头文件目录,使用CMake同样也需要给出头文件目录。
&emsp;&emsp;工程目录结构如下。

1
2
3
4
5
6
7
8
9
10
.
├── CMakeLists.txt
├── build
├── dri
│   ├── file1.c
│   ├── file1.h
│   ├── file2.c
│   └── file2.h
└── src
└── main.c

&emsp;&emsp;CMake编译需要正确添加所有依赖的源文件和头文件路径,可以编写以下CMakeLists.txt文件处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#添加头文件路径。
include_directories(
./src
./dri
)

#添加指定目录下的所有源文件存入变量SRC。
aux_source_directory(./dri SRC)
aux_source_directory(./src SRC)

#生成目标。
add_executable(Run ${SRC})

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

&emsp;&emsp; include_directories(<path>) 指令会将 <path> 指定的所有路径添加为头文件包含路径,多个路径时用空白字符分割。当工程具有较多源文件时,一一添加显然过于麻烦,可以使用 aux_source_directory(<path> <variable>) 函数将源文件路径下的所有源文件添加到变量中,这样就不需要每次创建一个源文件就修改一次CMakeLists.txt。

&emsp;&emsp;接着执行以下指令生成可执行文件。

1
make

CMake基础篇(二)——编写CMakeLists

前言:
&emsp;&emsp;CMake的编译规则由开发者指定,通过编写CMakeLists完成规则编写。

1 CMake简介

&emsp;&emsp;CMake是一种跨平台的编译工具,它语法简单,可以输出各种各样的makefile或project文件。CMake用于产生标准的构建档,使得开发者可以在不同的平台用标准的方式构建软件,实现一次编写编译规则,多个平台相同编译。

2 编写CMakeLists

&emsp;&emsp;在工程根目录创建一个名为 CMakeLists.txt 的文件。假设工程根目录结构如下。

&emsp;&emsp;在Ubuntu下终端输入指令 tree 查看目录结构,如果为安装过tree,需要先执行指令 sudo apt-get install tree 进行安装。

1
2
3
.
├── CMakeLists.txt
└── main.c

&emsp;&emsp;main.c文件内容如下:

1
2
3
4
5
6
7
8
#include <stdio.h>

int main(void)
{
printf("Hello World!\n");

return 0u;
}

&emsp;&emsp;对此,要将main.c编译为可执行文件可在CMakeLists.txt中编写如下编译规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#生成目标。
add_executable(Run main.c)

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

&emsp;&emsp;上面的代码指定了c编译器为 clang ,c++编译器为 clang++ 。在Ubuntu中需要安装clang,执行以下指令安装。

1
sudo apt-get install clang

&emsp;&emsp;也可以指定GCC编译,则CMakeLists.txt需要做以下修改。

1
2
3
4
#指定c编译器为gcc。
Set(CMAKE_C_COMPILER "/usr/bin/gcc")
#指定c++编译器为g++。
Set(CMAKE_CXX_COMPILER "/usr/bin/g++")

&emsp;&emsp;Ubuntu下需要安装GCC,执行以下指令安装。

1
2
sudo apt-get install gcc
sudo apt-get install g++

&emsp;&emsp; set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 使能产生compile_command.json文件,非必须,根据需要添加这样代码。

&emsp;&emsp;CMakeLists.txt的语法规则非常简单,也是函数调用的形式,命令不区分大小写。函数参数之间使用空白字符分割(注意:不是 , )。CMakeLists的行注释标识符为 #

  • cmake_minimum_required(VERSION 3.0): 限制了执行CMakeLists配置文件时所需的CMake最低版本要求;
  • project(Proj): 指定所编译工程的项目名;
  • add_executable(Run main.c): 指定编译输出的可执行文件名(Run),并且指定编译所以来的源文件(main.c)。

2 CMake编译

2.1 编译单个源文件

&emsp;&emsp;为了防止CMake编译出来的产物污染工程,我们在根目录下创建一个名为 build 的目录,并在该目录下执行CMake编译指令,这样产物就会生成在这个目录中。
&emsp;&emsp;Ubuntu下在工程根目录执行以下指令创建build目录。

1
mkdir build

&emsp;&emps;此时工程目录结构如下。

1
2
3
4
.
├── CMakeLists.txt
├── build
└── main.c

&emsp;&emsp;通过 cd build 指令进入到build目录中。在build目录下执行以下指令开始CMake编译。

1
cmake <path>

&emsp;&emsp; <path> 为CMakeLists.txt的目录路径,可以写相对路径,按上面的工程目录结构指令应该为 cmake .... 表示上一级目录。

cmake.png

&emsp;&emsp;接着执行以下指令生成可执行文件。

1
make

make.png

2.2 编译多个源文件

&emsp;&emsp;当工程有多个源文件时,只需将相关的源文件都添加到 add_executable 函数的参数中。

1
2
#生成目标,指定依赖的源文件。
add_executable(Run <file.c>)

&emsp;&emsp; <file.c> 为编译生成可执行文件Run时所需的依赖源文件,多个文件时用空白字符分隔。

&emsp;&emsp;若有如下目录结构,则指令为 add_executable(Run main.c file1.c)

1
2
3
4
5
6
.
├── CMakeLists.txt
├── build
├── file1.c
├── file1.h
└── main.c

&emsp;&emsp;更规范的方法可以定义变量,该变量的值为所有源文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#定义源文件变量。
Set(SRC
./main.c
./file1.c
)

#生成目标。
add_executable(Run ${SRC})

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

2.3 更复杂的目录结构

&emsp;&emsp;上面讲到的例子,代码都在根目录中,实际项目开发中稍微复杂点的项目都会有多级目录,IDE中需要添加头文件目录,使用CMake同样也需要给出头文件目录。
&emsp;&emsp;工程目录结构如下。

1
2
3
4
5
6
7
8
9
10
.
├── CMakeLists.txt
├── build
├── dri
│   ├── file1.c
│   ├── file1.h
│   ├── file2.c
│   └── file2.h
└── src
└── main.c

&emsp;&emsp;CMake编译需要正确添加所有依赖的源文件和头文件路径,可以编写以下CMakeLists.txt文件处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#添加头文件路径。
include_directories(
./src
./dri
)

#添加指定目录下的所有源文件存入变量SRC。
aux_source_directory(./dri SRC)
aux_source_directory(./src SRC)

#生成目标。
add_executable(Run ${SRC})

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

&emsp;&emsp; include_directories(<path>) 指令会将 <path> 指定的所有路径添加为头文件包含路径,多个路径时用空白字符分割。当工程具有较多源文件时,一一添加显然过于麻烦,可以使用 aux_source_directory(<path> <variable>) 函数将源文件路径下的所有源文件添加到变量中,这样就不需要每次创建一个源文件就修改一次CMakeLists.txt。

2.2 编译多个源文件

&emsp;&emsp;当工程有多个源文件时,只需将相关的源文件都添加到 add_executable 函数的参数中。

1
2
#生成目标,指定依赖的源文件。
add_executable(Run <file.c>)

&emsp;&emsp; <file.c> 为编译生成可执行文件Run时所需的依赖源文件,多个文件时用空白字符分隔。

&emsp;&emsp;若有如下目录结构,则指令为 add_executable(Run main.c file1.c)

1
2
3
4
5
6
.
├── CMakeLists.txt
├── build
├── file1.c
├── file1.h
└── main.c

&emsp;&emsp;更规范的方法可以定义变量,该变量的值为所有源文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#定义源文件变量。
Set(SRC
./main.c
./file1.c
)

#生成目标。
add_executable(Run ${SRC})

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

2.3 更复杂的目录结构

&emsp;&emsp;上面讲到的例子,代码都在根目录中,实际项目开发中稍微复杂点的项目都会有多级目录,IDE中需要添加头文件目录,使用CMake同样也需要给出头文件目录。
&emsp;&emsp;工程目录结构如下。

1
2
3
4
5
6
7
8
9
10
.
├── CMakeLists.txt
├── build
├── dri
│   ├── file1.c
│   ├── file1.h
│   ├── file2.c
│   └── file2.h
└── src
└── main.c

&emsp;&emsp;CMake编译需要正确添加所有依赖的源文件和头文件路径,可以编写以下CMakeLists.txt文件处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#CMake最低版本。
cmake_minimum_required(VERSION 3.0)

#指定c编译器为clang。
Set(CMAKE_C_COMPILER "/usr/bin/clang")
#指定c++编译器为clang++。
Set(CMAKE_CXX_COMPILER "/usr/bin/clang++")

#项目名。
project(Proj)

#添加头文件路径。
include_directories(
./src
./dri
)

#添加指定目录下的所有源文件存入变量SRC。
aux_source_directory(./dri SRC)
aux_source_directory(./src SRC)

#生成目标。
add_executable(Run ${SRC})

#使能生成compile_command.json文件。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

&emsp;&emsp; include_directories(<path>) 指令会将 <path> 指定的所有路径添加为头文件包含路径,多个路径时用空白字符分割。当工程具有较多源文件时,一一添加显然过于麻烦,可以使用 aux_source_directory(<path> <variable>) 函数将源文件路径下的所有源文件添加到变量中,这样就不需要每次创建一个源文件就修改一次CMakeLists.txt。