现已推出!阅读有关 10 月份新功能和修复的信息。

在 VS Code 中使用 C++ 和 WSL

在本教程中,您将配置 Visual Studio Code 以在 适用于 Linux 的 Windows 子系统 (WSL) 中的 Ubuntu 上使用 GCC C++ 编译器 (g++) 和 GDB 调试器。GCC 代表 GNU 编译器集合;GDB 是 GNU 调试器。WSL 是 Windows 中的 Linux 环境,直接在机器硬件上运行,而不是在虚拟机中运行。

注意:本教程的许多内容适用于直接在 Linux 机器上使用 C++ 和 VS Code。

Visual Studio Code 支持使用 WSL 扩展 直接在 WSL 中工作。我们推荐这种 WSL 开发 模式,其中所有源代码文件以及编译器都托管在 Linux 发行版上。有关更多背景信息,请参阅 VS Code 远程开发

完成本教程后,您将准备好创建和配置自己的 C++ 项目,并探索 VS Code 文档以获取有关其众多功能的更多信息。本教程不会教授您有关 GCC、Linux 或 C++ 语言的知识。对于这些主题,Web 上有很多优秀的资源可用。

如果您遇到任何问题,请随时在 VS Code 文档存储库 中为本教程提交问题。

先决条件

要成功完成本教程,您必须执行以下步骤

  1. 安装 Visual Studio Code

  2. 安装 WSL 扩展

  3. 安装 适用于 Linux 的 Windows 子系统,然后使用同一页面上的链接安装您选择的 Linux 发行版。本教程使用 Ubuntu。在安装过程中,请记住您的 Linux 用户密码,因为您需要它来安装其他软件。

设置 Linux 环境

  1. 打开 WSL 的 Bash shell。如果您安装了 Ubuntu 发行版,请在 Windows 搜索框中键入“Ubuntu”,然后在结果列表中单击它。对于 Debian,请键入“Debian”,依此类推。

    Ubuntu in Start Menu

    shell 将出现,并带有默认情况下由您的用户名和计算机名组成的命令提示符,并将您置于您的主目录中。对于 Ubuntu,它看起来像这样

    Bash Shell

  2. 创建一个名为 projects 的目录,然后在其下创建一个名为 helloworld 的子目录

    mkdir projects
    cd projects
    mkdir helloworld
    
  3. 虽然您将使用 VS Code 编辑源代码,但您将使用 g++ 编译器在 Linux 上编译源代码。您还将在 Linux 上使用 GDB 进行调试。这些工具不是 Ubuntu 的默认安装,因此您必须安装它们。幸运的是,这项任务非常简单!

  4. 从 WSL 命令提示符,首先运行 apt-get update 来更新 Ubuntu 包列表。过时的发行版有时会干扰尝试安装新包。

    sudo apt-get update
    

    如果您愿意,可以运行 sudo apt-get update && sudo apt-get dist-upgrade 来下载最新版本的系统包,但这可能会花费更长时间,具体取决于您的连接速度。

  5. 从命令提示符,通过键入以下内容安装 GNU 编译器工具和 GDB 调试器

    sudo apt-get install build-essential gdb
    
  6. 通过查找 g++ 和 gdb 验证安装是否成功。如果 whereis 命令未返回文件名,请尝试再次运行更新命令。

    whereis g++
    whereis gdb
    

注意:如果您直接在 Linux 机器上工作而不是在 WSL 中工作,则安装 g++ 编译器和 GDB 调试器的设置步骤适用。在您的 helloworld 项目中运行 VS Code,以及编辑、构建和调试步骤都是相同的。

在 WSL 中运行 VS Code

导航到您的 helloworld 项目文件夹,并使用 code . 从 WSL 终端启动 VS Code。

cd $HOME/projects/helloworld
code .

您将看到一条关于“安装 VS Code 服务器”的消息。VS Code 正在下载并在 Linux 侧安装一个小型服务器,桌面 VS Code 将与之通信。然后 VS Code 将启动并打开 helloWorld 文件夹。文件资源管理器显示 VS Code 现在在 WSL 的上下文中运行,标题栏为 WSL: Ubuntu

File Explorer in WSL

您还可以从状态栏判断远程上下文。

Remote context in the Status bar

如果您单击远程状态栏项目,您将看到一个适用于该会话的远程命令下拉列表。例如,如果您想结束在 WSL 中运行的会话,可以选择下拉列表中的 关闭远程连接 命令。从您的 WSL 命令提示符运行 code . 将重新启动在 WSL 中运行的 VS Code。

code . 命令在当前工作文件夹中打开了 VS Code,该文件夹将成为您的“工作区”。在您完成本教程时,您将在工作区中的 .vscode 文件夹中看到创建的三个文件

  • c_cpp_properties.json(编译器路径和 IntelliSense 设置)
  • tasks.json(构建说明)
  • launch.json(调试器设置)

添加源代码文件

在文件资源管理器标题栏中,选择 新建文件 按钮并将文件命名为 helloworld.cpp

New File title bar button

安装 C/C++ 扩展

创建文件后,VS Code 发现它是一个 C++ 语言文件,如果您尚未安装,可能会提示您安装 Microsoft C/C++ 扩展

C++ extension notification

选择 安装,然后在扩展视图中显示按钮时选择 重新加载所需内容,以完成安装 C/C++ 扩展。

如果您已经在 VS Code 中本地安装了 C/C++ 语言扩展,则需要转到扩展视图(⇧⌘X (Windows、Linux Ctrl+Shift+X))并将这些扩展安装到 WSL。可以通過選擇 **在 WSL 中安裝** 按鈕,然後選擇 **重新載入所需內容** 來將本地安裝的擴展安裝到 WSL。

Install in WSL button

添加 hello world 源代码

现在粘贴以下源代码

#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;
}

现在,按下 ⌘S (Windows, Linux Ctrl+S) 来保存文件。注意,您刚刚添加的文件现在显示在 VS Code 侧边栏的 文件资源管理器 视图中 (⇧⌘E (Windows, Linux Ctrl+Shift+E))。

File Explorer

您也可以通过勾选主 文件 菜单中的 自动保存 来启用 自动保存,以自动保存您的文件更改。

最左侧的活动栏允许您打开不同的视图,例如 搜索源代码管理运行。您将在本教程的后面部分学习 运行 视图。您可以在 VS Code 的 用户界面文档 中了解更多关于其他视图的信息。

探索 IntelliSense

在您的新 helloworld.cpp 文件中,将鼠标悬停在 vectorstring 上以查看类型信息。在 msg 变量声明之后,开始输入 msg.,就像您调用成员函数时一样。您应该立即看到一个显示所有成员函数的完成列表,以及一个显示 msg 对象类型信息的窗口。

Statement completion IntelliSense

您可以按下 Tab 键插入选定的成员;然后,当您添加左括号时,您将看到有关函数所需的任何参数的信息。

运行 helloworld.cpp

请记住,C++ 扩展使用您计算机上安装的 C++ 编译器来构建您的程序。在尝试在 VS Code 中运行和调试 helloworld.cpp 之前,请确保您已安装 C++ 编译器。

  1. 打开 helloworld.cpp,使其成为活动文件。

  2. 按下编辑器右上角的播放按钮。

    Screenshot of helloworld.cpp and play button

  3. 从系统上检测到的编译器列表中选择 g++ build and debug active file

    C++ debug configuration dropdown

您只会第一次运行 helloworld.cpp 时被要求选择编译器。该编译器将被设置为 tasks.json 文件中的“默认”编译器。

  1. 构建成功后,您的程序输出将显示在集成的 终端 中。

    screenshot of program output

您第一次运行程序时,C++ 扩展会创建 tasks.json,您可以在项目 .vscode 文件夹中找到它。tasks.json 存储构建配置。

您的新 tasks.json 文件应类似于以下 JSON 代码。

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "C/C++: 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
      },
      "detail": "Task generated by Debugger."
    }
  ]
}

注意:您可以在 变量引用 中了解有关 tasks.json 变量的更多信息。

command 设置指定要运行的程序;在本例中,该程序为 g++。args 数组指定将传递给 g++ 的命令行参数。这些参数必须按照编译器预期的方式进行指定。

该任务指示 g++ 获取活动文件 (${file}),对其进行编译,并在当前目录 (${fileDirname}) 中创建一个可执行文件,其名称与活动文件相同,但没有扩展名 (${fileBasenameNoExtension}),从而在我们的示例中生成 helloworld

label 值是您在任务列表中看到的,您可以将其命名为任何您喜欢的名称。

detail 值是您在任务列表中看到的任务描述。强烈建议您重命名此值,以将其与类似的任务区分开来。

从现在开始,播放按钮将从 tasks.json 读取以了解如何构建和运行您的程序。您可以在 tasks.json 中定义多个构建任务,并且标记为默认的任务将被播放按钮使用。如果您需要更改默认编译器,可以运行 任务:配置默认构建任务。或者,您也可以修改 tasks.json 文件,并通过用以下部分替换以下部分来删除默认值。

    "group": {
        "kind": "build",
        "isDefault": true
    },

用这个替换。

    "group": "build",

修改 tasks.json

您可以修改 tasks.json 以通过使用类似 "${workspaceFolder}/*.cpp" 而不是 "${file}" 的参数来构建多个 C++ 文件。这将构建当前文件夹中的所有 .cpp 文件。您还可以通过用硬编码文件名(例如 'helloworld.out')替换 "${fileDirname}/${fileBasenameNoExtension}" 来修改输出文件名。

调试 helloworld.cpp

要调试您的代码,请执行以下操作。

  1. 返回 helloworld.cpp,使其成为活动文件。
  2. 通过单击编辑器边距或在当前行上使用 F9 来设置断点。 screenshot of breakpoint in helloworld.cpp
  3. 从播放按钮旁边的下拉菜单中选择 Debug C/C++ FileScreenshot of play button drop-down
  4. 从系统上检测到的编译器列表中选择 C/C++: g++ build and debug active file(您只会第一次运行或调试 helloworld.cpp 时被要求选择编译器)。 C++ debug configuration dropdown

播放按钮有两种模式:运行 C/C++ 文件调试 C/C++ 文件。它将默认使用上次使用的模式。如果您在播放按钮中看到调试图标,您可以选择播放按钮进行调试,而不是选择下拉菜单项。

探索调试器

在您开始逐步执行代码之前,让我们花点时间注意用户界面中的几个变化。

  • 集成终端出现在源代码编辑器的底部。在 调试输出 选项卡中,您会看到指示调试器正在运行的输出。

  • 编辑器突出显示第 12 行,这是您在启动调试器之前设置的断点。

    Initial breakpoint

  • 左侧的 运行和调试 视图显示调试信息。您将在本教程后面的部分看到一个示例。

  • 在代码编辑器的顶部,会出现一个调试控制面板。您可以通过抓住左侧的点来将它移动到屏幕上的任何位置。

    Debugging controls

如果您在工作区中已经有一个 launch.json 文件,播放按钮将在确定如何运行和调试您的 C++ 文件时从该文件读取。如果您没有 launch.json,播放按钮会动态创建临时的“快速调试”配置,从而完全不需要 launch.json!

逐步执行代码

现在您已准备好开始逐步执行代码。

  1. 单击或按下调试控制面板中的 单步跳过 图标。

    Step over button

    这将使程序执行前进到 for 循环的第一行,并跳过在创建和初始化 msg 变量时调用的 vectorstring 类中的所有内部函数调用。注意侧边 变量 窗口中的变化。

    Debugging windows

  2. 再次按下 单步跳过 以前进到此程序中的下一条语句(跳过执行以初始化循环的所有内部代码)。现在,变量 窗口显示有关循环变量的信息。

  3. 再次按下 单步跳过 以执行 cout 语句。(请注意,C++ 扩展不会将任何输出打印到 调试控制台,直到最后一个 cout 执行。)

  4. 如果您愿意,您可以继续按下 单步跳过,直到向量中的所有单词都被打印到控制台。但如果您好奇,请尝试按下 单步进入 按钮来逐步执行 C++ 标准库中的源代码!

    Breakpoint in gcc standard library header

    要返回到您自己的代码,一种方法是继续按下 单步跳过。另一种方法是在您的代码中设置一个断点,方法是切换到代码编辑器中的 helloworld.cpp 选项卡,将插入点放在循环内的 cout 语句的某处,然后按下 F9。左侧的边距中会出现一个红色点,表示已在此行上设置了断点。

    Breakpoint in main

    然后按下 F5 以从标准库标头中的当前行开始执行。执行将在 cout 处中断。如果您愿意,可以再次按下 F9 以关闭断点。

    当循环完成时,您可以在集成终端的 调试控制台 选项卡中看到输出,以及 GDB 输出的一些其他诊断信息。

    Debug console display

设置监视

要跟踪变量在程序执行过程中的值,请对变量设置一个 监视器

  1. 将插入点放在循环内。在 监视器 窗口中,单击加号,并在文本框中输入 word,这是循环变量的名称。现在在逐步执行循环时查看监视器窗口。

    Watch window

  2. 要快速查看变量在断点暂停时的值,您可以在变量上悬停鼠标指针。

    Mouse hover

接下来,您将创建一个 tasks.json 文件来告诉 VS Code 如何构建(编译)程序。此任务将调用 g++ 编译器以从源代码创建可执行文件。

helloworld.cpp 保持在编辑器中很重要,因为下一步将使用编辑器中的活动文件作为上下文,在下一步中创建构建任务。

使用 launch.json 自定义调试

当您使用播放按钮或 F5 进行调试时,C++ 扩展会动态创建调试配置。

在某些情况下,您可能希望自定义调试配置,例如指定在运行时传递给程序的参数。您可以在 launch.json 文件中定义自定义调试配置。

要创建 launch.json,请从播放按钮下拉菜单中选择 添加调试配置

Add debug configuration play button menu

然后,您将看到一个包含各种预定义调试配置的下拉菜单。选择 g++ build and debug active file

C++ debug configuration dropdown

VS Code 创建一个 launch.json 文件,该文件看起来像这样。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++: g++ build and debug active file",
      "type": "cppdbg",
      "request": "launch",
      "program": "${fileDirname}/${fileBasenameNoExtension}",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "miDebuggerPath": "/usr/bin/gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ],
      "preLaunchTask": "C/C++: g++ build active file"
    }
  ]
}

在上面的 JSON 代码中,program 指定您要调试的程序。这里它被设置为活动文件文件夹 ${fileDirname} 和活动文件名(没有扩展名)${fileBasenameNoExtension},如果 helloworld.cpp 是活动文件,则它将为 helloworldargs 属性是在运行时传递给程序的参数数组。

默认情况下,C++ 扩展不会向您的源代码添加任何断点,并且 stopAtEntry 值被设置为 false

stopAtEntry 值更改为 true 以使调试器在您开始调试时在 main 方法上停止。

从现在开始,播放按钮和 F5 将在启动程序进行调试时从您的 launch.json 文件中读取。

C/C++ 配置

如果您想要对 C/C++ 扩展有更多控制权,您可以创建一个 c_cpp_properties.json 文件,它将允许您更改设置,例如编译器路径、包含路径、C++ 标准(默认值为 C++17)等等。

您可以通过从命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)) 中运行命令 C/C++: 编辑配置 (UI) 来查看 C/C++ 配置 UI。

Command Palette

这将打开 C/C++ 配置 页面。当您在此处进行更改时,VS Code 会将它们写入 .vscode 文件夹中的名为 c_cpp_properties.json 的文件。

Command Palette

只有当您的程序包含不在工作区或标准库路径中的头文件时,您才需要修改 包含路径 设置。

Visual Studio Code 将这些设置放在 .vscode/c_cpp_properties.json 中。如果您直接打开该文件,它应该看起来像这样。

{
  "configurations": [
    {
      "name": "Linux",
      "includePath": ["${workspaceFolder}/**"],
      "defines": [],
      "compilerPath": "/usr/bin/gcc",
      "cStandard": "c11",
      "cppStandard": "c++17",
      "intelliSenseMode": "clang-x64"
    }
  ],
  "version": 4
}

关闭 WSL 会话

完成在 WSL 中的工作后,您可以使用主 **文件** 菜单和命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)) 中提供的 **关闭远程连接** 命令关闭远程会话。这将重新启动本地运行的 VS Code。您可以从 **文件** > **最近打开** 列表中轻松重新打开您的 WSL 会话,方法是选择带有 **[WSL]** 后缀的文件夹。

后续步骤

  • 探索 VS Code 用户指南
  • 查看 C++ 扩展概述
  • 创建一个新的工作区,将您的 .json 文件复制到该工作区,调整新的工作区路径、程序名称等必要的设置,然后开始编码!