我真正意义上开始接触计算机是在大学的时候,在此之前我几乎完全不了解计算机的操作流程,甚至也不了解互联网的使用方法。阴差阳错地进入了计算机相关的专业,开始学习编程,这对我来说是一件新奇但又具有重大挑战的事情。当讲台上的老师向我讲诉如何编写运行第一个Hello World程序时,这里面的运行机制实在隐藏太深,以致我过了很久依然以为编写程序只能在vc6.0这样的软件上进行,更不论配置环境时那些操作的具体意义了。直到后来开始接触Linux,开始使用Terminal与计算机进行交互,开始了g++编译程序,学习使用vim进行编辑,gdb进行debug,我才逐渐理解写代码是一件快乐而自由的事情,我再也不用被限制在某个工具中了。
工作之后,开始重度使用VSCode,虽然偶尔还会怀念使用vim的那些日子,但是VSCode凭借着强大的插件,漂亮的界面,灵活自由的配置,终于将vim从我的工具链中挤下神坛,甚至硕士论文我也是在VSCode下配合LaTex完成的,对我而言,它就是目前最好的工具了。
写这篇文章,也是想介绍一下如何摆脱烦人的C++环境配置,比如需要配置OpenCV,我曾经花了大量时间在服务器上编译安装,踩了很多坑,回头想了一下,时间花了很多,收获却很少,有时候服务器上还不一定有管理员权限,安装环境就更加困难了。但是当有了Docker这个工具之后,有些问题就变得简单了一些。当我的环境配置完成之后,我可以在VSCode中进行各种C++任务的开发和测试,而不用担心搞坏服务器的环境,我可以轻易地从一种开发配置切换到另一种依赖库的开发环境中。而这一切配置项都是以文件形式管理的,也就是说,我们可以用git管理这些配置了,这将极大提升工作效率,工作本不应该在这些琐碎的事情上浪费时间。
在VSCode中使用容器进行开发
涉及到的概念:
- VSCode环境配置
- Docker安装或权限获取
- Docker Image的相关概念
- Dockerfile编辑
先要明确一点,本文不会过多涉及Docker部分的讲述,主要是一次经验分享。
参考:Developing inside a Container using Visual Studio Code Remote Development
首先需要确保已经安装好VSCode和Docker,并确定自己是否有足够权限使用Docker(包括不限于build image
,run image
)
有关系统要求的部分,请查阅上面参考链接中的System requirements部分
当安装好VSCode后,需要安装Dev Containers这个插件。完成安装之后,在VSC中打开项目的workspace,现在我们可以正常编辑项目代码了,但是如何进行编译开发呢,我们还需要配置开发环境。当然这次我们不想直接在系统上安装开发环境了。我们希望能够在Docker的容器中进行编译
首先添加devcontainer.json
文件,敲击shift+option+p
键(或按F1键),打开VSC的Command Palette,运行Dev Containers: Add Dev Container Configuration Files
,这样在项目目录下会自动生成一个.devcontainer
文件夹,里面有devcontainer.json
文件。
如果已经找到合适的Docker镜像,可以直接修改devcontainer.json
文件中的”image“节点:
"image": "image_name",
其中image_name替换成对应的镜像名(我找到了一个集成了g++环境的镜像,danger89/cmake
)。
如果没有合适的镜像或需要定制化的镜像,那么可以使用Dockerfile
或Docker-Compose
,这里我只介绍一下Dockerfile
的使用,首先将image
节点注释掉,然后添加build
节点
"build": {
// Path is relataive to the devcontainer.json file.
"dockerfile": "Dockerfile"
}
需要预先将Dockerfile
文件放置在.devcontainer
文件夹下。
然后就可以再次打开VSC的Command Palette,运行Dev Containers: Open Folder in Container...
命令了,这样我们成功进入了容器内部,并将项目的工作目录挂在容器中,可以使用容器中的编译工具和各种库文件了。编写一个HelloWorld.cpp
,打开VSC的命令行工具,输入
g++ -std=c++11 -g -o out HelloWorld.cpp
在一个有着g++编译环境的容器中应该是可以成功编译链接的。
当然你也可以使用make
或CMake
工具,我个人更喜欢xmake
,相对来说更加简洁易上手,而且还有包管理功能。
在VSCode中进行Debug
其实当我们成功进行编译后,我们可以直接使用GDB
进行C++的Debug,不过VSCode自带的Debug工具还是蛮好用的,比直接使用GDB
效率要高一点。(当然我个人比较建议了解一下GDB
,至少可以在命令行环境下也能保证可以进行开发,VIM
+GDB
是荒野求生时的瑞士军刀,学会这两样可以大大提高程序员的生存率~)
参考:Get Started with C++ on Linux in Visual Studio Code
这部分介绍两个文件,一个是tasks.json
和launch.json
确保已经安装了C++ extension for VS Code
插件
tasks.json
文件描述了编译设置,用什么编译器,使用哪些编译参数都在这个文件中进行配置
{
"type": "cppbuild",
"label": "G++Debug",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-std=c++11",
"-g",
"${fileDirname}/*.cc",
"-o",
"out",
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": false
},
"detail": "针对当前激活文件所在目录下的所有*.cc文件进行编译."
}
这里可以直接去参考链接中查看官方的配置,我这里小修改了一下,大家可以对比看一下。
配置文件中的args
列表描述了使用g++进行编译时的命令,其中-g
表示保留调试信息,否则无法进行Debug;${fileDirname}/*.cc
表示针对当前激活文件所在的目录下所有以.cc
为后缀的文件进行编译。detail
节点描述了当前配置的详细信息,建议写清楚。
当完成tasks.json
文件的配置时,我们就可以在VSCode界面的右上角使用Debug工具了
当然也可以在VSC中添加断点,愉快地进行Debug了
launch.json
文件描述了debugger设置,有关debug的一些参数都在这里进行配置
这里我直接贴官方的配置了
{
"version": "0.2.0",
"configurations": [
{
"name": "C/C++: g++ build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/out",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "G++Debug"
}
]
}
我修改了program
节点,因为在tasks.json
文件中我修改了输出文件的名字,所以要想找到需要Debug的文件,就需要修改成对应的文件,当然也要修改cwd
,不然当前工作目录会对不上,注意preLaunchTask
节点,这里是选择使用哪种编译方案的配置,所以我将该处修改为tasks.json
中的label
节点的值。
到此为止,整个VSCode的开发环境就讲完了(我遗留了一个c_cpp_properties.json
文件没讲,但是有需要的读者可以自行查阅官方文档了解一下了)。我们终于可以从繁琐的开发环境配置中解放出来了,以后需要针对新项目进行配置,只需要拉取对应开发环境的Docker镜像就好了(第一个编辑镜像的人可能要受点累,但是这项工作是可以在团队中复用的,其实是一件很有价值的事情)。
如果已经完成了上述的配置工作,建议有时间的情况下,熟悉一下VIM
+g++
+GDB
的工作模式,对熟悉命令行下工作很有帮助。