이 페이지에서는 매크로 사용의 기본사항을 다루며 일반적인 사용 사례, 디버깅, 규칙을 포함합니다.
매크로는 규칙을 인스턴스화할 수 있는 BUILD 파일에서 호출되는 함수입니다.
매크로는 기존 규칙과 기타 매크로의 캡슐화 및 코드 재사용에 주로 사용됩니다. 로딩 단계가 끝나면 매크로가 더 이상 존재하지 않으며 Bazel은 인스턴스화된 구체적인 규칙 집합만 확인합니다.
사용
매크로의 일반적인 사용 사례는 규칙을 재사용하려는 경우입니다.
예를 들어 BUILD 파일의 genrule은 명령어에 하드코딩된 some_arg 인수를 사용하여 //:generator으로 파일을 생성합니다.
genrule(
    name = "file",
    outs = ["file.txt"],
    cmd = "$(location //:generator) some_arg > $@",
    tools = ["//:generator"],
)
다른 인수를 사용하여 파일을 더 많이 생성하려면 이 코드를 매크로 함수로 추출하는 것이 좋습니다. name 및 arg 매개변수가 있는 매크로를 file_generator라고 하겠습니다. genrule을 다음으로 바꿉니다.
load("//path:generator.bzl", "file_generator")
file_generator(
    name = "file",
    arg = "some_arg",
)
file_generator(
    name = "file-two",
    arg = "some_arg_two",
)
file_generator(
    name = "file-three",
    arg = "some_arg_three",
)
여기서는 //path 패키지에 있는 .bzl 파일에서 file_generator 기호를 로드합니다. 매크로 함수 정의를 별도의 .bzl 파일에 배치하면 BUILD 파일을 깔끔하고 선언적으로 유지할 수 있습니다. .bzl 파일은 작업공간의 모든 패키지에서 로드할 수 있습니다.
마지막으로 path/generator.bzl에서 원래 genrule 정의를 캡슐화하고 매개변수화하는 매크로 정의를 작성합니다.
def file_generator(name, arg, visibility=None):
  native.genrule(
    name = name,
    outs = [name + ".txt"],
    cmd = "$(location //:generator) %s > $@" % arg,
    tools = ["//:generator"],
    visibility = visibility,
  )
매크로를 사용하여 규칙을 연결할 수도 있습니다. 이 예시에서는 이전 genrule의 출력을 입력으로 사용하는 연결된 genrule을 보여줍니다.
def chained_genrules(name, visibility=None):
  native.genrule(
    name = name + "-one",
    outs = [name + ".one"],
    cmd = "$(location :tool-one) $@",
    tools = [":tool-one"],
    visibility = ["//visibility:private"],
  )
  native.genrule(
    name = name + "-two",
    srcs = [name + ".one"],
    outs = [name + ".two"],
    cmd = "$(location :tool-two) $< $@",
    tools = [":tool-two"],
    visibility = visibility,
  )
이 예시에서는 두 번째 genrule에만 공개 상태 값을 할당합니다. 이를 통해 매크로 작성자는 작업공간의 다른 타겟에서 종속되는 중간 규칙의 출력을 숨길 수 있습니다.
확장 매크로
매크로의 기능을 조사하려면 --output=build와 함께 query 명령어를 사용하여 확장된 형식을 확인하세요.
$ bazel query --output=build :file
# /absolute/path/test/ext.bzl:42:3
genrule(
  name = "file",
  tools = ["//:generator"],
  outs = ["//test:file.txt"],
  cmd = "$(location //:generator) some_arg > $@",
)
네이티브 규칙 인스턴스화
네이티브 규칙 (load() 문장이 필요하지 않은 규칙)은 native 모듈에서 인스턴스화할 수 있습니다.
def my_macro(name, visibility=None):
  native.cc_library(
    name = name,
    srcs = ["main.cc"],
    visibility = visibility,
  )
패키지 이름 (예: 매크로를 호출하는 BUILD 파일)을 알아야 하는 경우 native.package_name() 함수를 사용하세요. native는 BUILD 파일이 아닌 .bzl 파일에서만 사용할 수 있습니다.
매크로의 라벨 해결
매크로는 로드 단계에서 평가되므로 매크로에 나오는 "//foo:bar"와 같은 라벨 문자열은 정의된 .bzl 파일이 아닌 매크로가 사용된 BUILD 파일을 기준으로 해석됩니다. 이 동작은 게시된 Starlark 규칙 세트의 일부이기 때문에 다른 저장소에서 사용하기 위한 매크로에는 일반적으로 바람직하지 않습니다.
Starlark 규칙과 동일한 동작을 얻으려면 라벨 문자열을 Label 생성자로 래핑하세요.
# @my_ruleset//rules:defs.bzl
def my_cc_wrapper(name, deps = [], **kwargs):
  native.cc_library(
    name = name,
    deps = deps + select({
      # Due to the use of Label, this label is resolved within @my_ruleset,
      # regardless of its site of use.
      Label("//config:needs_foo"): [
        # Due to the use of Label, this label will resolve to the correct target
        # even if the canonical name of @dep_of_my_ruleset should be different
        # in the main repo, such as due to repo mappings.
        Label("@dep_of_my_ruleset//tools:foo"),
      ],
      "//conditions:default": [],
    }),
    **kwargs,
  )
디버깅
- bazel query --output=build //my/path:all에서는 평가 후- BUILD파일이 어떻게 표시되는지 보여줍니다. 모든 매크로, glob, 루프가 확장됩니다. 알려진 제한사항: 현재- select표현식은 출력에 표시되지 않습니다.
- generator_function(규칙을 생성한 함수) 또는- generator_name(매크로의 이름 속성)를 기준으로 출력을 필터링할 수 있습니다.- bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'
- BUILD파일에서 규칙- foo이 생성되는 정확한 위치를 알아보려면 다음 방법을 시도해 보세요.- BUILD파일 상단 근처에- cc_library(name = "foo")줄을 삽입합니다. Bazel을 실행합니다. 이름 충돌로 인해 규칙- foo가 생성될 때 예외가 발생하며 전체 스택 트레이스가 표시됩니다.
- 디버깅을 위해 print를 사용할 수도 있습니다. 로드 단계에서 메시지를 - DEBUG로그 줄로 표시합니다. 드문 경우를 제외하고는 저장소에 코드를 제출하기 전에- print호출을 삭제하거나- False로 기본 설정된- debugging매개변수에서 조건부로 만드세요.
오류
오류를 발생시키려면 fail 함수를 사용합니다.
사용자에게 잘못된 부분과 BUILD 파일을 수정하는 방법을 명확하게 설명합니다.
오류를 포착할 수 없습니다.
def my_macro(name, deps, visibility=None):
  if len(deps) < 2:
    fail("Expected at least two values in deps")
  # ...
규칙
- 규칙을 인스턴스화하는 모든 공개 함수 (밑줄로 시작하지 않는 함수)에는 - name인수가 있어야 합니다. 이 인수는 선택사항이 아니어야 합니다 (기본값을 지정하지 않음).
- 공개 함수는 Python 규칙을 따르는 docstring을 사용해야 합니다. 
- BUILD파일에서 매크로의- name인수는 키워드 인수 (위치 인수 아님)여야 합니다.
- 매크로로 생성된 규칙의 - name속성에는 이름 인수가 접두사로 포함되어야 합니다. 예를 들어- macro(name = "foo")은- cc_library- foo및 genrule- foo_gen을 생성할 수 있습니다.
- 대부분의 경우 선택적 매개변수의 기본값은 - None이어야 합니다.- None는 네이티브 규칙에 직접 전달될 수 있으며, 이 경우 인수를 전달하지 않은 것과 동일하게 처리됩니다. 따라서 이 목적으로- 0,- False또는- []로 대체할 필요가 없습니다. 대신 매크로는 생성하는 규칙을 따라야 합니다. 규칙의 기본값이 복잡하거나 시간이 지남에 따라 변경될 수 있기 때문입니다. 또한 명시적으로 기본값으로 설정된 매개변수는 쿼리 언어나 빌드 시스템 내부를 통해 액세스할 때 설정되지 않은 매개변수 (또는- None로 설정된 매개변수)와 다르게 표시됩니다.
- 매크로에는 선택적 - visibility인수가 있어야 합니다.