Los grupos de ejecución permiten tener varias plataformas de ejecución dentro de un solo destino. Cada grupo de ejecución tiene sus propias dependencias de toolchain y realiza su propia resolución de toolchain.
Estado actual
Los grupos de ejecución para ciertas acciones declaradas de forma nativa, como CppLink
, se pueden usar dentro de exec_properties
para establecer requisitos de ejecución por acción y por destino. Para obtener más detalles, consulta la sección Grupos de ejecución predeterminados.
Fondo
Los grupos de ejecución permiten que el autor de la regla defina conjuntos de acciones, cada uno con una plataforma de ejecución potencialmente diferente. Varias plataformas de ejecución pueden permitir que las acciones se ejecuten de manera diferente, por ejemplo, compilar una app para iOS en un trabajador remoto (Linux) y, luego, vincular o firmar el código en un trabajador local de Mac.
Poder definir grupos de acciones también ayuda a aliviar el uso de mnemónicos de acción como proxy para especificar acciones. No se garantiza que las mnemónicas sean únicas y solo pueden hacer referencia a una sola acción. Esto es especialmente útil para asignar recursos adicionales a acciones específicas que requieren mucha memoria y procesamiento, como la vinculación en compilaciones de C++, sin asignar recursos en exceso a tareas menos exigentes.
Cómo definir grupos de ejecución
Durante la definición de la regla, los autores pueden declarar un conjunto de grupos de ejecución. En cada grupo de ejecución, el autor de la regla puede especificar todo lo necesario para seleccionar una plataforma de ejecución para ese grupo, es decir, cualquier restricción a través de exec_compatible_with
y tipos de cadenas de herramientas a través de 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"))
},
)
En el fragmento de código anterior, puedes ver que las dependencias de herramientas también pueden especificar la transición para un grupo de ejecución con el parámetro de atributo cfg
y el módulo config
. El módulo expone una función exec
que toma un solo parámetro de cadena, que es el nombre del grupo de ejecución para el que se debe compilar la dependencia.
Al igual que en las reglas nativas, el grupo de ejecución test
está presente de forma predeterminada en las reglas de prueba de Starlark.
Cómo acceder a los grupos de ejecución
En la implementación de la regla, puedes declarar que las acciones se deben ejecutar en la plataforma de ejecución de un grupo de ejecución. Puedes hacerlo con el parámetro exec_group
de los métodos de generación de acciones, específicamente ctx.actions.run
y ctx.actions.run_shell
.
# foo.bzl
def _impl(ctx):
ctx.actions.run(
inputs = [ctx.attr._some_tool, ctx.srcs[0]]
exec_group = "compile",
# ...
)
Los autores de reglas también podrán acceder a las cadenas de herramientas resueltas de los grupos de ejecución, de manera similar a como puedes acceder a la cadena de herramientas resuelta de un destino:
# 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 ejecución predeterminados
Los siguientes grupos de ejecución están predefinidos:
test
: Acciones del ejecutor de pruebas (para obtener más detalles, consulta la sección de la plataforma de ejecución de la Enciclopedia de pruebas).cpp_link
: Son acciones de vinculación de C++.
Cómo usar grupos de ejecución para establecer propiedades de ejecución
Los grupos de ejecución se integran con el atributo exec_properties
que existe en cada regla y permite que el escritor del destino especifique un diccionario de cadenas de propiedades que luego se pasa a la maquinaria de ejecución. Por ejemplo, si deseas establecer alguna propiedad, como la memoria, para el destino y asignar una mayor cantidad de memoria a ciertas acciones, escribirías una entrada exec_properties
con una clave aumentada por el grupo de ejecución, como la siguiente:
# BUILD
my_rule(
name = 'my_target',
exec_properties = {
'mem': '12g',
'link.mem': '16g'
}
…
)
Todas las acciones con exec_group = "link"
verían el diccionario de propiedades de ejecución como {"mem": "16g"}
. Como puedes ver aquí, la configuración a nivel del grupo de ejecución anula la configuración a nivel del destino.
Cómo usar grupos de ejecución para establecer restricciones de la plataforma
Los grupos de ejecución también se integran con los atributos exec_compatible_with
y exec_group_compatible_with
que existen en cada regla y permiten que el escritor de destino especifique restricciones adicionales que deben satisfacer las plataformas de ejecución seleccionadas para las acciones del destino.
Por ejemplo, si la regla my_test
define el grupo de ejecución link
además del grupo de ejecución predeterminado y el test
, el siguiente uso de estos atributos ejecutaría acciones en el grupo de ejecución predeterminado en una plataforma con una gran cantidad de CPU, la acción de prueba en Linux y la acción de vínculo en la plataforma de ejecución predeterminada:
# 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 ejecución para reglas nativas
Los siguientes grupos de ejecución están disponibles para las acciones definidas por reglas nativas:
test
: Son las acciones del ejecutor de pruebas.cpp_link
: Son acciones de vinculación de C++.
Grupos de ejecución y propiedades de ejecución de la plataforma
Es posible definir exec_properties
para grupos de ejecución arbitrarios en destinos de la plataforma (a diferencia de exec_properties
establecido directamente en un destino, donde se rechazan las propiedades para grupos de ejecución desconocidos). Luego, los destinos heredan el exec_properties
de la plataforma de ejecución que afecta al grupo de ejecución predeterminado y a cualquier otro grupo de ejecución pertinente.
Por ejemplo, supongamos que ejecutar pruebas en la plataforma de ejecución requiere que haya algún recurso disponible, pero no es necesario para compilar y vincular. Esto se puede modelar de la siguiente manera:
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"],
)
Los exec_properties
definidos directamente en los destinos tienen prioridad sobre los que se heredan de la plataforma de ejecución.