Plataformas

Informar un problema Ver fuente Por la noche · 7.2 · 7.1 · 7.0 · 6.5 · 6.4

Bazel puede compilar y probar código en una variedad de hardware, sistemas operativos y configuraciones del sistema con distintas versiones de herramientas de compilación, como vinculadores y compiladores. Para ayudar a gestionar esta complejidad, Bazel tiene un concepto de restricciones y plataformas Una restricción es una dimensión en la que entornos de producción diferentes, como la arquitectura de CPU, la presencia la ausencia de una GPU o la versión de un compilador instalado en el sistema. Una plataforma es un una colección de opciones con nombre para estas restricciones, que representa el tipo recursos que están disponibles en algún entorno.

Modelar el entorno como una plataforma ayuda a Bazel a seleccionar automáticamente el apropiado cadenas de herramientas para las acciones de compilación. Las plataformas también pueden usarse junto con el config_setting para escribir atributos configurables.

Bazel reconoce tres roles que puede cumplir una plataforma:

  • Host: La plataforma en la que se ejecuta Bazel.
  • Ejecución: Una plataforma en la que las herramientas de compilación ejecutan acciones de compilación para produzcan resultados intermedios y finales.
  • Destino: Es una plataforma en la que reside y se ejecuta un resultado final.

Bazel admite las siguientes situaciones de compilación relacionadas con plataformas:

  • Compilaciones de una sola plataforma (predeterminado): Plataformas de host, de ejecución y de destino son iguales. Por ejemplo, compilar un ejecutable de Linux en Ubuntu que se ejecute en una CPU Intel x64.

  • Compilaciones de compilación cruzada: Las plataformas de host y de ejecución son las mismas, pero la plataforma objetivo es diferente. Por ejemplo, compilar una app para iOS en macOS que se ejecuta en una MacBook Pro.

  • Compilaciones multiplataforma: Las plataformas de host, ejecución y segmentación son todas es diferente.

Definición de restricciones y plataformas

El espacio de opciones posibles para las plataformas se define usando constraint_setting y Reglas constraint_value en BUILD archivos. constraint_setting crea una dimensión nueva, mientras que constraint_value crea un valor nuevo para una dimensión determinada. juntos a definir eficazmente una enumeración y sus valores posibles. Por ejemplo, los siguientes El fragmento de un archivo BUILD introduce una restricción para la versión de glibc del sistema. con dos valores posibles.

constraint_setting(name = "glibc_version")

constraint_value(
    name = "glibc_2_25",
    constraint_setting = ":glibc_version",
)

constraint_value(
    name = "glibc_2_26",
    constraint_setting = ":glibc_version",
)

Las restricciones y sus valores pueden definirse en diferentes paquetes de la Workspace. Se hace referencia a ellos por etiqueta y están sujetos a la visibilidad habitual controles de seguridad. Si la visibilidad lo permite, puedes extender la configuración de una restricción existente definiendo tu propio valor para ello.

La regla platform presenta una plataforma nueva con ciertas opciones de valores de restricción. El siguiente crea una plataforma llamada linux_x86 y dice que describe cualquier que ejecuta un sistema operativo Linux en una arquitectura x86_64 con una Versión 2.25 de glibc. (Consulta a continuación para obtener más información sobre las restricciones integradas de Bazel).

platform(
    name = "linux_x86",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
        ":glibc_2_25",
    ],
)

Restricciones y plataformas que suelen ser útiles

Para mantener la coherencia del ecosistema, el equipo de Bazel mantiene un repositorio con definiciones de restricciones para las arquitecturas de CPU de la seguridad de la información. Todas estas se encuentran en https://github.com/bazelbuild/platforms.

Bazel se envía con la siguiente definición de plataforma especial: @platforms//host (con alias como @bazel_tools//tools:host_platform). Este es el valor de la plataforma de host detectado automáticamente representa la plataforma detectada automáticamente para el sistema en el que se ejecuta Bazel.

Cómo especificar una plataforma para una compilación

Puedes especificar las plataformas host y de destino para una compilación con las siguientes opciones: de línea de comandos:

  • --host_platform: El valor predeterminado es @bazel_tools//tools:host_platform.
    • Este destino tiene un alias para @platforms//host, que está respaldado por un repositorio. que detecta el SO y la CPU del host, y escribe el destino de la plataforma.
    • También está @platforms//host:constraints.bzl, que expone un array llamado HOST_CONSTRAINTS, que se puede usar en otras compilaciones Archivos de Starlark.
  • --platforms: El valor predeterminado es la plataforma host.
    • Esto significa que cuando no se establecen otras marcas, @platforms//host es la plataforma de segmentación.
    • Si estableces --host_platform y no --platforms, el valor de --host_platform es la plataforma host y de destino.

Cómo omitir destinos incompatibles

Si compilas para una plataforma de segmentación específica, a menudo es conveniente omitir objetivos que nunca funcionarán en esa plataforma. Por ejemplo, tu dispositivo con Windows este controlador generará muchos errores del compilador al compilar en un Máquina de Linux con //.... Usa el target_compatible_with para indicarle a Bazel qué restricciones de la plataforma de destino tiene tu código.

El uso más simple de este atributo restringe el destino a una sola plataforma. El destino no se creará para ninguna plataforma que no cumpla con todos los restricciones. En el siguiente ejemplo, se restringe win_driver_lib.cc a 64 bits Windows

cc_library(
    name = "win_driver_lib",
    srcs = ["win_driver_lib.cc"],
    target_compatible_with = [
        "@platforms//cpu:x86_64",
        "@platforms//os:windows",
    ],
)

:win_driver_lib solo es compatible con compilaciones en Windows de 64 bits y incompatible con todo lo demás. La incompatibilidad es transitiva. Cualquier objetivo que dependen transitivamente de un objetivo incompatible se consideran incompatibles.

¿Cuándo se omiten los objetivos?

Los destinos se omiten cuando se consideran incompatibles y se incluyen en el como parte de una expansión del patrón de destino. Por ejemplo, los dos siguientes las invocaciones omiten cualquier objetivo incompatible que se encuentre en una expansión del patrón de destino.

$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all

Las pruebas incompatibles en un test_suite son de manera similar si test_suite se especifica en la línea de comandos con --expand_test_suites En otras palabras, los objetivos test_suite en la línea de comandos se comportan como :all y ... Usar --noexpand_test_suites evita la expansión y causa Los destinos de test_suite con pruebas incompatibles también serán incompatibles.

Especificar explícitamente un destino incompatible en la línea de comandos da como resultado un un mensaje de error y una compilación con errores.

$ bazel build --platforms=//:myplatform //:target_incompatible_with_myplatform
...
ERROR: Target //:target_incompatible_with_myplatform is incompatible and cannot be built, but was explicitly requested.
...
FAILED: Build did NOT complete successfully

Los objetivos explícitos incompatibles se omiten de forma silenciosa si Se habilitó --skip_incompatible_explicit_targets.

Restricciones más expresivas

Para tener más flexibilidad en la expresión de restricciones, usa el @platforms//:incompatible constraint_value que ninguna plataforma satisface.

Usa select() en combinación con @platforms//:incompatible para expresar restricciones más complicadas. Para ejemplo, úsalo para implementar lógica OR básica. Lo siguiente permite marcar una biblioteca con macOS y Linux, pero no con otras plataformas.

cc_library(
    name = "unixish_lib",
    srcs = ["unixish_lib.cc"],
    target_compatible_with = select({
        "@platforms//os:osx": [],
        "@platforms//os:linux": [],
        "//conditions:default": ["@platforms//:incompatible"],
    }),
)

Lo anterior se puede interpretar de la siguiente manera:

  1. Cuando se orienta a macOS, el destino no tiene restricciones.
  2. Cuando se orienta a Linux, el destino no tiene restricciones.
  3. De lo contrario, el destino tiene la restricción @platforms//:incompatible. Porque @platforms//:incompatible no forma parte de ninguna plataforma, el destino es se consideran incompatibles.

Para que tus restricciones sean más legibles, usa skylib selects.with_or()

Puedes expresar la compatibilidad inversa de una manera similar. El siguiente ejemplo describe una biblioteca que es compatible con todo, excepto con ARM.

cc_library(
    name = "non_arm_lib",
    srcs = ["non_arm_lib.cc"],
    target_compatible_with = select({
        "@platforms//cpu:arm": ["@platforms//:incompatible"],
        "//conditions:default": [],
    }),
)

Cómo detectar destinos incompatibles con bazel cquery

Puedes usar la IncompatiblePlatformProvider en la producción de Starlark de bazel cquery para distinguir objetivos incompatibles de los compatibles.

Esto se puede usar para filtrar objetivos incompatibles. En el siguiente ejemplo, solo imprime las etiquetas de los destinos que son compatibles. Los destinos incompatibles son no se imprimen.

$ cat example.cquery

def format(target):
  if "IncompatiblePlatformProvider" not in providers(target):
    return target.label
  return ""


$ bazel cquery //... --output=starlark --starlark:file=example.cquery

Problemas conocidos

Orientaciones incompatibles ignorar visibilidad restricciones de uso.