Os grupos de execução permitem várias plataformas de execução em uma única meta. Cada grupo de execução tem suas próprias dependências de toolchain e realiza a própria resolução de toolchain.
Status atual
Grupos de execução para determinadas ações declaradas nativamente, como CppLink
, podem ser usados em exec_properties
para definir requisitos de execução por ação e por destino. Para mais detalhes, consulte a seção
Grupos de execução padrão.
Contexto
Os grupos de execução permitem que o autor da regra defina conjuntos de ações, cada um com uma plataforma de execução potencialmente diferente. Várias plataformas de execução podem permitir ações de execução de maneira diferente, por exemplo, compilando um app iOS em um worker remoto (Linux) e vinculando/assinando o código em um worker Mac local.
A capacidade de definir grupos de ações também ajuda a aliviar o uso de mnemônicos de ação como um proxy para especificar ações. Não há garantia de que os mnemônicos sejam exclusivos e só podem referenciar uma única ação. Isso é especialmente útil para alocar recursos extras a ações específicas de memória e processamento intensivo, como vinculação em builds C++, sem alocar demais para tarefas menos exigentes.
Definir grupos de execução
Durante a definição de regras, os autores podem
declarar
um conjunto de grupos de execução. Em cada grupo de execução, o autor da regra pode especificar tudo o que é necessário para selecionar uma plataforma de execução para esse grupo, ou seja, restrições via exec_compatible_with
e tipos de cadeia de ferramentas via 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"))
},
)
No snippet de código acima, é possível ver que as dependências de ferramentas também podem especificar
transição para um grupo de execução usando o
parâmetro de atributo cfg
e o módulo
config
. O módulo expõe uma função exec
que usa um único parâmetro de string, que é o nome do grupo de execução para o qual a dependência precisa ser criada.
Assim como nas regras nativas, o grupo de execução test
está presente por padrão nas regras de teste do Starlark.
Como acessar grupos de execução
Na implementação da regra, é possível declarar que as ações devem ser executadas na
plataforma de execução de um grupo de execução. Para isso, use o parâmetro exec_group
dos métodos de geração de ações, especificamente ctx.actions.run
e ctx.actions.run_shell
.
# foo.bzl
def _impl(ctx):
ctx.actions.run(
inputs = [ctx.attr._some_tool, ctx.srcs[0]]
exec_group = "compile",
# ...
)
Os criadores de regras também poderão acessar as cadeias de ferramentas resolvidas dos grupos de execução, assim como você pode acessar a cadeia de ferramentas resolvida de uma meta:
# 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",
# ...
)
Grupos de execução padrão
Os seguintes grupos de execução são predefinidos:
test
: ações do executor de testes. Para mais detalhes, consulte a seção de plataforma de execução da Test Encyclopedia.cpp_link
: ações de vinculação do C++.
Como usar grupos de execução para definir propriedades de execução
Os grupos de execução são integrados ao atributo
exec_properties
que existe em todas as regras e permite que o gravador de destino especifique um
dicionário de strings de propriedades que é transmitido ao mecanismo de execução. Por exemplo, se você quisesse definir alguma propriedade, como memória, para o destino e dar a determinadas ações uma alocação de memória maior, escreveria uma entrada exec_properties
com uma chave aumentada do grupo de execução, como:
# BUILD
my_rule(
name = 'my_target',
exec_properties = {
'mem': '12g',
'link.mem': '16g'
}
…
)
Todas as ações com exec_group = "link"
veriam o dicionário de propriedades de execução como {"mem": "16g"}
. Como você pode ver aqui, as configurações no nível do grupo de execução substituem as configurações no nível da meta.
Como usar grupos de execução para definir restrições de plataforma
Os grupos de execução também são integrados aos atributos
exec_compatible_with
e
exec_group_compatible_with
que existem em todas as regras e permitem que o gravador de destino especifique
restrições adicionais que precisam ser atendidas pelas plataformas de execução
selecionadas para as ações do destino.
Por exemplo, se a regra my_test
definir o grupo de execução link
, além do padrão e do grupo de execução test
, o uso a seguir desses atributos executaria ações no grupo de execução padrão em uma plataforma com um grande número de CPUs, a ação de teste no Linux e a ação de vinculação na plataforma de execução padrão:
# BUILD
constraint_setting(name = "cpu")
constraint_value(name = "high_cpu", constraint_setting = ":cpu")
platform(
name = "high_cpu_platform",
constraint_values = [":high_cpu"],
exec_properties = {
"cpu": "256",
},
)
my_test(
name = "my_test",
exec_compatible_with = ["//constraints:high_cpu"],
exec_group_compatible_with = {
"test": ["@platforms//os:linux"],
},
...
)
Grupos de execução para regras nativas
Os seguintes grupos de execução estão disponíveis para ações definidas por regras nativas:
test
: ações do executor de testes.cpp_link
: ações de vinculação do C++.
Grupos de execução e propriedades de execução da plataforma
É possível definir exec_properties
para grupos de execução arbitrários em destinos de plataforma (ao contrário de exec_properties
definido diretamente em um destino, em que propriedades para grupos de execução desconhecidos são rejeitadas). As metas herdam o exec_properties
da plataforma de execução que afeta o grupo de execução padrão e outros grupos relevantes.
Por exemplo, suponha que a execução de testes na plataforma de execução exija que algum recurso esteja disponível, mas não seja necessário para compilação e vinculação. Isso pode ser modelado da seguinte maneira:
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
definido diretamente em destinos tem precedência sobre aqueles que
são herdados da plataforma de execução.