在 VS Code 中试试

结合 MinGW 使用 GCC

在本教程中,你将配置 Visual Studio Code,使用 mingw-w64 中的 GCC C++ 编译器 (g++) 和 GDB 调试器来创建在 Windows 上运行的程序。配置 VS Code 后,你将编译、运行和调试一个 Hello World 程序。

本教程不讲解 GCC、GDB、minGW-w64 或 C++ 语言。关于这些主题,Web 上有许多优秀的资源。

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

先决条件

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

  1. 安装 Visual Studio Code

  2. 安装适用于 VS Code 的 C/C++ 扩展。你可以在“扩展”视图 (⇧⌘X (Windows, Linux Ctrl+Shift+X)) 中搜索“C++”来安装 C/C++ 扩展。

    C/C++ extension

安装 MinGW-w64 工具链

通过MSYS2获取最新版本的 MinGW-w64,它提供最新的 GCC、MinGW-w64 和其他有用的 C++ 工具和库的本地构建。这将为你提供编译代码、调试代码以及将其配置为与IntelliSense协作所需的工具。

要安装 MinGW-w64 工具链,请观看此视频或按照以下步骤操作

  1. 你可以从 MSYS2 页面下载最新的安装程序,或者使用此安装程序直链

  2. 运行安装程序并按照安装向导的步骤进行操作。请注意,MSYS2 需要 64 位 Windows 8.1 或更新版本。

  3. 在向导中,选择你想要的安装文件夹。记下此目录以备后用。在大多数情况下,推荐的目录是可接受的。当你进入设置开始菜单快捷方式的步骤时也是如此。完成后,确保选中 Run MSYS2 now(立即运行 MSYS2)复选框,然后选择 Finish(完成)。这将为你打开一个 MSYS2 终端窗口。

  4. 在该终端中,运行以下命令安装 MinGW-w64 工具链

    pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain
    
  5. Enter 接受 toolchain 组中的默认软件包数量。

    MYSS2 Installer

  6. 当提示是否继续安装时,输入 Y

  7. 使用以下步骤将 MinGW-w64 的 bin 文件夹路径添加到 Windows PATH 环境变量中

    1. 在 Windows 搜索栏中,输入 Settings(设置)以打开 Windows 设置。
    2. 搜索 Edit environment variables for your account(编辑帐户的环境变量)。
    3. User variables(用户变量)中,选择 Path 变量,然后选择 Edit(编辑)。
    4. 选择 New(新建),并将你在安装过程中记录的 MinGW-w64 目标文件夹添加到列表中。如果你使用了上述默认设置,则路径将是:C:\msys64\ucrt64\bin
    5. 选择 OK(确定),然后在 Environment Variables(环境变量)窗口中再次选择 OK(确定)以更新 PATH 环境变量。你必须重新打开任何控制台窗口,以便更新的 PATH 环境变量生效。

检查你的 MinGW 安装

要检查 MinGW-w64 工具是否正确安装并可用,请打开一个新的命令提示符并输入

gcc --version
g++ --version
gdb --version

你应该会看到输出,其中说明了你安装的 GCC、g++ 和 GDB 版本。如果情况并非如此

  1. 确保你的 PATH 变量条目与安装工具链的 MinGW-w64 二进制文件位置匹配。如果编译器不存在于该 PATH 条目中,请确保你遵循了之前的说明。
  2. 如果 gcc 输出正确但 gdb 没有,则你需要从 MinGW-w64 工具集安装你缺失的软件包。
    • 如果在编译时收到“The value of miDebuggerPath is invalid.”(miDebuggerPath 的值无效。)消息,一个原因可能是你缺失了 mingw-w64-gdb 软件包。

创建 Hello World 应用

首先,我们来设置一个项目。

  1. 启动 Windows 命令提示符(在 Windows 搜索栏中输入 Windows command prompt)。
  2. 运行以下命令。这些命令将创建一个名为 projects 的空文件夹,你可以在其中放置所有 VS Code 项目。然后,接下来的命令将创建并导航到一个名为 helloworld 的子文件夹。从那里,你将直接在 VS Code 中打开 helloworld
mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .

“code .”命令会在当前工作文件夹中打开 VS Code,该文件夹成为你的“工作区”。由于这是你自己创建的文件夹,请通过选择 Yes, I trust the authors(是的,我信任作者)来接受工作区信任对话框。

在学习本教程的过程中,你会在工作区的 .vscode 文件夹中看到创建的三个文件

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

添加一个 Hello World 源代码文件

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

New File title bar 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

你还可以通过选择 File(文件)> Auto Save(自动保存)来启用自动保存,以自动保存你的文件更改。你可以在 VS Code 的用户界面文档中了解更多关于其他视图的信息。

注意:当你保存或打开 C++ 文件时,你可能会看到来自 C/C++ 扩展的关于 Insiders 版本可用性的通知,该版本允许你测试新功能和修复。你可以通过选择 X (Clear Notification) 来忽略此通知。

探索 IntelliSense

IntelliSense 是一种工具,通过添加代码编辑功能(如代码补全、参数信息、快速信息和成员列表)来帮助你更快、更高效地编写代码。

要查看 IntelliSense 的实际效果,将鼠标悬停在 vectorstring 上以查看它们的类型信息。如果你在第 10 行输入 msg.,你会看到一个推荐的成员函数列表,所有这些都是由 IntelliSense 生成的

Statement completion IntelliSense

你可以按下 Tab 键插入选定的成员。如果你随后添加开括号,IntelliSense 将显示需要哪些参数的信息。

如果 IntelliSense 尚未配置,请打开命令面板 (⇧⌘P (Windows, Linux Ctrl+Shift+P)),然后输入 Select IntelliSense Configuration(选择 IntelliSense 配置)。从编译器下拉列表中,选择 Use gcc.exe 进行配置。更多信息可以在IntelliSense 配置文档中找到。

运行 helloworld.cpp

请记住,C++ 扩展使用你计算机上安装的 C++ 编译器来构建你的程序。在尝试在 VS Code 中运行和调试 helloworld.cpp 之前,请确保你已完成“安装 MinGW-w64 工具链”步骤。

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

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

    Screenshot of helloworld.cpp and play button

  3. 从系统检测到的编译器列表中选择 C/C++: g++.exe build and debug active file(C/C++: g++.exe 构建并调试活动文件)。

    C++ debug configuration dropdown

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

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

    screenshot of program output

恭喜你!你刚刚在 VS Code 中运行了你的第一个 C++ 程序!

了解 tasks.json

当你第一次运行程序时,C++ 扩展会创建一个 tasks.json 文件,该文件位于你项目的 .vscode 文件夹中。tasks.json 存储你的构建配置。

你的新 tasks.json 文件应该类似于下面的 JSON

{
  "tasks": [
    {
      "type": "cppbuild",
      "label": "C/C++: g++.exe build active file",
      "command": "C:\\msys64\\ucrt64\\bin\\g++.exe",
      "args": [
        "-fdiagnostics-color=always",
        "-g",
        "${file}",
        "-o",
        "${fileDirname}\\${fileBasenameNoExtension}.exe"
      ],
      "options": {
        "cwd": "${fileDirname}"
      },
      "problemMatcher": ["$gcc"],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "detail": "Task generated by Debugger."
    }
  ],
  "version": "2.0.0"
}

注意:你可以在变量参考中了解更多关于 tasks.json 变量的信息。

command 设置指定要运行的程序;在本例中为 g++

args 数组指定传递给 g++ 的命令行参数。这些参数在此文件中按编译器预期的特定顺序排列。

此任务告诉 g++ 获取活动文件 (${file}),编译它,并在当前目录 (${fileDirname}) 中创建一个输出文件 (-o 切换),该文件的名称与活动文件相同,但扩展名为 .exe (${fileBasenameNoExtension}.exe)。对我们而言,这将生成 helloworld.exe

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

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

problemMatcher 值选择用于在编译器输出中查找错误和警告的输出解析器。对于 GCC,如果你使用 $gcc problem matcher,你将获得最佳结果。

从现在开始,播放按钮将从 tasks.json 中读取,以确定如何构建和运行你的程序。你可以在 tasks.json 中定义多个构建任务,并且播放按钮将使用标记为默认的任务。如果你需要更改默认编译器,可以在命令面板中运行 Tasks: Configure Default Build Task(任务:配置默认构建任务)。或者,你可以修改 tasks.json 文件,通过替换此片段来删除默认设置

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

替换为

    "group": "build",

修改 tasks.json

自 2024 年 11 月 3 日起,MSYS2 默认禁用 mingw-w64 的通配符支持。此更改会影响构建命令中如何处理 "*.cpp" 等通配符。要在 tasks.json 中构建多个 C++ 文件,你必须显式列出文件,使用 makecmake 等构建系统,或实现以下变通方法:https://www.msys2.org/docs/c/#expanding-wildcard-arguments。

如果你之前使用 "${workspaceFolder}/*.cpp" 编译当前文件夹中的所有 .cpp 文件,这将不再直接起作用。你可以改为手动列出文件或定义构建脚本。

调试 helloworld.cpp

要调试你的代码,

  1. 返回 helloworld.cpp,使其成为活动文件。
  2. 通过单击编辑器边距或在当前行上使用 F9 设置断点。 helloworld.cpp 中的断点截图
  3. 从播放按钮旁边的下拉菜单中,选择 Debug C/C++ File(调试 C/C++ 文件)。 播放按钮下拉菜单截图
  4. 从系统检测到的编译器列表中选择 C/C++: g++ build and debug active file(C/C++: g++ 构建并调试活动文件)(只有在你第一次运行或调试 helloworld.cpp 时才会要求你选择编译器)。 C++ 调试配置下拉菜单

播放按钮有两种模式:Run C/C++ File(运行 C/C++ 文件)和 Debug C/C++ File(调试 C/C++ 文件)。它将默认使用上次使用的模式。如果你在播放按钮中看到调试图标,你可以直接选择播放按钮进行调试,而无需使用下拉菜单。

探索调试器

在开始单步调试代码之前,让我们花点时间注意用户界面的几个变化

  • 集成终端出现在源代码编辑器的底部。在调试控制台选项卡中,你会看到表明调试器已启动并正在运行的输出。

  • 编辑器会突出显示你在启动调试器之前设置的断点所在的行

    Initial breakpoint

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

  • 在代码编辑器的顶部,会出现一个调试控制面板。你可以通过抓取左侧的点将其在屏幕上移动。

    Debugging controls

单步调试代码

现在你已准备好开始单步调试代码了。

  1. 选择调试控制面板中的单步跳过图标。

    Step over button

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

    Debugging windows

    在这种情况下,出现错误是意料之中的,因为尽管循环的变量名称现在对于调试器来说是可见的,但该语句尚未执行,因此此时无法读取任何内容。然而,msg 的内容是可见的,因为该语句已经完成。

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

  3. 再次按下单步跳过,执行 cout 语句。(请注意,C++ 扩展在循环退出之前不会向调试控制台打印任何输出。)

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

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

    Breakpoint in main

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

    循环完成后,你可以在集成终端中看到输出,以及 GDB 输出的一些其他诊断信息。

    Debug output in terminal

设置监视

有时你可能想在程序执行时跟踪变量的值。你可以通过在变量上设置监视来实现此目的。

  1. 将插入点放在循环内部。在监视窗口中,选择加号并在文本框中输入 word,它是循环变量的名称。现在,在你单步执行循环时查看“监视”窗口。

    Watch window

  2. 通过在循环之前添加语句 int i = 0; 来添加另一个监视。然后,在循环内部添加语句 ++i;。现在,像上一步一样为 i 添加一个监视。

  3. 要在执行暂停在断点时快速查看任何变量的值,可以将鼠标指针悬停在其上。

    Mouse hover

使用 launch.json 自定义调试

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

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

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

Add debug configuration play button menu

然后你会看到一个包含各种预定义调试配置的下拉菜单。选择 C/C++: g++.exe build and debug active file(C/C++: g++.exe 构建并调试活动文件)。

C++ debug configuration dropdown

VS Code 在 .vscode 文件夹中创建一个 launch.json 文件,该文件如下所示

{
  "configurations": [
    {
      "name": "C/C++: g++.exe build and debug active file",
      "type": "cppdbg",
      "request": "launch",
      "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${fileDirname}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "miDebuggerPath": "C:\\msys64\\ucrt64\\bin\\gdb.exe",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        },
        {
          "description": "Set Disassembly Flavor to Intel",
          "text": "-gdb-set disassembly-flavor intel",
          "ignoreFailures": true
        }
      ],
      "preLaunchTask": "C/C++: g++.exe build active file"
    }
  ],
  "version": "2.0.0"
}

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

默认情况下,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++: Edit Configurations (UI)(C/C++: 编辑配置 (UI))来查看 C/C++ 配置 UI。

Command Palette

这将打开 C/C++ Configurations(C/C++ 配置)页面。在此处所做的更改,VS Code 会将它们写入 .vscode 文件夹中名为 c_cpp_properties.json 的文件中。

在这里,我们将Configuration name(配置名称)更改为 GCC,将Compiler path(编译器路径)下拉菜单设置为 g++ 编译器,并将IntelliSense mode(IntelliSense 模式)设置为与编译器匹配 (gcc-x64)。

Command Palette

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

{
  "configurations": [
    {
      "name": "GCC",
      "includePath": ["${workspaceFolder}/**"],
      "defines": ["_DEBUG", "UNICODE", "_UNICODE"],
      "windowsSdkVersion": "10.0.22000.0",
      "compilerPath": "C:/msys64/mingw64/bin/g++.exe",
      "cStandard": "c17",
      "cppStandard": "c++17",
      "intelliSenseMode": "windows-gcc-x64"
    }
  ],
  "version": 4
}

仅当你的程序包含不在你的工作区或标准库路径中的头文件时,才需要添加到Include path(包含路径)数组设置中。对于我们支持的编译器,强烈建议不要将系统包含路径添加到 includePath 设置中。

编译器路径

扩展使用 compilerPath 设置来推断 C++ 标准库头文件的路径。当扩展知道在哪里找到这些文件时,它可以提供诸如智能补全和转到定义导航等功能。

C/C++ 扩展会尝试根据在你的系统上找到的内容,使用默认编译器填充 compilerPath。扩展会查找几个常见的编译器位置,但只会自动选择位于“Program Files”文件夹之一或其路径列在 PATH 环境变量中的编译器。如果找到 Microsoft Visual C++ 编译器,则会选择它,否则将选择 gcc、g++ 或 clang 的版本。

如果你安装了多个编译器,你可能需要更改 compilerPath 以匹配项目首选的编译器。你也可以在命令面板中使用 C/C++: Select InteliSense Configuration...(C/C++: 选择 IntelliSense 配置...)命令来选择扩展检测到的其中一个编译器。

故障排除

MSYS2 已安装,但仍找不到 g++ 和 gdb

你必须按照MSYS2 网站上的步骤,使用 MSYS CLI 安装完整的 MinGW-w64 工具链 (pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain),以及所有必需的先决条件。该工具链包含 g++ 和 gdb。

作为 Windows 用户,运行 pacman 命令时出错

Windows 计算机上的 UCRT 仅包含在 Windows 10 或更高版本中。如果你使用其他版本的 Windows,请运行以下不使用 UCRT 的命令

pacman -S --needed base-devel mingw-w64-x86_64-toolchain

将 MinGW-w64 目标文件夹添加到环境变量列表时,默认路径将是:C:\msys64\mingw64\bin

MinGW 32 位

如果你需要 32 位版本的 MinGW 工具集,请查阅 MSYS2 wiki 上的下载部分。它包含 32 位和 64 位安装选项的链接。

下一步

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