이 페이지에서는 매크로 사용의 기본사항을 설명하고 일반적인 사용 사례, 디버깅, 규칙을 설명합니다.
매크로는 규칙을 인스턴스화할 수 있는 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은 이전 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,
)
이 예에서는 2genrule에만 공개 상태 값을 할당합니다. 따라서 매크로 작성자가 중간 규칙의 출력이 작업공간의 다른 대상에 종속되지 않도록 숨길 수 있습니다.
확장 매크로
매크로의 기능을 조사하려면 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()
문이 필요하지 않은 규칙)은 네이티브 모듈에서 인스턴스화할 수 있습니다.
def my_macro(name, visibility=None):
native.cc_library(
name = name,
srcs = ["main.cc"],
visibility = visibility,
)
패키지 이름을 알아야 하는 경우 (예: 매크로를 호출하는 BUILD
파일) native.package_name() 함수를 사용합니다. native
는 .bzl
파일에서만 사용할 수 있고 WORKSPACE
또는 BUILD
파일에는 사용할 수 없습니다.
매크로의 라벨 해상도
매크로는 로드 단계에서 평가되므로 매크로에서 발생하는 "//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 workspace, 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
및 genrulefoo_gen
를 생성할 수 있습니다.대부분의 경우 선택적 매개변수의 기본값은
None
입니다.None
는 네이티브 규칙에 직접 전달할 수 있으며, 네이티브 규칙은 인수를 전달하지 않은 것처럼 동일하게 처리됩니다. 따라서 이를 위해0
,False
또는[]
로 바꿀 필요가 없습니다. 대신 매크로는 새로 만드는 규칙을 따라야 합니다. 기본값이 복잡하거나 시간이 지남에 따라 변경될 수 있기 때문입니다. 또한 명시적으로 기본값으로 설정된 매개변수는 쿼리 언어 또는 빌드 시스템 내부 기능을 통해 액세스될 때 설정되지 않은 (또는None
로 설정된) 매개변수와 다르게 보입니다.매크로에는 선택적
visibility
인수가 있어야 합니다.