本文最后更新于:4 分钟前
前提
本文主要涉及VSCode的相关配置,编译及调试工具需要提前安装好。
- 已经安装好
riscv-toolchain
,包括riscv64-unknown-elf-gcc
,riscv64-unknown-elf-gdb
- 已经安装好
qemu
,包括riscv32-softmmu,riscv32-linux-user,riscv64-softmmu,riscv64-linux-user
- 已经安装好
g++
,gdb
调试流程简介
对于我这样的新手,要调试一个项目源码最怕的就是开始,也就是怎么能把项目跑起来。
我们以一个简单的test
项目,看看在VSCode里怎么跑起来。
拿到源码后,将其以文件夹形式,加入到VSCode中,文件-打开文件夹-选择test项目文件夹
。项目就会在VSCode 中打开,但是此时我们还无法编译运行,我们需要在VSCode上
构建出一个C语言的编译与调试环境。
首先得安装一个插件C/C++
,打开插件中心Ctrl+Shit+X
,搜索,安装。
然后输入F5
,会弹出对话框,选择C++(GDB)
,继续选择g++
。VSCode会自动创建.vscode
文件夹,已经两个文件launch.json
和tasks.json
。
launch.json
用来配置调试环境,tasks.json
主要用来配置编译环境,当然也可以配置其他任务。task.json
里配置的每个任务其实就相当于多开一个控制台。
配置tasks.json
因为我们先要编译源码,生成.out
或者.exe
文件,才能调试,所以先进行编译任务配置。
自动生成的文件是个配置模板,我们可以根据自己的实际情况进行配置,也有一部分可以保持默认。
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
| { "version": "2.0.0", "tasks": [ { "label": "C/C++: g++ build active file", "type": "shell", "command": "g++", "args": [ "'-Wall'", "-g", "'-std=c++17'", "'${file}'", "-o", "'${fileBasenameNoExtension}.exe'", ], } ] }
|
如果项目是通过Makefile编译的,那就更加简单,只需要配置一个任务即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "version": "2.0.0", "tasks": [ { "label": "Make Project", "type": "shell", "command": "make", "args":[ "-j8", ], }, ] }
|
运行该任务时就会执行make
命令进行编译。
配置launch.json
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 27 28 29 30 31 32 33
|
{ "version": "0.2.0", "configurations": [ { "name": "g++ - Build and debug active file", "preLaunchTask": "C/C++: g++ build active file", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ] }] }
|
运行
经过以上配置后,我们打开main.cpp
文件,在cout
处打一个断点,按F5
,即可编译,运行,调试。一定要打开main.cpp
文件,不能随便打开文件就开始哦。因为我们在配置时使用了一些预定义,比如${file}
表示当前文件,所以只有打开需要调试的文件才能开始。
程序将会在cout
语句停下来。
我们可以注意一下界面下方的控制台,可以更直观了解launch.jason
和tasks.jason
。
右边的框,就是我们在tasks.jason
中配置的任务,左边的框就是我们在tasks.jason
中command
以及args
的内容,他就是帮我们提前写好编译的选项。然后在shell中运行。
编译调试RISCV程序
了解以上这些,就可以按需配置所需的环境了。我们还是从tasks.jason
开始。因为开发用的电脑是x86
的,所以先要编译出riscv
的程序,再用模拟器模拟出rsicv
的环境,然后在模拟的环境中运行程序,最后才能开始调试。
假设已经安装好开头所提到的工具。首先配置tasks.jason
:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| { "version": "2.0.0", "tasks": [ { "type": "shell", "label": "C/C++(RISCV): Build active file", "command": "/opt/riscv/bin/riscv64-unknown-elf-g++", "args": [ "-Wall", "-g", "${file}", "-o", "${workspaceFolder}/debug/${fileBasenameNoExtension}" ], "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": [ "$gcc" ] }, { "type": "shell", "label": "Run Qemu Server(RISCV)", "dependsOn": "C/C++(RISCV): Build active file", "command": "qemu-system-riscv64", "args": [ "-g", "65500", "${workspaceFolder}/debug/${fileBasenameNoExtension}" ], }, { "type": "shell", "label": "Kill Qemu Server(RISCV)", "command": "ps -C qemu-riscv64 --no-headers | cut -d \\ -f 1 | xargs kill -9", } ] }
|
tasks.jason
是可以配置多个任务的,第一个任务用来编译成riscv
架构下的程序,第二个任务用来启动qemu,让程序在qemu上运行起来。
第一个任务中,command
就是配置编译器riscv64-unkonown-elf-gcc
的属性,第二个任务中,command
是配置qemu模拟器qemu-system-riscv32
的属性。第三个任务中,用来配置结束qemu模拟器的命令。
接下来配置launch.jason
:
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 27 28
| { "version": "0.2.0", "configurations": [ { "name": "C/C++(RISCV) - Debug Active File", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/debug/${fileBasenameNoExtension}", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "为 gdb 启用整齐打印", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "miDebuggerPath": "/opt/riscv/bin/riscv64-unknown-elf-gdb", "miDebuggerServerAddress": "localhost:65500" } ] }
|
我们在配置x86
下的调试环境时,launch.jason
中有个 "preLaunchTask": "C/C++: g++ build active file"
,属性,这个属性的目的是在启动调试之前,先执行任务名字为"C/C++: g++ build active file"
任务,也是就编译的任务。
因为启动qemu会导致阻塞,所以这里没有加preLaunchTask
,在启动调试之前,先把qemu运行起来。输入Ctrl+Shift+P
,打开VSCode命令行。输入Run Task
,
点击第一个,选择任务,我们可以看到出现的三个任务就是我们在tasks.jason
中配置的三个任务。选择第一个Build,编译出程序,再重复操作,选择第三个执行QEMU任务。
预定义变量
官网