八卦一下Starlark語言
編譯移植TensorFlow時用到Bazel這一構建工具,Bazel用Starlark語法來編寫WORKSPACE/BUILD文件,它們是類似於Make中的makeifle、CMake中的CMakeLists的存在。
來源:https://blog.bazel.build/2017/03/21/design-of-skylark.html
Starlark語言簡史
早些年google用make+makefile構建代碼,后來代碼多了,發現make不適合(反正我是覺得makefile語法太怪異了,之前看ucore/JOS操作系統內核時候就很慌)。
一個臨時辦法是手寫一個描述文件BUILD
,然后用Python生成makefile文件(沿着這種思路,考慮VC/gcc/XCode等多種平台,就是cmake了)。
但是其實Make更大問題是速度太慢,於是google搞了個Blaze,開源版本叫Bazel(比如TensorFlow默認就用Bazel構建)。
Blaze2006年一路過來,也是各種經驗啊:用BUILD
替代Makefile
,用Blaze
替代Make
,那么似乎應該讓Blaze
來解析BUILD
然后調編譯器連接器干活,因為Make
就是先聽Makefile嗶嗶然后向gcc和ar發號施令的。
但是既然已經是重新實現一個構建系統了,能不能把描述文件的語法搞的human friendly一點啊?干脆用Python寫算了吧!
誒,如果BUILD
用純Python寫,那Blaze
就不需要解析BUILD
了。但是!純Python寫/解析BUILD
,太特么自由了,A君寫一個宏,B君又寫一個宏,實現同樣功能。天啊,google那么多項目,這么搞搞死人啊。
好吧,捋一捋:
- 構建的描述文件,語法得簡單,或者說大家基本上熟悉的,門檻低點
- 構建描述文件中常用的什么目標啊、庫啊、路徑啊、依賴啊,得有統一的版本
- 構建速度得快點
其中對於前面兩點,干脆搞個閹割版的Python(語言)吧!搞一些限定,但是python的常用基本語法給他留着。
好了,這就是Starlark了。對,它改過名,以前叫Skylark。
Starlark設計需求
Starlark除了是一門Python方言,它更是Blaze(Bazel)的前端。要想Bazel構建速度快,應該避免重復計算,Starlark作為預處理器,這么干的:
- 搞了一個依賴圖(graph of dependencies),這么一來不管你在
BUILD
和.bzl
文件中怎么瞎import
,import
的順序不會影響構建速度 - 根據這個圖呢,先算“葉子節點”,也就是不依賴任何東西的任務,然后把依賴葉子節點的任務做做掉。好吧,這就是圖的搜索算法,主要標記visit flag來避免重復計算。
- 每個文件只被加載一次:緩存着,避免I/O阻塞計算速度
- 考慮到多個BUILD文件中可能使用了同一個變量,多線程解析各個BUILD文件時給變量加只讀鎖