Grupos de ejecución

Informar un problema Ver fuente

Los grupos de ejecución permiten múltiples plataformas de ejecución dentro de un solo destino. Cada grupo de ejecución tiene sus propias dependencias de la cadena de herramientas y realiza su propia resolución de la cadena de herramientas.

Información general

Los grupos de ejecución permiten que el autor de la regla defina conjuntos de acciones, cada una 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, puedes compilar una app para iOS en un trabajador remoto (linux) y, luego, vincular o firmar el código en un trabajador mac local.

Poder definir grupos de acciones también ayuda a aliviar el uso de los mnemónicos de acciones como un proxy para especificar acciones. No se garantiza que los mnemónicos sean únicos y solo pueden hacer referencia a una sola acción. Esto es muy útil para asignar recursos adicionales a memoria específica y procesar acciones intensivas, como la vinculación en compilaciones de C++, sin sobreasignar a tareas menos exigentes.

Define grupos de ejecución

Durante la definición de reglas, los autores de estas 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 las herramientas también pueden especificar la transición para un grupo de ejecución mediante 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.

Herencia del grupo de ejecución

Además de definir sus propias restricciones y cadenas de herramientas, un nuevo grupo de ejecución puede declarar que quiere heredar del grupo de ejecución predeterminado de la regla pasando el parámetro copy_from_rule = True. Es un error establecer copy_from_rule como verdadero y pasar también exec_compatible_with o toolchains.

Un grupo de ejecución que se hereda del grupo de ejecución predeterminado copia las restricciones, las cadenas de herramientas y las propiedades de ejecución del grupo predeterminado. Esto incluye restricciones y propiedades de ejecución establecidas en el nivel objetivo, no solo las que especifica la regla en sí. En otras palabras, teniendo en cuenta lo siguiente:

# 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"],
)

El grupo de ejecución copied para el demo de destino configurado incluirá lo siguiente: - //fool_tools:toolchain_type - @platforms//os:linux - :local_constraint

Accede a grupos de ejecución

En la implementación de reglas, puedes declarar que las acciones deben ejecutarse 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 las 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",
     # ...
  )

Usa 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 de destino especifique un dict de string de propiedades que, luego, se pasa a la maquinaria de ejecución. Por ejemplo, si deseas establecer alguna propiedad, como memoria, para el destino y asignar una mayor cantidad de memoria a determinadas acciones, deberías escribir 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án 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 a nivel del objetivo.

Grupos de ejecución para reglas nativas

Los siguientes grupos de ejecución están disponibles para acciones definidas por reglas nativas:

  • test: Prueba las acciones del ejecutor.
  • cpp_link: Acciones de vinculación de C++

Crea grupos de ejecución para configurar propiedades de ejecución

En ocasiones, deseas usar un grupo de ejecución para otorgar diferentes propiedades de ejecución a acciones específicas, pero, en realidad, no quieres cadenas de herramientas ni restricciones diferentes a las de la regla. En estas situaciones, puedes crear grupos de ejecución con el parámetro 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"],
        ),
    },
)

#

Grupos de ejecución y propiedades de ejecución de plataformas

Es posible definir exec_properties para grupos de ejecución arbitrarios en los objetivos de la plataforma (a diferencia de exec_properties configurado directamente en un destino, en el que se rechazan las propiedades de grupos de ejecución desconocidos). Luego, los objetivos 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 relevante.

Por ejemplo, supongamos que ejecutar una prueba de C++ requiere que haya algún recurso disponible, pero no es necesario para la compilación y la vinculación. 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 heredados de la plataforma de ejecución.