1. 程式人生 > 其它 >簡述Clang 與LLVM 以及其關係

簡述Clang 與LLVM 以及其關係

簡述Clang 與LLVM 以及其關係

隨著 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 是一個高度模組化開發的輕量級編譯器,編譯速度快、佔用記憶體小、有著友好的出錯提示。

然後說下 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 大致可以對應到編譯器的前端,主要處理一些和具體機器無關的針對語言的分析操作;編譯器的優化器和後端部分就是之前提到的 LLVM 後端,即狹義的 LLVM。

此外,由於 LLVM 的命名最早源自於底層虛擬機器(Low Level Virtual Machine) 的首字母縮寫,但這個專案的範圍並不侷限於建立一個虛擬機器,這個縮寫導致了大量的疑惑。LLVM 成長之後已成為眾多編譯工具及低階工具技術的統稱,使得這個名字變得更不貼切,所以開發者決定放棄這個縮寫的涵義,現在 LLVM 已獨立成為一個品牌,適用於 LLVM 下的所有專案,包括 LLVM 中介碼、LLVM 除錯工具、LLVM C++ 標準庫等。


參考文件:
https://www.cnblogs.com/ainima/p/6331943.html
https://www.jianshu.com/p/7e2c65dcf632