本来想打个酱油就撤退,结果没想到跨平台开发这么费劲,要想把CODE真正用起来还是有不少的麻烦事。尤其是随着开发的深入,字符集、多线程、数据库什么的不断被拉入解决方案的时候,如果前面没有把CODE的配置弄清楚,真会陷入抓狂的境地,一点点小问题耗个一两天时间去解决都是相当正常的情况。所以,没办法,既然油瓶子都怼上了,只能奉陪到底吧。
前提说一下,因为一直用C/C++来着,所以下面基本上都针对C/C++环境的构建和使用说事儿,python之类的,啥时候用得上啥时候再记录吧,打酱油的时候尽量不打醋。
一、CODE的C++环境构建
实际上,CODE的自我介绍里面说得很清楚,它就是一个编辑器,不是编译器,也不是调试器。所以,基于CODE的编译调试,需要将其与第三方编译器、调试器关联起来,而这个工作,一般是依靠插件来完成的,当然,有特殊需要的时候,还是需要借助我们自己来进行配置。所以,网上有些教程会直接扔出来一堆配置脚本,让拷贝到哪里哪里云云;有些教程又会说,下载某个插件就可以如何如何等等。其实,核心就一句话,如果基于某个编译器或者调试器,你能在命令行里面把它玩转了,那么不管是插件还是配置脚本,都可以轻松理解了。
1. Windows上的C++环境构建
不论是配置哪种系统上的C++环境,安装C++ extension的第三方插件还是不可少的。至少它可以帮助我们把基础的工作先完成了。
在Windows上安装VSCODE没什么好说的。安好后我们用一个例子来逐步说明各种配置方法:新建一个用于管理程序的文件夹,双击进入该文件夹后,在文件菜单中选择“打开Windows Powershell窗口”;然后在命令行中,该文件夹的目录下,输入“code .”启动CODE——这是CODE推荐的启动方式。
在CODE中新建test.cpp文件,敲上经典代码,开始我们的测试:
如果测试的机器是联网的话,那么右下角应该会出现提示,要求安装C++扩展:
如果没有也不要紧,所有的扩展都可以在CODE插件市场里下载,然后离线安装。这个c++扩展的名字叫做“C++ Extension” ,直接搜索就行。VSCODE市场里一个比较特别的事情是真的可能出现名字一样但是实现不一样的插件,所以需要认真作者安装。比如我安装第一个,作者是微软。:)
这个扩展包会安装好几个插件,如果是离线的话,那就得一个个下了:
安装完成后,回到test.cpp,点击调试(左边那个带虫子的三角)。这里提醒一下,由于调试器脚本使用“当前活动文件”宏来定位被调试对象,所以当有好多个文件的时候,调试前一定要把被调试文件作为激活窗口,否则会收到一堆莫名其妙的提示。
点击运行和调试,旁边的对话框会弹出两个选项,提示我们选windows还是GDB,这个就是插件提供的内容了;其中,windows使用VisualStudio的cl编译器;GDB则使用gcc/g++编译器。
(1)基于cl的编译链接
由于我的机器上已经安装过Visual Studio 2019,理所当前要先试一下cl好用不。然而如果选择这一项,CODE会提示需要到Visual Studio 2019的命令行环境中启动才可用——显然,CODE依赖于该命令行中的一些与宏定义相关的执行环境(如PATH、包含路径、库路径一类)。当然,如果cl的路径已经在系统环境变量中设置好,一般的CMD进去实际也是可以的。
这个环境启动的地方可以到开始菜单的VS2019里面去找,比如“Developer Command Prompt
for VS2019。关掉刚才那个CODE,在VS2019的命令行环境中,导航到刚才的文件夹里面,再执行code .命令。
点击调式和运行,选择Windows的那个选项后,再点击cl.exe生成和调试活动文件选项:
稍等一会,程序就能够生成并运行:
看看终端输出里面,CODE的插件的动作,就能明白不过是先使用cl.exe进行了编译,然后使用调试加载了生成的内容:
把这一行放到刚才打开的命令行里,可以看到执行结果一模一样:
证明这不过就是插件干的活。
(2)cl编译器参数的配置
回头在CODE的资源管理器里面,我们可以看到CODE自动生成了一个.vscode的文件夹,下面多了一个task.json的文件——这个其实就是隐藏在插件内部的配置文件,主要负责生成可执行文件;后面我们还会见到lauch.json——主要负责调试参数设置和c_cpp_properties.json——主要负责智能语法检查:
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: cl.exe 生成活动文件",
"command": "cl.exe",
"args": [
"/Zi",
"/EHsc",
"/nologo",
"/Fe:",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"${file}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$msCompile"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
根据刚才观察所得,这个配置文件中,“args”栏下参数其实就是命令行中参数,碰上空格就需要换一行而已。所以,在这个配置下,只要我们知道Visual Studio会给程序选择什么样的编译参数,我们就可以依葫芦画瓢配置这个文件,构建起一样的编译调试环境。
另外,该文件中的“label”标签需要关注一下,如果需要自定义调试文件,则需要这个标签来关联调试的对象。
2. CENTOS上构建C++环境
很多关于构建CODE的C++编译环境的文章都使用MinGW提供的编译环境,不过一些会借助Cygwin或者MSYS2等进行安装。我不大喜欢如此,这样感觉太重了。好在MinGW也提供了更加简便的安装方式。
(1)安装MinGW
在MinGW的官网上,选择Download下的MingW-W64-builds跳转到SourceForge上
在这个界面下面,不要直接下载,那个应该需要make的;点击一下“MinGW-w64-for 32 and 64 bit Windows”。
跳到这个界面下,选择标签页中的Files,选择最新版本的MinGW-W64 GCC就行,目前是8.1.0版本,选择seh版本。至于posix还是win32,我也不知道。网上有所如果多线程需要posix,但是我选win32貌似也调通了……
解压直接仍在C盘下面就行。
(2)配置MinGW
打开我们拷贝过来的mingw64文件夹,可以发现编译调试所需的各种可执行程序在bin目录下都是存在的:
由于我们总是从代码文件所在目录的CMD进入CODE的——注意这个条件。所以如果我们能够在这个CMD下使用gcc或者g++编译源程序,CODE也就能。重新从代码目录启动CMD,然后看看gcc能不能执行:
我想这里估计都不用多说,一般都会很容易想到是PATH环境变量的问题。嗯,把c:\mingw64\bin加入到环境变量里面,重新启动CMD:
这一次,gcc就可用了,当然g++和gdb也就可用了。直接在命令行里尝试编译下:
喏,果然是可以的,注意-o指定输出可执行文件的名称,-g表示需要内嵌调试信息,否则是没法调试的。
因为内嵌了调试信息,所以如上,是可以通过gdb进行命令行调试的。能做到这一步,实际也就是说有没有VSCODE都行,VSCODE只不过就是把vim和g++、gdb都团到一起,让我们干活更方便而已。
所以,接下来我们看看CODE怎么团的:
(3)CODE里的GDB/LLDB运行和调试配置
在命令行里用“code .”进入CODE,在调试中选择C++(GDB/LLDB)调试:
然后不出意外的收获警告
因为我们还没有配置 gdb下的生成方法,a.exe都没有生成,自然不会运行调试。
其实配置也挺简单,因为刚才我们设置好环境变量后,还没有重新启动过CMD和CODE。也就是说环境变量没有机会得到更新——这个也就是重新启动一下即可。然后再选择gdb方法,可以看到已经多出了g++选项
选择并成功运行,可以再下方输出界面看到如下反馈:
此时,再观察task.json文件,可以发现多出了有关g++的配置:
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: cl.exe 生成活动文件",
"command": "cl.exe",
"args": [
"/Zi",
"/EHsc",
"/nologo",
"/Fe:",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"${file}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$msCompile"
],
"group": "build",
"detail": "调试器生成的任务。"
},
{
"type": "cppbuild",
"label": "C/C++: g++.exe 生成活动文件",
"command": "C:\\mingw64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": "build",
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}
显然,插件已经精准掌握了g++的路径,并且为代码构造了生成参数。到这里,基本上我们就完成了Windows环境下初步的VSCODE C++环境配置。
二、CODE调试环境配置
对于基本的编程需求,前面那些配置完成后基本就可以应付了。但是再多一点点要求,比如编译器带参数怎么办?比如-pthread参数,或者mysql需要带上的编译参数等等;又比如命令行带参数怎么办?(main函数带参数的情况),那么调试的时候就需要明确给main函数提供参数。
前面已经提到,类似于-pthread之类的生成参数,可以在task.json文件中直接添加。那么调试参数呢?
实际上我们在点击“运行和调试”时,插件是使用的默认的调试脚本启动的生成程序,如果我们需要自定义,则需要在运行和调试界面中选择“创建launch.json文件”,同样在弹出的菜单中选择GDB/LLDB,得到一个空文件:
在工作区右下角选择“添加配置”,在弹出菜单中选择C/C++:(gdb)启动。
得到模块如下所示:
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "输入程序名称,例如 ${workspaceFolder}/a.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/path/to/gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
这里需要改动的有4处:
① “program”标签:这里需要改为与task.json文件中的“args”标签中所对应的生成目标文件一致,也就是g++的-o参数所对应的那个,比如上面我们的那个是“${fileDirname}\\${fileBasenameNoExtension}.exe”,一般来说也就是这个。
②“args”标签,也就是我们需要携带的命令行参数,格式嘛,参考task.json即可。
③“miDebuggerPath”标签,对应mingw64中gdb所在,改为“c:/mingw64/bin/gdb”
④在“configuration”里面的最后一行(注意别弄错地方),加上preLaunchTask,里面对应的内容与task.json的label一致即可。注意是g++那个,不是cl,在我这是“C/C++: g++.exe 生成活动文件”。表示在调试前,需要调用这个“task”生成好被调用的对象。
填好后脚本如下:
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [
"Hello",
"World",
"!"
],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "c:\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++.exe 生成活动文件"
}
]
}
调整helloworld代码如下所示,运行一下看看:
这时会发现,左边的调试按钮再不需要选择多次了,就只剩一个只能点一下就开始的按钮。如果想选择别的配置,右上角那个调试按钮还是可以选择的。
结果也如预期,命令行参数被正确解析了。
三、CODE远程连接
使用CODE的最直接原因,当然时跨系统开发(对我来说主要是在Linux上开发)。如果不为跨系统,在Windows上倒腾这么多事干什么呢,直接用Visual Studio不就很好?但是使用CODE开发Linux程序最扎心的2点:一是千万不要在window环境下先开发后移植,否则谁移植谁知道,巨坑一个接一个,一个不小心使用了原生Window的c++库,后面会死得很难看;而是Linux的老破机器外加显卡支持不是很好,屏幕清晰度有限,一页看不了多少行程序。这两点搞得我写个程序畏手畏脚的,频繁出错……。所以最好是显示如Windows,环境真Linux,如此远程连接就显得很有必要了。
1. 远端CENTOS
既然CODE只作为远程控制器使用,那么实际编译调试环境都应该在远端CENTOS上才对。从这个角度看,远端系统必须把gcc gdb g++环境装好是没有话说的:
然后据说CODE远程连接是使用SSHD服务,所以看一眼自带的sshd.service是否安好也是有必要的。
2. 本机CODE环境配置
(1)检查环境
本机CODE这一边,当然是首先确定机器能否联通,否则玩笑就大了。远端ifconfig,本机这边ping一下看看:
然后sshd登录一下看看:
这些都没问题,就可以下载远程插件进行配置操作了。
(2)安装插件
市场上搜索ssh,实际我们安装的就是第一个和第三个。在线安装第一个的话,第三个会被自动安装。
安装完毕后左边工具栏上会出现对应工具图标:
(3)配置插件参数
右键选择已安装好的插件的图标,点选扩展设置
拉到基本底部的位置,勾选Remote.SSH:Show Login Terminal的选项。
顶部位置,检查这一项是否也设置到了“c:\Users\你的用户名\.ssh\config”这个位置;在.ssh目录下,通常还有known-host文件,记录了曾经登录过的远端机。——如果这个地方是空值,连接的时候会报“试图连接的管道不存在错误”,如果曾经有过“不正确”的远端机登录,生成了与此地相冲突的known-host文件,也会报管道不存在错误(这是删掉.ssh目录就好)。
(4)添加远程主机连接
选择工具图标,在“SSH TARGETS”右边选择加号以添加远程客户端:
看看弹出窗口上的实例,是不是眼熟——这个其实就是我们进行环境检查时敲的命令行
键入“ssh root@192.168.232.131”,就是我的用户名@远端主机IP地址,回车后会弹出一个下拉单,询问我们准备将配置存放在何处。比如我选择第一个“c:\Users\你的用户名\.ssh\config”——一般Windows的CMD远程连接的参数都存放在这里。
完事后“SSH TARGETS下面会出现该远程机的连接选项,右下角也会询问打开配置还是连接。配置看不看的都无所谓了,直接连吧。
第一次连接时需要选择一下远端平台,我的远端是Linux
连上后,会弹出一个确认连接的界面,这个和在CMD中使用SSH连接时一样的:
确认yes后输入root用户的口令:
然后回到资源浏览器,会要求确认打开的文件夹,即远端机上的程序文件夹,然后再输入一遍口令,就能够打开程序进行编辑了。
这个时候回头看一下扩展设置,会发现刚才连接的远端机和平台设置已经在里面了
(5)远程调试环境构建
直接运行远程打开的代码,会出现“没有C++扩展的”提示,这需要我们为远程机安装相应的扩展。如果远近端都是在线上,直接点击在SSH安装就行;否则可能需要离线安装code和插件……。这个我就没有再进一步测试了。
安装完成后就可以选择g++进行调试了。当然,也可以进一步设置自定义的生成和调试参数,只不过这里的设置需要以远端机系统为参考。
四、CODE智能补全的参数设置
这里先提一下,因为可能在下一篇Mysql的安装使用中涉及到。
①选择左下角的设置图标,选择命令面板。或者直接ctrl+shift+P进入。
②选择C/C++:编辑配置(UI)
③如果是在Windows上,默认是Window32,对应MSVC的编译环境
CODE将使用MSVC的库进行智能语法检查和补全分析。如果是跨平台,可能会如前所述,将我们带进大坑。
④添加符合Linux环境的配置
所以我们需要增加Linux下的配置,让CODE用g++的语法及库进行分析。或者干脆就把WIN32库删掉,以免CODE总是默认选它。当然,如果是远程使用Linux主机上的程序,该处直接会生成Linux类型的参数。
需要重点指出的一个是编译器路径,插件会根据这个路径去分析寻找包含库以支持智能分析;
其二是包含路径,这里需要将第三方库以及我们自己产生的头文件包含在内,注意两个**代表迭代分析子目录。当然,这并不代表在Linux下你可以不用子目录进行包含,比如改写#include"mysql/mysql.h"的时候,也还是得写的。
设置完毕后,会发现.vscode下多了一个c_cpp_properties.json的文件,其中记录的就是刚才我们填入的参数:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
五、VSCODE及插件的远程离线安装
首先我得证明一下我搭的这个环境确实是远程机与本机联通,两级均不能连接互联网的状态
以免回头哪台机器明明可以联网导致从头到尾写了个寂寞……
好了,以下构建过程主要参考了这篇文章,因为毕竟我的好多安全工具都搭建在了离线Linux环境中,但是编程这东西,我还是希望有一个Windows机可以远程挂进去,兼用Linux的环境和Windows的界面。
1. VSCODE远程连接目标服务器
目标服务器是CENTOS8,VSCODE远程连接服务器需要安装ssh插件,这个上面已经记录过,再来一遍而已:
连接离线环境下的远程服务器
同样的配置一下文件
连接
然后在终端栏输入口令
然后不出意外的连接失败。
当然,这一步是必不可少的,因为这一连接过程会在远程服务器上的用户目录下建立相关的配置文件,我们需要的是对应目录下的一串数字:
[root@bogon usr]# cd ~
[root@bogon ~]# ls -l -a
总用量 48
dr-xr-x---. 16 root root 4096 5月 24 06:17 .
dr-xr-xr-x. 17 root root 224 4月 24 16:48 ..
drwxr-xr-x. 2 root root 6 5月 3 17:29 公共
drwxr-xr-x. 2 root root 6 5月 3 17:29 模板
drwxr-xr-x. 2 root root 6 5月 3 17:29 视频
drwxr-xr-x. 2 root root 6 5月 3 17:29 图片
drwxr-xr-x. 2 root root 6 5月 3 17:29 文档
drwxr-xr-x. 2 root root 6 5月 3 17:29 下载
drwxr-xr-x. 2 root root 6 5月 3 17:29 音乐
drwxr-xr-x. 2 root root 6 5月 3 17:29 桌面
-rw-------. 1 root root 1032 4月 24 16:55 anaconda-ks.cfg
-rw-------. 1 root root 8 5月 24 06:12 .bash_history
-rw-r--r--. 1 root root 18 5月 11 2019 .bash_logout
-rw-r--r--. 1 root root 176 5月 11 2019 .bash_profile
-rw-r--r--. 1 root root 176 5月 11 2019 .bashrc
drwx------. 11 root root 254 5月 21 03:52 .cache
drwx------. 14 root root 279 5月 24 06:09 .config
-rw-r--r--. 1 root root 100 5月 11 2019 .cshrc
drwx------. 3 root root 25 4月 24 16:55 .dbus
-rw-------. 1 root root 16 5月 3 17:29 .esd_auth
-rw-------. 1 root root 310 5月 3 17:29 .ICEauthority
-rw-r--r--. 1 root root 1259 4月 24 16:56 initial-setup-ks.cfg
drwx------. 3 root root 19 5月 3 17:29 .local
drwxr-----. 3 root root 19 5月 3 17:29 .pki
-rw-r--r--. 1 root root 129 5月 11 2019 .tcshrc
-rw-------. 1 root root 1407 5月 21 03:54 .viminfo
drwxr-xr-x. 3 root root 17 5月 24 06:17 .vscode-server
[root@bogon ~]# cd .vscode-server/
[root@bogon .vscode-server]# ls
bin
[root@bogon .vscode-server]# cd bin
[root@bogon bin]# ls
c3511e6------------------------------4d5
[root@bogon bin]#
取决于vscode的版本,stalbe或者insider,这里的目录会不一样。不如我的stable,这里的目录是.vscode-server,该目录下有一个一大串字母数字的目录。我们需要的就是这个,将这个串拷出来,替换下面地址中的ID后下载:
.vscode-server的情况:
https://update.code.visualstudio.com/commit:ID/server-linux-x64/stable
.vscode-serinsider的情况
https://update.code.visualstudio.com/commit:ID/server-linux-x64/inside
下载后解压,是一个名为vscode-server-linux-x64的目录——当然不同系统应该不一样。把这个目录下的东西全部拷贝到这一大串字母数据的目录下。(记得把目录下那个没下载成功的vscode-server.tar.gz删了)
然后再连接,就没有问题了。
2. 远程插件的离线安装
如上面提到的那篇文章所述,确实没有什么好的办法。好在我们在下篇文章里为了搭建mysql的远程编程环境下了一堆远程插件,这些插件存放在用户目录对应的那个.vscode-server下面,注意这下面有两个extension,我说的是外面这个。bin下面那个一串字符目录下面那个可以不用管了。把这个extension里面的所有文件拷贝到我们的离线远程服务器下面的对应目录(此时应该是空的)。
然后就可以愉快的干活了。
顺嘴提一下,远程服务器记得编译环境要装好,毕竟code就是个编辑器,这点不要忘了。