Reserva la fecha: BazelCon 2023 se celebrará el 24 y 25 de octubre en Google Múnich. Más información

Cómo adaptar las reglas de Bazel para la ejecución remota

Informa un problema Ver código fuente

Esta página está destinada a los usuarios de Bazel que escriben reglas de compilación y de prueba personalizadas que desean comprender los requisitos de las reglas de Bazel en el contexto de la ejecución remota.

La ejecución remota permite a Bazel ejecutar acciones en una plataforma independiente, como un centro de datos. Bazel usa un protocolo de gRPC para su ejecución remota. Puedes probar la ejecución remota con bazel-buildfarm, un proyecto de código abierto que tiene como objetivo proporcionar una plataforma de ejecución remota distribuida.

En esta página, se usa la siguiente terminología cuando se hace referencia a diferentes tipos de entornos o plataformas:

  • Plataforma de host: lugar en el que se ejecuta Bazel.
  • Plataforma de ejecución: Es la plataforma en la que se ejecutan las acciones de Bazel.
  • Plataforma de destino: dónde se ejecutan los resultados de la compilación (y algunas acciones)

Descripción general

Cuando configures una compilación de Bazel para la ejecución remota, debes seguir los lineamientos que se describen en esta página a fin de asegurarte de que la compilación se ejecute de forma remota sin errores. Esto se debe a la naturaleza de la ejecución remota, es decir,

  • Acciones de compilación aisladas. Las herramientas de compilación no conservan el estado y las dependencias no pueden filtrarse entre ellas.

  • Entornos de ejecución diversos. La configuración de la compilación local no siempre es adecuada para entornos de ejecución remota.

En esta página, se describen los problemas que pueden surgir cuando se implementan reglas de compilación y prueba personalizadas de Bazel para la ejecución remota y cómo evitarlas. Se abarcan los siguientes temas:

Invoca herramientas de compilación a través de reglas de la cadena de herramientas

Una regla de la cadena de herramientas de Bazel es un proveedor de configuración que le indica a una regla de compilación qué herramientas de compilación, como compiladores y vinculadores, debe usar y cómo configurarlas con parámetros definidos por el creador de la regla. Una regla de cadena de herramientas permite que las reglas de compilación y prueba invoquen herramientas de compilación de forma predecible y preconfigurada que sea compatible con la ejecución remota. Por ejemplo, usa una regla de la cadena de herramientas en lugar de invocar herramientas de compilación mediante PATH, JAVA_HOME o alguna otra variable local que no esté configurada en valores equivalentes (o, en absoluto) en el entorno de ejecución remota.

En este momento, existen reglas de la cadena de herramientas para las reglas de compilación y prueba de Bazel para Scala, Rust y Go, y se están desarrollando nuevas reglas de cadena de herramientas para otros lenguajes y herramientas, como bash. Si no existe una regla de la cadena de herramientas para la herramienta que esta usa, considera crear una regla de la cadena de herramientas.

Administra dependencias implícitas

Si una herramienta de compilación puede acceder a dependencias en las acciones de compilación, esas acciones fallarán cuando se ejecuten de forma remota porque cada acción de compilación remota se ejecuta por separado de otras. Algunas herramientas de compilación conservan el estado entre las acciones de compilación y las dependencias de acceso que no se incluyeron de forma explícita en la invocación de la herramienta, lo que hará que fallen las acciones de compilación ejecutadas de forma remota.

Por ejemplo, cuando Bazel le indica a un compilador con estado que compile foo de forma local, el compilador retiene referencias a los resultados de compilación de foo. Luego, cuando Bazel le indica al compilador que compile bar, que depende de foo, sin indicar explícitamente que la dependencia del archivo BUILD se incluye en la invocación del compilador, la acción se ejecuta correctamente siempre que la misma instancia del compilador se ejecute para ambas acciones (como suele suceder en la ejecución local). Sin embargo, como en una situación de ejecución remota cada acción de compilación ejecuta una instancia del compilador separada, el estado del compilador y la dependencia implícita de bar en foo se perderán y la compilación fallará.

A fin de ayudar a detectar y eliminar estos problemas de dependencia, Bazel 0.14.1 ofrece la zona de pruebas local de Docker, que tiene las mismas restricciones para las dependencias que la ejecución remota. Usa la zona de pruebas a fin de preparar tu compilación para la ejecución remota. Para ello, identifica y resuelve los errores de compilación relacionados con las dependencias. Consulta Soluciona problemas de Bazel Remote Execution con Docker Sandbox para obtener más información.

Administra objetos binarios dependientes de la plataforma

Por lo general, un objeto binario compilado en la plataforma host no puede ejecutarse de forma segura en una plataforma de ejecución remota arbitraria debido a que las dependencias pueden no coincidir. Por ejemplo, el objeto binario SingleJar suministrado con Bazel apunta a la plataforma host. Sin embargo, para la ejecución remota, SingleJar debe compilarse como parte del proceso de compilación del código, de modo que se oriente a la plataforma de ejecución remota. (Consulta la lógica de selección de destino).

No envíes archivos binarios de las herramientas de compilación requeridas por la compilación con tu código fuente, a menos que estés seguro de que se ejecutarán de forma segura en la plataforma de ejecución. En cambio, realiza una de las siguientes acciones:

  • Enviar o referir de forma externa el código fuente de la herramienta a fin de que pueda compilarse para la plataforma de ejecución remota.

  • Instala la herramienta en el entorno de ejecución remota (por ejemplo, un contenedor de la cadena de herramientas) si es lo suficientemente estable, y usa las reglas de la cadena para ejecutarla en tu compilación.

Administra reglas de estilo de configuración de WORKSPACE

Las reglas WORKSPACE de Bazel se pueden usar a fin de sondear la plataforma de host para las herramientas y las bibliotecas requeridas por la compilación, que, para las compilaciones locales, también es la plataforma de ejecución de Bazel. Si la compilación depende de forma explícita de herramientas y artefactos de compilación locales, fallará durante la ejecución remota si la plataforma de ejecución remota no es idéntica a la plataforma host.

Las siguientes acciones que realizan las reglas WORKSPACE no son compatibles con la ejecución remota:

  • Compilación de objetos binarios. Ejecutar acciones de compilación en las reglas WORKSPACE da como resultado objetos binarios incompatibles con la plataforma de ejecución remota si son diferentes a los de la plataforma host.

  • Instala paquetes pip. Los paquetes pip instalados a través de reglas WORKSPACE requieren que sus dependencias estén preinstaladas en la plataforma host. Esos paquetes, compilados específicamente para la plataforma host, no serán compatibles con la plataforma de ejecución remota si son diferentes a los de la plataforma host.

  • Sincronización con herramientas o artefactos locales. Los enlaces simbólicos a herramientas o bibliotecas instalados en la plataforma host creada a través de reglas WORKSPACE harán que la compilación falle en la plataforma de ejecución remota, ya que Bazel no podrá localizarlas. En su lugar, crea symlinks mediante acciones de compilación estándar para que se pueda acceder a las herramientas y las bibliotecas con symlink desde el árbol runfiles de Bazel. No uses repository_ctx.symlink para vincular symlinks a archivos de destino fuera del directorio de repositorio externo.

  • Silenciar la plataforma host. Evita crear archivos fuera del árbol runfiles de Bazel, crear variables de entorno y acciones similares, ya que pueden comportarse de forma inesperada en la plataforma de ejecución remota.

Para ayudar a detectar posibles comportamientos no herméticos, puedes usar el registro de reglas de Workspace.

Si una dependencia externa ejecuta operaciones específicas que dependen de la plataforma host, debes dividir esas operaciones entre WORKSPACE y las reglas de compilación de la siguiente manera:

  • Inspección de plataformas y enumeración de dependencias. Estas operaciones pueden ejecutarse de forma local segura mediante las reglas de WORKSPACE, que pueden verificar qué bibliotecas están instaladas, descargar paquetes que se deben compilar y preparar los artefactos necesarios para la compilación. Para la ejecución remota, estas reglas también deben admitir el uso de artefactos verificados a fin de proporcionar la información que, por lo general, se obtendría durante la inspección de la plataforma host. Los artefactos verificados previamente permiten que Bazel describa las dependencias como si fueran locales. Para esto, usa declaraciones condicionales o la marca --override_repository.

  • Generar o compilar artefactos específicos del destino y mutaciones de la plataforma. Estas operaciones deben ejecutarse mediante reglas de compilación regulares. Las acciones que producen artefactos específicos del destino para dependencias externas deben ejecutarse durante la compilación.

A fin de generar de forma más fácil artefactos verificados previamente para la ejecución remota, puedes usar reglas de WORKSPACE a fin de emitir archivos generados. Puedes ejecutar esas reglas en cada entorno de ejecución nuevo (por ejemplo, dentro de cada contenedor de la cadena de herramientas) y verificar los resultados de tu compilación de ejecución remota en el repositorio de origen para consultarlos.

Por ejemplo, en las reglas de Tensorflow para cuda y python, las reglas WORKSPACE producen lo siguiente BUILD files. Para la ejecución local, se usan los archivos generados mediante la comprobación del entorno del host. Para la ejecución remota, una declaración condicional en una variable de entorno permite que la regla use archivos registrados en el repositorio.

Los archivos BUILD declaran genrules, que se puede ejecutar de forma local y remota, y realizan el procesamiento necesario que se realizó anteriormente mediante repository_ctx.symlink, como se muestra aquí.