Migración a plataformas

Bazel tiene compatibilidad sofisticada para modelar plataformas y cadenas de herramientas para compilaciones de varias arquitecturas y compilaciones cruzadas.

En esta página, se resume el estado de esta compatibilidad.

Consulta lo siguiente:

Estado

C++

Las reglas de C++ usan plataformas para seleccionar cadenas de herramientas cuando --incompatible_enable_cc_toolchain_resolution se establece.

Esto significa que puedes configurar un proyecto de C++ con lo siguiente:

bazel build //:my_cpp_project --platforms=//:myplatform

en lugar de lo heredado:

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

Esto se habilitará de forma predeterminada en Bazel 7.0 (#7260).

Para probar tu proyecto de C++ con plataformas, consulta Cómo migrar tu proyecto y Cómo configurar cadenas de herramientas de C++.

Java

Las reglas de Java usan plataformas para seleccionar cadenas de herramientas.

Esto reemplaza las marcas heredadas --java_toolchain, --host_java_toolchain, --javabase y --host_javabase.

Consulta Java y Bazel para obtener más detalles.

Android

Las reglas de Android usan plataformas para seleccionar cadenas de herramientas cuando --incompatible_enable_android_toolchain_resolution se establece.

Esto significa que puedes configurar un proyecto de Android con lo siguiente:

bazel build //:my_android_project --android_platforms=//:my_android_platform

en lugar de con marcas heredadas como --android_crosstool_top, --android_cpu, y --fat_apk_cpu.

Esto se habilitará de forma predeterminada en Bazel 7.0 (#16285).

Para probar tu proyecto de Android con plataformas, consulta Cómo migrar tu proyecto.

Apple

Las reglas de Apple no admiten plataformas y aún no están programadas para la compatibilidad.

Aún puedes usar las APIs de plataforma con compilaciones de Apple (por ejemplo, cuando compilas con una combinación de reglas de Apple y C++ puro) con asignaciones de plataforma.

Otros idiomas

Si tienes un conjunto de reglas de idioma, consulta Cómo migrar tu conjunto de reglas para agregar compatibilidad.

Información general

Se introdujeron plataformas y cadenas de herramientas para estandarizar la forma en que los proyectos de software se orientan a diferentes arquitecturas y se compilan de forma cruzada.

Esto se inspiró en la observación de que los mantenedores de idiomas ya lo hacían de formas ad hoc e incompatibles. Por ejemplo, las reglas de C++ usaban --cpu y --crosstool_top para declarar una CPU y una cadena de herramientas de destino. Ninguna de ellas modela correctamente una "plataforma". Esto produjo compilaciones incómodas e incorrectas.

Java, Android y otros idiomas desarrollaron sus propias marcas para propósitos similares, ninguna de las cuales interoperaba entre sí. Esto hizo que las compilaciones de varios idiomas confusas y complicadas.

Bazel está diseñado para proyectos grandes, de varios idiomas y plataformas. Esto exige una compatibilidad más basada en principios para estos conceptos, incluida una API estándar clara.

Necesidad de migración

La actualización a la nueva API requiere dos esfuerzos: lanzar la API y actualizar la lógica de reglas para usarla.

El primero ya se realizó, pero el segundo está en curso. Esto consiste en garantizar que se definan las plataformas y las cadenas de herramientas específicas del idioma, que la lógica del idioma lea las cadenas de herramientas a través de la nueva API en lugar de las marcas antiguas como --crosstool_top y que config_settings seleccione en la nueva API en lugar de las marcas antiguas.

Este trabajo es sencillo, pero requiere un esfuerzo distinto para cada idioma, además de una advertencia justa para que los propietarios del proyecto prueben los próximos cambios.

Por eso, se trata de una migración en curso.

Objetivo

Esta migración se completa cuando todos los proyectos se compilan con el formulario:

bazel build //:myproject --platforms=//:myplatform

Esto implica lo siguiente:

  1. Las reglas de tu proyecto eligen las cadenas de herramientas adecuadas para //:myplatform.
  2. Las dependencias de tu proyecto eligen las cadenas de herramientas adecuadas para //:myplatform.
  3. //:myplatform hace referencia a declaraciones comunes de CPU, OS y otras propiedades genéricas independientes del idioma.
  4. Todas las select()s relevantes coinciden correctamente con //:myplatform.
  5. //:myplatform se define en un lugar claro y accesible: en el repositorio de tu proyecto si la plataforma es exclusiva de tu proyecto o en un lugar común que todos los proyectos que consumen puedan encontrar.

Las marcas antiguas como --cpu, --crosstool_top y --fat_apk_cpu dejarán de estar disponibles y se quitarán en cuanto sea seguro hacerlo.

En última instancia, esta será la única forma de configurar arquitecturas.

Cómo migrar tu proyecto

Si compilas con idiomas que admiten plataformas, tu compilación ya debería funcionar con una invocación como la siguiente:

bazel build //:myproject --platforms=//:myplatform

Consulta Estado y la documentación de tu idioma para obtener detalles precisos.

Si un idioma requiere una marca para habilitar la compatibilidad con la plataforma, también debes establecer esa marca. Consulta Estado para obtener más detalles.

Para que se compile tu proyecto, debes verificar lo siguiente:

  1. //:myplatform debe existir. Por lo general, es responsabilidad del propietario del proyecto definir plataformas, ya que los diferentes proyectos se orientan a diferentes máquinas. Consulta Plataformas predeterminadas.

  2. Deben existir las cadenas de herramientas que deseas usar. Si usas cadenas de herramientas de stock, los propietarios del idioma deben incluir instrucciones para registrarlas. Si escribes tus propias cadenas de herramientas personalizadas, debes registrarlas en tu MODULE.bazel archivo o con --extra_toolchains.

  3. Los select() y las transiciones de configuración deben resolverse correctamente. Consulta select() y Transiciones.

  4. Si tu compilación combina idiomas que admiten y no admiten plataformas, es posible que necesites asignaciones de plataforma para ayudar a que los idiomas heredados funcionen con la nueva API. Consulta Asignaciones de plataforma para obtener más detalles.

Si aún tienes problemas, comunícate con el equipo de asistencia.

Plataformas predeterminadas

Los propietarios del proyecto deben definir plataformas explícitas para describir las arquitecturas para las que desean compilar. Luego, se activan con --platforms.

Cuando no se establece --platforms, Bazel usa de forma predeterminada un platform que representa la máquina de compilación local. Se genera automáticamente en @platforms//host (con el alias @bazel_tools//tools:host_platform) , por lo que no es necesario definirla de forma explícita. Asigna OS y CPU de la máquina local con constraint_values declarados en @platforms.

select()

Los proyectos pueden select() en constraint_value objetivos pero no en plataformas completas. Esto es intencional, por lo que select() admite la mayor variedad posible de máquinas. Una biblioteca con fuentes específicas de ARM debe admitir todas las máquinas con tecnología ARM, a menos que haya un motivo para ser más específico.

Para seleccionar uno o más constraint_values, usa lo siguiente:

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

Esto equivale a seleccionar tradicionalmente en --cpu:

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

Más detalles aquí.

selects en --cpu, --crosstool_top, etc., no entienden --platforms. Cuando migres tu proyecto a plataformas, debes convertirlos en constraint_values o usar asignaciones de plataforma para admitir ambos estilos durante la migración.

Transiciones

Las transiciones de Starlark cambian las marcas en partes de tu gráfico de compilación. Si tu proyecto usa una transición que establece --cpu, --crossstool_top, o cualquier otra marca heredada, las reglas que leen --platforms no verán estos cambios.

Cuando migres tu proyecto a plataformas, debes convertir los cambios como return { "//command_line_option:cpu": "arm" } a return { "//command_line_option:platforms": "//:my_arm_platform" } o usar asignaciones de plataforma para admitir ambos estilos durante la migración. ventana.

Cómo migrar tu conjunto de reglas

Si tienes un conjunto de reglas y deseas admitir plataformas, debes hacer lo siguiente:

  1. Haz que la lógica de reglas resuelva las cadenas de herramientas con la API de cadena de herramientas. Consulta la API de cadena de herramientas (ctx.toolchains).

  2. Opcional: Define una marca --incompatible_enable_platforms_for_my_language para que la lógica de reglas resuelva cadenas de herramientas de forma alternativa a través de la nueva API o marcas antiguas como --crosstool_top durante las pruebas de migración.

  3. Define las propiedades relevantes que componen los componentes de la plataforma. Consulta Propiedades comunes de la plataforma.

  4. Define cadenas de herramientas estándar y haz que los usuarios puedan acceder a ellas a través de las instrucciones de registro de tu regla (detalles)

  5. Asegúrate de que las transiciones de select()s y configuración admitan plataformas. Este es el mayor desafío. Es particularmente desafiante para proyectos de varios idiomas (que pueden fallar si todos los idiomas no pueden leer --platforms).

Si necesitas combinar con reglas que no admiten plataformas, es posible que necesites asignaciones de plataforma para cerrar la brecha.

Propiedades comunes de la plataforma

Las propiedades comunes de la plataforma entre idiomas, como OS y CPU, deben declararse en @platforms. Esto fomenta el uso compartido, la estandarización y la compatibilidad entre idiomas.

Las propiedades exclusivas de tus reglas deben declararse en el repositorio de tu regla. Esto te permite mantener una propiedad clara sobre los conceptos específicos de los que son tus reglas responsables.

Si tus reglas usan SO o CPU de propósito personalizado, estos deben declararse en el repositorio de tu regla en lugar de @platforms.

Asignaciones de plataforma

Las asignaciones de plataforma son una API temporal que permite que la lógica compatible con la plataforma se combine con la lógica heredada en la misma compilación. Es una herramienta directa que solo está diseñada para suavizar las incompatibilidades con diferentes plazos de migración.

Una asignación de plataforma es un mapa de un platform() a un conjunto correspondiente de marcas heredadas o al revés. Por ejemplo:

platforms:
  # Maps "--platforms=//platforms:ios" to "--ios_multi_cpus=x86_64 --apple_platform_type=ios".
  //platforms:ios
    --ios_multi_cpus=x86_64
    --apple_platform_type=ios

flags:
  # Maps "--ios_multi_cpus=x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
  --ios_multi_cpus=x86_64
  --apple_platform_type=ios
    //platforms:ios

  # Maps "--cpu=darwin_x86_64 --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin_x86_64
  --apple_platform_type=macos
    //platforms:macos

Bazel usa esto para garantizar que todos los parámetros de configuración, tanto los basados en la plataforma como los heredados, se apliquen de manera coherente en toda la compilación, incluso a través de las transiciones.

De forma predeterminada, Bazel lee asignaciones del archivo platform_mappings en la raíz de tu espacio de trabajo. También puedes establecer --platform_mappings=//:my_custom_mapping.

Consulta el diseño de las asignaciones de plataforma para obtener más detalles.

Revisión de la API

Un platform es una colección de constraint_value objetivos:

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

Un constraint_value es una propiedad de la máquina. Los valores del mismo "tipo" se agrupan en un constraint_setting común:

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

Un toolchain es una regla de Starlark. Sus atributos declaran las herramientas de un idioma (como compiler = "//mytoolchain:custom_gcc"). Sus proveedores pasan esta información a las reglas que deben compilarse con estas herramientas.

Las cadenas de herramientas declaran los constraint_values de las máquinas a las que pueden orientarse (target_compatible_with = ["@platforms//os:linux"]) y las máquinas en las que se pueden ejecutar sus herramientas (exec_compatible_with = ["@platforms//os:mac"]).

Cuando compilas $ bazel build //:myproject --platforms=//:myplatform, Bazel selecciona automáticamente una cadena de herramientas que se puede ejecutar en la máquina de compilación y compilar objetos binarios para //:myplatform. Esto se conoce como resolución de cadena de herramientas.

El conjunto de cadenas de herramientas disponibles se puede registrar en el MODULE.bazel archivo con register_toolchains o en la línea de comandos con --extra_toolchains.

Para obtener más información, consulta aquí.

Preguntas

Si tienes preguntas o necesitas asistencia general sobre el cronograma de migración, comunícate con bazel-discuss o los propietarios de las reglas correspondientes.

Para obtener información sobre el diseño y la evolución de las APIs de plataforma o cadena de herramientas, comunícate con bazel-dev.

Consulta también