一文搞懂C/C++常用編譯器

陌尘(MoChen)發表於2024-08-08
  • 1. C++ 編譯器介紹
    • 1.1. MSVC
      • 1.1.1. Visual C++Visual Studio的版本對應關係
      • 1.1.2. 工具鏈的主要工具
    • 1.2. GCC
      • 1.2.1. GCC的主要優點
      • 1.2.2. GCC的常用工具
      • 1.2.3. MinGW
    • 1.3. Clang/LLVM
      • 1.3.1. Clang介紹
      • 1.3.2. Clang與LLVM的關係
      • 1.3.3. Clang/LLVM與GCC
  • 2. C++ 編譯器的安裝
    • 2.1. Windows
      • 2.1.1. MSVC安裝
      • 2.1.2. 環境變數配置
    • 2.2. Linux(Ubuntu)
      • 2.2.1. 安裝GCC/GDB
      • 2.2.2. 安裝CMake
    • 2.3. macOS
      • 2.3.1. clang的安裝
      • 2.3.2. 為什麼gcc的版本號顯示的是Clang version
      • 2.3.3. gcc的安裝
  • 3. 驗證編譯器是否安裝正常
    • 3.1. 寫一個測試Demo
    • 3.2. 編譯並執行
      • 3.2.1. Windows
      • 3.2.2. Linux
      • 3.2.3. macOS

1. C++ 編譯器介紹

MSVC,GCC和Clang是業界三種最主流的C/C++編譯器,下面粗劣比較一下他們的差異:

C++編譯器 編譯器全稱 支援的平臺 備註
MSVC Microsoft Visual C++ Windows 由微軟開發,主要用於Windows平臺應用程式的開發。Visual Studio系列IDE預設整合了該編譯器
GCC GNU Compiler Collection Windows, Linux, macOS 開源編譯器,支援多種平臺,Linux下C++開發一般預設會使用此編譯器
Clang Clang / Low Level Virtual Machine Windows, Linux, macOS LLVM專案的一部分,提供高效的編譯效能。macOS的XCode工具預設整合了此編譯器

1.1. MSVC

  1. MSVC(Microsoft Visual C++)由微軟開發,主要用於Windows平臺應用程式的開發。
  2. Visual Studio系列IDE預設整合了該編譯器,可以透過下載安裝Visual Studio安裝包來安裝。
  3. MSVC只能在Windows下用,不支援跨平臺。

1.1.1. Visual C++Visual Studio的版本對應關係

_MSC_VER: 是MSVC編譯器內建的宏定義,可以在原始碼中直接引用。其值代表了MSVC編譯器的版本,如:1900表示Visual Studio 2015(MSVC++ 14.0)。

MSC    1.0   _MSC_VER == 100
MSC    2.0   _MSC_VER == 200
MSC    3.0   _MSC_VER == 300
MSC    4.0   _MSC_VER == 400
MSC    5.0   _MSC_VER == 500
MSC    6.0   _MSC_VER == 600
MSC    7.0   _MSC_VER == 700
MSVC++ 1.0   _MSC_VER == 800
MSVC++ 2.0   _MSC_VER == 900
MSVC++ 4.0   _MSC_VER == 1000 (Developer Studio 4.0)
MSVC++ 4.2   _MSC_VER == 1020 (Developer Studio 4.2)
MSVC++ 5.0   _MSC_VER == 1100 (Visual Studio 97 version 5.0)
MSVC++ 6.0   _MSC_VER == 1200 (Visual Studio 6.0 version 6.0)
MSVC++ 7.0   _MSC_VER == 1300 (Visual Studio .NET 2002 version 7.0)
MSVC++ 7.1   _MSC_VER == 1310 (Visual Studio .NET 2003 version 7.1)
MSVC++ 8.0   _MSC_VER == 1400 (Visual Studio 2005 version 8.0)
MSVC++ 9.0   _MSC_VER == 1500 (Visual Studio 2008 version 9.0)
MSVC++ 10.0  _MSC_VER == 1600 (Visual Studio 2010 version 10.0)
MSVC++ 11.0  _MSC_VER == 1700 (Visual Studio 2012 version 11.0)
MSVC++ 12.0  _MSC_VER == 1800 (Visual Studio 2013 version 12.0)
MSVC++ 14.0  _MSC_VER == 1900 (Visual Studio 2015 version 14.0)
MSVC++ 14.1  _MSC_VER == 1910 (Visual Studio 2017 version 15.0)
MSVC++ 14.11 _MSC_VER == 1911 (Visual Studio 2017 version 15.3)
MSVC++ 14.12 _MSC_VER == 1912 (Visual Studio 2017 version 15.5)
MSVC++ 14.13 _MSC_VER == 1913 (Visual Studio 2017 version 15.6)
MSVC++ 14.14 _MSC_VER == 1914 (Visual Studio 2017 version 15.7)
MSVC++ 14.15 _MSC_VER == 1915 (Visual Studio 2017 version 15.8)
MSVC++ 14.16 _MSC_VER == 1916 (Visual Studio 2017 version 15.9)
MSVC++ 14.2  _MSC_VER == 1920 (Visual Studio 2019 Version 16.0)
MSVC++ 14.21 _MSC_VER == 1921 (Visual Studio 2019 Version 16.1)
MSVC++ 14.22 _MSC_VER == 1922 (Visual Studio 2019 Version 16.2)
MSVC++ 14.30 _MSC_VER == 1930 (Visual Studio 2022 Version 17.0)
MSVC++ 14.31 _MSC_VER == 1931 (Visual Studio 2022 Version 17.1)

1.1.2. 工具鏈的主要工具

工具 功能描述
cl.exe 編譯程式
link.exe 連結程式
lib.exe 載入lib庫的程式
nmake.exe 用makefile進行構建、編譯的工具

備註: 使用者只需要呼叫cl.exe,即可完成編譯-連結全過程。因為cl.exe程式在編譯時自己會去呼叫link.exe、lib.exe等程式。

1.2. GCC

GCC最開始的原名是GNU C Compiler,是GNU專案的C語言編譯器。後來逐步擴充支援了更多的語言,支援編譯C、C++、Fortran、Pascal、Objective-C、Java、Ada、Go等,所以變成了GNU Compiler Collection(GNU編譯器套裝),是一套由GNU專案開發的支援多種程式語言的編譯器工具鏈

GCC支援多種平臺和作業系統,包括Linux、Windows、macOS等,並且是許多開源專案和作業系統的標準編譯器,如Linux核心。GCC還支援多種CPU指令集架構,如:X86、ARM等。

1.2.1. GCC的主要優點

  • 支援多語言: 支援多種程式語言,如C、C++、Fortran、Pascal、Objective-C、Java、Ada、Go等。
  • 跨平臺性: GCC編譯器能夠在不同的作業系統和硬體平臺上編譯和執行程式碼,確保了程式碼的高度可移植性。
  • 效能最佳化: GCC編譯器內建了多種最佳化策略,可以根據不同的編譯選項進行程式碼最佳化,從而提升程式的執行效率。
  • 功能豐富: 編譯時可生成除錯資訊,便於開發者進行除錯。並提供了廣泛的編譯選項和擴充套件功能,以滿足不同開發者的需求。

1.2.2. GCC的常用工具

工具 描述
gcc GCC的主要編譯器,用於將原始碼編譯為可執行檔案或庫。支援多種語言(如C、C++、Fortran等),並提供豐富的編譯選項。
g++ GCC的C++編譯器,用於將C++原始碼編譯為可執行檔案或庫。與gcc共享許多相同的編譯選項,同時支援針對C++的特定選項。
gdb GCC附帶的偵錯程式,用於除錯程式。允許在程式執行時設定斷點、單步執行程式碼、檢視變數值等。支援多種程式語言,提供強大的除錯功能。
objdump 用於反彙編目標檔案或可執行檔案,顯示二進位制檔案的彙編程式碼。還可顯示符號表資訊、重定位表等相關資訊。
nm 用於列出目標檔案或可執行檔案中的符號表。顯示函式、變數以及其他符號的名稱和地址。
ar 用於建立、修改和提取靜態庫檔案。允許將多個目標檔案打包成一個庫檔案,以便在編譯時連結使用。
size 用於檢視目標檔案或可執行檔案的大小資訊。顯示程式碼段、資料段和符號表等各部分的大小統計。
readelf 用於顯示ELF(Executable and Linkable Format)格式的二進位制檔案的詳細資訊。顯示段表、符號表、動態連結資訊等。

1.2.3. MinGW

MinGW(Minimalist GNU for Windows)是一個用於Windows平臺的開發環境,它提供了GNU編譯器集合(GCC)的Windows版本。MinGW允許開發者在Windows上使用GCC編譯器來編譯C、C++和其他支援的語言。MinGw只支援32位Widnows系統,MinGW-w64 支援32位和64位。所以現在說MinGW時,一般預設指的MinGW-w64,見 MinGW官網

主要特點:

  • GCC編譯器: MinGW包含了GCC編譯器,支援C、C++、Fortran等語言。
  • 跨平臺開發: 開發者可以使用MinGW編譯的程式在Windows上執行,同時保持與Linux和其他Unix-like系統的相容性。
  • 開源: MinGW是開源的,遵循GNU通用公共許可證(GPL)。
  • 輕量級: MinGW提供了一個輕量級的開發環境,不需要複雜的安裝和配置。

1.3. Clang/LLVM

1.3.1. Clang介紹

Clang是一個由 LLVM 專案開發的 C、C++、Objective-C 等程式語言的編譯器前端。它旨在提供更快的編譯速度、更好的錯誤報告及與GCC相容的編譯器驅動程式。Clang 是 LLVM 編譯器基礎設施的一部分,通常與 LLVM 後端一起使用來生成機器程式碼。

Clang的主要特點包括:

  1. 快速編譯和低記憶體使用: Clang 的設計目標之一是提供比 GCC 更快的編譯速度和更低的記憶體佔用。
  2. 高質量的錯誤和警告資訊: Clang 提供了詳細和易於理解的錯誤和警告資訊,有助於開發者更快地找到和修復問題。
  3. 與 GCC 相容: Clang 支援大多數 GCC 的編譯器選項和工具鏈,使得從 GCC 遷移到 Clang 相對容易。
  4. 模組化設計: Clang 的架構是模組化的,易於擴充套件和整合到其他工具和流程中。
  5. 支援現代語言特性: Clang 支援最新的 C++ 標準和其他語言特性,使得開發者可以使用最新的程式設計技術。

Clang 不僅是一個編譯器前端,還是一個強大的工具集,包括靜態分析工具(clang-tidy)、程式碼格式化工具(clang-format)、重構工具等,這些工具可以幫助開發者提高程式碼質量和開發效率。

1.3.2. Clang與LLVM的關係

編譯器的組成:

一個完整的編譯器通常由三部分組成。

前端(FrontEnd): 主要負責詞法和語法分析,將原始碼轉化為抽象語法樹;
最佳化器(Optimizer): 則是在前端的基礎上,對得到的中間程式碼進行最佳化,使程式碼更加高效;
後端(BackEnd): 後端則是將已經最佳化的中間程式碼轉化為針對各自平臺的機器程式碼。

Clang與LLVM的關係:

更粗粒度的劃分是把最佳化器後端統稱為後端,整個編譯器就由前端和後端兩部分組成。Clang就是編譯器的前端,負責詞法和語法分析;LLVM就是編譯器的後端,負責最佳化和生成機器程式碼。

Clang/llvm的編譯過程如下圖:
file

LLVM 包括了兩個概念:

  • 廣義的 LLVM: 指的是一個完整的 LLVM 編譯器框架系統,包括了前端、最佳化器、後端、眾多的庫函式以及很多的模組。
  • 狹義的 LLVM: 則是聚焦於編譯器後端功能的一系列模組和庫,包括程式碼最佳化、程式碼生成、JIT 等。

1.3.3. Clang/LLVM與GCC

GCC和LLVM是競爭對手,都是編譯器框架系統。GCC包含前端和後端,LLVM也包含前端和後端,只是他的前端通常是Clang,所以Clang是LLVM 編譯器框架系統 的前端

他們可能的組合如下:
file

眼尖的同學可能會問:為什麼沒有“Clang前端、GCC後端”的組合?

個人理解: GCC發展的時間非常早,帶有很大的歷史包袱。GCC後端的介面設計沒有那麼靈活,不能提供Clang足夠的介面支撐(這也是LLVM架構最開始設計就考慮到的問題)。

LLVM Compiler發展過程的早期就經歷了LLVM-GCC這種過渡期的組合(GCC前端+LLVM後端)。

2. C++ 編譯器的安裝

2.1. Windows

2.1.1. MSVC安裝

  1. 進入微軟官網下載頁面:https://visualstudio.microsoft.com/zh-hans/downloads/
  2. 選擇要下載的最新版本安裝包下載器:
    1. 如果要下載完整的Visual Studio IDE,選擇:Visual Studio 2022 -> 版本型別(如果是個人開發使用,可以選擇Visual Studio Community 2022
    2. 如果只需要下載MSVC編譯器,選擇: 用於Visual Studio的工具 -> Visual Studio 2022 生成工具。
      file
    3. 我希望用VSCode(而不是Visual Studio)來開發C++, 所有我只需要下載MSVC編譯器。
  3. 雙擊開啟下載好的vs_BuildTools.exe,一路點選“繼續”,到安裝包選擇頁面時,選擇“C++桌面開發”。
    file

2.1.2. 環境變數配置

方法一 指定的命令列:

MSVC安裝後會生成特定命令列工具,可以在“開始 -> 搜尋”查詢一下命令列:

  • Developer Command Prompt for VS 2022: 用 32位x86編譯器 構建 32位x86 的目標程式。
  • x86 Native Tools Command Prompt for VS 2022: 用 32位x86編譯器 構建 32位x86 的目標程式。
  • x64 Native Tools Command Prompt for VS 2022: 用 64位x64編譯器 構建 64位x64 的目標程式。
  • x86_x64 Cross Tools Command Prompt for VS 2022: 用 86位x32編譯器 構建 64位x64 的目標程式。
  • x64_x86 Cross Tools Command Prompt for VS 2022: 用 64位x64編譯器 構建 32位x86 的目標程式。

開啟對於的命令列,然後在此命令列下執行cl xx.cpp等相關編譯命令。

方法二 bat指令碼設定:

C:\software\MicrosoftVisualStudio\2022\BuildTools\VC\Auxiliary\Build下存在多個批處理檔案,這些批處理檔案可以初始化相應構建需求的環境變數:

  • vcvars32.bat: 使用 32位x86 編譯器構建 32位x86 程式碼。
  • vcvars64.bat: 使用 64位x64 編譯器構建 64位x64 程式碼。
  • vcvarsx86_amd64.bat: 使用 32位x86 本機相容工具生成 64位x64 程式碼。
  • vcvarsamd64_x86.bat: 使用 64位x64 本機相容工具生成 32位x86 程式碼。
  • vcvarsx86_arm.bat: 使用 32位x86 本機相容工具生成 ARM 程式碼。
  • vcvarsamd64_arm.bat: 使用 64位x64 本機相容工具生成 ARM 程式碼。
  • vcvarsx86_arm64.bat: 使用 32位x86 本機相容工具生成 ARM64 程式碼。
  • vcvarsamd64_arm64.bat: 使用 64位x64 本機相容工具生成 ARM64 程式碼。

開啟cmd命令列或者power shell, 然後執行相應的.bat指令碼然,再執行cl xx.cpp等相關編譯命令。

方法三 手動配置:

MSVC編輯器的預設安裝在C:\Program Files (x86)\Microsoft Visual Studio,安裝時可以自定義安裝路徑。在安裝目錄下的2022\BuildTools\VC\Tools\MSVC\14.40.33807\bin路徑下,其中有兩個資料夾,分別是hostx64和hostx86,這兩個資料夾下又分別有x64和x86,他們的含義如下:

bin
  Hostx64 # 主機是64位的編譯器
    x64 # 編譯的目標檔案是64位程式
    x86 # 編譯的目標檔案是32位程式
  Hostx86 # 主機是32位的編譯器
    x64 # 編譯的目標檔案是64位程式
    x86 # 編譯的目標檔案是32位程式

根據自己的需求,選擇對應的路徑,如:我的主機是64位的,我希望用64位的編譯器編譯32位的目標程式,設定環境變數如下:

MSVC_DIR: C:\software\MicrosoftVisualStudio\2022\BuildTools\VC\Tools\MSVC\14.40.33807

include: %MSVC_DIR%\include
lib: %MSVC_DIR%\lib\x86;
path: %MSVC_DIR%\bin\Hostx64\x86;

2.2. Linux(Ubuntu)

2.2.1. 安裝GCC/GDB

1. 安裝:

# 更新軟體源
sudo apt update
# 透過以下命令安裝編譯器和偵錯程式
sudo apt install build-essential gdb

Ubuntu 預設情況下沒有提供C/C++編譯環境的,你可以單獨安裝gcc、g++等工具,但會比較麻煩。Ubuntu提供了一個build-essential軟體包,安裝了該軟體包,編譯c/c++所需要的軟體包也都會被安裝。

2. 校驗:

# 執行以下命令確認每個軟體是否安裝成功
# 如果成功,則顯示版本號
gcc --version
g++ --version
gdb --version

2.2.2. 安裝CMake

1. 安裝:

sudo apt install cmake

1. 校驗:

cmake --version

2.3. macOS

2.3.1. clang的安裝

macOS下,我們可以透過安裝Xcode命令列工具來安裝clang,因為Xcode命令列工具中包含了clang。

  1. 在命令列中輸入xcode-select --install,之後你會看到一個皮膚,要求你安裝 Xcode 命令列工具。
    file

  2. 點選 “Install”(安裝),開始下載和安裝過程。
    file

  3. 當安裝完成後,你會看到一個確認資訊。
    file

  4. 驗證 XCode 是否安裝成功
    輸入 xcode-select -p,如果看到下面的內容說明安裝成功:/Library/Developer/CommandLineTools

  5. 驗證 Clang 是否安裝成功
    輸入 clang --version,如果看到下面的內容,說明安裝成功:

    Apple Clang version 15.0.0 (Clang-1500.3.9.4)
    Target: x86_64-apple-darwin23.5.0
    Thread model: posix
    InstalledDir: /Library/Developer/CommandLineTools/usr/bin
    

2.3.2. 為什麼gcc的版本號顯示的是Clang version

Xcode命令列工具安裝完後,就已經包含gcc/g++工具了,我們可以檢視一下其版本號

➜  ~ gcc --version
Apple Clang version 15.0.0 (Clang-1500.3.9.4)
Target: x86_64-apple-darwin23.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

➜  ~ g++ --version
Apple Clang version 15.0.0 (Clang-1500.3.9.4)
Target: x86_64-apple-darwin23.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

你有沒有發現一個奇怪的現象:我們要檢視的是gcc/g++的版本號,這裡顯示的版本號為什麼是Apple Clang version XXX

個人的理解: 這裡的gcc/g++已經不是GNU Compiler Collection中的gcc/g++了, 某種意義上講,他可能是 Clang/clang++ 的一個別名,底層的實現可能都換了,只是在介面上他做到了與GCC相容。因為 Clang 設計的初衷就是為了超越和取代GCC的。

2.3.3. gcc的安裝

如果你想獨立安裝GNU Compiler Collection,而不是XCode自帶的gcc/g++,要如何操作?

  1. 用homebrew安裝gcc(如果homebrew未安裝請自行安裝,這裡不再講解homebrew的安裝方法)。
brew install gcc
  1. 安裝完後,找到上述命令安裝的GCC版本
➜  ~ ls -l /usr/local/bin | grep g++
lrwxr-xr-x  1 spencer  admin      33  8  2 17:08 g++-14 -> ../Cellar/gcc/14.1.0_2/bin/g++-14
lrwxr-xr-x  1 spencer  admin      55  8  2 17:08 x86_64-apple-darwin23-g++-14 -> ../Cellar/gcc/14.1.0_2/bin/x86_64-apple-darwin23-g++-14
➜  ~ 
➜  ~ g++-14 --version
g++-14 (Homebrew GCC 14.1.0_2) 14.1.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

說明我們的GCC安裝成功,安裝的版本是:14.1.0。可以用同樣的方式查詢gcc。

  1. 修改配置

~/.bash_profile 檔案新增如下內容:

alias gcc='gcc-14'
alias cc='gcc-14'
alias g++='g++-14'
alias c++='c++-14'

如果你用的是zsh,則在~/.zshrc檔案中新增。

  1. 載入配置
# bash
source ~/.bash_profile
# zsh
source ~/.zshrc
  1. 再次驗證版本號
➜  ~ gcc --version
gcc-14 (Homebrew GCC 14.1.0_2) 14.1.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

➜  ~ g++ --version
g++-14 (Homebrew GCC 14.1.0_2) 14.1.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

可以看到現在版本號不再顯示Apple Clang version XXX了。

3. 驗證編譯器是否安裝正常

3.1. 寫一個測試Demo

  1. 建立一個目錄,如test_demo,並進入該目錄。
  2. 在該目錄下建立一個test.cpp檔案,並輸入以下程式碼:
#include <iostream>

int main()
{
    std::cout << "Hello, world!" << std::endl;
    return 0;
}

3.2. 編譯並執行

3.2.1. Windows

cl test.cpp
test.exe

3.2.2. Linux

g++ test.cpp
./a.out

3.2.3. macOS

clang++ test.cpp
./a.out

如何有正常輸出Hello, world!則說明編譯器安裝成功。


大家好,我是陌塵。

IT從業10年+, 北漂過也深漂過,目前暫定居於杭州,未來不知還會飄向何方。

搞了8年C++,也幹過2年前端;用Python寫過書,也玩過一點PHP,未來還會折騰更多東西,不死不休。

感謝大家的關注,歡迎加我微信(Spencer_MC),期待與大家一起交流。



【SunLogging】
一文搞懂C/C++常用編譯器
掃碼二維碼,關注微信公眾號,閱讀更多精彩內容

相關文章