執行群組

7.3 · 7.2 · 7.1 · 7.0 · 6.5

執行群組可讓單一指定目標包含多個執行平台。每個執行群組都有自己的工具鏈依附元件,並執行自己的工具鏈解析

背景

執行群組可讓規則作者定義一組動作,每個動作可能使用不同的執行平台。多個執行平台可讓動作以不同方式執行,例如在遠端 (Linux) 工作站上編譯 iOS 應用程式,然後在本機 Mac 工作站上進行連結/程式碼簽署。

定義動作群組也有助於減少使用動作助憶法做為指定動作的代理程式。系統無法保證助憶碼是唯一的,而且只能參照單一動作。這對於將額外資源分配給特定記憶體和處理密集型動作 (例如在 C++ 版本中連結) 特別有用,而且不會將資源過度分配給需求較低的作業。

定義執行群組

在規則定義期間,規則作者可以declare一組執行群組。在每個執行群組中,規則作者可以指定選取該執行群組的執行平台所需的所有內容,也就是透過 exec_compatible_with 的任何限制條件,以及透過 toolchain 的工具鍊類型。

# foo.bzl
my_rule = rule(
    _impl,
    exec_groups = {
        link: exec_group(
            exec_compatible_with = [ "@platforms//os:linux" ]
            toolchains = ["//foo:toolchain_type"],
        ),
        test: exec_group(
            toolchains = ["//foo_tools:toolchain_type"],
        ),
    },
    attrs = {
        "_compiler": attr.label(cfg = config.exec("link"))
    },
)

在上述程式碼片段中,您可以看到工具依附元件也可以使用 cfg 屬性參數和 config 模組,為執行群組指定轉換。模組會公開 exec 函式,該函式會使用單一字串參數,也就是應建構依附元件的執行群組名稱。

與原生規則一樣,Starlark 測試規則預設會顯示 test 執行群組。

執行群組繼承

除了定義自己的限制條件和工具鍊外,新的執行群組也可以透過傳遞 copy_from_rule = True 參數,宣告要從規則的預設執行群組繼承。如果將 copy_from_rule 設為 true,並傳遞 exec_compatible_withtoolchains,則會發生錯誤。

從預設執行群組繼承的執行群組會複製限制、工具鍊和執行屬性。這包括在目標層級設定的限制和執行屬性,而不只是規則本身指定的屬性。換句話說,請參考以下內容:

# foo.bzl
my_rule = rule(
    _impl,
    exec_groups = {
        copied: exec_group(
            copy_from_rule = True,
            # This will inherit exec_compatible_with and toolchains.
            # Setting them here directly would be an error, however.
        ),
    },
    toolchains = ["//foo_tools:toolchain_type"],
    exec_compatible_with = ["@platforms//os:linux"],
)

# BUILD

my_rule(
    name = "demo",
    exec_compatible_with = [":local_constraint"],
)

已設定目標 democopied 執行群組會包含下列所有項目: - //fool_tools:toolchain_type - @platforms//os:linux - :local_constraint

存取執行群組

在規則實作中,您可以宣告應在執行群組的執行平台上執行動作。您可以使用動作產生方法的 exec_group 參數,具體來說就是 ctx.actions.runctx.actions.run_shell

# foo.bzl
def _impl(ctx):
  ctx.actions.run(
     inputs = [ctx.attr._some_tool, ctx.srcs[0]]
     exec_group = "compile",
     # ...
  )

規則作者也可以存取執行群組的已解析的工具鍊,這與存取目標的已解析工具鍊類似:

# foo.bzl
def _impl(ctx):
  foo_info = ctx.exec_groups["link"].toolchains["//foo:toolchain_type"].fooinfo
  ctx.actions.run(
     inputs = [foo_info, ctx.srcs[0]]
     exec_group = "link",
     # ...
  )

使用執行群組設定執行屬性

執行群組會與每項規則中的 exec_properties 屬性整合,並允許目標寫入者指定屬性的字串字典,接著再傳遞至執行機器。舉例來說,如果您想為目標設定某些屬性 (例如記憶體),並為目標設定較高的記憶體分配方式,則必須使用執行群組強化金鑰編寫 exec_properties 項目,例如:

# BUILD
my_rule(
    name = 'my_target',
    exec_properties = {
        'mem': '12g',
        'link.mem': '16g'
    }
    
)

所有含有 exec_group = "link" 的動作都會將執行屬性字典視為 {"mem": "16g"}。如您所見,執行群組層級設定會覆寫目標層級設定。

原生規則的執行群組

原生規則定義的動作可使用下列執行群組:

  • test:Test Runner 動作。
  • cpp_link:C++ 連結動作。

建立執行群組以設定執行屬性

有時您可能會想使用執行群組為特定動作提供不同的執行屬性,但實際上不想使用與規則不同的工具鍊或限制。在這些情況下,您可以使用 copy_from_rule 參數建立執行群組:

# foo.bzl

# Creating an exec group with `copy_from_rule=True` is the same as explicitly
# setting the exec group's toolchains and constraints to the same values as the
# rule's respective parameters.
my_rule = rule(
    _impl,
    exec_compatible_with = ["@platforms//os:linux"],
    toolchains = ["//foo:toolchain_type"],
    exec_groups = {
        # The following two groups have the same toolchains and constraints:
        foo: exec_group(copy_from_rule = True),
        "bar": exec_group(
            exec_compatible_with = ["@platforms//os:linux"],
            toolchains = ["//foo:toolchain_type"],
        ),
    },
)

#

執行群組和平台執行屬性

您可以為平台目標的任意執行群組定義 exec_properties (與直接在目標上設定的 exec_properties 不同,後者會拒絕不明執行群組的屬性)。目標接著會沿用執行平台的 exec_properties,進而影響預設執行群組和其他相關執行群組。

舉例來說,假設執行 C++ 測試需要使用某些資源,但編譯和連結時並不需要這些資源,這可以模擬如下:

constraint_setting(name = "resource")
constraint_value(name = "has_resource", constraint_setting = ":resource")

platform(
    name = "platform_with_resource",
    constraint_values = [":has_resource"],
    exec_properties = {
        "test.resource": "...",
    },
)

cc_test(
    name = "my_test",
    srcs = ["my_test.cc"],
    exec_compatible_with = [":has_resource"],
)

exec_properties 直接在目標上定義的值,優先順序高於從執行平台繼承的值。