Compila con plataformas

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

Bazel ofrece una asistencia sofisticada para el modelado de plataformas y cadenas de herramientas. La integración de esto con proyectos reales requiere entre propietarios de código, encargados de mantener reglas y desarrolladores principales de Bazel.

En esta página, se resume el propósito de las plataformas y se muestra cómo compilar con ellas.

tl;dr: Las APIs de la plataforma y la cadena de herramientas de Bazel están disponibles, pero no funcionan. en todas partes hasta todas las reglas de idioma, select() y otras referencias heredadas las actualizaciones de software. Realizamos este proceso con frecuencia. Eventualmente, todas las compilaciones se basarán en la plataforma. Sigue leyendo para ver dónde encajan tus compilaciones.

Para obtener documentación más formal, consulta lo siguiente:

Información general

Las plataformas y las cadenas de herramientas se introdujeron para estandarizar la manera en que el software Los proyectos se orientan a distintas máquinas y compilan con las herramientas de lenguaje adecuadas.

Esta es una incorporación relativamente reciente a Bazel. Era inspirado por la observación de que los encargados de mantener el lenguaje ya hacían esto en el anuncio hoc e incompatibles. Por ejemplo, las reglas de C++ usan --cpu y --crosstool_top. para configurar la CPU de destino de una compilación y la cadena de herramientas C++. Ninguno de estos modelos corresponde una "plataforma". Los intentos históricos de hacerlo causaron compilaciones incómodas e imprecisas. Estas marcas tampoco controlan la compilación de Java, que evolucionó su propia independiente con --java_toolchain.

Bazel está diseñado para proyectos grandes multilingües y multiplataforma. Esta demanda una asistencia más fundamentada para estos conceptos, incluidas APIs claras que fomentar la interoperabilidad del lenguaje y el proyecto. Así son las nuevas APIs .

Migración

Las APIs de la plataforma y la cadena de herramientas solo funcionan cuando los proyectos realmente las usan. Esta no es trivial porque la lógica de reglas, las cadenas de herramientas, las dependencias y Los objetos select() deben admitirlos. Esto requiere una secuencia de migración cuidadosa para mantener todos los proyectos y sus dependencias funcionando correctamente.

Por ejemplo, Bazel Las reglas de C++ admiten plataformas. Sin embargo, las reglas de Apple no lo hacen. Tu proyecto de C++ es posible que Apple no se interese en Apple. Pero otros sí. De esta manera, Aún no es seguro habilitar plataformas globalmente para todas las compilaciones de C++.

En el resto de esta página, se describe esta secuencia de migración, cómo y cuándo encajan tus proyectos.

Objetivo

La migración de la plataforma de Bazel se completa cuando todos los proyectos se compilan con el siguiente formato:

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

Esto implica lo siguiente:

  1. Las reglas que usa tu proyecto pueden inferir cadenas de herramientas correctas a partir de //:myplatform
  2. Las reglas que usan las dependencias de tu proyecto pueden inferir cadenas de herramientas correctas desde //:myplatform.
  3. Los proyectos que dependen del tuyo admiten //:myplatform o tu admite las APIs heredadas (como --crosstool_top).
  4. //:myplatform referencias [declaraciones comunes][Declaración de plataforma común]{: .external} de CPU, OS y otros conceptos genéricos que admiten la ejecución automática entre proyectos compatibilidad.
  5. Todos los proyectos relevantes select()s comprender las propiedades de la máquina implícitas por //:myplatform
  6. //:myplatform se define en un lugar claro y reutilizable: en la biblioteca si la plataforma es única para tu proyecto; de lo contrario, en algún lugar donde que puedan encontrar los usuarios de esta plataforma.

Las APIs antiguas se quitarán en cuanto se logre este objetivo. Entonces, ser la forma estándar en que los proyectos seleccionan plataformas y cadenas de herramientas.

¿Debería usar plataformas?

Si solo quieres crear o compilar de forma cruzada un proyecto, debes seguir las la documentación oficial del proyecto.

Si eres responsable de mantener proyectos, lenguajes o cadenas de herramientas, con el tiempo querrás para admitir las nuevas APIs. Si esperas hasta que se complete la migración global o la habilitación temprana depende de tus necesidades específicas de valor / costo:

Valor

  • Puedes usar select() o elegir cadenas de herramientas de las propiedades exactas que te interesan. en lugar de marcas hard-coded como --cpu. Por ejemplo, varias CPU admite el mismo conjunto de instrucciones.
  • Compilaciones más adecuadas. Si usas select() con --cpu en el ejemplo anterior, agregar una nueva CPU que admita el mismo conjunto de instrucciones, la select() no reconoce la CPU nueva. Sin embargo, un select() en las plataformas sigue siendo preciso.
  • Experiencia del usuario más sencilla Todos los proyectos entienden lo siguiente: --platforms=//:myplatform No se necesitan varios idiomas en la línea de comandos.
  • Diseño de lenguaje más simple Todos los lenguajes comparten una API común para definir cadenas de herramientas, usar cadenas de herramientas y seleccionar la correcta para una plataforma.
  • Los objetivos se pueden omitir en la de compilación y prueba si son incompatibles con la plataforma seleccionada.

Costos

  • Es posible que los proyectos dependientes que aún no admiten plataformas no funcionen automáticamente. con la tuya.
  • Para hacerlos funcionar, es posible que se requiera mantenimiento temporal adicional.
  • La coexistencia de APIs nuevas y heredadas requiere una guía más cuidadosa del usuario para evitar confusiones.
  • Definiciones canónicas para propiedades comunes, como OS y CPU siguen evolucionando y es posible que requieran contribuciones iniciales adicionales.
  • Las definiciones canónicas para las cadenas de herramientas específicas del lenguaje siguen evolucionando y pueden requerir contribuciones iniciales adicionales.

Revisión de la API

Un platform es una colección de Destinos de constraint_value:

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

Un constraint_value es una máquina propiedad. Valores del mismo “tipo” se agrupan en constraint_setting:

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. Es Los atributos declaran las herramientas de un idioma (como compiler = "//mytoolchain:custom_gcc"). Pase de proveedores esta información a las reglas que deben crearse con estas herramientas.

Las cadenas de herramientas declaran los constraint_value de las máquinas que pueden objetivo (target_compatible_with = ["@platforms//os:linux"]) y máquinas que sus herramientas 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 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 WORKSPACE con register_toolchains o en el la línea de comandos con --extra_toolchains.

Obtén más detalles aquí.

Estado

La compatibilidad actual de la plataforma varía según los idiomas. Todas las reglas principales de Bazel son a pasar a las plataformas. Pero este proceso llevará tiempo. Esto se debe a tres razones principales:

  1. Se debe actualizar la lógica de la regla para obtener información de la herramienta desde la nueva cadena de herramientas. API (ctx.toolchains) y dejar de leer la configuración heredada, como --cpu y --crosstool_top. Esto es relativamente sencillo.

  2. Los encargados de mantenimiento de la cadena de herramientas deben definir cadenas de herramientas y hacerlas accesibles para (en repositorios de GitHub y entradas de WORKSPACE). Esto es técnicamente sencillo, pero debe organizarse de manera inteligente para mantener una experiencia del usuario sencilla.

    Las definiciones de la plataforma también son necesarias (a menos que compiles para la misma máquina se ejecuta Bazel). En general, los proyectos deben definir sus propias plataformas.

  3. Se deben migrar los proyectos existentes. select() s y transiciones también deben migrado. Este es el mayor desafío. Es particularmente desafiante para proyectos multilingües (que pueden fallar si todos los idiomas no pueden leer) --platforms).

Si estás diseñando un nuevo conjunto de reglas, debes admitir las plataformas del empezando. Esto automáticamente hace que sus reglas sean compatibles con otras y proyectos, que tienen un valor cada vez mayor a medida que la API de la plataforma se convierte sea más omnipresente.

Propiedades comunes de la plataforma

Las propiedades de plataforma, como OS y CPU, que son comunes en todos los proyectos deben declararse en un lugar estándar y centralizado. Esto fomenta las fases y compatibilidad entre lenguajes.

Por ejemplo, si MyApp tiene un select() en constraint_value. @myapp//cpus:arm y SomeCommonLib tienen un select() activado @commonlib//constraints:arm, activan su "brazo" con modelos incompatibles con tus criterios.

Las propiedades globales comunes se declaran en el @platforms repositorio (por lo tanto, la etiqueta canónica para el ejemplo anterior es @platforms//cpu:arm). Las propiedades de lenguaje común deben declararse en los repositorios de sus respectivas idiomas.

Plataformas predeterminadas

Generalmente, los propietarios del proyecto deben definir platforms para describir la tipos de máquinas para las que quieren compilar. Luego, estas se activan con --platforms

Cuando --platforms no está configurado, Bazel usa de forma predeterminada una platform que representa el máquina de compilación local. Este valor se genera automáticamente a la(s) @local_config_platform//:host por lo que no es necesario definirla explícitamente. Asigna el OS de la máquina local. y CPU con constraint_value declarados en @platforms

C++

Las reglas de C++ de Bazel usan plataformas para seleccionar cadenas de herramientas cuando las estableces --incompatible_enable_cc_toolchain_resolution (#7260).

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

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

en lugar de la heredada:

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

Si tu proyecto es C++ puro y no dependen de proyectos que no son de C++, puedes usar de forma segura, siempre y cuando tus select y transiciones son compatibles. Consulta #7260 y Configura cadenas de herramientas de C++ para obtener más orientación.

Este modo no está habilitado de forma predeterminada. Esto se debe a que los proyectos de Apple sigue configurando dependencias de C++ con --cpu y --crosstool_top. (ejemplo). Esto depende de las reglas de Apple que migren a las plataformas.

Java

Las reglas de Java de Bazel usan plataformas.

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

Para aprender a usar las marcas de configuración, consulta el manual de Bazel y Java. Para obtener información adicional, consulta el documento de diseño.

Si aún usas marcas heredadas, sigue el proceso de migración en el problema n.o 7849.

Android

Las reglas de Bazel para Android usan plataformas para seleccionar cadenas de herramientas cuando las estableces --incompatible_enable_android_toolchain_resolution

Esta opción no está habilitada de forma predeterminada. Pero la migración está en camino.

Apple

Las reglas de Bazel de Apple aún no son compatibles con plataformas para seleccionar cadenas de herramientas de Apple.

Tampoco son compatibles con las dependencias C++ habilitadas para la plataforma porque usan el --crosstool_top heredado para configurar la cadena de herramientas de C++ Hasta que se migren, puede mezclar proyectos de Apple con C++ habilitado para platrm y platform asignaciones (ejemplo).

Otros idiomas

Si estás diseñando reglas para un lenguaje nuevo, usa plataformas para seleccionar las cadenas de herramientas de tu lenguaje. Consulta la documentación de cadenas de herramientas para obtener una buena explicación.

select()

Los proyectos pueden select() en Destinos constraint_value pero no completo y plataformas de Google Cloud. Esto es intencional para que los objetos select() admitan una amplia variedad la mayor cantidad de máquinas posible. Una biblioteca con fuentes específicas de ARM debería ser compatible 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 elementos constraint_value, usa lo siguiente:

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

Esto equivale a seleccionar de forma tradicional en --cpu:

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

Obtén más detalles aquí.

Los elementos select en --cpu, --crosstool_top, etc. no comprenden --platforms. Cuándo migrar tu proyecto a plataformas, debes convertirlos a constraint_values o usa asignaciones de plataforma para admitir ambos estilos a través del período de migración.

Transiciones

Cambio de las transiciones de Starlark te permite marcar partes del gráfico de compilación. Si en tu proyecto se usa una transición que Configura --cpu, --crossstool_top, o bien otras marcas heredadas, reglas que leen --platforms no verá estos cambios.

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

Cómo usar plataformas hoy en día

Si solo quieres crear o compilar de forma cruzada un proyecto, debes seguir las la documentación oficial del proyecto. Depende de los encargados de mantener el lenguaje y los proyectos determinan cómo y cuándo realizar integraciones en las plataformas, y qué valor ofrece.

Si eres responsable de mantenimiento de proyectos, lenguajes o cadenas de herramientas y tu compilación no usan plataformas de forma predeterminada, tienen tres opciones (además de esperar a la migración):

  1. Activa las "plataformas de uso" marca para los idiomas de tu proyecto (si tienen una) y hacer las pruebas que necesites para ver si los proyectos que te interesan sobre el trabajo.

  2. Si los proyectos que te interesan aún dependen de marcas heredadas como --cpu y --crosstool_top, úsalas junto con --platforms:

    bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...

    Esto tiene algunos costos de mantenimiento (tienes que asegurarte de que los ajustes de coincidencias). Pero esto debería funcionar en ausencia de renegado transiciones.

  3. Escribe asignaciones de plataforma para admitir ambos estilos asignación de configuraciones de estilo --cpu a las plataformas correspondientes y viceversa

Asignaciones de plataformas

Las asignaciones de plataforma son una API temporal que permite la lógica con tecnología heredada coexiste en la misma compilación hasta que esta última deje de estar disponible en la ventana modal.

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 --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin
  --apple_platform_type=macos
    //platforms:macos

Bazel usa esto para garantizar toda la configuración, tanto basada en la plataforma como heredadas, se aplican de forma coherente en toda la compilación, incluso mediante transiciones.

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

Consulta aquí para ver todos los detalles.

Preguntas

Si necesita asistencia general o tiene preguntas sobre el cronograma de migración, comuníquese con bazel-discuss@googlegroups.com o los propietarios de las reglas correspondientes.

Para debatir sobre el diseño y la evolución de las APIs de plataforma/cadena de herramientas, consulta lo siguiente: contacto bazel-dev@googlegroups.com.

Consulta también