在Windows 10系统中配置VS Code下的C/C++开发环境

1,787 阅读4分钟

VS Code作为一款最受程序员欢迎的轻量级的程序编辑器,在使用方面有着无可替代的灵活性与优势。但同样由于其轻量级和灵活性,在进行开发时,也有很多需要自行手动配置的地方,不像其臃肿的同门兄弟Visual Studio(虽然VS Code与Visual Studio相似之处仅仅在于名称和同是微软出品)那样,让很多操作都傻瓜化。对于新手来说,傻瓜化的操作当然有其便捷性,但失去了配置的过程,很多人虽然在VisualStudio下可以写出能执行的代码,但始终连程序是如何编译、链接到运行的都搞不懂。

在VS Code官方文档中,对各种开发语言的配置方式都有详尽的介绍,在Windows下进行C/C++开发时,官方提供了三种不同的配置方式,分别是使用Microsoft C++,Windows下的GCC和利用Windows10内置的WSL linux子系统的GCC进行开发和配置。本文仅就后两种方式进行示例和介绍。

1. 准备工作

  • 在安装完Visual Studio Code后,要进行C/C++开发时,需要先安装C/C++语言插件。

cpp-extension.png

  • 创建一个空文件夹,并在其中创建演示用的项目文件。通过命令行操作时顺序如下:
mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .

最后一行code .命令是在命令行下快速调用code打开当前文件夹的指令,在实际使用中非常方便。

  • 在文件夹中添加一个helloworld.cpp文件(可以通过vs code创建)并包含以下内容(代码来自vs code官网)
#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"};

    for (const string& word : msg)
    {
        cout << word << " ";
    }
    cout << endl;
}
  • 如果要在WSL(Windows Subsystem Linux,windows内置的Linux子系统)下运行,还需要安装 Remote-WSL extension插件。安装方式与其他插件安装方式相同。
  • 在安装完c/c++插件后,编写c/c++代码时,就可以看到VS Code的智能感知(IntelliSense)系统了,这也是VS Code引以为傲的地方之一,在编写代码时,可以自动为程序员提供快速建议和完善语句的参考。

msg-intellisense.png

2. 在Windows下安装GCC并进行C++语言开发

按照官方的指导,要在Windows下安装开源的GCC编译器,需要安装Mingw-w64,这是GCC在Windows下运行的版本。在Mingw-w64官网可以开到不同的发行版本,一般来说推荐仅安装官方的mingw-w64即可,但由于国内网络环境的原因,直接安装mingw-w64可能是非常缓慢甚至难以成功的。这里选择安装mingw-w64的一个名为MSYS2的发行版进行安装,并通过清华大学开源软件镜像站进行加速。

2.1 安装 msys2

按照清华大学开源软件镜像站(或者USTC镜像)的官方说明,在该网站MSYS2文件夹下的distrib/目录下选择相应的名为msys2-<架构>-<日期>.exe文件下载并安装。一般建议直接安装在 C:/msys2 目录下。安装完成后,在该目录下查找并编辑以下文件,以使用清华开源站的软件仓库来代替默认的海外仓库:

编辑 /etc/pacman.d/mirrorlist.mingw32 ,在文件开头添加: Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686 编辑 /etc/pacman.d/mirrorlist.mingw64 ,在文件开头添加: Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64 编辑 /etc/pacman.d/mirrorlist.msys ,在文件开头添加: Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch 然后打开msys2.ext文件,在命令行执行 pacman -Sy 刷新软件包数据.

pacman是arch linux下的包管理器,与centos下的yum或者ubuntu下的apt类似。要在msys2下查找并安装linux兼容的软件包,需要通过pacman进行。

2.2 使用pacman安装软件包

常用的pacman命令包括:

pacman -Sy 更新软件包数据
pacman -R package-name 删除软件包
pacman -S package-name 安装软件包
pacman -Syu 更新所有
pacman -Ss xx 查询软件xx的信息

安装gcc,gdb。可以根据需要选择安装32位或64位gcc,gdb发行版。 如果需要安装32位软件包。可输入

pacman -S mingw32/mingw-w64-i686-gcc
pacman -S mingw32/mingw-w64-i686-gdb

如果要安装64位包,可以相应的改为mingw64/mingw-w64-x86_64-gcc等。也可以直接将gcc改为toolchain,可完整安装整个工具链。

2.3 设置环境变量

安装完成后,需要将对应的c:/msys2/mingw32/bin或者c:/msys2/mingw64/bin添加到windows系统路径的path下。添加方式如下: (Win+R并输入control)打开控制面板-->系统-->高级系统设置 在弹出窗口中选择高级-->环境变量,在下方的系统变量中寻找Path并双击。选择新建并输入上述路径(msys2以及相应的软件包对应的安装路径)

c389a85533e268e402a553f2ed4c5737.png

打开命令行,输入下列命令,如果能看到相应的版本信息,则说明安装和路径设置成功。

C:\Users\weizy>g++ --version
g++ (Rev1, Built by MSYS2 project) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

C:\Users\weizy>gdb --version
GNU gdb (GDB) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

2.4 配置task.json文件

回到helloworld.cpp文件所在的目录下,用vs code打开文件夹,选择Terminal-->Configure Default Build Task(终端,配置默认build任务),选择c/c++: g++.exe build active file,会创建一个新的tasks.json文件。参考官网示例编辑该文件如下:

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "g++.exe build active file",
      "command": "C:\\msys2\\mingw32\\\bin\\g++.exe",
      "args": ["-g", "${file}", "-o", "${fileDirname}\\${fileBasenameNoExtension}.exe"],
      "options": {
        "cwd": "C:\\msys2\\mingw32\\bin"
      },
      "problemMatcher": ["$gcc"],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}
  • 这个配置文件中,用到了vs code内置的变量来使配置文件更灵活。{fileBasenameNoExtension}表示要编译文件不含扩展名的名字,加上后缀就会编译为.exe文件,本例中即编译出helloworld.exe文件,{fileDirname}表示文件所在目录,VS code官网列出了所有的系统变量参考
  • command和cwd中的文件夹要和实际安装的位置一致,并且用双反斜杠来表示文件路径。
  • 考虑到该配置文件的通用性,可以保存并用于以后项目和文件使用。

2.5 执行编译

关闭task.json文件并回到helloworld.cpp文件(否则系统会认为要编译的文件是task.json)。选择Terminal-->Tasks:Tun Build Task (终端-->任务:执行编译任务),快捷键为Ctrl+Shift+B (这个快捷键和我的输入法表情文件冲突,需要修改掉)。一切正常的话编译会迅速完成,并在相同目录下生成helloworld.exe文件。在终端运行 .\helloworld.exe可以看到文件的输出结果。

3.在Windows的WSL子系统中通过GCC配置C++开发环境

3.1 安装Ubuntu Linux子系统

可参考微软官方的WSL子系统安装说明,从windows store或者命令行下载并安装。windows server也可以下载并且手动解压缩和安装。这里在windows商店中搜索并安装ubuntu18.04版本。安装过程中两个常见的错误及解决方案如下:

  • 安装失败并出现错误 0x80070003
    • 适用于 Linux 的 Windows 子系统只能在系统驱动器(通常是 C: 驱动器)中运行。 请确保将分发版存储在系统驱动器上:
    • 打开“设置”->“存储”->“更多存储设置: 更改新内容的保存位置”
  • WslRegisterDistribution 失败并出现错误 0x8007019e
    • 未启用“适用于 Linux 的 Windows 子系统”可选组件:
    • 打开“控制面板” -> “程序和功能” -> “打开或关闭 Windows 功能”-> 选中“适用于 Linux 的 Windows 子系统”,或使或打开Windows Power Shell并且命 Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

安装完成后,在开始菜单中搜索Ubuntu即可打开WSL的ubuntu linux子环境,在命令行输入bash也可直接进入ubuntu bash‘中。第一次今进入WSL子系统时需要设置Linux子系统的用户名和密码。

为了提高访问速度,这里同样使用清华大学开源软件站的仓库替换默认的Ubuntu仓库。方法为修改ubuntu文件/etc/apt/sources.list(修改前建议先备份该文件),将文件内容替换为以下内容,保存文件后输入sudo apt-get update,即可通过清华大学开源软件站仓库更新软件。

# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse

3.2 安装编译环境

在WSL子系统中输入以下命令以安装编译环境。

sudo apt-get install build-essential gdb

安装完成后可输入以下命令检查是否安装成功。

whereis g++
whereis gdb

3.3 通过VS Code打开WSL子系统并配置编译C++文件

安装完VS Code的Remote-WSL插件后,可以通过下列方式在VS Code中打开WSL子系统。

remotewsl.png
通过VS Code打开子系统后,同样需要为WSL子系统安装C/C++插件,以实现后续的调试等功能。在插件栏中搜索C++安装即可。

和前一节类似地,在WSL中新建helloworld文件夹,并在其中新建helloworld.cpp文件。参考VS Code官网配置tasks.json文件如下。

{
    "version": "2.0.0",
    "tasks": [
      {
        "type": "shell",
        "label": "g++ build active file",
        "command": "/usr/bin/g++",
        "args": ["-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}"],
        "options": {
          "cwd": "/usr/bin"
        },
        "problemMatcher": ["$gcc"],
        "group": {
          "kind": "build",
          "isDefault": true
        }
      }
    ]
  }

注意:

  • 在linux系统下并不会通过文件后缀来判断文件是否可执行,因此.exe的后缀是没有必要的。只要文件权限中包含x执行权限即可执行。参考前节进行编译后,即可生成helloworld文件,在终端中执行可看到输出情况。
  • 在WSL子系统中,windows原有盘符映射到了/mnt目录下,比如c盘路径为/mnt/c,d盘为/mnt/d,为了方便两个系统的文件互通,我在d盘新建了wsl目录,并将其通过软连接连接到WSL子系统的主目录下,这样在该文件夹中的文件可以很方便的通过两个系统查找使用。linux下建立该软连接的命令如下。
mkdir /mnt/d/wsl
ln -s /mnt/d/wsl ~/wsl

4. 程序调试

4.1 配置

一般来说,程序设计不可能一蹴而就就可以编译成功的。在编译前可能需要大量的调试工作。和编译类似,程序调试也需要在VS Code中进行配置。选择Run-->Add Configuration(运行-->添加配置)添加配置,选择C++(GDB/LLDB)(如果默认没有出现,则需选择最下面的more进行安装相应插件)。在下拉菜单中选择需要的编译器,使用windows下的gcc时选择g++.exe,使用WSL子系统时选择g++ build and debug active file.截图分别如下。

build-and-debug-active-file.png

build-and-debug-active-file _1_.png

该选择会生成不同的launch.json文件。在windows系统的gcc编译器下launch.json文件如下(目录已修改为和实际目录一致)

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++.exe build and debug active file",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\msys2\\mingw32\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "g++.exe build active file"
        }
    ]
}

在WSL子系统下的lauch.json配置文件如下:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++ build and debug active file",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "g++ build active file",
            "miDebuggerPath": "/usr/bin/gdb"
        }
    ]
}

4..2 程序调试

回到helloworld.cpp下,按F5或者选择Run-->Start Debugging开始进行程序调试。如果使用过Visual Studio或者其他IDE工具,就会发现其中的相似性,在程序段左侧的代码行数标识左边,可以通过鼠标给程序打断点(break point),这样在调试时遇到相应断点会自动停下,这在调试时都是很有用的功能。

step-over-button.png

关于调试另外一个很有用的功能是watch。在调试开始后,程序栏左侧会出现watch窗口。在watch窗口中可以输入想要监视的变量,例如本例中的变量名为word的变量。双击watch窗口下的空白处并输入watch,在程序步进执行(上图中按钮)时,就可以看到随着程序执行,watch变量不断变化的值。这个比起调试时用print输出变量要方便又好用的多。

watch-window.png