由于平时一直使用Arch Linux环境写代码,但是公司只给用Windows,对Windows MinGW开发环境的场景觉得很不顺手。由于业务是Linux业务,在本地开发无法编译,需要使用远程编译机编译。这种模式使得调试程序只能远端编译后,在远端不使用GDB,而GDB命令行不仅难用还有高昂的学习成本。最近新发现一写远程开发/调试的方案,再次整理出来以应付C++跨平台开发的场景。
创建样例程序
- 本机环境:Windows X64
- 远端环境:Linux(Armbian)aarch64
- 本地IDE: VSCode
创建一个CMake项目用于演示:.
├── build/
├── CMakeLists.txt
├── include/
│ └── Student.h
└── src/
├── main.cpp
└── Student.cpp
基于SSH远程开发
第一种方案就是使用Remote-Develop套件:它包含:
- Remote-SSH 用于SSH链接到远端环境开发/调试
- Remote-Container 用于链接到容器开发/调试
- Remote-WSL 用于链接到WSL开发/调试
远端开发相当把整个工作环境搬到远端,项目在远端,编译调试也在远端,VSCode只充当一个VNC的角色。此时在VSCode上开发就好似拥有了一台本地ARM开发环境一样。
flowchart LR; subgraph Host [Host ARM Enviroment] remote_extension(Remote VSCode Extension) --control--> compiler remote_extension --control--> debugger remote_extension --edit--> project_source compiler(Compiler) --compile--> project_source project_source(Project Source) --> ELF[(Project Release ELF)] debugger(Debugger) --debug---> ELF end subgraph Local [Local] vscode(Local VSCode IDE) end remote_extension <-.SSH.-> vscode
第一步需要添加远端环境,配置IP,用户名,密码
配置完成后将项目上传到远端环境,VSCode打开远端目录。此时项目可以看到提示环境已经切换到远端,编译器已经切换为arm的编译器,项目目录提示这是远端目录。
由于是完全在远端开发,在远端环境需要重新安装项目相关的插件,点击按钮同步本地插件。
配置远端
launch.json
和本地版本无异:{
"configurations": [
{
"name": "Remote Dev",
"request": "launch",
"type": "cppdbg",
"cwd": "${fileDirname}",
"program": "/home/xuranus/workspace/Demo/build/demo",
"args": [],
"stopAtEntry": false,
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "enable pretty print for gdb",
"text": "-enable-pretty-print",
"ignoreFailures": true
}
],
}
]
}
这种开发模式是完全基于远端的,文件全部存在远端,每次修改代码直接在远端修改,网络延迟很大决定了实际的开发体验,建议在网络较好的内网环境下使用。远端开发需要在远端上安装VSCode插件,可能会污染远端环境。
远程编译,Attach调试
还有一种方式就是利用管道程序,Attach远端进程调试。这种方式在本地开发,远端编译,远端运行。与之前不同的是:项目存放在本地。需要将本地文件与远端文件同步,手动编译远端文件,启动远端进程,再Attach远端进程并在本地调试。
flowchart LR; subgraph Local [Local X86 Enviroment] vscode(VSCode IDE) <--> plink plink(plink.exe) end subgraph Remote [Remote ARM Enviroment] compiler(Compiler) --compile --> project_source(Project Source) project_source --> ELF[(Project Release ELF)] debugger(Debugger) --debug--> Process ELF --run--> Process((Process)) end plink <-.SSH.-> Process vscode -.SFTP.-> project_source
首先需要下载一个本地管道程序,它用于SSH链接到远端,Attach一个远端进程,在本地调试远端程序。建议使用Putty的plink作为管道程序。
本地安装SFTP插件。
SFTP是一个用于同步本地和远程目录的基于SSH的插件,首次使用时需要先配置,F1使用SFTP Sync: Local -> Remote
将本地目录上传到远端。之后每次保存文件时,插件都会自动同步该文件。
配置SFTP sftp.json
{
"name": "My Remote ARM Compiler",
"host": "192.168.100.1",
"protocol": "sftp",
"password": "**********",
"port": 22,
"username": "xuranus",
"remotePath": "/home/xuranus/workspace/Demo",
"uploadOnSave": true
}
- 配置
launch.json
其中要注意的是:{
"configurations": [
{
"name": "GDB Remote Attach",
"request": "attach",
"type": "cppdbg",
"processId":"${command:pickRemoteProcess}",
"cwd": "${workspaceFolder}",
"program": "/home/xuranus/workspace/Demo/build/demo",
"args": [],
"stopAtEntry": true,
"sourceFileMap": {
"/home/xuranus/workspace/Demo": "C:\\Users\\XUranus\\Desktop\\Demo"
},
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "enable pretty print for gdb",
"text": "-enable-pretty-print",
"ignoreFailures": true
}
],
"pipeTransport": {
"pipeCwd": "",
"pipeProgram": "C:\\Users\\XUranus\\Downloads\\plink.exe",
"pipeArgs": ["-ssh", "root@192.168.1.6", "-pw", "********"],
"debuggerPath": "/usr/bin/gdb"
}
}
]
}sourceFileMap
配置本地文件目录和远端目录的映射关系,用于打断点processId
配置"${command:pickRemoteProcess}"
,在每次debug时手动选择远端要被Attach的进程request
需要为attach
,意味着附带Debug远端进程
由于每次启动本地plink attach debug必须让远端进程先跑起来才能选择remote的进程号,我解决方案是在程序入口sleep
一段时间,在这个时间段内启动本地plink attach debug。虽然觉得这个方案比较蠢,但是目前没有想到更好的解决办法。