透過 MinGW 使用 GCC
在本教程中,你將配置 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
資料夾路徑新增到 Windows 的PATH
環境變數中- 在 Windows 搜尋欄中,輸入“設定”以開啟你的 Windows 設定。
- 搜尋“編輯賬戶的環境變數”。
- 在你的“使用者變數”中,選擇
Path
變數,然後選擇“編輯”。 - 選擇“新建”,並將你在安裝過程中記錄的 MinGW-w64 目標資料夾新增到列表中。如果你使用了上述預設設定,那麼路徑將是:
C:\msys64\ucrt64\bin
。 - 選擇“確定”,然後在“環境變數”視窗中再次選擇“確定”,以更新
PATH
環境變數。你必須重新開啟任何控制檯視窗,更新後的PATH
環境變數才會生效。
檢查你的 MinGW 安裝
要檢查你的 MinGW-w64 工具是否已正確安裝並可用,請開啟一個“新”的命令提示符並輸入
gcc --version
g++ --version
gdb --version
你應該會看到輸出,說明你安裝的 GCC、g++ 和 GDB 的版本。如果不是這種情況
- 確保你的 PATH 變數條目與安裝工具鏈的 MinGW-w64 二進位制檔案位置相匹配。如果編譯器在該 PATH 條目中不存在,請確保你已遵循之前的說明。
- 如果
gcc
輸出正確但gdb
不正確,那麼你需要從 MinGW-w64 工具集中安裝你缺少的軟體包。- 如果在編譯時收到“miDebuggerPath 的值無效”的訊息,一個可能的原因是你缺少
mingw-w64-gdb
軟體包。
- 如果在編譯時收到“miDebuggerPath 的值無效”的訊息,一個可能的原因是你缺少
建立一個 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 build and debug active file”。
你只會在第一次執行 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}
) 中建立一個與活動檔案同名但副檔名為 .exe
的輸出檔案 (-o
開關) (${fileBasenameNoExtension}.exe
)。對我們來說,這將生成 helloworld.exe
。
label
值是你在任務列表中將看到的內容;你可以隨意命名。
detail
的值將作為任務列表中該任務的描述。強烈建議重新命名此值以區別於類似的任務。
problemMatcher
的值用於選擇輸出解析器,以便在編譯器輸出中查詢錯誤和警告。對於 GCC,使用 $gcc
問題匹配器會得到最好的結果。
從現在開始,播放按鈕將從 tasks.json
中讀取資訊,以確定如何構建和執行你的程式。你可以在 tasks.json
中定義多個構建任務,任何被標記為預設的任務都將被播放按鈕使用。如果你需要更改預設編譯器,可以在命令面板中執行“任務:配置預設生成任務”。或者,你可以修改 tasks.json
檔案,並透過替換以下片段來移除預設設定
"group": {
"kind": "build",
"isDefault": true
},
替換為
"group": "build",
修改 tasks.json
從 2024 年 11 月 3 日起,MSYS2 預設停用了 mingw-w64
的萬用字元支援。此更改會影響像 "*.cpp"
這樣的萬用字元在構建命令中的處理方式。要在你的 tasks.json
中構建多個 C++ 檔案,你必須顯式列出檔案,使用像 make
或 cmake
這樣的構建系統,或實施以下解決方法:https://www.msys2.org/docs/c/#expanding-wildcard-arguments。
如果你以前使用 "${workspaceFolder}/*.cpp"
來編譯當前資料夾中的所有 .cpp
檔案,這將不再直接有效。相反,你可以手動列出檔案或定義一個構建指令碼。
除錯 helloworld.cpp
要除錯你的程式碼,
- 回到
helloworld.cpp
,使其成為活動檔案。 - 透過單擊編輯器邊距或在當前行使用 F9 設定斷點。
- 從播放按鈕旁邊的下拉選單中,選擇除錯 C/C++ 檔案。
- 從你係統上檢測到的編譯器列表中選擇“C/C++: g++ build and debug active file”(你只有在第一次執行或除錯
helloworld.cpp
時才會被要求選擇編譯器)。
播放按鈕有兩種模式:“執行 C/C++ 檔案”和“除錯 C/C++ 檔案”。它將預設為上次使用的模式。如果你在播放按鈕中看到除錯圖示,你可以直接選擇播放按鈕進行除錯,而無需使用下拉選單。
探索偵錯程式
在開始單步除錯程式碼之前,我們花點時間注意使用者介面中的幾處變化
-
整合終端出現在原始碼編輯器的底部。在“除錯控制檯”選項卡中,你會看到表明偵錯程式已啟動並正在執行的輸出。
-
編輯器會高亮顯示你在啟動偵錯程式之前設定斷點的行
-
左側的執行和除錯檢視顯示除錯資訊。你將在本教程的後面看到一個示例。
-
程式碼編輯器頂部會出現一個除錯控制面板。你可以透過抓取左側的點來在螢幕上移動它。
單步除錯程式碼
現在你已準備好開始單步除錯程式碼。
-
在除錯控制面板中選擇“單步跳過”圖示。
這將使程式執行前進到 for 迴圈的第一行,並跳過在建立和初始化
msg
變數時呼叫的vector
和string
類中的所有內部函式呼叫。請注意左側“變數”視窗中的變化。在這種情況下,出現錯誤是預期的,因為儘管迴圈的變數名現在對偵錯程式可見,但該語句尚未執行,所以此時沒有任何東西可讀。然而,
msg
的內容是可見的,因為那條語句已經完成了。 -
再次按跳過以推進到此程式中的下一個語句(跳過用於初始化迴圈的所有內部程式碼)。現在,變數視窗顯示有關迴圈變數的資訊。
-
再次按“單步跳過”以執行
cout
語句。(請注意,C++ 擴充套件在迴圈退出之前不會向“除錯控制檯”列印任何輸出。) -
如果你願意,可以繼續按單步跳過,直到向量中的所有單詞都列印到控制檯。但如果你好奇,可以嘗試按單步進入按鈕來單步執行 C++ 標準庫中的原始碼!
要返回到你自己的程式碼,一種方法是繼續按單步跳過。另一種方法是在你的程式碼中設定一個斷點,方法是切換到程式碼編輯器中的
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 build and debug active file”。
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)等設定。
你可以透過從命令面板 (⇧⌘P (Windows、Linux 為 Ctrl+Shift+P)) 執行 C/C++: 編輯配置 (UI) 命令來檢視 C/C++ 配置 UI。
這將開啟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
}
只有當你的程式包含不在你的工作區或標準庫路徑中的標頭檔案時,你才需要新增到“包含路徑”陣列設定中。強烈建議不要將系統包含路徑新增到我們支援的編譯器的 includePath
設定中。
編譯器路徑
擴充套件使用 compilerPath
設定來推斷 C++ 標準庫標頭檔案的路徑。當擴充套件知道在哪裡找到這些檔案時,它就可以提供像智慧補全和“轉到定義”導航等功能。
C/C++ 擴充套件會嘗試根據它在你係統上找到的內容,為 compilerPath
填充一個預設編譯器。擴充套件會在幾個常見的編譯器位置查詢,但只會自動選擇位於“Program Files”資料夾之一或其路徑列在 PATH 環境變數中的編譯器。如果能找到 Microsoft Visual C++ 編譯器,它將被選中,否則它將選擇一個版本的 gcc、g++ 或 clang。
如果你安裝了多個編譯器,你可能需要更改 compilerPath
以匹配你專案的首選編譯器。你也可以在命令面板中使用“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 檔案複製到其中,為新的工作區路徑、程式名稱等調整必要的設定,然後開始編碼吧!