记录用VS Code调试C/C++程序的基本流程,加深对工程构建、编译链接的理解。我自己目前的体会是不适合在实际工程中使用,除非对makefile工程构建、C/C++相关的工具链有深刻的认识,否则很难驾驭。
按照《参考1》搭建VS Code C/C++调试环境,大致的流程如下,
注意,微软的C/C++插件并不包含C++编译器和调试器,这些需要自己安装,比较常用的C++编译器有Windows下的mingw-w64、macOS下的Clang for XCode和linux下的GCC,Windows需要把工具链的安装地址添加至环境变量PATH里。
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "",
"compilerPath": "C:\\MinGW\\bin\\gcc.exe",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}
{
"version": "2.0.0",
"tasks": [
{
"label": "build hello world",
"type": "shell",
"command": "g++",
"args": [
"-g", "helloworld.cpp"
]
}
]
}
如果你想通过菜单[任务]->[运行生成任务...]或快捷键(Ctrl+shift+B)build代码,需要在刚才的文件tasks.json添加组build,如下,这样就可以build代码生成可执行的文件了:
{
"version": "2.0.0",
"tasks": [
{
"label": "build hello world",
"type": "shell",
"command": "g++",
"args": [
"-g", "helloworld.cpp"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/a.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "C:\\mingw\\bin\\gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build hello world"
}
]
}
至此,点击左侧工具栏的调试图标,再点击绿色的运行图标,就能build代码->调试程序了,这时,在终端已经可以看到“hello world”了!
没有实践的理论就是空中楼阁。
#include
int main(int argc, char const *argv[])
{
printf("hello world!\n");
printf("hello world!\n");
getchar();
return 0;
}
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/clang++-3.5",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}
需要关注的有两项,"includePath"为包含文件的目录,根据源码结构自行设置,由于该源码就一个hello.cpp文件,不用设置,默认的即可;"compilerPath"为编译器的目录,根据需要修改
{
"version": "2.0.0",
"tasks": [
{
"label": "build hello", // 起个自己喜欢的名字
"type": "shell",
"command": "g++", // 编译的命令
"args": [ // 编译命令的参数,会不会下就看会不会这些编译命令的使用了
"-g", "ex.cpp", "-o", "qb.out"
],
// 以上是以Others为模板的Build任务配置文件tasks.json的内容
// 菜单[Tasks]->[Run Build Task...],还是提示在build hello工程里没有build任务,按提示配置即生成如下配置内容
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
g++ -g ex.cpp -o qb.out
这时可以在目录下发现生成的目标文件qb.out
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/qb.out", // 输出文件
"args": [],
"stopAtEntry": false, // 开始调试时,是否停在程序入口
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb", // 调试命令
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
// 以下是另添加,作用是调试前的的任务,下面定义的是之前定义的那个build任务
"preLaunchTask": "build hello"
}
]
}
VS Code 配合 Makefile 来提高 C/C++ 工程的可移植性,这个方案的思路是:使用 Makefile 来构建工程, VS Code 通过 Tasks 调用 make 工具来编译,通过调用 gdb 来调试。其优点在于不是过分依赖 VS Code 自身的配置,一个合适的 Makefile 可以在各个平台上执行编译,但是在开发过程中又可以用到 VS Code 自身的插件带来的便利,减少命令输入,减少命令行 gdb 调试带来的烦恼。
# originating https://github.com/TheNetAdmin/Makefile-Templates
# tool marcros
CC := g++
CCFLAG := -std=c++14
DBGFLAG := -g
CCOBJFLAG := $(CCFLAG) -c
# path marcros
BIN_PATH := bin
OBJ_PATH := obj
SRC_PATH := src
DBG_PATH := debug
# compile marcros
TARGET_NAME := main
ifeq ($(OS),Windows_NT)
TARGET_NAME := $(addsuffix .exe,$(TARGET_NAME))
endif
TARGET := $(BIN_PATH)/$(TARGET_NAME)
TARGET_DEBUG := $(DBG_PATH)/$(TARGET_NAME)
MAIN_SRC := src/main.cpp
# src files & obj files
SRC := $(foreach x, $(SRC_PATH), $(wildcard $(addprefix $(x)/*,.c*)))
OBJ := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
OBJ_DEBUG := $(addprefix $(DBG_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
# clean files list
DISTCLEAN_LIST := $(OBJ) \
$(OBJ_DEBUG)
CLEAN_LIST := $(TARGET) \
$(TARGET_DEBUG) \
$(DISTCLEAN_LIST)
# default rule
default: all
# non-phony targets
$(TARGET): $(OBJ)
$(CC) $(CCFLAG) -o $@ $?
$(OBJ_PATH)/%.o: $(SRC_PATH)/%.c*
$(CC) $(CCOBJFLAG) -o $@ $<
$(DBG_PATH)/%.o: $(SRC_PATH)/%.c*
$(CC) $(CCOBJFLAG) $(DBGFLAG) -o $@ $<
$(TARGET_DEBUG): $(OBJ_DEBUG)
$(CC) $(CCFLAG) $(DBGFLAG) $? -o $@
# phony rules
.PHONY: all
all: $(TARGET)
.PHONY: debug
debug: $(TARGET_DEBUG)
.PHONY: clean
clean:
@echo CLEAN $(CLEAN_LIST)
@rm -f $(CLEAN_LIST)
.PHONY: distclean
distclean:
@echo CLEAN $(CLEAN_LIST)
@rm -f $(DISTCLEAN_LIST)
- Project
- Makefile
- src: 所有源文件 (不得放在子目录)
- add.cpp
- add.h
- sub.cpp
- sub.h
- main.cpp
- obj
- 空
- debug
- 空
- bin
- 空
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "make",
"args": [
"default"
],
"type": "shell"
},
{
"label": "build-debug",
"command": "make",
"args": [
"debug"
],
"type": "shell"
},
{
"label": "clean",
"command": "make",
"args": [
"clean"
],
"type": "shell"
}
]
}
文件launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
// 修改为新的测试目标文件路径
"program": "${workspaceRoot}/debug/main",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
//"miDebuggerPath": "gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build-debug"
}
]
}
到此可以按上节的步骤使用编译和调试工具了。
参考使用VSCode和VS2017编译调试STM32程序,能下载运行,不能正常调试。
也许是JLINK不是正版造成的,也许是哪没设置正确,以后再整。