Visual Studio被称为是宇宙最强IDE,以前开发Linux C/C++服务器程序,基本上都是在Windows上使用VS编写跨平台的C/C++代码,然后先在VS中编译、链接、调试,然后在Linux下编译、链接,再针对Linux下的特定代码进行调试。后面VisualGDB的出现,终于有所改变了,参见笔者之前的博文:Windows下开发Linux C/C++项目。
也许是VisualGDB的推波助澜,也许是微软CEO纳德拉的拥抱开源战略,让VS也更加开放,对开发者越来越友好。
以前VS只支持使用微软自己的开发工具进行Windows程序的开发;到VS2008的时候可以安装VisualGDB插件使用GNU的编译套件进行Windows程序的开发也可以通过SSH远程连接到Linux/MacOS系统进行开发;再到VS2017支持火热的CMake系统,可以直接支持SSH远程连接到Linux/MacOS系统进行开发(笔者没用过VS2017、VS2019,直接从VS2015跳到VS2022),到目前的VS2022更是对非微软系的工具(包括GNU的工具和LLVM的工具)支持越来越好,虽然不有不如意的地方,但会越来越好。
以前介绍过VS2022与MinGW的本地开发方式,参见系列博文:
Visual Studio 2022使用MinGW来编译调试C/C++程序
Visual Studio 2022 CMake+MinGW+GDB 调试目标程序
Visual Studio 2022使用CMake+MinGW+Clang+LLDB作为开发环境
本文就介绍一下VS2022使用SSH远程连接到Linux/MacOS进行C/C++的远程开发方式。
本文链接:https://blog.csdn.net/witton/article/details/132297160
一、环境
先介绍一下环境,Windows环境为Win10,VS2022版本为17.7,远程系统为Ubuntu 22.04/CentOS7/MacOS catalina,Linux下又涉及有容器中的Linux。
1.系统准备
关于Linux系统的安装配置,以及相应编译、链接、调试器的安装可以参考博文:
详细安装Ubuntu 21.10
配置与管理Ubuntu 21.10
搭建ubuntu容器内C/C++开发调试环境
如果使用容器,一定要在创建podman
容器时添加参数:--cap-add=SYS_PTRACE
,创建docker
容器时添加参数:--cap-add=SYS_PTRACE --security-opt seccomp=unconfined
,否则不能使用调试器。
如果是SSH远程连接到macOS开发,可以看看博文:
SSH远程连接MacOS catalina并进行终端颜色配置
2.开发套件准备
关于GNU套件以及LLVM套件的安装,如果要使用C++20标准,强烈建议使用源码安装最新版本的GCC和最新版本的Clang,如果觉得系统源中已有的版本够用,就可以不用源码安装,直接使用系统源中的版本安装即可。
VS包括VSCode要使用LLDB
调试器进行源码调试,都必须要有lldb-mi,所以必须要安装lldb-mi
,博文VSCode远程连接Ubuntu使用LLDB调试程序中有介绍lldb-mi
的安装。
macOS系统如果安装过VSCode
,则可以直接使用VSCode
中安装的lldb-mi
,将之软链接到/usr/local/bin
即可。
这里需要注意的一点是lldb-mi
最好与lldb
的安装目录一致,一般为/usr/local/bin
。如果是源码安装的,建议都安装在/usr/local/
,则都在/usr/local/bin
目录下。
如果是使用的系统源的LLDB包安装的,比如ubuntu 22.04中安装的lldb-15,它默认是安装在/usr/lib/llvm-15/bin
下,则需要将之添加到PATH路径中,并建立一个lldb-server具体版本号的符号链接到lldb-mi
的安装目录下,否则会报错unable to locate lldb-server-XX.X.X
:
比如ubuntu 22.04中安装的lldb-15,具体版本号为15.0.7,lldb-mi安装在/usr/local/bin
,使用下面命令建立符号链接:
ln -s /usr/lib/llvm-15/bin/lldb-server-15.0.7 /usr/local/bin/lldb-server-15.0.7
lldb-mi README中有提到可以设置环境变量LLDB_DEBUGSERVER_PATH
,但是笔者试了一下,没用。
二、项目实例
使用VS2022创建一个CMake项目t
,默认会创建四个文件t.h
,t.cpp
,CMakeLists.txt
和CMakePresets.json
,并且默认是本地计算机
的x64 Debug
配置。CMakePresets.json
是CMake的预设配置,它定义了以下几种配置:
- 本地计算机,也就是Windows的
x64 Debug
,x64 Release
,x86 Debug
,x86 Release
- 远程Linux的
Linux Debug
- 远程MacOS的
macOS Debug
是否启用CMake预设配置文件,可以通过菜单工具
/选项
/CMake
来选择:
1.使用CMake预设配置文件
如果VS启用了CMake预设配置文件,则可以在本地计算机
下拉框中选择不同的连接,可以看到不同的预设配置:
远程连接可以通过菜单工具
/选项
/跨平台
/连接管理器
来管理,最方便的是通过前面本地计算机
的下拉列表中选择管理连接
直接转到连接管理器
页面:
1.1 添加预设配置
CMakePresets.json
中仅定义了几种预设值,比如Linux下仅定义了Linux Debug
配置,默认是使用GCC编译器,如果想要使用Clang编译器,则需要添加预设配置。在CMakePresets.json
右键菜单中选择“添加配置”:
再选择“Linux Debug”添加预配置:
默认会添加如下配置:
{"name": "linux-debug2","displayName": "Linux Debug","description": "面向适用于 Linux 的 Windows 子系统(WSL)或远程 Linux 系统。","generator": "Ninja","binaryDir": "${sourceDir}/out/build/${presetName}","installDir": "${sourceDir}/out/install/${presetName}","cacheVariables": {"CMAKE_BUILD_TYPE": "Debug"},"condition": {"type": "equals","lhs": "${hostSystemName}","rhs": "Linux"},"vendor": {"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"}}}
可以改名为linux-clang-debug
,显示名为:Linux Clang Debug
,然后添加cacheVariables
变量设置C/C++编译器即可:
{"name": "linux-clang-debug","displayName": "Linux Clang Debug","description": "Clang","generator": "Ninja","binaryDir": "${sourceDir}/out/build/${presetName}","installDir": "${sourceDir}/out/install/${presetName}","cacheVariables": {"CMAKE_BUILD_TYPE": "Debug","CMAKE_C_COMPILER": "clang","CMAKE_CXX_COMPILER": "clang++"},"condition": {"type": "equals","lhs": "${hostSystemName}","rhs": "Linux"},"vendor": {"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"}}}
1.2 Ubuntu 22.04/CentOS7配置
目前VS2022连接Ubuntu系统进行调试有性能问题,启动调试器非常慢,不管是使用GDB还是LLDB都非常慢。笔者已经反馈给开发者,目前还在考虑修复中。连接CentOS7进行远程调试没这样的问题。
VS默认情况下是使用GDB进行调试的:
使用GDB进行调试,有一个不方便的地方就是函数嵌套调用:
#include using namespace std;int f(){return 1;}void foo(int i){cout << i << endl;}int main(){foo(f());cout << "Hello CMake." << endl;return 0;}
如果调试时在f
函数的}
按F10
执行next
命令,则会跳过foo
函数直接到下一行代码了,如果想调试foo
函数就必须按F11
执行step
命令。这点习惯与VS的调试器习惯不一样,而LLDB调试器与VS的习惯一致。如果知道如何修改GDB的这一行为的读者可以下方留言。
GDB调试器毕竟是老牌调试器,使用很广泛,支持得也比较好,VS默认已经配置并处理好GDB调试器了,所以使用GDB调试器,基本上是一帆风顺。
但如果要使用LLDB调试器,就需要自行添加配置,而且预置的LLDB配置也不完善,有许多麻烦事,而且LLDB使用了许多新技术,注定是一条曲折之路,不过笔者都为大家踩过坑了,大家只需要照搬即可:
得到launch.vs.json
配置如下:
{"version": "0.2.1","defaults": {},"configurations": [{"type": "cppgdb","name": "CMakeLists.txt","project": "CMakeLists.txt","projectTarget": "","comment": "了解如何配置远程调试。有关详细信息,请参阅 http://aka.ms/vslinuxdebug","debuggerConfiguration": "gdb","MIMode": "lldb","args": [],"env": {}}]}
将projectTarget
设置为目标t
,此时会有CMakeList.txt
选项了:
原以为就这样简单配置就可以使用LLDB调试器了,毕竟是使用VS的向导生成的。还是想得太简单,启动报错:
Unable to start debugging. Unexpected LLDB output from command "-interpreter-exec console "settings set target.env-vars ASAN_OPTIONS=\"detect_leaks=0\""". Undefined command: "settings". Try "Help".
VS并没有默认启动lldb-mi来调试,需要指定gdbPath
,默认为 /usr/bin/gdb
,可以查看文档http://aka.ms/vslinuxdebug,这里需要设置为lldb-mi
的路径:/usr/local/bin/lldb-mi
。再次启动,就一直卡在Initializing Debugger
界面。
笔者在网上查了很多资料,也没查到相应的配置,咨询了开发者才知道原来还需要加一个"preDebugCommand":"echo"
,看来LLDB的配置不是一般的复杂啊,暴露了太多细节给开发者了,不知道VS与Linux的交互细节,根本就不知道需要配置这个,为啥需要这条指令。
此时如果连接的是CentOS7系统,会报如下错误:
personality set failed: Function not implemented
前面笔者写了一文进行分析解决:解决lldb调试时可能出现的personality set failed: Function not implemented
CentOS7由于系统glibc较老没实现personality
函数,但Ubuntu 22.04
的glibc是实现了的,没此问题。
如果是连接的容器中的Ubuntu 22.04,则会报如下错误:
'A' packet returned an error: 8
实体机以及虚拟机中的Ubuntu 22.04没此问题。
其实这两个问题都是LLDB禁用了ASLR
导致,需要使用settings set target.disable-aslr 0
来关闭禁用。
完整配置如下:
{"version": "0.2.1","defaults": {},"configurations": [{"type": "cppgdb","name": "t.lldb","project": "CMakeLists.txt","projectTarget": "t","comment": "了解如何配置远程调试。有关详细信息,请参阅 http://aka.ms/vslinuxdebug","debuggerConfiguration": "gdb","MIMode": "lldb","gdbPath": "/usr/local/bin/lldb-mi","preDebugCommand": "echo","args": [],"env": {},"setupCommands": [{"text": "settings set target.disable-aslr 0"}]}]}
至此,终于可以使用LLDB调试程序了。
如果想要在命令行中使用LLDB进行调试,可以创建一个~/.lldbinit
文件,添加内容:
settings set target.disable-aslr 0
即LLDB启动时会自动执行里面的命令。
但VS中不行,VS是启动的lldb-mi
,再启动的lldb-server
。
1.3 macOS配置
macOS的默认配置如下:
{"name": "macos-debug","displayName": "macOS Debug","generator": "Ninja","binaryDir": "${sourceDir}/out/build/${presetName}","installDir": "${sourceDir}/out/install/${presetName}","cacheVariables": {"CMAKE_BUILD_TYPE": "Debug"},"condition": {"type": "equals","lhs": "${hostSystemName}","rhs": "Darwin"},"vendor": {"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"}}}
使用默认的macOS配置会有一点问题,就是找不到cmake,如果没安装ninja
的话也会找不到ninja
:
VS在macOS系统应该是使用whereis
来查找程序的,可以看到whereis
是没有找到cmake的,而which
是可以正确查到cmake程序的(VS为啥不在whereis
没找到时再用which
查找一下,或者直接优先使用which
查找):
可以查看whereis
的man手册,原来在macOS系统是使用sysctl
命令获取的user.cs_path
路径来查找程序的。
通过sysctl -a | grep user
可以看到whereis
的搜索路径为/usr/bin:/bin:/usr/sbin:/sbin
,没有/usr/local/bin
,所以找不到。
看到这里可能会想修改这个值,但是通过查看man sysctl
发现这个值根本不能修改(为no的都不能修改):
这点与Linux不一样,Linux下的whereis
以及which
都是可以通过PATH路径搜索的。
可能会想到像Linux一样在/usr/bin下创建一个cmake的符号链接,由于MacOS系统/usr/bin不可修改,也不行。
只好修改cmake配置了:
{"name": "macos-debug","displayName": "macOS Debug","cmakeExecutable": "/usr/local/bin/cmake",// 指定cmake的绝对路径"generator": "Unix Makefiles",// 如果没安装Ninja就改为"Unix Makefiles""binaryDir": "${sourceDir}/out/build/${presetName}","installDir": "${sourceDir}/out/install/${presetName}","cacheVariables": {"CMAKE_BUILD_TYPE": "Debug"},"condition": {"type": "equals","lhs": "${hostSystemName}","rhs": "Darwin"},"vendor": {"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"}}}
此时开始调试程序还可能会遇到如下错误:
developer mode is not enabled on this machine and this is a non-interactive debug session
这是macOS系统还没打开开发者模式,使用下面的命令打开:
sudo DevToolsSecurity enable
2.不使用CMake预设配置文件
如果不使用预设配置文件,则变更本地计算机
下拉列表中的连接时,不会自动变更后面的配置,即不会根据远程连接,自动变更配置。默认只有本地计算机
的x64-Debug
配置。要想使用其它配置,需要手动添加,选择管理配置
,就会创建一个CMakeSetings.json
文件,并进入CMakeSetings.json
的编辑界面(如果没有使用文本编辑器打开的话):
选择添加配置,则会弹出如下界面,可以选择使用GCC还是Clang的Debug或者Release配置:
远程计算机中可以指定远程连接,也可以使用${defaultRemoteMachineName}
,这样会使用连接管理器中选择的默认连接,即列表中标识为默认
的连接:
前面选择是使用GCC还是Clang的时候如果选错了或者想更改,可以通过修改工具集来改变:
CMake生成器默认为Ninja
,如果远程系统没安装则可以选择Unix Makefiles
,IntelliSense模式默认是没有选择任何内容的,这里根据是64位系统还是32位系统选择linux-gcc-x64
或者linux-gcc-x86
:
目前使用GCC工具集的智能提示不是很完善,比如boost库(笔者使用的1.82版本)中asio相关的的提示有问题,也不知道是GCC的问题还是VS的问题。推荐使用Clang工具集,Clang工具集没此问题。
写得非常详细,关于LLDB的部分是笔者的踩坑经历,希望对大家有帮助!
欢迎点赞,收藏。转载请注明出处!