如何使用VSCode进行C++开发

利用Docker镜像快速构建C++开发环境

Posted by QITINGSHE on March 14, 2023

我真正意义上开始接触计算机是在大学的时候,在此之前我几乎完全不了解计算机的操作流程,甚至也不了解互联网的使用方法。阴差阳错地进入了计算机相关的专业,开始学习编程,这对我来说是一件新奇但又具有重大挑战的事情。当讲台上的老师向我讲诉如何编写运行第一个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 imagerun 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)。

如果没有合适的镜像或需要定制化的镜像,那么可以使用DockerfileDocker-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++编译环境的容器中应该是可以成功编译链接的。

当然你也可以使用makeCMake工具,我个人更喜欢xmake,相对来说更加简洁易上手,而且还有包管理功能。

在VSCode中进行Debug

其实当我们成功进行编译后,我们可以直接使用GDB进行C++的Debug,不过VSCode自带的Debug工具还是蛮好用的,比直接使用GDB效率要高一点。(当然我个人比较建议了解一下GDB,至少可以在命令行环境下也能保证可以进行开发,VIM+GDB是荒野求生时的瑞士军刀,学会这两样可以大大提高程序员的生存率~)

参考Get Started with C++ on Linux in Visual Studio Code

这部分介绍两个文件,一个是tasks.jsonlaunch.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的工作模式,对熟悉命令行下工作很有帮助。