使用GCC与MinGW
在本教程中,您将配置Visual Studio Code以使用来自mingw-w64的GCC C++编译器(g++)和GDB调试器来创建在Windows上运行的程序。配置完VS Code后,您将编译、运行并调试一个Hello World程序。
本教程不教授关于GCC、GDB、minGW-w64或C++语言的知识。对于这些主题,网上有许多优秀的资源可供参考。
如果您有任何问题,请随时在本教程的VS Code 文档仓库中提交问题。
先决条件
要成功完成本教程,您必须执行以下步骤:
-
安装VS Code的C/C++扩展。您可以通过在扩展视图(⇧⌘X (Windows, Linux Ctrl+Shift+X))中搜索'C++'来安装C/C++扩展。
安装 MinGW-w64 工具链
通过MSYS2获取最新版本的MinGW-w64,它提供了最新的GCC、MinGW-w64以及其他有用的C++工具和库的本地构建。这将为您提供编译代码、调试代码以及配置代码以与IntelliSense配合使用所需的必要工具。
要安装MinGW-w64工具链,请查看此视频或按照以下步骤操作:
-
您可以从MSYS2页面下载最新的安装程序,或使用此直接链接到安装程序。
-
运行安装程序并按照安装向导的步骤操作。请注意,MSYS2需要64位的Windows 8.1或更新版本。
-
在向导中,选择您所需的安装文件夹。请记录此目录以备后用。在大多数情况下,推荐的目录是可以接受的。当您进入设置开始菜单快捷方式的步骤时,同样适用。完成后,请确保选中立即运行MSYS2复选框,然后选择完成。这将为您打开一个MSYS2终端窗口。
-
在此终端中,通过运行以下命令安装MinGW-w64工具链:
pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain
-
按Enter键接受
toolchain
组中的默认包数量。 -
当提示是否继续安装时,输入
Y
。 -
将您的MinGW-w64
bin
文件夹路径添加到WindowsPATH
环境变量中,步骤如下:- In the Windows search bar, type Settings to open your Windows Settings.
- Search for Edit environment variables for your account.
- In your User variables, select the
Path
variable and then select Edit. - Select New and add the MinGW-w64 destination folder you recorded during the installation process to the list. If you used the default settings above, then this will be the path:
C:\msys64\ucrt64\bin
. - Select OK, and then select OK again in the Environment Variables window to update the
PATH
environment variable. You have to reopen any console windows for the updatedPATH
environment variable to be available.
检查你的MinGW安装
要检查您的MinGW-w64工具是否正确安装并可用,请打开一个新的命令提示符并输入:
gcc --version
g++ --version
gdb --version
你应该看到输出,说明你安装了哪些版本的GCC、g++和GDB。如果不是这种情况:
- 确保您的PATH变量条目与安装工具链的MinGW-w64二进制位置匹配。如果编译器在该PATH条目中不存在,请确保您遵循了之前的说明。
- 如果
gcc
有正确的输出但gdb
没有,那么你需要从 MinGW-w64 工具集中安装你缺少的包。- 如果在编译时你收到 "The value of miDebuggerPath is invalid." 消息,一个可能的原因是你缺少
mingw-w64-gdb
包。
- 如果在编译时你收到 "The value of miDebuggerPath is invalid." 消息,一个可能的原因是你缺少
创建一个Hello World应用
首先,让我们设置一个项目。
- 启动Windows命令提示符(在Windows搜索栏中输入Windows命令提示符)。
- 运行以下命令。这些命令将创建一个名为
projects
的空文件夹,您可以在其中放置所有VS Code项目。接下来,这些命令将创建并导航到一个名为helloworld
的子文件夹。从那里,您将直接在VS Code中打开helloworld
。
mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .
"code ." 命令在当前工作文件夹中打开 VS Code,该文件夹将成为您的“工作区”。由于这是您创建的文件夹,请通过选择是,我信任作者来接受工作区信任对话框。
在您学习教程的过程中,您将看到在工作区的.vscode
文件夹中创建了三个文件:
tasks.json
(构建指令)launch.json
(调试器设置)c_cpp_properties.json
(编译器路径和IntelliSense设置)
添加一个Hello World源代码文件
在文件资源管理器的标题栏中,选择新建文件按钮并将文件命名为helloworld.cpp
。
添加 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)):
你也可以通过选择文件 > 自动保存来启用自动保存,以自动保存你的文件更改。你可以在VS Code的用户界面文档中了解更多关于其他视图的信息。
注意: 当你保存或打开一个C++文件时,你可能会看到来自C/C++扩展的通知,提示有Insiders版本可用,该版本允许你测试新功能和修复。你可以通过选择
X
(清除通知)来忽略此通知。
探索 IntelliSense
IntelliSense 是一个工具,通过添加代码编辑功能(如代码补全、参数信息、快速信息和成员列表)来帮助您更快、更高效地编写代码。
要查看IntelliSense的实际效果,
将鼠标悬停在vector
或string
上以查看它们的类型信息。如果您在第10行输入msg.
,您可以看到由IntelliSense生成的推荐成员函数的完成列表:
您可以按下 Tab 键来插入选定的成员。如果您随后添加开括号,IntelliSense 将显示所需参数的信息。
如果尚未配置IntelliSense,请打开命令面板(⇧⌘P (Windows, Linux Ctrl+Shift+P))并输入选择IntelliSense配置。从编译器下拉列表中,选择使用gcc.exe
进行配置。更多信息可以在IntelliSense配置文档中找到。
运行 helloworld.cpp
请记住,C++ 扩展使用您机器上安装的 C++ 编译器来构建您的程序。在尝试在 VS Code 中运行和调试 helloworld.cpp
之前,请确保您已完成“安装 MinGW-w64 工具链”步骤。
-
打开
helloworld.cpp
使其成为活动文件。 -
按下编辑器右上角的播放按钮。
-
从系统检测到的编译器列表中选择C/C++: g++.exe 构建并调试活动文件。
您只需在第一次运行helloworld.cpp
时选择编译器。此编译器将被设置为tasks.json
文件中的“默认”编译器。
-
构建成功后,您的程序的输出将显示在集成的终端中。
恭喜!您刚刚在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
问题匹配器,您将获得最佳结果。
从现在开始,播放按钮将从tasks.json
中读取以确定如何构建和运行您的程序。您可以在tasks.json
中定义多个构建任务,播放按钮将使用标记为默认的任务。如果您需要更改默认编译器,可以在命令面板中运行任务:配置默认构建任务。或者,您可以修改tasks.json
文件并通过替换以下部分来移除默认设置:
"group": {
"kind": "build",
"isDefault": true
},
用这个:
"group": "build",
修改 tasks.json
你可以修改你的tasks.json
,通过使用像"${workspaceFolder}/*.cpp"
这样的参数来构建多个C++文件,而不是"${file}"
。这将构建你当前文件夹中的所有.cpp
文件。你也可以通过将"${fileDirname}\\${fileBasenameNoExtension}.exe"
替换为硬编码的文件名(例如"${workspaceFolder}\\myProgram.exe"
)来修改输出文件名。
调试 helloworld.cpp
调试你的代码,
- 返回到
helloworld.cpp
,使其成为活动文件。 - 通过点击编辑器边距或使用F9在当前行设置断点。
- 从播放按钮旁边的下拉菜单中,选择调试C/C++文件。
- 从系统检测到的编译器列表中选择C/C++: g++ 构建并调试活动文件(只有在首次运行或调试
helloworld.cpp
时才会要求选择编译器)。
播放按钮有两种模式:运行 C/C++ 文件 和 调试 C/C++ 文件。它将默认为上次使用的模式。如果您在播放按钮中看到调试图标,您可以直接选择播放按钮进行调试,而不是使用下拉菜单。
探索调试器
在开始逐步查看代码之前,让我们花点时间注意用户界面中的几个变化:
-
集成终端出现在源代码编辑器的底部。在调试控制台标签中,您会看到指示调试器已启动并正在运行的输出。
-
编辑器在启动调试器之前突出显示您设置断点的行:
-
左侧的运行和调试视图显示调试信息。在本教程的后面部分,您将看到一个示例。
-
在代码编辑器的顶部,会出现一个调试控制面板。您可以通过抓住左侧的点在屏幕上移动它。
逐步执行代码
现在你已经准备好开始逐步执行代码了。
-
在调试控制面板中选择Step over图标。
这将使程序执行前进到for循环的第一行,并跳过在创建和初始化
msg
变量时调用的vector
和string
类中的所有内部函数调用。请注意左侧变量窗口中的变化。在这种情况下,出现错误是预期的,因为尽管循环的变量名称现在对调试器可见,但语句尚未执行,因此此时没有内容可读取。然而,
msg
的内容是可见的,因为该语句已经完成。 -
再次按下Step over以推进到程序中的下一个语句(跳过所有用于初始化循环的内部代码)。现在,Variables窗口显示了有关循环变量的信息。
-
再次按下Step over以执行
cout
语句。(请注意,C++扩展在循环退出之前不会向Debug Console打印任何输出。) -
如果你愿意,你可以一直按Step over,直到向量中的所有单词都被打印到控制台。但如果你好奇,可以尝试按Step Into按钮,逐步查看C++标准库中的源代码!
要返回到您自己的代码,一种方法是持续按下Step over。另一种方法是在代码编辑器中切换到
helloworld.cpp
标签,将插入点放在循环内的cout
语句上,然后按下F9。左侧的装订线会出现一个红点,表示已在此行设置了断点。然后按下 F5 从标准库头文件的当前行开始执行。执行将在
cout
处中断。如果你愿意,可以再次按下 F9 来关闭断点。当循环完成后,您可以在集成终端中看到输出,以及一些由GDB输出的其他诊断信息。
设置监视
有时你可能希望在程序执行时跟踪变量的值。你可以通过在变量上设置监视来实现这一点。
-
将插入点放在循环内部。在监视窗口中,选择加号并在文本框中输入
word
,这是循环变量的名称。现在,当您逐步执行循环时,查看监视窗口。 -
在循环之前添加以下语句来添加另一个监视:
int i = 0;
。然后,在循环内部添加以下语句:++i;
。现在,像上一步一样为i
添加一个监视。 -
要在执行在断点处暂停时快速查看任何变量的值,您可以将鼠标指针悬停在其上。
使用 launch.json 自定义调试
当你使用播放按钮或F5进行调试时,C++扩展会动态创建一个调试配置。
在某些情况下,您可能希望自定义调试配置,例如指定在运行时传递给程序的参数。您可以在launch.json
文件中定义自定义调试配置。
要创建 launch.json
,请从播放按钮下拉菜单中选择 添加调试配置。
然后你会看到一个下拉菜单,其中包含各种预定义的调试配置。选择C/C++: g++.exe 构建并调试活动文件。
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.exe
。args
属性是在运行时传递给程序的参数数组。
默认情况下,C++ 扩展不会向您的源代码添加任何断点,并且 stopAtEntry
值设置为 false
。
将stopAtEntry
值更改为true
,以便在开始调试时使调试器在main
方法处停止。
从现在开始,当启动程序进行调试时,播放按钮和 F5 将从您的
launch.json
文件中读取。
添加额外的C/C++设置
如果您想对C/C++扩展进行更多控制,可以创建一个c_cpp_properties.json
文件,该文件允许您更改设置,例如编译器的路径、包含路径、C++标准(默认为C++17)等。
您可以通过从命令面板运行命令C/C++: 编辑配置 (UI)来查看C/C++配置界面(⇧⌘P (Windows, Linux Ctrl+Shift+P))。
这将打开C/C++配置页面。当您在此处进行更改时,VS Code会将它们写入.vscode
文件夹中名为c_cpp_properties.json
的文件。
在这里,我们将配置名称更改为GCC,将编译器路径下拉菜单设置为g++编译器,并将IntelliSense模式设置为与编译器匹配(gcc-x64)。
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
}
如果您的程序包含不在您的工作区或标准库路径中的头文件,您只需要添加到包含路径数组设置中。
编译器路径
扩展使用compilerPath
设置来推断C++标准库头文件的路径。当扩展知道在哪里找到这些文件时,它可以提供智能补全和转到定义导航等功能。
C/C++ 扩展尝试根据在您的系统上找到的内容,使用默认编译器位置填充 compilerPath
。该扩展会在几个常见的编译器位置中查找。
compilerPath
的搜索顺序是:
- 首先检查Microsoft Visual C++编译器
- 然后在适用于 Linux 的 Windows 子系统 (WSL) 上查找 g++
- 然后使用 g++ 编译 MinGW-w64。
如果您已安装Visual Studio或WSL,可能需要更改compilerPath
以匹配您项目的首选编译器。例如,如果您使用i686架构、Win32线程和sjlj异常处理安装选项安装了MinGW-w64版本8.1.0,路径将如下所示:C:\Program Files (x86)\mingw-w64\i686-8.1.0-win32-sjlj-rt_v6-rev0\mingw64\bin\g++.exe
。
故障排除
已安装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维基上的下载部分。它包括32位和64位安装选项的链接。
下一步
- 探索VS Code 用户指南。
- 查看C++扩展概述。
- 创建一个新的工作区,将你的
.vscode
JSON文件复制到其中,调整新工作区路径、程序名称等的必要设置,然后开始编码!