Bazel tiene una compatibilidad sofisticada con el modelado de plataformas y cadenas de herramientas para compilaciones multiarquitectura y compiladas de forma cruzada.
En esta página, se resume el estado de esta asistencia.
También consulte lo siguiente:
Estado
C++
Las reglas C++ usan plataformas para seleccionar cadenas de herramientas cuando
se establece --incompatible_enable_cc_toolchain_resolution
.
Esto significa que puedes configurar un proyecto de C++ de la siguiente manera:
bazel build //:my_cpp_project --platforms=//:myplatform
en lugar de la versión heredada:
bazel build //:my_cpp_project` --cpu=... --crosstool_top=... --compiler=...
Se habilitará de forma predeterminada en Bazel 7.0 (#7260).
Para probar tu proyecto de C++ con plataformas, consulta Migra tu proyecto y Configura las 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
se configura --incompatible_enable_android_toolchain_resolution
.
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 marcas heredadas como --android_crosstool_top
, --android_cpu
y --fat_apk_cpu
.
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 hacerlo.
Puedes usar las API de la plataforma con compilaciones de Apple (por ejemplo, cuando compilas con una combinación de reglas de Apple y C++ puro) con asignaciones de plataformas.
Otros idiomas
- Las reglas de Go son totalmente compatibles con las plataformas.
- Las reglas de Rust son totalmente compatibles con las plataformas.
Si tienes un conjunto de reglas de idioma, consulta Cómo migrar tu conjunto de reglas para agregar compatibilidad.
Información general
Las plataformas y cadenas de herramientas se introdujeron para estandarizar la manera en que los proyectos de software se orientan a diferentes arquitecturas y realizan compilaciones cruzadas.
Esto se inspiró en la observación de que los encargados del mantenimiento del lenguaje ya lo hacían de maneras ad hoc y incompatibles. Por ejemplo, las reglas de C++ usaron --cpu
y --crosstool_top
para declarar una CPU de destino y una cadena de herramientas. Ninguno de estos modelos
representa correctamente una "plataforma". Esto produjo compilaciones incómodas y incorrectas.
Java, Android y otros lenguajes desarrollaron sus propias marcas para fines similares, ninguno de los cuales interoperaba entre sí. Esto hacía que las compilaciones en diferentes lenguajes fueran confusas y complicadas.
Bazel está diseñado para proyectos grandes de varias plataformas y con varios lenguajes. Esto requiere una compatibilidad más fundamentada para estos conceptos, incluida una API estándar clara.
Necesidad de migración
La actualización a la API nueva requiere dos esfuerzos: lanzar la API y actualizar la lógica de la regla para usarla.
El primero está listo, pero el segundo está en curso. Esto consiste en garantizar que se definan plataformas y cadenas de herramientas específicas del lenguaje, que la lógica del lenguaje lea las cadenas de herramientas a través de la API nueva en lugar de marcas antiguas, como --crosstool_top
, y que config_setting
seleccione en la API nueva en lugar de marcas antiguas.
Este trabajo es sencillo, pero se requiere un esfuerzo distinto para cada lenguaje, además de una advertencia justa a fin de que los propietarios del proyecto prueben los próximos cambios.
Esta es la razón por la que esta es una migración en curso.
Objetivo
Esta migración se completa cuando todos los proyectos se compilan con el siguiente formato:
bazel build //:myproject --platforms=//:myplatform
Esto implica lo siguiente:
- Las reglas de tu proyecto eligen las cadenas de herramientas correctas para
//:myplatform
. - Las dependencias de tu proyecto eligen las cadenas de herramientas correctas para
//:myplatform
. //:myplatform
hace referencia a declaraciones comunes deCPU
,OS
y otras propiedades genéricas independientes del lenguaje.- Todos los
select()
relevantes coinciden correctamente con//:myplatform
. //:myplatform
se define en un lugar claro y accesible: en el repositorio de tu proyecto si la plataforma es única para tu proyecto o en algún lugar común que puedan encontrar todos los proyectos de consumo
Las marcas antiguas como --cpu
, --crosstool_top
y --fat_apk_cpu
quedarán obsoletas y se quitarán tan pronto como sea seguro hacerlo.
En última instancia, esta será la única forma de configurar las arquitecturas.
Migra tu proyecto
Si compilas con lenguajes 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 más detalles.
Si un lenguaje requiere una marca para habilitar la compatibilidad de la plataforma, también debes establecer esa marca. Consulta Estado para obtener más información.
Para que tu proyecto se compile, debes verificar lo siguiente:
//:myplatform
debe existir. Por lo general, es responsabilidad del propietario del proyecto definir las plataformas porque los diferentes proyectos se orientan a máquinas diferentes. Consulta Plataformas predeterminadas.Las cadenas de herramientas que quieres usar deben existir. Si usas cadenas de herramientas de stock, los propietarios de lenguajes deben incluir instrucciones para registrarlas. Si escribes tus propias cadenas de herramientas personalizadas, debes registrarlas en tu
WORKSPACE
o con--extra_toolchains
.Las
select()
y las transiciones de configuración deben resolverse de forma correcta. Consulta select() y Transitions.Si tu compilación combina lenguajes que admiten y no admiten plataformas, es posible que necesites asignaciones de plataforma para ayudar a que los idiomas heredados funcionen con la API nueva. Consulta Mapeos de plataformas para obtener más información.
Si los problemas persisten, comunícate con el equipo de asistencia.
Plataformas predeterminadas
Los propietarios del proyecto deben definir plataformas explícitas para describir las arquitecturas que desean compilar. Estos se activan con --platforms
.
Cuando no se configura --platforms
, Bazel establece de manera predeterminada un platform
que representa la
máquina de compilación local. Esto se genera automáticamente en @local_config_platform//:host
, por lo que no es necesario definirlo de forma explícita. Asigna el OS
y la CPU
de la máquina local con los constraint_value
declarados en @platforms
.
select()
Los proyectos pueden select()
en constraint_value
destinos, 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 una razón para ser más específica.
Para seleccionar en una o más constraint_value
, usa lo siguiente:
config_setting(
name = "is_arm",
constraint_values = [
"@platforms//cpu:arm",
],
)
Esto equivale a realizar las selecciones tradicionales en --cpu
:
config_setting(
name = "is_arm",
values = {
"cpu": "arm",
},
)
Obtén más detalles aquí.
Los select
en --cpu
, --crosstool_top
, etc., no comprenden --platforms
.
Cuando migres tu proyecto a plataformas, debes convertirlos a constraint_values
o usar asignaciones de plataformas para admitir ambos estilos durante la migración.
Transiciones
Las transiciones de Starlark cambian marcas en las partes del grafo de compilación. Si tu proyecto usa una transición que establece --cpu
, --crossstool_top
o alguna otra marca heredada, las reglas que lean --platforms
no verán estos cambios.
Cuando migres tu proyecto a plataformas, debes convertir cambios como return { "//command_line_option:cpu": "arm" }
en return {
"//command_line_option:platforms": "//:my_arm_platform" }
o usar asignaciones de plataformas para admitir ambos estilos durante la migración.
Migra tu conjunto de reglas
Si tienes un conjunto de reglas y deseas admitir plataformas, debes hacer lo siguiente:
Haz que la lógica de la regla resuelva las cadenas de herramientas con la API de la cadena de herramientas. Consulta la API de la cadena de herramientas (
ctx.toolchains
).Opcional: Define una marca
--incompatible_enable_platforms_for_my_language
para que la lógica de las reglas resuelva de forma alternativa las cadenas de herramientas a través de la API nueva o marcas antiguas como--crosstool_top
durante las pruebas de migración.Definir las propiedades relevantes que conforman los componentes de la plataforma Consulta las Propiedades comunes de la plataforma.
Define las cadenas de herramientas estándar y haz que sean accesibles para los usuarios a través de las instrucciones de registro de tu regla (detalles).
Asegúrate de que las plataformas de asistencia de
select()
y de transición de configuración sean compatibles. Este es el mayor desafío. En particular, es un proyecto desafiante para varios lenguajes (que puede fallar si todos los idiomas no pueden leer--platforms
).
Si necesitas mezclar con reglas que no admiten las plataformas, es posible que necesites asignaciones de plataformas para cerrar la brecha.
Propiedades comunes de la plataforma
Las propiedades comunes de la plataforma en varios lenguajes, como OS
y CPU
, deben declararse en @platforms
.
Esto fomenta el uso compartido, la estandarización y la compatibilidad entre lenguajes.
Las propiedades exclusivas de tus reglas se deben declarar en el repositorio de tu regla. Esto te permite mantener una propiedad clara de los conceptos específicos de los que son responsables tus reglas.
Si tus reglas usan SO o CPU de propósito personalizado, deben declararse en el repositorio de tu regla en lugar de @platforms
.
Asignaciones de plataforma
Las asignaciones de plataformas son una API temporal que permite que la lógica con reconocimiento de plataformas se combine con la lógica heredada en la misma compilación. Esta es una herramienta contundente que solo está diseñada para reducir las incompatibilidades con diferentes períodos de migración.
Una asignación de plataforma es un mapa de un platform()
a un conjunto correspondiente de marcas heredadas o viceversa. Por ejemplo:
platforms:
# Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
//platforms:ios
--cpu=ios_x86_64
--apple_platform_type=ios
flags:
# Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
--cpu=ios_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, basados en la plataforma y heredados, se apliquen de manera coherente durante toda la compilación, incluidas las transiciones.
De forma predeterminada, Bazel lee las asignaciones del archivo platform_mappings
en la raíz del lugar de trabajo. También puedes configurar --platform_mappings=//:my_custom_mapping
.
Consulte el diseño de asignaciones de plataformas para obtener más información.
Revisión de la API
Un objeto platform
es una colección de destinos constraint_value
:
platform(
name = "myplatform",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm",
],
)
Un constraint_value
es una propiedad de máquina. Los valores de la misma “categoría” 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",
)
Una toolchain
es una regla de Starlark. Sus atributos declaran las herramientas de un lenguaje (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_value
de las máquinas a las que se pueden orientar (target_compatible_with = ["@platforms//os:linux"]
) y las máquinas en las que se pueden ejecutar (exec_compatible_with = ["@platforms//os:mac"]
).
Cuando compilas $ bazel build //:myproject --platforms=//:myplatform
, Bazel
selecciona automáticamente una cadena de herramientas que puede ejecutarse en la máquina de compilación y
los objetos binarios de compilación para //:myplatform
. Esto se conoce como resolución de la cadena de herramientas.
El conjunto de cadenas de herramientas disponibles se puede registrar en el WORKSPACE
con register_toolchains
o en la línea de comandos con --extra_toolchains
.
Obtén más información aquí.
Preguntas
Para obtener asistencia y preguntas generales sobre el cronograma de migración, comunícate con bazel-discuss o con los propietarios de las reglas apropiadas.
Para debatir sobre el diseño y la evolución de las API de las plataformas y las cadenas de herramientas, comunícate con bazel-dev.