本頁將概述 Starlark (舊稱 Skylark),這是 Bazel 使用的語言。如需函式和型別的完整清單,請參閱 Bazel API 參考資料。
如要進一步瞭解這項語言,請參閱 Starlark 的 GitHub 存放區。
如要查看 Starlark 語法和行為的權威規格,請參閱 Starlark 語言規格。
語法
Starlark 的語法是以 Python3 為靈感。以下是 Starlark 的有效語法:
def fizz_buzz(n):
"""Print Fizz Buzz numbers from 1 to n."""
for i in range(1, n + 1):
s = ""
if i % 3 == 0:
s += "Fizz"
if i % 5 == 0:
s += "Buzz"
print(s if s else i)
fizz_buzz(20)
Starlark 的語意可能與 Python 不同,但行為差異很少,除非 Starlark 引發錯誤。支援的 Python 型別如下:
可變動性
Starlark 偏好不可變更性。系統提供兩種可變動的資料結構:清單和字典。對可變動資料結構所做的變更 (例如將值附加至清單,或刪除字典中的項目),只對目前環境中建立的物件有效。脈絡完成後,其值會變成不可變動。
這是因為 Bazel 建構作業會使用平行執行。在建構期間,每個 .bzl 檔案和每個 BUILD 檔案都會取得自己的執行環境。每項規則也會在各自的脈絡中進行分析。
我們以 foo.bzl 檔案為例:
# `foo.bzl`
var = [] # declare a list
def fct(): # declare a function
var.append(5) # append a value to the list
fct() # execute the fct function
Bazel 會在載入 foo.bzl 時建立 var。var因此屬於 foo.bzl 的情境。fct() 執行時,會在 foo.bzl 的環境中執行。完成 foo.bzl 的評估後,環境會包含不可變動的項目 var,值為 [5]。
當另一個 bar.bzl 從 foo.bzl 載入符號時,載入的值會維持不變。因此,bar.bzl 中的下列程式碼無效:
# `bar.bzl`
load(":foo.bzl", "var", "fct") # loads `var`, and `fct` from `./foo.bzl`
var.append(6) # runtime error, the list stored in var is frozen
fct() # runtime error, fct() attempts to modify a frozen list
在 bzl 檔案中定義的全域變數,只能在定義該變數的 bzl 檔案中變更。如同上述使用 bzl 檔案的範例,規則傳回的值不可變更。
BUILD 檔案與 .bzl 檔案的差異
BUILD 檔案會透過呼叫規則向目標註冊。.bzl 檔案提供常數、規則、巨集和函式的定義。
原生函式和原生規則是 BUILD 檔案中的全域符號。bzl 檔案需要使用 native 模組載入。
BUILD 檔案有兩項語法限制:1) 宣告函式屬於違法行為,2) 不允許使用 *args 和 **kwargs 引數。
與 Python 的差異
全域變數無法變更。
頂層不允許使用
for陳述式。請改為在函式中使用這些值。您可以在BUILD檔案中使用清單理解。頂層不允許使用
if陳述式。不過,您可以使用if運算式first = data[0] if len(data) > 0 else None。以確定性順序疊代字典。
不允許遞迴。
Int 型別僅限 32 位元帶正負號整數。溢位會擲回錯誤。
在疊代期間修改集合會發生錯誤。
除了等號測試外,比較運算子
<、<=、>=、>等並未跨值型別定義。簡而言之:5 < 'foo'會擲回錯誤,而5 == "5"則會傳回 false。在元組中,只有當元組位於括號之間時,尾隨逗號才有效,也就是撰寫
(1,)而非1,時。字典常值不得有重複的鍵。舉例來說,以下是錯誤:
{"a": 4, "b": 7, "a": 1}。字串以雙引號表示 (例如呼叫 repr 時)。
字串無法疊代。
不支援下列 Python 功能: