Carbon Language

??? Carbon Language
Google 新推出 Carbon 語言,聞要成為 C++ 的接班人,基于 LLVM 現(xiàn)代編譯器框架開發(fā)。這么利害,那么就來學一下這種語言使用的默認構(gòu)建工具,Bazel,這是大型項目的構(gòu)建工具,快速、高效,只編譯需要構(gòu)建的文件,支持多種語言。單一可執(zhí)行文件,自動下載依賴工具。可根據(jù)項目需要伸縮、擴展。
C++ 引入外部依賴的方式可以大致分為兩類:二進制依賴,或源碼依賴。前者有 ABI 兼容問題,不支持更換平臺或系統(tǒng),所有的二進制文件都需要為不同平臺重新編譯;后者的缺點是,第一次構(gòu)建的時候需要編譯所有代碼,比較耗時。Google 推崇第二種依賴方式,所以才會那么在乎 Bazel 的編譯速度。
? ? A rule is a function, and a target is a function call
Bazel 規(guī)則(Rule)就是一個函數(shù),BUILD 腳本文件中可以直接使用,這是 Python 腳本的簡化版。內(nèi)置規(guī)則有 genrule、cc_binary、cc_library、java_binary、py_library 等等,Target 就是調(diào)用規(guī)則,并且相應產(chǎn)生輸出。
規(guī)則 rule 也是函數(shù),擁有函數(shù)的大部分特性,但相比函數(shù),受到了更多的約束。比如 load 是函數(shù)但不是規(guī)則,load 用于從其他文件載入規(guī)則,load 不能用于規(guī)則中。又如 glob 是函數(shù),用于查找與路徑規(guī)則匹配的文件。
[Action Graph](https://u98yad7iy.oss-cn-shanghai.aliyuncs.com/imgsbed/2021/11/05/10-27-23-bazel_out-177ed5b6632.jpg)
Bazel 的執(zhí)行分為三個階段:
?**Loading**,加載 Bazel 腳本文件,WORKSPACE、BUILD、bzl 文件;
?**Analysis**,解析所有腳本并生成 Action Graph。解析過程包含外部資源下載,本地資源準備等;
?**Execution**,執(zhí)行 Action Graph 以生成目標文件;
動作(action)是 Bazel 中最小的執(zhí)行單元,一般用于將輸入文件轉(zhuǎn)換為合適的輸出文件,比如將 C/C++?文件轉(zhuǎn)換為 .o 或 .a 文件。動作可以沒有輸入文件,但至少有一個輸出文件。BUILD 腳本中一個 target 對應一個或多個動作,Bazel 會自動將 target 解析為動作并在執(zhí)行階段執(zhí)行。
Action Graph 執(zhí)行過程中,由動作生成的目標文件會被集中緩存。再次編譯時,只有依賴文件被修改的目標才會被更新,這一點和 CMake 一致。Bazel 可以設(shè)置遠程緩存與分布式編譯環(huán)境。
Bazel 編譯生成的緩存文件一般保存在項目目錄下以 bazel-* 為名稱的目錄下,所以盡量不要在項目中創(chuàng)建類似名稱的文件夾,避免和緩存文件夾沖突。
Bazel 官方代碼倉庫包含了文檔和示范用例,整個工程包含多個 BUILD 腳本,項目工作目錄頂層向子目錄深入,例如 example/cpp 目錄包含的 C++ 演示案例。這些腳本就是 Python 腳本的簡化版:
Bazel 稱工程中的子目錄為 package,例如 example 目錄下的 BUILD 腳本定義其為 public:
可以使用 query 查詢工程子目錄下的構(gòu)建配置信息。然后,執(zhí)行 build 或 test 進行構(gòu)建或測試。指定構(gòu)建目標,指定 target 是 BUILD 配置的各種庫、程序目標的 name 屬性內(nèi)容??梢园暾捻椖磕夸浡窂?,以斜杠開頭,路徑后跟冒號接 target 名稱。如果在 target 的所在目錄,也可以省略路徑信息:
Carbon 語言當前的實現(xiàn)稱為 Explorer,官方提供在線體驗網(wǎng)站,它是基于 LLVM 現(xiàn)代編譯器框架開發(fā)的一個前端編譯器,按以下操作可以從源代碼編譯:
本地已經(jīng)安裝 LLVM 編譯器的情況下,Bazel 還會根據(jù)配置文件下載和配置 llvm-project。這可能由于網(wǎng)絡(luò)不暢通而不能下載到依賴工具,從而導致編譯失敗。需要手動解決,安裝 LLVM Project 到提示的目錄下:
llvm-raw 目錄下存放的是下載好的 llvm-project 倉庫原始文件,使用它時會復制到需要的位置使用。獲取 LLVM 工具的過程中,會使用到 llvm-project-overlay 創(chuàng)建目錄鏈接,將原始文件鏈接到工作目錄。目前穩(wěn)定版 Bazel 6.0.0,如果使用 Nightly 版本,可能導致以上錯誤。
可以嘗試深度清理緩存文件:
? ? bazel clean --expunge
輸出的錯誤信息顯示,在 llvm-project-overlay 鏈接目錄時遇到有目錄沖突,可以是 Windows 平臺下兼容問題沒處理好,對 llvm-raw/utils/bazel/overlay_directories.py 做一下小手術(shù),添加目錄存在與否的條件判斷,避免對已經(jīng)存在的目錄做鏈接:
但還是不行,目前 Windows 系統(tǒng)上體驗 Carbon 只能進入 WSL 系統(tǒng)。
參考
-?[Carbon programming language](https://github.com/carbon-language/carbon-lang)
- [Compiler Explorer](https://carbon.compiler-explorer.com)
- [Bazel - Build and test tool](https://github.com/bazelbuild/bazel)
- [The LLVM Project](https://github.com/llvm/llvm-project)
- [Bazel vs. CMake](https://yearn.xyz/posts/tools/bazelcmake/)
- [Building on Windows](https://github.com/carbon-language/carbon-lang/issues/298)