一、解释为什么用CMake

        一般而已,一个Cpp项目我们都不是直接用g++编译器去编译的。因为这样干不通用,而且遇到稍微大型点的项目手写g++命令行是件很复杂的事情。

        因此,我们必须要手写CMakeLists.txt去再使用cmake命令来生成对应的MakeFile来帮助我们编译源文件和链接头文件进而再用make命令产生可执行文件。

        注意①:当然,cmake的底层还是帮我们使用gcc + -lstdc++ 或者 g++来做编译链接工作的!

        注意②:CMakeLists.txt用写好之后,用cmake命令生成一次makefile即可。后面若你还修改了.h头文件或者.cpp源文件的话,可以直接在linux终端下用make命令生成新的可执行文件即可!

这样的一个好处就是,当你的Cpp项目很大时,有几百上千个.cpp源文件和.h头文件,若你只修改了某个.cpp or .h头文件的话,就不需要再使用g++重新编译链接了,这样会耗费大量的时间,改一次就得重新build一次,效率可太低了!你只需要再用make命令去生成对应的新的可执行文件即可!哪儿改了就从哪儿重新编译而已!

比如:

//xusanduo.cpp中的代码:

Xusanduo::~Xusanduo(){
    cout<<"hhhwolail!"<<endl;
}
//变成
Xusanduo::~Xusanduo(){
    cout<<"hhh"<<endl;
}

二、介绍写CMakeLists.txt的一般格式:

cmake_minimum_required(VERSION X.X.X) #指定项目使用的cmake的最低要求的版本
#在linux终端下可用 cmake --version来查看对应当前系统下的cmake版本

project(Project_Name) #生成的项目的名字(英文)这个一般你自定义即可!

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall ") #这行代码是给
#项目程序如果是为了进行调试而编译时, 必须要打开调试选项 (-g)。另外还有一些可选项,比如:在尽量不


#-g 选项的作用:是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几
#行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证 gdb 能找到源文件。

#-o2 选项的作用:开启优化代码的选项(一般不要加这个选项,因为不利于debug调试)

#-o0 选项的作用:当影响程序运行的行为的情况下,关掉编译器的优化选项

#-Wall 选项的作用:打开所有 warning,即可以发现许多警告问题,避免一些不必要的 bug。

include_directories(${CMAKE_SOURCE_DIR}/include) # or include_directories(./include)

#这行命令代码用来包含头文件
#()里面是添加能找到include这个文件在你的linux系统下的相对路径/绝对路径
#当然,我用${CMAKE_SOURCE_DIR}这个变量来写就代表是取include文件夹的绝对路径
#当然,左边这种是万能写法!写左边的include_directories(${CMAKE_SOURCE_DIR}/include)比较稳妥!


#一般而言,我们都把头文件都放在一个叫include的文件夹中 然后用这个cmake命令include进项目
#且一般我们都把源文件放在一个叫src的文件夹中,把头文件放在一个叫include的文件夹中
#创建一个叫build的文件夹,把生成的关于makefile相关的all文件都放在里面
#并在$ ...XXX/build的目录下 用命令行:$cmake .. 来生成对应的makefile文件
#            用命令行:$make 生成可执行文件,这样你的程序就可以运行了!
#(因为我们一般都是把CMakeLists.txt、include、src、build这4东西放在同级目录下)
#. or ./ 表示当前本级目录
#.. or ../ 表示当前本级的上一级目录
#这样这行命令可以直接写为include_directories( ./include) or include_directories(include)
#这就是写Cpp项目的一般代码管理规范

set(CMAKE_BUILD_TYPE Debug)
#设置编译类型为 Debug,当你的程序要发布出去时,可以改Debug为Release


add_executable(Project_Exe_Name main.cpp src/X1.cpp src/X2.cpp ... src/Xn.cpp)
#这行命令代码用来将源文件生成可执行文件
# ==> g++ main.cpp src/X1.cpp src/X2.cpp ... src/Xn.cpp -o Project_Exe_Name 

无注释版CMakeLists.txt一般必写的几行命令代码:(写一般项目都可以直接套用)

cmake_minimum_required(VERSION X.X.X)

project(Project_Name)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall") 

set(CMAKE_BUILD_TYPE Debug)

include_directories(${CMAKE_SOURCE_DIR}/include)

add_executable(Project_Exe_Name main.cpp src/X1.cpp src/X2.cpp ... src/Xn.cpp)

具体例子:

(案例的代码在我的这篇博客中):为多态基类定义纯虚析构函数时必须给其一个空实现代码

当前的CMakeLists.txt: 

cmake_minimum_required(VERSION 3.0.0)

project(SOLDIER_TUJI)

set(CMAKE_BUILD_TYPE Debug)

include_directories(${CMAKE_SOURCE_DIR}/include)

add_executable(TUJI_cmake main.cpp src/gun.cpp src/soldier.cpp src/xusanduo.cpp)

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!        

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!

        注意:不论是在windows下还是在linux下,当你按照我上述说的文件目录方式来组织文件后,一定要在build这个文件夹下去做cmake ..和make命令!!!

重要的事情说8遍!!!

        执行cmake命令后:

         执行make命令后:

(make是linux下的编译命令。如果你是在windows下使用vscode编译cpp文件的话,就在终端用mingw32-make.exe命令来do即可)

        经过make后,成功built目标可执行文件 TUJI_cmake!

        执行TUJI_cmake这个可执行文件:

添加了这行cmake命令前,再main.cpp中添加测试代码:

int main(void){
    int a{1};//test codes
    //...
    return 0;
}

添加了set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -o2") 这行cmake命令后:

当前的CMakeLists.txt:

cmake_minimum_required(VERSION 3.0.0)

project(SOLDIER_TUJI)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall") 

set(CMAKE_BUILD_TYPE Debug)

include_directories(${CMAKE_SOURCE_DIR}/include)

add_executable(TUJI_cmake main.cpp src/gun.cpp src/soldier.cpp src/xusanduo.cpp)

终端命令执行结果: 

 会提示我们,a这个int型变量根本就没有使用过!这很利于我们发现项目代码中的问题!

(若你再CMakeLists.txt中不加-Wall选项来do编译的话根本就不会显示出来这个warning的信息!)

三、介绍写json调试配置文件的一般格式:

        在写cpp项目时,除了要写CMakeLists.txt来帮助我们生成makefile文件以供我们make编译外,还需要添加2份便于调试的json文件,分别是launch.json和tasks.jason。这2个文件也是我们使用Vscode时最容易被卡住的配置文件!但是这2个文件对于你项目的debug来说非常重要!!!

        注意:json文件再Vscode中默认是会给你自动放在一个叫做.vscode的文件夹中的!

        注意:其实配置好launch.json文件就可以在linux下的vscode中按F5进行调试程序了,但是如果你想要在调试时边改动代码边按F5进行调试的话,就必须要配置好tasks.json文件! (抄着写即可)

①lauch.json(use for debug):

lauch.json中最为关键的2行代码就是:(配置lauch.json时着重关注这2条)

"program":...
"preLaunchTask":...

launch文件一般只需要改动2个地方:

        ①"program": "${workspaceFolder}/build/你的项目名称.exe",改成你的项目的名称

        "miDebuggerPath": "/usr/bin/gdb"这个gdb调试器文件目录一般是不用改的。因为你在linux下用命令行安装gdb时默认是装在这里的。

下面我直接给出一般写法(带注释版本):

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 启动",
            "type": "cppdbg",
            "request": "launch",
            //fill the absolutely path of your project
            "program": "${workspaceFolder}/build/main_cmake",
            //注释:
            //这行代码是写上你的项目经过cmake和make后生成的可执行文件的绝对路径
            //如果你按照我上述所说的创建和管理Cpp项目的一般规则,可知道
            //我们一般都是使用外部构建cmake的方式来编译项目文件的
            //也即创建一个叫做build的文件夹来存放cmake和make后产生的all文件
            //(这其中就包括make后产生的你这个项目的可执行文件)
            //这样你就可以直接在"program"这里写上"${workspaceFolder}/build/项目可执行文件名"

            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask":"Build",
            //在你调试debug前帮你自动build!lauch前先取执行label == Build的tasks任务!
            //这样你就不需要每次debug改动代码时再执行一次make命令就能看到debug效果了!
            //因为此时你配置好的launch和tasks这2个json文件可以帮你调试时自动编译一次代码
            //(if你在调试代码时有修改的话)
            "miDebuggerPath": "/usr/bin/gdb"
            //这个gdb调试器文件目录一般是不用改的
            //因为你在linux下用命令行安装gdb时默认是装在这里的
        }
    ]
}

一般写法(不带注释版本):(写一般项目都可以直接套用)

{ 
   "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 启动",
            "type": "cppdbg",
            "request": "launch",
            //fill the absolutely path of your project
            "program": "${workspaceFolder}/build/your_project_exe_name",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask":"Build",
            "miDebuggerPath": "/usr/bin/gdb"
        }
    ]
}

②tasks.json(use for build before debug):

        一般无需改动,直接copy来用即可,只要你按照我这篇博客中说的项目文件目录的设置规则

        有了tasks.json文件后,你就不需要在每一次调试改动了代码时都手动输入make命令再编译你最新的cpp文件生成最新的可执行文件了,这样就非常方便你去do调试的工作了!

下面我直接给出一般写法(带注释版本):

{    
    "version": "2.0.0",
        "options": {
            "cwd": "${workspaceFolder}/build"//这里写的是build文件的绝对路径
             //只要你按照我上述所说的管理Cpp文件的一般规则,这里直接这样写就行!
            //意思是:当前你的项目文件夹下的build文件夹的路径
        },
        "tasks": [
            {
                "type": "shell",
                "label": "cmake",
                "command": "cmake",
                "args": [
                    ".."
                ],
            },
            {
                "label": "make",
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "command": "make",
                "args": [
    
                ],
            },
            {
                "label": "Build",
                //这里的Build文件与lauch.json文件中的"preLaunchTask":"Build" 中的
                //这个Build是指的一个Build文件夹!
                "dependsOrder": "sequence",//按照一列来执行
                "dependsOn":[
                    "cmake",
                    "make"
                ]
            }
        ],
    
    }

一般写法(不带注释版本):(写一般项目都可以直接套用)

{ 
       "version": "2.0.0",
        "options": {
            "cwd": "${workspaceFolder}/build"
        },
        "tasks": [
            {
                "type": "shell",
                "label": "cmake",
                "command": "cmake",
                "args": [
                    ".."
                ],
            },
            {
                "label": "make",
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "command": "make",
                "args": [
    
                ],
            },
            {
                "label": "Build",
                "dependsOrder": "sequence",
                "dependsOn":[
                    "cmake",
                    "make"
                ]
            }
        ],
    
    }

        好了,当你的Cpp项目配置好CMakeLists.txt、include、src、build、lauch.json、tasks.json文件之后,就可以方便放心的编译运行和调试你的程序了!

        以上就是我对于写CMakeLists.txt以及json调试配置文件的学习总结,写这篇博客是为了方便自己日后coding时候查漏补缺,希望也对看到这里的读者起到一点点的帮助~

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐