このページでは、Bazel で使用される言語である Starlark(旧称 Skylark)の概要について説明します。関数と型の完全なリストについては、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 引数は許可されていない、という 2 つの構文上の制限があります。
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 機能はサポートされていません。