Starlark 언어

문제 신고 소스 보기 나이틀리 빌드 · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

이 페이지에서는 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는 불변성을 선호합니다. 목록사전이라는 두 가지 변경 가능한 데이터 구조를 사용할 수 있습니다. 목록에 값을 추가하거나 딕셔너리에서 항목을 삭제하는 등 변경 가능한 데이터 구조의 변경사항은 현재 컨텍스트에서 생성된 객체에만 유효합니다. 컨텍스트가 종료되면 값이 변경 불가능해집니다.

이는 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을 만듭니다. 따라서 varfoo.bzl의 컨텍스트에 속합니다. fct()이 실행되면 foo.bzl 컨텍스트 내에서 실행됩니다. foo.bzl 평가가 완료되면 환경에는 값이 [5]인 변경 불가능한 항목 var이 포함됩니다.

다른 bar.bzlfoo.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 기능은 지원되지 않습니다.

  • 암시적 문자열 연결 (명시적 + 연산자 사용)
  • 연결된 비교 (예: 1 < x < 5)
  • class (struct 함수 참고)
  • import (load 문 참고)
  • while, yield:
  • float 및 set 유형입니다.
  • 생성기 및 생성기 표현식
  • is (대신 == 사용)
  • try, raise, except, finally (심각한 오류는 fail 참고)
  • global, nonlocal:
  • 대부분의 내장 함수, 대부분의 메서드