Adapta reglas de Bazel para la ejecución remota

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

La ejecución remota permite que Bazel ejecute acciones en una plataforma independiente, como un centro de datos. Bazel usa un protocolo 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 utiliza la siguiente terminología para referirse a diferentes tipos de entornos o plataformas:

  • Plataforma del host: donde se ejecuta Bazel.
  • Plataforma de ejecución: donde se ejecutan las acciones de Bazel.
  • Plataforma de destino: Es la plataforma donde se ejecutan los resultados de la compilación (y algunas acciones).

Descripción general

Cuando configuras 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, en particular:

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

  • Entornos de ejecución diversos. La configuración de 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 personalizadas de compilación y prueba de Bazel para la ejecución remota y cómo evitarlos. Abarca los siguientes temas:

Cómo invocar herramientas de compilación mediante reglas de cadenas 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 una manera predecible y preconfigurada que es compatible con la ejecución remota. Por ejemplo, usa una regla de cadena de herramientas en lugar de invocar herramientas de compilación a través de PATH, JAVA_HOME o cualquier otra variable local que no esté configurada en valores equivalentes (o que no los ejecute en absoluto) en el entorno de ejecución remota.

Actualmente, existen reglas de cadena de herramientas para las reglas de compilación y prueba de Bazel para Scala, Rust y Go, y hay nuevas reglas de cadena de herramientas en curso para otros lenguajes y herramientas como Bash. Si no existe una regla de cadena de herramientas para la herramienta que usa tu regla, considera crear una regla de cadena de herramientas.

Administra dependencias implícitas

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

Por ejemplo, cuando Bazel le indica a un compilador con estado que compile foo de forma local, el compilador conserva 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 en el archivo BUILD para incluirla 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 es habitual 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 por separado, el estado del compilador y la dependencia implícita de bar en foo se perderán y la compilación fallará.

Para 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 de dependencias que la ejecución remota. Usa la zona de pruebas a fin de preparar tu compilación para la ejecución remota mediante la identificación y resolución de errores de compilación relacionados con la dependencia. Consulta Cómo solucionar problemas de Bazel Remote Execution con Docker Sandbox para obtener más información.

Administra objetos binarios que dependen de la plataforma

Por lo general, un objeto binario compilado en la plataforma host no se puede ejecutar de forma segura en una plataforma arbitraria de ejecución remota debido a dependencias potencialmente no coincidentes. Por ejemplo, el objeto binario SingleJar proporcionado con Bazel apunta a la plataforma host. Sin embargo, para la ejecución remota, SingleJar debe compilarse como parte del proceso de compilación de tu código para que se oriente a la plataforma de ejecución remota. (consulta la lógica de selección de objetivos).

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

  • Envía o haz una referencia externa al código fuente de la herramienta para que se pueda compilar en la plataforma de ejecución remota.

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

Administra reglas de WORKSPACE de estilo de configuración

Se pueden usar las reglas WORKSPACE de Bazel para sondear la plataforma host en busca de herramientas y bibliotecas que requiere la compilación. Para las compilaciones locales, también es la plataforma de ejecución de Bazel. Si la compilación depende de manera 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 de WORKSPACE no son compatibles con la ejecución remota:

  • Compilación de objetos binarios. La ejecución de acciones de compilación en reglas WORKSPACE genera objetos binarios que son incompatibles con la plataforma de ejecución remota (si son diferentes de la plataforma host).

  • Instalando 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 de ella.

  • Simultaneidad a herramientas o artefactos locales. Los vínculos simbólicos a herramientas o bibliotecas instaladas en la plataforma host creada mediante reglas WORKSPACE provocarán que la compilación falle en la plataforma de ejecución remota, ya que Bazel no podrá ubicarlas. En cambio, crea symlinks mediante acciones de compilación estándar para que se pueda acceder a las herramientas y bibliotecas symlinks desde el árbol runfiles de Bazel. No uses repository_ctx.symlink para establecer un symlink de archivos de destino fuera del directorio del repositorio externo.

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

Para ayudarte a encontrar un posible comportamiento no hermético, 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 la plataforma y enumeración de dependencias. Es seguro que estas operaciones se ejecuten localmente a través de las reglas WORKSPACE, que pueden verificar qué bibliotecas están instaladas, descargar paquetes que se deben compilar y preparar los artefactos necesarios para la compilación. En el caso de la ejecución remota, estas reglas también deben admitir el uso de artefactos previamente verificados para proporcionar la información que se obtendría normalmente durante la inspección de la plataforma host. Los artefactos ya verificados permiten que Bazel describa las dependencias como si fueran locales. Para ello, usa declaraciones condicionales o la marca --override_repository.

  • Generar o compilar artefactos específicos del destino y mutación de plataforma Esas operaciones se deben ejecutar a través de reglas de compilación regulares. Las acciones que producen artefactos específicos de destino para dependencias externas deben ejecutarse durante la compilación.

Si deseas generar con mayor facilidad artefactos ya verificados para la ejecución remota, puedes usar las reglas de WORKSPACE para emitir los archivos generados. Puedes ejecutar esas reglas en cada entorno de ejecución nuevo, como dentro de cada contenedor de la cadena de herramientas, y verificar los resultados de la ejecución remota en el repositorio de código fuente para hacer referencia.

Por ejemplo, en el caso de 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 producidos mediante la verificación del entorno del host. En el caso de la ejecución remota, una declaración condicional en una variable de entorno permite que la regla use archivos que se registran en el repositorio.

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