本文介绍了常用的VSCode+CMake编译场景:

① 无层级场景:只有源文件,且在同级目录下;

② 父子级情景:父子级项目,按照父子级依赖关系进行编译;

③ include、src多层级情景:头文件、源文件分别位于include、src目录下,最常用的场景;

④ 编译成库(动态库、静态库):导出库,大型合作项目场景。

四个场景看起来是由简到繁,但本质上都是一回事,容我慢慢道来。

【注意:在操作前需要安装并配置好VSCode、C++、CMake、MinGW环境。如何检查CMake,MinGW是否配置成功:(TODO:欢迎催更(#^.^#))】

一、无层级的简单情形

① 创建工作区:(VSCode_WorkSpace,建议工作区不要出现中文,使用全英文路径),构建Example项目,项目仅包含两个.cpp文件。提前创建好CMakeLists.txt文件(大小写也要一致)和build文件夹。

firstMain.cpp功能:打印"first main"。

secondMain.cpp功能:打印"second main"。

② 进入CMakeLists.txt,输入下图中的内容:

  1. cmake_minimum_required用于限定允许的最低cmake版本为3.16;
  2. PROJECT(项目名称 项目版本  LANGUAGES 编程语言):项目名称、项目版本都可以自己定义,编程语言使用C++(CXX);
  3. 第3行的SET,设置了C++的编译标准,这里设置为C++11;
  4. 第4行的SET,ON表示强制使用第3行的编译标准;
  5. 第6、7行设置了一个小细节:可以注意到firstMain和secondMain中均包含main函数,这在单个C++项目中是不被允许的,于是cmake提供了下图中的办法,分别将两个cpp编译进不同的项目中,分别生成2个exe文件。add_executable(生成的exe文件名 源文件)

③ 准备工作已做好,接下来开始初始化项目。

在左侧工作区右键build文件夹,在集成终端中打开

集成终端中输入:

cmake -G 'MinGW Makefiles' ..

使用MinGW编译器初始化成功:

④ 编译。

 集成终端中输入:

cmake --build .

可以看到编译了两个exe文件。

⑤ 运行exe验证。

在build目录下可以看到firstMain.exe,second.exe两个可执行文件,分别在集成终端中打开。

在终端中依次输入:

.\firstMain.exe
.\secondMain.exe

可以看到两个项目都正常执行。

二、父子级项目情形

父子级项目具有两层结构,父级项目下可以存在多个子集项目

① 本文设定PExample(Parent Example)为父级项目,包含两个子级项目C1、C2。根据特点建立下图层级。

先别问为什么,把下面的文件都建起来,后面一个个解释。

C1的源文件功能:打印"C1 main"。

C2的源文件功能:打印"C2 main"。

可以看到,两个子项目也都包含main函数。不过根据第一节的讨论我们知道包含多个main函数的情形是可以解决的,不慌,我们继续。

② 配置CMakeLists.txt。可以注意到,PExample、C1、C2路径下各有一个CMakeLists.txt,C1和C2路径下的txt分别用于创建各自的exe,PEample路径下的txt用于设置子项目C1、C2与父项目的连接关系。

首先来配置PExample:

  1. 第1~4行不用变;
  2. 第7、8行用于设置子项目。

再来配置C1、C2:

只需添加add_executable,指定生成的exe即可。

初始化:

编译:

分别生成两个exe文件。

编译完成后,build目录下生成C1、C2两个文件夹,各文件夹下均有1个exe文件。

⑤ 运行exe验证。

与第一章操作一致,略。

三、include、src多层级情形

多层级情景,将头文件和源文件分别放在include和src路径下,且允许出现更深层级的子目录(如本节中的otherCal),很灵活。

创建MExample(Multiple Example)为多层级项目,建立下图层级

注意层级关系:

MExample

        -build

        -include

                cal.h

                -otherCal

                        otherCal.h

        -src

                main.cpp

                cal.cpp

                -otherCal

                        otherCal.cpp

        CMakeLists.txt

建立头文件、源文件

cal.h包含add函数声明:

#include <iostream>
using namespace std;

int add(int a, int b);

otherCal.h包含sub函数声明:

int sub(int a, int b);

cal.cpp包含add函数声明:

#include "cal.h"
int add(int a, int b)
{
    return(a+b);
}

otherCal.cpp包含sub函数实现:

【注意:-otherCal属于-include的子目录,在引用时,需带上 "otherCal/otherCal.h"】

#include "otherCal/otherCal.h"

int sub(int a,int b)
{
    return (a-b);
}

main.cpp打印函数结果:

#include "cal.h"
#include "otherCal/otherCal.h"

int main()
{
    cout << add(1,2) << endl;
    cout << sub(4,2) << endl;
    return 0;
}

配置CMakeLists.txt

为在编译时让编译器知道我们项目下包含头文件和源文件,加上:

# 指定源文件来源于src目录下的所有.cpp文件:
file(GLOB_RECURSE SRC_LIST src/*.cpp)

# 指定MExample项目以PRIVATE权限引用include目录下的头文件
target_include_directories(MExample PRIVATE include)

添加message()打印SRC_LIST,查看是否完整包含-src目录下的所有.cpp文件,完整CMakeLists如下:

cmake_minimum_required(VERSION 3.16)
PROJECT(Example VERSION 1.0 LANGUAGES CXX)
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)

# aux_source_directory只能找到单一层级的源文件
# aux_source_directory(src/ SRC_LIST)
# message(STATUS "${SRC_LIST}")

file(GLOB_RECURSE SRC_LIST src/*.cpp)
message(STATUS "${SRC_LIST}")
message(STATUS "${SRC_LIST}")
message(STATUS "${SRC_LIST}")

add_executable(MExample ${SRC_LIST})
target_include_directories(MExample PRIVATE include)

④ 初始化:略。

⑤ 编译:略。

⑥ 运行exe验证:略。

四、生成动态库、静态库情形(TODO)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐