原文

https://www.cnblogs.com/luoweifu/p/18348981

转载

大致介绍

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工具默认集成了此编译器

MSVC

  1. MSVC(Microsoft Visual C++)由微软开发,主要用于Windows平台应用程序的开发。

  2. Visual Studio系列IDE默认集成了该编译器,可以通过下载安装Visual Studio安装包来安装。

  3. MSVC只能在Windows下用,不支持跨平台。

_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)

工具

功能描述

cl.exe

编译程序

link.exe

链接程序

lib.exe

加载lib库的程序

nmake.exe

用makefile进行构建、编译的工具

用户只需要调用cl.exe,即可完成编译-链接全过程。因为cl.exe程序在编译时自己会去调用link.exe、lib.exe等程序。

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等。

GCC的主要优点:

  • 支持多语言: 支持多种编程语言,如C、C++、Fortran、Pascal、Objective-C、Java、Ada、Go等。

  • 跨平台性: GCC编译器能够在不同的操作系统和硬件平台上编译和运行代码,确保了代码的高度可移植性。

  • 性能优化: GCC编译器内置了多种优化策略,可以根据不同的编译选项进行代码优化,从而提升程序的运行效率。

  • 功能丰富: 编译时可生成调试信息,便于开发者进行调试。并提供了广泛的编译选项和扩展功能,以满足不同开发者的需求。

工具

描述

gcc

GCC的主要编译器,用于将源代码编译为可执行文件或库。支持多种语言(如C、C++、Fortran等),并提供丰富的编译选项。

g++

GCC的C++编译器,用于将C++源代码编译为可执行文件或库。与gcc共享许多相同的编译选项,同时支持针对C++的特定选项。

gdb

GCC附带的调试器,用于调试程序。允许在程序运行时设置断点、单步执行代码、查看变量值等。支持多种编程语言,提供强大的调试功能。

objdump

用于反汇编目标文件或可执行文件,显示二进制文件的汇编代码。还可显示符号表信息、重定位表等相关信息。

nm

用于列出目标文件或可执行文件中的符号表。显示函数、变量以及其他符号的名称和地址。

ar

用于创建、修改和提取静态库文件。允许将多个目标文件打包成一个库文件,以便在编译时链接使用。

size

用于查看目标文件或可执行文件的大小信息。显示代码段、数据段和符号表等各部分的大小统计。

readelf

用于显示ELF(Executable and Linkable Format)格式的二进制文件的详细信息。显示段表、符号表、动态链接信息等。

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)、重构工具等,这些工具可以帮助开发者提高代码质量和开发效率。

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,见 https://www.mingw-w64.org/

主要特点:

  • GCC编译器: MinGW包含了GCC编译器,支持C、C++、Fortran等语言。

  • 跨平台开发: 开发者可以使用MinGW编译的程序在Windows上运行,同时保持与Linux和其他Unix-like系统的兼容性。

  • 开源: MinGW是开源的,遵循GNU通用公共许可证(GPL)。

  • 轻量级: MinGW提供了一个轻量级的开发环境,不需要复杂的安装和配置。

编译器组成

一个完整的编译器通常由三部分组成。

  • 前端(FrontEnd): 主要负责词法和语法分析,将源代码转化为抽象语法树;

  • 优化器(Optimizer): 则是在前端的基础上,对得到的中间代码进行优化,使代码更加高效;

  • 后端(BackEnd): 后端则是将已经优化的中间代码转化为针对各自平台的机器代码。

更粗粒度的划分是把优化器和后端统称为后端,整个编译器就由前端和后端两部分组成。Clang就是编译器的前端,负责词法和语法分析;LLVM就是编译器的后端,负责优化和生成机器代码。

504387-20240808150624931-1318141392-ujOf.webp

LLVM 包括了两个概念:

  • 广义的 LLVM: 指的是一个完整的 LLVM 编译器框架系统,包括了前端、优化器、后端、众多的库函数以及很多的模块。

  • 狭义的 LLVM: 则是聚焦于编译器后端功能的一系列模块和库,包括代码优化、代码生成、JIT 等。

GCC和LLVM是竞争对手,都是编译器框架系统。GCC包含前端和后端,LLVM也包含前端和后端,只是他的前端通常是Clang,所以Clang是LLVM 编译器框架系统 的前端。他们可能的组合如下:

504387-20240808150625226-1544061570-gyvq.webp

这里我单独说一下,并不存在官方正式的 使用GCC作为前端和LLVM作为后端的编译器,这种编译器只有社区支持。

安装

引入

如果你查看原文,你会发现,原文作者已经开始了老生常谈的安装编译器的环节,而且也是使用了最经典的从官网下载相应的二进制包。但是我想告诉你的是,VSCode的官网配置教程中,推荐的方式是使用Msys2下载编译器。而之所以采用Msys2,就是因为Msys2自带包管理器,关于Msys2的安装包,这里我建议使用清华大学镜像获得Msys2的安装包:https://mirrors.tuna.tsinghua.edu.cn/msys2/distrib/

2025-12-10_022755-bkuk.webp

关于Msys2 你还需要对子系统有所了解,Msys2 安装到操作系统上后,你会发现开始菜单上多了5个子系统入口,而安装位置有六个子系统入口(MINGW32没有创建在开始菜单),不同的子系统都有独立的Path变量,工具链,运行时库,并且包管理器的安装目录也各不相同。所以在不同的子系统中,你都需要独立的重新安装相应的工具链,因为这些子系统相互独立。

名称

解释

CLANG64

clang编译器组

CLANGARM64

clang编译器组

MINGW32

微软传统C运行库组

MINGW64

微软传统C运行库组

MSYS

纯模拟linux组

UCRT64

GCC编译器 + 微软新 C 运行库组

接下来就是重点环节了,官网的教程未必是最好的,因为他需要考虑到让小白十分简单的就可以上手,比如在官网教程中,就推荐你直接安装编译器工具链,一次性安装所有可能用到的工具,即使你用不上,虽然很方便,但是也臃肿,更好的方式是,你知道需要什么东西,然后仅仅下载需要的东西,不需要的东西不用管。

cpp-install-msys2-toolchain-afyB.webp

上边是执行官网安装流程显示的命令信息,你可以看到,虽然我们什么事情都没有开始做,但是所有可以用上的工具都已经展示出来了,你可以选择性安装,但是这种方法并不通用,在更多的时候你利用msys2安装的不仅仅是编译器,还可以是各种各样的编程框架,官方介绍的方式只适用于编译器的安装(虽然十分全面),但是我个人仍然建议你采取更加通用的方式 - 使用包管理器检索关键词,然后选取相应的版本。

就拿微软新运行库组UCRT对应的子系统来说,你需要安装的是gcc 编译器,所以你需要进入子系统后搜索gcc包,键入命令:pacman -Ss "\-gcc$" 这里解释一下,“-gcc$” 表示包名必须以 gcc 结尾,且 g 前面需带有 ‘-’ (因为 ‘-’ 被用作参数引导 ,所以需要带上转义符: \ )。大概会搜索出以下项:

# pacman -Ss "\-gcc$"
clangarm64/mingw-w64-clang-aarch64-gcc-compat 21.1.5-1
    GCC compatibility aliases for Clang (mingw-w64)
clangarm64/mingw-w64-clang-aarch64-perl 5.38.4-1
    A highly capable, feature-rich programming language (mingw-w64)
mingw32/mingw-w64-i686-gcc 15.2.0-8 (mingw-w64-i686-toolchain)
    GNU Compiler Collection (C,C++,OpenMP) for MinGW-w64
mingw64/mingw-w64-x86_64-arm-none-eabi-gcc 13.3.0-1 (mingw-w64-x86_64-arm-none-eabi-toolchain)
    GNU Tools for ARM Embedded Processors - GCC (mingw-w64)
mingw64/mingw-w64-x86_64-avr-gcc 15.2.0-1 (mingw-w64-x86_64-avr-toolchain)
    GNU compiler collection for AVR 8-bit and 32-bit microcontrollers (mingw-w64)
mingw64/mingw-w64-x86_64-gcc 15.2.0-8 (mingw-w64-x86_64-toolchain)
    GNU Compiler Collection (C,C++,OpenMP) for MinGW-w64
mingw64/mingw-w64-x86_64-perl 5.38.4-1
    A highly capable, feature-rich programming language (mingw-w64)
mingw64/mingw-w64-x86_64-riscv64-unknown-elf-gcc 15.1.0-2 (mingw-w64-x86_64-riscv64-unknown-elf-toolchain)
    GNU Tools for RISC-V Embedded Processors - GCC (mingw-w64)
ucrt64/mingw-w64-ucrt-x86_64-arm-none-eabi-gcc 13.3.0-1 (mingw-w64-ucrt-x86_64-arm-none-eabi-toolchain)
    GNU Tools for ARM Embedded Processors - GCC (mingw-w64)
ucrt64/mingw-w64-ucrt-x86_64-avr-gcc 15.2.0-1 (mingw-w64-ucrt-x86_64-avr-toolchain)
    GNU compiler collection for AVR 8-bit and 32-bit microcontrollers (mingw-w64)
ucrt64/mingw-w64-ucrt-x86_64-gcc 15.2.0-8 (mingw-w64-ucrt-x86_64-toolchain) [已安装]
    GNU Compiler Collection (C,C++,OpenMP) for MinGW-w64
ucrt64/mingw-w64-ucrt-x86_64-perl 5.38.4-1
    A highly capable, feature-rich programming language (mingw-w64)
ucrt64/mingw-w64-ucrt-x86_64-riscv64-unknown-elf-gcc 15.1.0-2 (mingw-w64-ucrt-x86_64-riscv64-unknown-elf-toolchain)
    GNU Tools for RISC-V Embedded Processors - GCC (mingw-w64)
clang64/mingw-w64-clang-x86_64-arm-none-eabi-gcc 13.3.0-1 (mingw-w64-clang-x86_64-arm-none-eabi-toolchain)
    GNU Tools for ARM Embedded Processors - GCC (mingw-w64)
clang64/mingw-w64-clang-x86_64-avr-gcc 15.2.0-1 (mingw-w64-clang-x86_64-avr-toolchain)
    GNU compiler collection for AVR 8-bit and 32-bit microcontrollers (mingw-w64)
clang64/mingw-w64-clang-x86_64-gcc-compat 21.1.5-1
    GCC compatibility aliases for Clang (mingw-w64)
clang64/mingw-w64-clang-x86_64-perl 5.38.4-1
    A highly capable, feature-rich programming language (mingw-w64)
clang64/mingw-w64-clang-x86_64-riscv64-unknown-elf-gcc 15.1.0-2 (mingw-w64-clang-x86_64-riscv64-unknown-elf-toolchain)
    GNU Tools for RISC-V Embedded Processors - GCC (mingw-w64)
msys/mingw-w64-cross-gcc 15.2.0-1 (mingw-w64-cross-toolchain mingw-w64-cross)
    Cross GCC for the MinGW-w64 (meta package, for backward compatibility)
msys/mingw-w64-cross-mingw32-gcc 15.2.0-1 (mingw-w64-cross-toolchain mingw-w64-cross)
    Cross GCC for the MinGW-w64
msys/mingw-w64-cross-mingw64-gcc 15.2.0-1 (mingw-w64-cross-toolchain mingw-w64-cross)
    Cross GCC for the MinGW-w64
msys/mingw-w64-cross-mingwarm64-gcc 15.0.1dev-1 (mingw-w64-cross-toolchain mingw-w64-cross)
    Cross GCC for the MinGW-w64
msys/mingw-w64-cross-ucrt64-gcc 15.2.0-1 (mingw-w64-cross-toolchain mingw-w64-cross)
    Cross GCC for the MinGW-w64

我向你解释一下这里的包名:

ucrt64/mingw-w64-ucrt-x86_64-arm-none-eabi-gcc 13.3.0-1
  1. UCRT64/ 表示适用于ucrt64子系统,所有的包前都有自己适用的子系统名,这很大的减少了阅读量。

  2. mingw-w64 表示该包归属于mingw-w64 (Minimalist GNU for Windows)项目。也就是允许在Windows上运行GNU工具链,或者说编译器的各项工具都是exe的格式。

  3. ucrt 表示该包采用了Universal CRT 运行时。

  4. x86_64 宿主机架构。

  5. arm-none-eabi-gcc 目标架构为 arm 嵌入式无os。

重点:

  • 上面的案例比较典型,是一个支持交叉编译的编译器,会出现两个架构,前者为宿主机架构,后者为目标平台架构,如果你只看到一个架构信息,那么他是一个典型本地编译器,目标架构和宿主机架构都是同一个架构。

  • 有些软件包不会标注自己的运行时,如果不进行标注,说明其采用的是msvcrt的传统运行时,这种运行时适用于win10以前的平台,性能较低。你需要认识到,MinGW项目中的编译器如果目标平台是X86,那么他就是为Windows开发而准备的,而Windows开发在GCC中只有两种运行时,一种是性能不高的msvcrt 另一种是性能高一些的 ucrt ,ucrt是后续添加的,在MinGW项目早期,只有一种运行时,那就是msvcrt,这就是为什么ucrt运行时额外标注,但是msvcrt 运行时不会标注的情况。

  • 你有时可以看到gcc 包名以gcc-compat 结尾,这些编译器本身并不是gcc,而是叫做gcc兼容包,实质为其他的编译器类型,本质上是其他的编译器允许以gcc的名字调用。mingw-w64-clang-aarch64-gcc-compat 21.1.5-1 就比如这个包一样,clang表示这个实质上是一个clang编译器,gcc-compact表示兼容gcc的调用方法,创建这种包的目的就是 “使构建脚本无需修改即可调用 Clang。”

  • 从上边命令行的输出可以看到,msys2似乎只提供了 “Windows本地工具链” “嵌入式裸机工具链” “AVR(8位控制器)工具链” “Clang兼容包” “MSYS2内部构建MinGW的交叉编译器” 但是并没有提供目标平台为linux的编译器,这是因为,虽然GCC 是支持交叉编译的,但是MinGW主要是为了Windows本地编程设计,如果要进行Linux开发,直接在Linux上编程会有更好的兼容性。并且Linux 程序通常依赖 glibc、systemd、特定内核 ABI、动态链接器(/lib64/ld-linux-x86-64.so.2)等,这些在 Windows 上难以模拟或复现。

  • 你可以看到MinGW支持在Windows平台上为嵌入式设备进行开发,这主要是因为嵌入式设备有时无系统,并且性能低,所以一般都是在宿主机进行代码的编写,编译和调试。这一部分功能是后续添加上去的,因为实现简单,而且用户群体众多,所以后续添加进去了。

演示

看了上边的长篇大论的介绍后,你基本就对编译器的情况已经有所了解了,对于一般的左面开发而言,尤其是GNU工具链,我们重点是要准备 gcc gdb 还有 make 这几个包。但是在进行所有操作前,我建议你先更换一下更新源,因为国内访问外网有点慢:

  1. 进入 msys64\etc\pacman.d\ 目录,用记事本打开其中的 “mirrorlist.ucrt64”,你将看到一行又一行以 “Server = ” 打头的文本内容;

  2. 搜索 mirrors.tuna.tsinghua.edu.cn,复制所在行,再将它粘贴到文件的第一行(或放在 “## Primary” 之下的第一行)。回到之前找到的那一行,在它前面加上一个 # 和 空格,以注释它;

  3. 保存文件文件。

  4. 进入UCRT64 环境,在其内输入 :pacman -Suy 并回车。pacman 是 Arch Linux 的包管理器,类似 UBUNTU Linux 的 apt-get。该指令将检查 MSYS2是否有新近更新的内容。

  5. 如果有更新,可输入 Y 字母,或直接直接回车(当提示中的 Y 字母是大写时),即可开始更新,更新后,可能还会提示是否关闭当前MSYS,同样选择输入 Y。

接下来开始正戏,按照通用的方法你需要执行的检索命令如下,然后你需要根据编译器的用途选择合适的包。

pacman -Ss "\-gcc$"
pacman -Ss "\-gdb$"
pacman -Ss "\-make$"

如果你是为Windows10环境编程,那么推荐你直接进入ucrt的子环境,并且在该环境中输入检索命令,然后执行安装命令:

pacman -S mingw-w64-ucrt-x86_64-gcc
pacman -S mingw-w64-ucrt-x86_64-gdb
pacman -S mingw-w64-ucrt-x86_64-make

安装完毕后,你就可以在Msys2的安装目录下的子目录ucrt目录下的bin目录看到安装的编译器了,记住这个位置,接下来配置VS Code的代码编译器需要用到这个位置,但是强烈建议你不要将这个路径添加到系统或者用户Path中,作为高级开发者,你应该通过VS Code的配置文件指定编译器工具链的位置,通过切换配置文件切换不同的编译器。