このページでは、Bazel で使用される言語(Skylark)の Starlark の概要を説明します。関数と型の完全なリストについては、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 は不変性を優先します。可変データ構造には、リストと辞書の 2 つがあります。可変データ構造への変更(リストへの値の追加、辞書のエントリの削除など)は、現在のコンテキストで作成されたオブジェクトに対してのみ有効です。コンテキストが終了すると、その値は不変になります。
これは、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
の評価が完了すると、環境には値 [5]
の不変エントリ var
が含まれます。
別の 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 機能はサポートされていません。