我对文章进行了排版,并将其中的关键部分进行了标记,方便抓住重点


引言

随着 Android P 的逐步应用,越来越多的客户要求编译库时用 ​libc++​ 来代替​ libstdc++​。​libc++​ 和 ​libstdc++​ 这两个库有关系呢?它们两个都是 C++ 标准库,​libc++​ 是针对 Clang 编译器特别重写的 C++ 标准库,而 ​libstdc++​ 则是 GCC 的对应 C++ 标准库了。从 Android 市场来说,Android NDK 已在具体应用中放弃了 GCC,全面转向 Clang,正如很早前 Android NDK 在 Changelog 中提到的那样:


Everyone should be switching to Clang.
GCC in the NDK is now deprecated.


Android NDK 从 r11 开始建议大家切换到 Clang,并且把 GCC 标记为 deprecated,将 GCC 版本锁定在 GCC 4.9 不再更新;

Android NDK 从 r13 起,默认使用 Clang 进行编译,但是暂时也没有把 GCC 删掉,Google 会一直等到 libc++ 足够稳定后再删掉 GCC;

Android NDK 在 r17 中宣称不再支持 GCC 并在后续的 r18 中删掉 GCC,具体可见 NDK 的版本历史。


什么是 Clang

Clang 是一个 C、C++、Objective-C 和 Objective-C++ 编程语言的编译器前端,采用底层虚拟机(LLVM)作为后端。至于为什么有了 GCC 还要开发 Clang?Clang 相比 GCC 又有什么优势呢?网上有很多信息可以参考,这里只简单提两点:

  1. Clang 采用的是 BSD 协议的许可证,而 GCC 采用的是 GPL 协议,显然前者更为宽松;
  2. Clang 是一个高度模块化开发的轻量级编译器,编译速度快、占用内存小、有着友好的出错提示。

【转载】简述 LLVM 与 Clang 及其关系_编译器


Clang 背后的 LLVM(Low Level Virtual Machine)

LLVM 是以 ​BSD 许可​来开发的开源的编译器框架系统,基于 C++ 编写而成,​利用​虚拟技术来优化​以任意程序语言编写的程序的编译时间、链接时间、运行时间以及空闲时间​,最早以 C/C++ 为实现对象,对开发者保持开放,并兼容已有脚本。LLVM 计划启动于 2000 年,最初由 University of Illinois at Urbana-Champaign 的 Chris Lattner 主持开展,2006 年 Chris Lattner 加盟苹果公司并致力于 LLVM 在苹果公司开发体系中的应用,所以苹果公司也是 LLVM 计划的主要资助者。目前 LLVM 因其宽松的许可协议,更好的模块化、更清晰的架构,成为很多厂商或者组织的选择,已经被苹果 IOS 开发工具、Facebook、Google 等各大公司采用,像 Swift、Rust 等语言都选择了以 LLVM 为后端。

在理解 LLVM 之前,先说下​传统编译器的工作原理​,基本上都是三段式的,可以分为​前端、优化器和后端​。

  • 前端​负责解析源代码,检查语法错误,并将其翻译为抽象的语法树;
  • 优化器​对这一中间代码进行优化,试图使代码更高效;
  • 后端​则负责将优化器优化后的中间代码转换为目标机器的代码,这一过程后端会最大化的利用目标机器的特殊指令,以提高代码的性能。

基于这个认知,我们可以认为 LLVM 包括了两个概念:一个​广义的 LLVM​ 和一个​狭义的 LLVM​ 。广义的 LLVM 指的是一个完整的 LLVM 编译器框架系统,包括了前端、优化器、后端、众多的库函数以及很多的模块;而狭义的 LLVM 则是聚焦于编译器后端功能的一系列模块和库,包括代码优化、代码生成、JIT 等。


LLVM 和 Clang 的关系

我们将它们对应于传统的编译器当中的几个独立的部分,这样能够更加方便明确的表述出它们之间的关系。

【转载】简述 LLVM 与 Clang 及其关系_android_02


  • 对应到这个图中,可以非常明确的找出它们的关系。整体的编译器架构就是​ LLVM 架构​;
  • Clang 大致可以对应到编译器的前端,主要处理一些和具体机器无关的针对语言的分析操作;
  • 编译器的优化器和后端部分就是之前提到的 LLVM 后端,即​狭义的 LLVM​。

此外,由于 LLVM 的命名最早源自于底层虚拟机(Low Level Virtual Machine) 的首字母缩写,​但这个项目的范围并不局限于创建一个虚拟机,这个缩写导致了大量的疑惑​。LLVM 成长之后已成为众多编译工具及低级工具技术的统称,使得这个名字变得更不贴切,所以​开发者决定放弃这个缩写的涵义​,现在 LLVM 已独立成为一个品牌,适用于 LLVM 下的所有项目,包括 LLVM 中介码、LLVM 除错工具、LLVM C++ 标准库等。