매크로

문제 신고 <ph type="x-smartling-placeholder"></ph> 소스 보기 1박 · 7.2 · 7.1 · 7.0 · 6.5 · 6.4

이 페이지에서는 매크로 사용의 기본 사항을 다루며 일반적인 사용 사례를 포함합니다. 디버깅 및 규칙으로 변경할 수 있습니다.

매크로는 규칙을 인스턴스화할 수 있는 BUILD 파일에서 호출되는 함수입니다. 매크로는 주로 기존 규칙의 캡슐화 및 코드 재사용에 사용됩니다. 사용할 수 있습니다. 로드 단계에서는 매크로가 더 이상 존재하지 않습니다. Bazel에게는 인스턴스화된 구체적인 규칙 집합만 표시됩니다.

사용

매크로의 일반적인 사용 사례는 규칙을 재사용하려는 경우입니다.

예를 들어 BUILD 파일의 genrule은 다음을 사용하여 파일을 생성합니다. 명령어에 하드코딩된 some_arg 인수가 있는 //:generator:

genrule(
    name = "file",
    outs = ["file.txt"],
    cmd = "$(location //:generator) some_arg > $@",
    tools = ["//:generator"],
)

다른 인수로 더 많은 파일을 생성하려면 매크로 함수로 추출해야 합니다. file_generator 매크로의 이름을 지정해 보겠습니다. namearg 매개변수가 있습니다. 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",
)

다음과 같은 .bzl 파일에서 file_generator 기호를 로드합니다. (//path 패키지에서) 매크로 함수 정의를 .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은 이전 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에 공개 상태 값만 할당합니다. 이렇게 하면 매크로 작성자가 중간 규칙의 출력에 의존하지 않도록 숨깁니다. 영향을 줄 수 있습니다

확장 매크로

매크로의 기능을 조사하려면 query 명령어를 --output=build를 클릭하여 확장된 양식을 확인합니다.

$ 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.bzl 파일에서만 사용할 수 있고 BUILD 파일에서는 사용할 수 없습니다.

매크로의 라벨 확인

매크로는 로드 단계에서 평가되므로 매크로에서 발생하는 "//foo:bar"과 같은 라벨 문자열은 이는 매크로가 사용되는 BUILD 파일을 기준으로 합니다. 정의된 .bzl 파일 이 동작은 일반적으로 바람직하지 않습니다. 다른 저장소에서 사용할 매크로(예: 게시된 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 (매크로 이름 속성)을 통해 가능합니다. <ph type="x-smartling-placeholder">bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'</ph>

  • BUILD 파일에서 foo 규칙이 정확히 어디에 생성되는지 알아보려면 다음을 실행합니다. 다음과 같은 트릭을 시도해 볼 수 있습니다. BUILD 상단 근처에 다음 줄을 삽입하세요. 파일: cc_library(name = "foo"). Bazel을 실행합니다. 다음과 같은 경우 예외가 적용됩니다. 이름 충돌로 인해 foo 규칙이 만들어졌으며, 해당 규칙은 풀 스택 트레이스

  • 디버깅에 print를 사용할 수도 있습니다. 다음을 표시합니다. 로드 단계에서 메시지를 DEBUG 로그 줄로 표시합니다. 드물게 제외 print 호출을 삭제하거나 다음에 따라 조건부로 만드세요. 코드를 제출하기 전에 기본값이 Falsedebugging 매개변수 찾을 수도 있습니다.

오류

오류를 발생시키려면 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 인수가 있어야 합니다.