구성

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
문제 신고 소스 보기

이 페이지에서는 프로젝트 빌드 방식을 맞춤설정하는 Bazel의 API인 Starlark 구성의 이점과 기본 사용법을 설명합니다. 빌드 설정을 정의하는 방법을 포함하고 예를 제공합니다.

이를 통해 다음을 할 수 있습니다.

  • 프로젝트의 커스텀 플래그를 정의하여 --define의 필요성을 제거합니다.
  • 전환을 작성하여 상위 요소와 다른 구성(예: --compilation_mode=opt 또는 --cpu=arm)으로 deps 구성
  • 더 나은 기본값 (예: 지정된 SDK로 //my:android_app을 자동으로 빌드)을 규칙에 베이킹합니다.

이 외에도 다양한 기능이 .bzl 파일에서 제공됩니다 (Bazel 출시 버전 불필요). 예시bazelbuild/examples 저장소를 참고하세요.

사용자 정의 빌드 설정

빌드 설정은 단일 구성 정보입니다. 구성을 키-값 매핑으로 생각하세요. --cpu=ppc--copt="-DFoo"를 설정하면 {cpu: ppc, copt: "-DFoo"}와 같은 구성이 생성됩니다. 각 항목은 빌드 설정입니다.

cpucopt와 같은 기본 플래그는 네이티브 설정으로, 키의 정의와 값은 네이티브 bazel 자바 코드 내부에 설정됩니다. Bazel 사용자는 명령줄 및 기본적으로 유지관리되는 다른 API를 통해서만 읽고 쓸 수 있습니다. 네이티브 플래그 및 네이티브 플래그를 노출하는 API를 변경하려면 bazel 출시 버전이 필요합니다. 사용자 정의 빌드 설정은 .bzl 파일에 정의되어 있으므로 변경사항을 등록하는 데 bazel 버전이 필요하지 않습니다. 또한 명령줄을 통해 설정할 수도 있지만(flags로 지정된 경우 아래 내용 참고) 사용자 정의 전환을 통해 설정할 수도 있습니다.

빌드 설정 정의

엔드 투 엔드 예

build_setting rule() 매개변수

빌드 설정은 다른 규칙과 마찬가지로 Starlark rule() 함수의 build_setting 속성을 사용하여 구분됩니다.

# example/buildsettings/build_settings.bzl
string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)

build_setting 속성은 빌드 설정의 유형을 지정하는 함수를 사용합니다. 이 유형은 boolstring와 같은 기본 Starlark 유형 집합으로 제한됩니다. 자세한 내용은 config 모듈 문서를 참고하세요. 더 복잡한 입력은 규칙의 구현 함수에서 가능합니다. 자세한 내용은 아래를 참조하세요.

config 모듈의 함수는 불리언 매개변수인 flag(선택사항)을 사용합니다. 기본적으로 false로 설정됩니다. flag를 true로 설정하면 명령줄에서 사용자가 빌드 설정을 설정할 수 있으며, 기본값 및 전환을 통해 내부적으로 규칙 작성자가 설정할 수 있습니다. 사용자가 모든 설정을 지정할 수 있는 것은 아닙니다. 예를 들어 규칙 작성자가 테스트 규칙 내에서 사용하려는 디버그 모드가 있는 경우 다른 비테스트 규칙 내에서 해당 기능을 무차별적으로 사용 설정하는 기능을 사용자에게 제공해서는 안 됩니다.

ctx.build_setting_value 사용

모든 규칙과 마찬가지로 빌드 설정 규칙에는 구현 함수가 있습니다. 빌드 설정의 기본적인 Starlark 유형 값은 ctx.build_setting_value 메서드를 통해 액세스할 수 있습니다. 이 메서드는 빌드 설정 규칙의 ctx 객체에만 사용할 수 있습니다. 이러한 구현 메서드는 빌드 설정 값을 직접 전달하거나 유형 확인 또는 더 복잡한 구조체 생성과 같은 추가 작업을 할 수 있습니다. enum 유형의 빌드 설정을 구현하는 방법은 다음과 같습니다.

# example/buildsettings/build_settings.bzl
TemperatureProvider = provider(fields = ['type'])

temperatures = ["HOT", "LUKEWARM", "ICED"]

def _impl(ctx):
    raw_temperature = ctx.build_setting_value
    if raw_temperature not in temperatures:
        fail(str(ctx.label) + " build setting allowed to take values {"
             + ", ".join(temperatures) + "} but was set to unallowed value "
             + raw_temperature)
    return TemperatureProvider(type = raw_temperature)

temperature = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)

다중 집합 문자열 플래그 정의

문자열 설정에는 명령줄이나 bazelrcs에서 플래그를 여러 번 설정할 수 있는 추가 allow_multiple 매개변수가 있습니다. 기본값은 여전히 문자열 유형 속성으로 설정됩니다.

# example/buildsettings/build_settings.bzl
allow_multiple_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True, allow_multiple = True)
)
# example/buildsettings/BUILD
load("//example/buildsettings:build_settings.bzl", "allow_multiple_flag")
allow_multiple_flag(
    name = "roasts",
    build_setting_default = "medium"
)

플래그의 각 설정은 단일 값으로 취급됩니다.

$ bazel build //my/target --//example:roasts=blonde \
    --//example:roasts=medium,dark

위의 내용은 {"//example:roasts": ["blonde", "medium,dark"]}로 파싱되며 ctx.build_setting_value은 목록 ["blonde", "medium,dark"]를 반환합니다.

빌드 설정 인스턴스화

build_setting 매개변수로 정의된 규칙에는 암시적 필수 build_setting_default 속성이 있습니다. 이 속성은 build_setting 매개변수에 선언된 것과 동일한 유형을 사용합니다.

# example/buildsettings/build_settings.bzl
FlavorProvider = provider(fields = ['type'])

def _impl(ctx):
    return FlavorProvider(type = ctx.build_setting_value)

flavor = rule(
    implementation = _impl,
    build_setting = config.string(flag = True)
)
# example/buildsettings/BUILD
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
    name = "favorite_flavor",
    build_setting_default = "APPLE"
)

사전 정의된 설정

엔드 투 엔드 예

Skylib 라이브러리에는 커스텀 Starlark를 쓰지 않고 인스턴스화할 수 있는 사전 정의된 설정 집합이 포함되어 있습니다.

예를 들어 제한된 문자열 값 집합을 허용하는 설정을 정의하려면 다음 안내를 따르세요.

# example/BUILD
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
string_flag(
    name = "myflag",
    values = ["a", "b", "c"],
    build_setting_default = "a",
)

전체 목록은 일반적인 빌드 설정 규칙을 참고하세요.

빌드 설정 사용

빌드 설정에 따라 다름

대상이 구성 정보를 읽으려는 경우 일반 속성 종속 항목을 통해 빌드 설정에 직접 종속하면 됩니다.

# example/rules.bzl
load("//example/buildsettings:build_settings.bzl", "FlavorProvider")
def _rule_impl(ctx):
    if ctx.attr.flavor[FlavorProvider].type == "ORANGE":
        ...

drink_rule = rule(
    implementation = _rule_impl,
    attrs = {
        "flavor": attr.label()
    }
)
# example/BUILD
load("//example:rules.bzl", "drink_rule")
load("//example/buildsettings:build_settings.bzl", "flavor")
flavor(
    name = "favorite_flavor",
    build_setting_default = "APPLE"
)
drink_rule(
    name = "my_drink",
    flavor = ":favorite_flavor",
)

언어는 해당 언어의 모든 규칙이 종속된 표준 빌드 설정 집합을 생성하는 것이 좋습니다. fragments의 기본 개념이 Starlark 구성 환경에서 더 이상 하드코딩된 객체로 존재하지는 않지만 이 개념을 변환하는 한 가지 방법은 공통 암시적 속성 집합을 사용하는 것입니다. 예:

# kotlin/rules.bzl
_KOTLIN_CONFIG = {
    "_compiler": attr.label(default = "//kotlin/config:compiler-flag"),
    "_mode": attr.label(default = "//kotlin/config:mode-flag"),
    ...
}

...

kotlin_library = rule(
    implementation = _rule_impl,
    attrs = dicts.add({
        "library-attr": attr.string()
    }, _KOTLIN_CONFIG)
)

kotlin_binary = rule(
    implementation = _binary_impl,
    attrs = dicts.add({
        "binary-attr": attr.label()
    }, _KOTLIN_CONFIG)

명령줄에서 빌드 설정 사용

대부분의 네이티브 플래그와 마찬가지로 명령줄을 사용하여 플래그로 표시된 빌드 설정을 지정할 수 있습니다. 빌드 설정의 이름은 name=value 문법을 사용하는 전체 타겟 경로입니다.

$ bazel build //my/target --//example:string_flag=some-value # allowed
$ bazel build //my/target --//example:string_flag some-value # not allowed

특수 불리언 구문이 지원됩니다.

$ bazel build //my/target --//example:boolean_flag
$ bazel build //my/target --no//example:boolean_flag

빌드 설정 별칭 사용

빌드 설정 대상 경로에 별칭을 설정하여 명령줄에서 더 쉽게 읽을 수 있습니다. 별칭은 네이티브 플래그와 비슷하게 작동하며 이중 대시 옵션 문법도 사용합니다.

.bazelrc--flag_alias=ALIAS_NAME=TARGET_PATH를 추가하여 별칭을 설정합니다. 예를 들어 별칭을 coffee로 설정하려면 다음을 실행합니다.

# .bazelrc
build --flag_alias=coffee=//experimental/user/starlark_configurations/basic_build_setting:coffee-temp

권장사항: 별칭을 여러 번 설정하면 가장 최근의 별칭이 우선 적용됩니다. 의도치 않은 파싱 결과를 방지하려면 고유한 별칭 이름을 사용합니다.

별칭을 사용하려면 빌드 설정 대상 경로 대신 별칭을 입력하세요. 위의 .bazelrc 예시를 사용자의 .bazelrc에 설정합니다.

$ bazel build //my/target --coffee=ICED

다음을 대신해서 사용합니다.

$ bazel build //my/target --//experimental/user/starlark_configurations/basic_build_setting:coffee-temp=ICED

권장사항: 명령줄에서 별칭을 설정할 수 있지만 .bazelrc에 그대로 두면 명령줄이 복잡해집니다.

라벨 유형 빌드 설정

엔드 투 엔드 예

다른 빌드 설정과 달리 라벨 유형 설정은 build_setting 규칙 매개변수를 사용하여 정의할 수 없습니다. 대신 bazel에는 label_flaglabel_setting의 두 가지 기본 제공 규칙이 있습니다. 이러한 규칙은 빌드 설정이 설정된 실제 타겟의 제공업체를 전달합니다. label_flaglabel_setting는 전환을 통해 읽고 쓸 수 있으며 label_flag는 다른 build_setting 규칙과 마찬가지로 사용자가 설정할 수 있습니다. 단, 맞춤 설정할 수 없다는 점만 다릅니다.

라벨이 지정된 설정은 나중에 기한이 지정된 기본값의 기능을 대체합니다. 기한이 지정된 기본 속성은 라벨 유형의 속성으로서 최종 값이 구성의 영향을 받을 수 있습니다. 이는 Starlark에서 configuration_field API를 대체합니다.

# example/rules.bzl
MyProvider = provider(fields = ["my_field"])

def _dep_impl(ctx):
    return MyProvider(my_field = "yeehaw")

dep_rule = rule(
    implementation = _dep_impl
)

def _parent_impl(ctx):
    if ctx.attr.my_field_provider[MyProvider].my_field == "cowabunga":
        ...

parent_rule = rule(
    implementation = _parent_impl,
    attrs = { "my_field_provider": attr.label() }
)

# example/BUILD
load("//example:rules.bzl", "dep_rule", "parent_rule")

dep_rule(name = "dep")

parent_rule(name = "parent", my_field_provider = ":my_field_provider")

label_flag(
    name = "my_field_provider",
    build_setting_default = ":dep"
)

빌드 설정 및 select()

엔드 투 엔드 예

사용자는 select()를 사용하여 빌드 설정의 속성을 구성할 수 있습니다. 빌드 설정 타겟은 config_settingflag_values 속성에 전달할 수 있습니다. 구성에 대응하는 값은 String로 전달된 다음, 일치를 위해 빌드 설정 유형에 파싱됩니다.

config_setting(
    name = "my_config",
    flag_values = {
        "//example:favorite_flavor": "MANGO"
    }
)

사용자 정의 전환

구성 전환은 구성된 그래프에서 빌드 그래프 내의 다른 대상으로 변환을 매핑합니다.

규칙을 설정하는 규칙에는 특수 속성을 포함해야 합니다.

  "_allowlist_function_transition": attr.label(
      default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
  )

전환을 추가하면 빌드 그래프의 크기를 상당히 폭발적으로 늘릴 수 있습니다. 그러면 이 규칙의 대상을 만들 수 있는 패키지의 허용 목록이 설정됩니다. 위 코드 블록의 기본값은 모든 항목을 허용합니다. 규칙을 사용할 수 있는 사용자를 제한하려면 이 속성이 자체 커스텀 허용 목록을 가리키도록 설정하면 됩니다. 빌드 성능이 전환에 미치는 영향을 이해하는 데 도움이 필요하거나 도움이 필요하면 bazel-discuss@googlegroups.com에 문의하세요.

정의

전환은 규칙 간의 구성 변경사항을 정의합니다. 예를 들어 '상위 CPU가 아닌 다른 CPU에 대한 종속 항목 컴파일'과 같은 요청이 전환에 의해 처리됩니다.

공식적으로 전환은 입력 구성에서 하나 이상의 출력 구성으로의 함수입니다. 대부분의 전환은 '--cpu=ppc로 입력 구성 재정의'와 같이 1:1로 이루어집니다. 1:2 이상의 전환도 존재할 수 있지만 특별한 제한사항이 있습니다.

Starlark에서 전환은 transition()함수 및 구현 함수를 사용하여 규칙과 매우 비슷하게 정의됩니다.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {"//example:favorite_flavor" : "MINT"}

hot_chocolate_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//example:favorite_flavor"]
)

transition() 함수는 구현 함수, 읽을 빌드 설정 집합(inputs), 작성할 빌드 설정 집합(outputs)을 사용합니다. 구현 함수에는 settingsattr의 두 매개변수가 있습니다. settingsinputs 매개변수에 transition()로 선언된 모든 설정의 {String:Object} 사전입니다.

attr은 전환이 연결된 규칙의 속성 및 값 사전입니다. 발신 에지 전환으로 연결될 때 이러한 속성 값은 모두 SELECT() 이후 해상도로 구성됩니다. 수신 에지 전환으로 연결되면 attr는 선택기를 사용하여 값을 확인하는 속성을 포함하지 않습니다. --foo의 수신 에지 전환이 bar 속성을 읽은 후 --foo를 선택하여 bar 속성을 설정하면 전환에서 수신되는 에지 전환이 잘못된 bar 값을 읽을 수 있습니다.

구현 함수는 적용할 새 빌드 설정 값의 사전 (또는 여러 출력 구성으로 전환하는 경우 사전 목록)을 반환해야 합니다. 반환된 사전 키 세트에는 전환 함수의 outputs 매개변수에 전달된 빌드 설정 집합이 정확하게 포함되어야 합니다. 이는 빌드 설정이 전환 과정 중에 실제로 변경되지 않은 경우에도 마찬가지입니다. 원래 값은 반환된 사전에서 명시적으로 전달되어야 합니다.

1:2+ 전환 정의

엔드 투 엔드 예

발신 에지 전환은 단일 입력 구성을 둘 이상의 출력 구성에 매핑할 수 있습니다. 이는 멀티 아키텍처 코드를 번들로 묶는 규칙을 정의하는 데 유용합니다.

1:2 이상의 전환은 전환 구현 함수에서 사전 목록을 반환하여 정의됩니다.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return [
        {"//example:favorite_flavor" : "LATTE"},
        {"//example:favorite_flavor" : "MOCHA"},
    ]

coffee_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//example:favorite_flavor"]
)

규칙 구현 함수가 개별 종속 항목을 읽는 데 사용할 수 있는 커스텀 키를 설정할 수도 있습니다.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {
        "Apple deps": {"//command_line_option:cpu": "ppc"},
        "Linux deps": {"//command_line_option:cpu": "x86"},
    }

multi_arch_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"]
)

전환 연결

엔드 투 엔드 예

전환은 들어오는 가장자리와 나가는 가장자리의 두 위치에 연결할 수 있습니다. 실질적으로는 규칙이 자체 구성 (접속 전환)을 전환하고 종속 항목 구성을 전환 (발신 에지 전환)할 수 있음을 의미합니다.

참고: 현재 Starlark 전환을 기본 규칙에 연결할 수 있는 방법은 없습니다. 그렇게 해야 하는 경우 해결 방법에 대한 도움이 필요한 경우 bazel-discuss@googlegroups.com에 문의하세요.

수신 에지 전환

수신 에지 전환은 rule()cfg 매개변수에 transition()로 생성된 transition 객체를 연결하여 활성화됩니다.

# example/rules.bzl
load("example/transitions:transitions.bzl", "hot_chocolate_transition")
drink_rule = rule(
    implementation = _impl,
    cfg = hot_chocolate_transition,
    ...

수신 에지 전환은 1:1 전환이어야 합니다.

발신 에지 전환

발신 에지 전환은 속성의 cfg 매개변수에 transition()로 생성된 transition 객체를 연결하여 활성화됩니다.

# example/rules.bzl
load("example/transitions:transitions.bzl", "coffee_transition")
drink_rule = rule(
    implementation = _impl,
    attrs = { "dep": attr.label(cfg = coffee_transition)}
    ...

발신 에지 전환은 1:1 또는 1:2+일 수 있습니다.

이러한 키를 읽는 방법은 전환을 사용한 속성 액세스를 참고하세요.

네이티브 옵션 전환

엔드 투 엔드 예

Starlark 전환은 옵션 이름의 특수 프리픽스를 통해 네이티브 빌드 구성 옵션에 관한 읽기 및 쓰기를 선언할 수도 있습니다.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {"//command_line_option:cpu": "k8"}

cpu_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"]

지원되지 않는 네이티브 옵션

Bazel은 --define"//command_line_option:define"로 전환하는 것을 지원하지 않습니다. 대신 맞춤 빌드 설정을 사용하세요. 일반적으로 --define를 새로 사용하는 것은 빌드 설정으로 권장되지 않습니다.

Bazel은 --config에서 전환을 지원하지 않습니다. --config가 다른 플래그로 확장되는 '확장' 플래그이기 때문입니다.

결정적으로, --config에는 빌드 구성에 영향을 미치지 않는 플래그(예: --spawn_strategy)가 포함될 수 있습니다. Bazel은 의도적으로 이러한 플래그를 개별 대상에 바인딩할 수 없습니다. 즉, 전환에 적용할 수 있는 일관된 방법이 없습니다.

이 문제를 해결하려면 전환에서 구성에 포함된 플래그를 명시적으로 항목화할 수 있습니다. 이를 위해서는 --config의 확장을 두 위치에 유지 관리해야 하며, 이는 알려진 UI 결함입니다.

여러 빌드 설정 허용에 관한 전환

여러 값을 허용하는 빌드 설정을 지정할 때는 목록으로 설정 값을 설정해야 합니다.

# example/buildsettings/build_settings.bzl
string_flag = rule(
    implementation = _impl,
    build_setting = config.string(flag = True, allow_multiple = True)
)
# example/BUILD
load("//example/buildsettings:build_settings.bzl", "string_flag")
string_flag(name = "roasts", build_setting_default = "medium")
# example/transitions/rules.bzl
def _transition_impl(settings, attr):
    # Using a value of just "dark" here will throw an error
    return {"//example:roasts" : ["dark"]},

coffee_transition = transition(
    implementation = _transition_impl,
    inputs = [],
    outputs = ["//example:roasts"]
)

노옵스(no-ops) 전환

전환 시 {}, [] 또는 None가 반환되는 경우 이는 모든 설정을 원래 값으로 유지하기 위한 약식입니다. 이렇게 하면 각 출력을 명시적으로 설정하는 것보다 편리합니다.

# example/transitions/transitions.bzl
def _impl(settings, attr):
    _ignore = (attr)
    if settings["//example:already_chosen"] is True:
      return {}
    return {
      "//example:favorite_flavor": "dark chocolate",
      "//example:include_marshmallows": "yes",
      "//example:desired_temperature": "38C",
    }

hot_chocolate_transition = transition(
    implementation = _impl,
    inputs = ["//example:already_chosen"],
    outputs = [
        "//example:favorite_flavor",
        "//example:include_marshmallows",
        "//example:desired_temperature",
    ]
)

전환으로 속성 액세스

엔드 투 엔드 예

발신 에지에 전환을 연결할 때(전환이 1:1인지 1:2+ 전환인지에 관계없이) ctx.attr는 목록이 아닌 경우 강제로 목록에 표시됩니다. 이 목록의 요소 순서는 지정되지 않습니다.

# example/transitions/rules.bzl
def _transition_impl(settings, attr):
    return {"//example:favorite_flavor" : "LATTE"},

coffee_transition = transition(
    implementation = _transition_impl,
    inputs = [],
    outputs = ["//example:favorite_flavor"]
)

def _rule_impl(ctx):
    # Note: List access even though "dep" is not declared as list
    transitioned_dep = ctx.attr.dep[0]

    # Note: Access doesn't change, other_deps was already a list
    for other dep in ctx.attr.other_deps:
      # ...


coffee_rule = rule(
    implementation = _rule_impl,
    attrs = {
        "dep": attr.label(cfg = coffee_transition)
        "other_deps": attr.label_list(cfg = coffee_transition)
    })

전환이 1:2+이고 맞춤 키를 설정하는 경우 ctx.split_attr를 사용하여 각 키의 개별 deps를 읽을 수 있습니다.

# example/transitions/rules.bzl
def _impl(settings, attr):
    _ignore = (settings, attr)
    return {
        "Apple deps": {"//command_line_option:cpu": "ppc"},
        "Linux deps": {"//command_line_option:cpu": "x86"},
    }

multi_arch_transition = transition(
    implementation = _impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"]
)

def _rule_impl(ctx):
    apple_dep = ctx.split_attr.dep["Apple deps"]
    linux_dep = ctx.split_attr.dep["Linux deps"]
    # ctx.attr has a list of all deps for all keys. Order is not guaranteed.
    all_deps = ctx.attr.dep

multi_arch_rule = rule(
    implementation = _rule_impl,
    attrs = {
        "dep": attr.label(cfg = multi_arch_transition)
    })

여기에서 전체 예를 참고하세요.

플랫폼 및 도구 모음과 통합

오늘날 --cpu--crosstool_top와 같은 많은 네이티브 플래그는 도구 모음 확인과 관련이 있습니다. 향후 이러한 유형의 플래그에 관한 명시적 전환은 타겟 플랫폼에서 전환으로 대체될 가능성이 높습니다.

메모리 및 성능 고려사항

빌드에 전환 및 새 구성을 추가하면 비용이 증가합니다. 빌드 그래프가 커지고 이해하기 어려운 빌드 그래프가 느려지며 빌드 속도가 느려집니다. 빌드 규칙에서 전환 사용을 고려할 때 이러한 비용을 고려하는 것이 좋습니다. 다음은 전환을 통해 빌드 그래프의 지수 성장이 발생하는 방법의 예입니다.

잘못 동작된 빌드: 우수사례

확장성 그래프

그림 1. 최상위 대상과 그 종속 항목을 보여주는 확장성 그래프

이 그래프는 두 타겟(//pkg:1_0 및 //pkg:1_1)에 종속되는 최상위 타겟 //pkg:app을 보여줍니다. 두 타겟 모두 //pkg:2_0 및 //pkg:2_1의 두 대상에 종속됩니다. 이 두 타겟은 //pkg:3_0 및 //pkg:3_1의 두 대상에 종속됩니다. 이는 하나의 타겟인 //pkg:dep에 종속되는 //pkg:n_0과 //pkg:n_1까지 계속됩니다.

//pkg:app 빌드에는 \(2n+2\) 대상이 필요합니다.

  • //pkg:app
  • //pkg:dep
  • \([1..n]\)및 \(i\) 의 //pkg:i_0//pkg:i_1

--//foo:owner=<STRING> 플래그를 //pkg:i_b로 적용한다고 구현한다고 가정해 보겠습니다.

depConfig = myConfig + depConfig.owner="$(myConfig.owner)$(b)"

즉, //pkg:i_b는 모든 deps의 이전 값 --ownerb를 추가합니다.

이렇게 하면 다음과 같은 구성된 대상이 생성됩니다.

//pkg:app                              //foo:owner=""
//pkg:1_0                              //foo:owner=""
//pkg:1_1                              //foo:owner=""
//pkg:2_0 (via //pkg:1_0)              //foo:owner="0"
//pkg:2_0 (via //pkg:1_1)              //foo:owner="1"
//pkg:2_1 (via //pkg:1_0)              //foo:owner="0"
//pkg:2_1 (via //pkg:1_1)              //foo:owner="1"
//pkg:3_0 (via //pkg:1_0 → //pkg:2_0)  //foo:owner="00"
//pkg:3_0 (via //pkg:1_0 → //pkg:2_1)  //foo:owner="01"
//pkg:3_0 (via //pkg:1_1 → //pkg:2_0)  //foo:owner="10"
//pkg:3_0 (via //pkg:1_1 → //pkg:2_1)  //foo:owner="11"
...

//pkg:dep 구성 중인 대상 \(2^n\) : config.owner= \(b_0b_1...b_n\)모든 대상 \(b_i\) 에서 \(\{0,1\}\)

이렇게 하면 빌드 그래프가 대상 그래프보다 기하급수적으로 커지며 해당하는 메모리 및 성능에 영향을 줍니다.

TODO: 이러한 문제의 측정 및 완화 전략을 추가하세요.

추가 자료

빌드 구성 수정에 관한 자세한 내용은 다음을 참고하세요.