隨着 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
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 的版本歷史。c++
接下來,簡要的介紹一下 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++ 標準庫等。模塊化