本頁概述 Starlark (舊稱 Skylark),這是 Bazel 使用的語言。如需函式和類型的完整清單,請參閱 Bazel API 參考資料。
如要進一步瞭解這門語言,請參閱 Starlark 的 GitHub 存放區。
如需 Starlark 語法和行為的權威規格,請參閱 Starlark 語言規格。
語法
Starlark 的語法受到 Python 3 的啟發。以下是 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 偏好不可變性。您可以使用兩種可變動的資料結構:清單和dicts。變更可變動的資料結構 (例如在清單中附加值或刪除字典中的項目) 只適用於在目前情境中建立的物件。當情境結束後,其值就會變成不可變動。
這是因為 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 功能: