在 Windows 上使用 MinGW 的 GCC

在本教學中,您將設定 Visual Studio Code 以使用來自 mingw-w64 的 GCC C++ 編譯器 (g++) 與 GDB 除錯器,進而在 Windows 上建立並執行程式。完成 VS Code 的設定後,您將會編譯、執行並偵錯一個 Hello World 程式。

本教學不會介紹 GCC、GDB、MinGW-w64 或 C++ 語言本身。若您想深入了解這些主題,網路上有許多優質的學習資源。

如果您遇到任何問題,歡迎在 VS Code 文件儲存庫中為本教學提交 Issue。

先決條件

若要成功完成本教學課程,您必須執行下列步驟

  1. 安裝 Visual Studio Code

  2. 安裝 VS Code 的 C/C++ 擴充功能。您可以透過擴充功能檢視中搜尋「C++」來安裝此擴充功能(⇧⌘X (Windows、Linux 為 Ctrl+Shift+X))。

    C/C++ extension

安裝 MinGW-w64 工具鏈

透過 MSYS2 取得最新版本的 MinGW-w64,它提供最新的 GCC 原生組建、MinGW-w64 以及其他有用的 C++ 工具與函式庫。這將為您提供編譯程式碼、偵錯,以及設定以與 IntelliSense 搭配運作所需的工具。

若要安裝 MinGW-w64 工具鏈,請觀看此影片或遵循以下步驟:

  1. 您可以從 MSYS2 頁面下載最新的安裝程式,或直接使用此 安裝程式直接連結

  2. 執行安裝程式並依照安裝精靈的步驟操作。請注意,MSYS2 需要 Windows 8.1 64 位元或更新版本。

  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. 請按照以下步驟將 ucrt64 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) 視窗中再次選擇 確定 以更新 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 搜尋列中輸入 命令提示字元)。
  2. 執行下列指令。這將建立一個名為 projects 的空白資料夾,您可以在其中放置所有的 VS Code 專案。接著,下一個指令將建立一個名為 helloworld 的子資料夾並切換至該路徑。從那裡,您將直接在 VS Code 中開啟 helloworld
mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .

指令「code .」會以當前資料夾開啟 VS Code,該資料夾即成為您的「工作區」。由於這是您自己建立的資料夾,請在 工作區信任 (Workspace Trust) 對話框中選擇 Yes, I trust the authors (是的,我信任作者)

在閱讀本教學的過程中,您會看到工作區中建立了一個 .vscode 資料夾,內含三個檔案:

  • tasks.json(建置指示)
  • launch.json(偵錯工具設定)
  • c_cpp_properties.json(編譯器路徑與 IntelliSense 設定)

新增一個 Hello World 原始碼檔案

在檔案總管標題列中,選取新增檔案按鈕,並將檔案命名為 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清除通知)來忽略此通知。

探索 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++ 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}),編譯它,並使用 -o 參數在當前目錄 (${fileDirname}) 下建立一個輸出檔案,其名稱與作用中檔案相同,但副檔名為 .exe (${fileBasenameNoExtension}.exe)。對我們來說,這會產生 helloworld.exe

label 值是您在工作清單中看到的名稱;您可以隨意命名。

detail 的值是您在任務清單中看到的任務描述。強烈建議重新命名此值,以便與類似的任務區分開來。

problemMatcher 值會選擇用來分析編譯器輸出以尋找錯誤與警告的剖析器。對於 GCC,使用 $gcc 問題比對器能獲得最佳結果。

從現在起,執行按鈕(播放鍵)將會讀取 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播放按鈕下拉式選單截圖
  4. 從系統偵測到的編譯器清單中選擇 C/C++: g++ build and debug active file (建置並偵錯作用中的檔案)(您僅會在第一次執行或偵錯 helloworld.cpp 時被要求選擇編譯器)。 C++ 除錯設定下拉式選單

執行按鈕有兩種模式:執行 C/C++ 檔案偵錯 C/C++ 檔案。它預設會使用上次使用的模式。如果您在執行按鈕上看到除錯圖示,您可以直接點擊執行按鈕進行偵錯,無需使用下拉式選單。

探索偵錯器

在開始逐步執行程式碼之前,讓我們花點時間留意使用者介面的幾項變更

  • 整合式終端機會出現在原始碼編輯器的底部。在 偵錯主控台 (Debug Console) 分頁中,您會看到顯示除錯器已啟動並執行的輸出訊息。

  • 編輯器會反白顯示您在啟動偵錯工具前設定中斷點的那一行。

    Initial breakpoint

  • 左側的「執行與偵錯」檢視會顯示偵錯資訊。您稍後會在教學課程中看到範例。

  • 在程式碼編輯器的頂部,會出現一個偵錯控制面板。您可以透過抓取左側的點將其移至畫面其他位置。

    Debugging controls

逐步執行程式碼

現在您已準備好開始逐步執行程式碼。

  1. 選取除錯控制面板中的 跳過 (Step over) 圖示。

    Step over button

    這會將程式執行進度推進到 for 迴圈的第一行,並跳過當 msg 變數建立與初始化時,vectorstring 類別內部的所有函式呼叫。請注意左側 變數 (Variables) 視窗中的變化。

    Debugging windows

    在此情況下,這些錯誤是預期的,因為儘管迴圈的變數名稱現在對於除錯器而言是可見的,但該語句尚未執行,因此目前沒有內容可讀取。然而,msg 的內容是可見的,因為該語句已經執行完成。

  2. 再次按下「跳過」以推進到程式中的下一個陳述式(跳過初始化迴圈所執行的所有內部程式碼)。現在,「變數」視窗會顯示迴圈變數的相關資訊。

  3. 再次按下 跳過 (Step over) 以執行 cout 語句。(請注意,在迴圈結束之前,C++ 擴充功能不會將任何輸出列印到 偵錯主控台。)

  4. 如果您願意,可以持續按下逐步跳過,直到向量中的所有單字都列印到主控台為止。但如果您感到好奇,請嘗試按下逐步執行 (Step Into) 按鈕,以逐步追蹤 C++ 標準函式庫中的原始程式碼!

    若要回到您自己的程式碼,一種方法是持續按下「跳過」。另一種方法是在您的程式碼中設定中斷點:切換至程式碼編輯器中的 helloworld.cpp 索引標籤,將插入點放在迴圈內 cout 陳述式的某處,然後按下 F9。左側裝訂邊會出現一個紅點,表示已在此行設定中斷點。

    Breakpoint in main

    然後按下 F5 從標準程式庫標頭中的目前行開始執行。程式執行將會在 cout 處中斷。如果您願意,可以再次按下 F9 來取消中斷點。

    當迴圈完成時,您可以在整合式終端機中看到輸出,以及 GDB 所輸出的其他診斷資訊。

    Debug output in terminal

設定監看式 (Watch)

有時您可能希望在程式執行時追蹤變數的值。您可以透過對該變數設定 監看 (watch) 來達成。

  1. 將游標放置在迴圈內部。在 監看 (Watch) 視窗中,選取加號並在文字框中輸入 word(迴圈變數的名稱)。現在,當您逐行執行迴圈時,請觀察監看視窗。

    Watch window

  2. 在迴圈前新增此陳述式以增加另一個監看式:int i = 0;。然後在迴圈內新增此陳述式:++i;。現在,像前一步驟那樣,為 i 新增監看式。

  3. 若要在執行於中斷點暫停時快速查看任何變數的值,您可以將滑鼠指標懸停在該變數上。

    Mouse hover

使用 launch.json 自訂偵錯

當您使用執行按鈕或 F5 進行偵錯時,C++ 擴充功能會即時建立動態偵錯設定。

在某些情況下,您會希望自訂偵錯設定,例如指定在執行階段傳遞給程式的參數。您可以在 launch.json 檔案中定義自訂偵錯設定。

若要建立 launch.json,請從執行按鈕下拉式選單中選擇 新增偵錯設定

Add debug configuration play button menu

接著您會看到各種預先定義除錯設定的下拉式清單。請選擇 C/C++: g++.exe build and debug active file

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。

Command Palette

這會開啟 C/C++ 設定頁面。當您在此處進行變更時,VS Code 會將其寫入 .vscode 資料夾中名為 c_cpp_properties.json 的檔案。

在這裡,我們將 Configuration name (設定名稱) 更改為 GCC,將 Compiler path (編譯器路徑) 下拉選單設為 g++ 編譯器,並將 IntelliSense mode 設為與編譯器相符的模式 (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 陣列設定。強烈建議不要將系統的 include 路徑加入至我們所支援編譯器的 includePath 設定中。

編譯器路徑

擴充功能會使用 compilerPath 設定來推斷 C++ 標準函式庫標頭檔的路徑。當擴充功能知道去哪裡尋找這些檔案時,就能提供如智慧補全與 前往定義 (Go to Definition) 導覽等功能。

C/C++ 擴充功能會嘗試根據系統上找到的編譯器,自動填入 compilerPath 的預設值。擴充功能會搜尋幾個常見的編譯器位置,但只會自動選擇那些位於「Program Files」資料夾中,或是路徑已列在 PATH 環境變數中的編譯器。如果能找到 Microsoft Visual C++ 編譯器,它將會被選取;否則它會選擇 gcc、g++ 或 clang 的版本。

如果您安裝了多個編譯器,您可能需要變更 compilerPath 以符合您專案偏好的編譯器。您也可以在指令選擇區中使用 C/C++: Select IntelliSense Configuration... (選取 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 位元

如果您需要 MinGW 工具集的 32 位元版本,請查閱 MSYS2 wiki 上的 Downloading (下載) 章節。其中包含了 32 位元與 64 位元安裝選項的連結。

後續步驟

  • 探索 VS Code 使用者指南
  • 查閱 C++ 擴充功能總覽
  • 建立一個新的工作區,將您的 .vscode JSON 檔案複製過去,根據新工作區的路徑、程式名稱等調整必要的設定,然後開始撰寫程式碼!
© . This site is unofficial and not affiliated with Microsoft.