使用VS Code进行完整项目开发
参考链接: link
一、合理设置项目目录
案例:士兵突击 需求: 1.士兵有一把枪 2.士兵可以开火 3.士兵可以给枪装填子弹 4.枪能够发射子弹 5.枪能够装填子弹—“增加子弹数量” 开发: 开发枪类 开发士兵类 提取到的两个类的属性和动作如下图:
二、编写项目源文件
新建文件夹 vscode_c_learning_3,在终端用输入code . 用 vscode 打开新建的文件夹vscode_c_learning_3。 然后在该文件夹下创建清晰明了的目录结构 然后编写每个文件,如下:
#pragma once
#include <string>
class Gun
{
public:
Gun();
~Gun();
Gun(std::string type)
{
this->_bullet_count = 0;
this->_type = type;
}
void addBullet(int bullet_number);
bool shoot();
private:
int _bullet_count;
std::string _type;
};
#include "Gun.h"
#include <iostream>
Gun::Gun()
{
}
Gun::~Gun()
{
}
void Gun::addBullet(int bullet_number)
{
this->_bullet_count += bullet_number;
}
bool Gun::shoot()
{
if (this->_bullet_count <= 0)
{
std::cout << "There is no bullet!" << std::endl;
return false;
}
this->_bullet_count -= 1;
std::cout << "shoot successfully!" << std::endl;
return true;
}
#pragma once
#include <string>
#include "Gun.h"
class Solider
{
public:
Solider();
Solider(std::string name)
{
this->_name = name;
this->_ptr_gun = NULL;
}
~Solider();
void addGun(Gun *ptr_gun);
void addBulletToGun(int num);
bool fire();
private:
std::string _name;
Gun *_ptr_gun;
};
#include "Solider.h"
Solider::Solider()
{
}
void Solider::addGun(Gun *ptr_gun)
{
this->_ptr_gun = ptr_gun;
}
void Solider::addBulletToGun(int num)
{
this->_ptr_gun->addBullet(num);
}
bool Solider::fire()
{
return this->_ptr_gun->shoot();
}
Solider::~Solider()
{
if(this->_ptr_gun == NULL)
{
return;
}
delete this->_ptr_gun;
this->_ptr_gun = NULL;
}
#include "Solider.h"
#include "Gun.h"
void test()
{
Solider sanduo("xusanduo");
sanduo.addGun(new Gun("AK47"));
sanduo.addBulletToGun(20);
sanduo.fire();
}
int main()
{
test();
return 0;
}
三、编译工程
3.1 使用 g++ 命令进行编译
利用快捷键 Ctrl + ` 打开终端,输入 ls 查看文件夹的文件情况;输入 tree . 来查看文件结构。 首先,通过在终端使用 g++ 直接编译:
g++ main.cpp src/Gun.cpp src/Solider.cpp -Iinclude -o myexe
编译成功后生成 myexe 可执行文件,运行 ./myexe 可以看到输出结果:shoot successfully! 也可以在 g++ 命令后面加上一些参数:
g++ main.cpp src/Gun.cpp src/Solider.cpp -Iinclude -o myexe -Wall -g -o2
3.2 使用 cmake 进行编译
首先,开始编写 CMakeLists.txt 文件:
cmake_minimum_required(VERSION 3.0)
project(SOLIDERFIRE)
#在g++编译时,添加编译参数,比如-Wall可以输出一些警告信息
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 -Wall")
#添加头文件
include_directories(include)
#或者通过绝对路径来进行添加,include_directories(${CMAKE_SOURCE_DIR}/include)
#其中${CMAKE_SOURCE_DIR}就是VSCODE_C_LEARNING_3这个文件夹的绝对路径
add_executable(my_cmake_exe main.cpp src/Gun.cpp src/Solider.cpp)
编译完成后,在终端完成编译:
mkdir build
cd build
cmake ..
make
这时如果更改以下main.cpp,然后在终端重新输入 make 命令重新编译,此时可以看到系统只会对更改的文件进行重新编译,这对于一个大型工程来说是非常节约时间的。
四、配置VS Code的 json 文件并调试项目
接下来对工程进行调试。调试时要进行launch.json和tasks.json的编写 然后选择第一个 C++(GDB/LLDB),然后选择第一个 g++:生成和调试活动文件, 可以得到如下 launch.json 模板:
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request":"launch",
"program":"${fileDirname}/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启动整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ build active file",
"miDebuggerPath": "/usr/bin/gdb"
}
]
}
其中最重要的是: 1.“program”:代表了要调试的可执行文件的绝对路径,2.“preLaunchTask”:指的是在调试之前要做一个task 因此,需要对这两个参数进行更改,编写 launch.json文件, 其中"cwd": "
w
o
r
k
s
p
a
c
e
F
o
l
d
e
r
"
中
"
{workspaceFolder}"中"
workspaceFolder"中"{workspaceFolder}"代表当前工程文件夹的顶层目录, 然后先将"preLaunchTask"注释掉,不进行更改
"program":"${workspaceFolder}/build/my_cmake_exe",
更改完的 launch.json 文件:
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request":"launch",
"program":"${workspaceFolder}/build/my_cmake_exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启动整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"miDebuggerPath": "/usr/bin/gdb"
}
]
}
然后到目前为止就可以进行调试工作了。 打开终端,在 build 文件夹下重新 make 下,然后在 main.cpp中打个端点,利用快捷键 F5 进行调试。 可以看出,成功命中断点。 在单步调试中发现有时会单步进入不了,可能是由于编译时set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -g -O2 -Wall”)中 -g 和 -O2 发生冲突导致。因此将这两个删除,然后再加一句,更改完的 CMakeLists.txt 如下:
cmake_minimum_required(VERSION 3.0)
project(SOLIDERFIRE)
#在g++编译时,添加编译参数,比如-Wall可以输出一些警告信息
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
#一定要加上这句话,加上这个生成的可执行文件才是可以Debug的,不然不加或者是Release的话生成的可执行文件是无法进行调试的
set(CMAKE_BUILD_TYPE Debug)
#添加头文件
include_directories(include)
#或者通过绝对路径来进行添加,include_directories(${CMAKE_SOURCE_DIR}/include)
#其中${CMAKE_SOURCE_DIR}就是VSCODE_C_LEARNING_3这个文件夹的绝对路径
add_executable(my_cmake_exe main.cpp src/Gun.cpp src/Solider.cpp)
重新 make,然后再调试。这时 Debug 功能正常,但不进入功能也正常了。这时为什么尼? 因为原来 CMakeLists.txt 中有个 -O2 的选项,这个选项会帮助优化代码,这会导致在调试过程中出现意料不到的效果。 接着,打开 launch.json 文件中的 “preLaunchTask”。
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request":"launch",
"program":"${workspaceFolder}/build/my_cmake_exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启动整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++ build active file",
"miDebuggerPath": "/usr/bin/gdb"
}
]
}
然后要配置 tasks.launch。点击 选项栏 Terminal->Configure Default Build Task,然后随便选择一个,建立一个 task.json 文件。 将 tasks.json 文件中内容删除,替换为下面的内容:
{
"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"
]
}
]
}
然后要在 launch.json文件中改一下 “preLaunchTask” 指明的名字,从 tasks.json 中可以看出,最后一个 label 叫做 “Build”, 因此将launch.json文件中 “preLaunchTask” 指明的名字改为 “Build”。
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request":"launch",
"program":"${workspaceFolder}/build/my_cmake_exe",
"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"
}
]
}
至此,launch.json 和 tasks.json 全部配置完成。至此,就可以完成自动化的调试了。 举例: 比如在 main.cpp 中随便加一句: 然后,在下一句处打断点,F5运行,发现直接调到断点处且这句输出直接打印出来。 这说明在修改工程文件后再也不用手动编译后再调试,而是直接对工程修改后直接打断点进行调试。系统会自动进行编译和调试。(就是通过launch.json中的 "preLaunchTask"完成的,而这个就是 tasks.json 完成的) 详情如下图所示: 总结:在一个工程中要建两个 json 文件,一个是 launch.json 文件, 一个是 tasks.json 文件。 launch.json 的模板如下:
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request":"launch",
"program":"${workspaceFolder}/build/my_cmake_exe",
"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"
}
]
}
需要更改 “program” 和 “preLaunchTask”。 tasks.json 的模板如下:
{
"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"
]
}
]
}
其中最后一个 label 的名字要和 launch.json 中 “preLaunchTask” 的名字一致。
|