Guía de estilo .bzl

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

En esta página, se abordan los lineamientos básicos de estilo de Starlark y también se incluye información sobre macros y reglas.

Starlark es un un lenguaje común que define cómo se crea el software y, por lo tanto, es un programación y un lenguaje de configuración.

Usarás Starlark para escribir archivos BUILD, macros y reglas de compilación. Macros y son, en esencia, metalenguajes: definen cómo se escriben los archivos BUILD. El objetivo de los archivos BUILD es que sean simples y repetitivos.

Todo el software se lee más seguido de lo que está escrito. Esto es especialmente cierto para Starlark, a medida que los ingenieros leen los archivos BUILD para comprender las dependencias de su objetivos y los detalles de sus compilaciones. Esta lectura suele ocurrir al pasar, apurado o en paralelo a lograr alguna otra tarea. Por lo tanto, la simplicidad y la legibilidad son muy importantes para que los usuarios puedan analizar y comprender archivos BUILD rápidamente

Cuando un usuario abre un archivo BUILD, quiere conocer rápidamente la lista de destinos de el archivo; o revisar la lista de fuentes de esa biblioteca C++; o quitar un del objeto binario de Java. Cada vez que agregas una capa de abstracción, dificultar que un usuario realice estas tareas.

Los archivos BUILD también se analizan y actualizan con muchas herramientas diferentes. Es posible que las herramientas no podrás editar tu archivo BUILD si usa abstracciones. Se mantendrán los BUILD archivos simples te permitirá obtener mejores herramientas. A medida que crece una base de código, se vuelve cada vez más frecuente hacer cambios en muchos archivos BUILD para actualizar una biblioteca o hacer una limpieza.

Consejo general

Estilo

Estilo de Python

Si tienes dudas, sigue la Guía de estilo PEP 8 siempre que sea posible. En particular, usa cuatro espacios en lugar de dos para que la sangría siga el Convención de Python.

Desde Starlark no es Python, no se aplican algunos aspectos del estilo Python. Por ejemplo, PEP 8 recomienda que las comparaciones con singletons se realizarán con is, que no es un operador en Starlark.

Cadena de documentos

Documenta archivos y funciones con docstrings. Usa una docstring en la parte superior de cada archivo .bzl y una docstring para cada archivo público .

Reglas y aspectos de los documentos

Las reglas y los aspectos, junto con sus atributos, así como los proveedores y sus deben documentarse con el argumento doc.

Convención de nombres

  • Los nombres de las variables y las funciones usan minúsculas con palabras separadas por guiones bajos ([a-z][a-z0-9_]*), como cc_library
  • Los valores privados de nivel superior comienzan con un guion bajo. Bazel aplica no se pueden usar valores privados de otros archivos. Las variables locales no deben usa el prefijo de guion bajo.

Longitudes de línea

Al igual que en los archivos BUILD, no hay un límite estricto de longitud de línea, ya que las etiquetas pueden ser largas. Cuando sea posible, intenta usar un máximo de 79 caracteres por línea (según la PEP 8). Este lineamiento no se deben aplicar de manera estricta: los editores deben mostrar más de 80 columnas, los cambios automatizados suelen introducir líneas más largas, y las personas pasan tiempo dividiendo líneas que ya son legibles.

Argumentos de palabras clave

En los argumentos de palabras clave, se prefieren los espacios alrededor del signo igual:

def fct(name, srcs):
    filtered_srcs = my_filter(source = srcs)
    native.cc_library(
        name = name,
        srcs = filtered_srcs,
        testonly = True,
    )

Valores booleanos

Se prefieren los valores True y False (en lugar de 1 y 0) para valores booleanos (por ejemplo, cuando se usa un atributo booleano en una regla).

No uses la función print() en el código de producción. solo están destinados a depuraciones y enviará spam a todos los usuarios indirectos y directos de tu archivo .bzl. El La única excepción es que puedes enviar un código que use print() si está inhabilitado. de forma predeterminada y solo se puede habilitar editando la fuente, por ejemplo, si todas los usos de print() están protegidos por if DEBUG:, donde DEBUG está codificado como False Ten en cuenta si estas afirmaciones son lo suficientemente útiles para justificar su impacto en la legibilidad.

Macros

Una macro es una función que crea una instancia de una o más reglas durante la carga en la fase de desarrollo. En general, usa reglas siempre que sea posible en lugar de macros. La compilación gráfico que ve el usuario no es el mismo que usó Bazel durante el Compilación: Las macros se expanden antes de que Bazel realice análisis de gráficos de compilación.

Debido a esto, cuando algo sale mal, el usuario tendrá que entender la implementación de tu macro para solucionar problemas de compilación. Además, los resultados de bazel query pueden ser difíciles de interpretar porque los objetivos se muestran en ellos. provienen de la expansión de macros. Por último, los aspectos no tienen en cuenta las macros, por lo que las herramientas dependiendo de los aspectos (IDEs y otros) podría fallar.

Un uso seguro de las macros es definir objetivos adicionales para directamente en la CLI de Bazel o en los archivos de COMPILACIÓN; en ese caso, solo se usuarios finales de esos destinos deben conocerlos y deben informarse sobre cualquier problema de compilación que introducen las macros nunca están lejos de su uso.

Para las macros que definen objetivos generados (detalles de implementación de la macro) a las que no se debe hacer referencia en la CLI ni de las que los destinos esa macro no crea una instancia), sigue estas prácticas recomendadas:

  • Una macro debería tomar un argumento name y definir un objetivo con ese nombre. Ese objetivo se convierte en el objetivo principal de la macro.
  • Los objetivos generados, es decir, todos los demás objetivos definidos por una macro, deben cumplir con lo siguiente:
    • Tienen sus nombres con el prefijo <name> o _<name>. Por ejemplo, name = '%s_bar' % (name)
    • Tienen visibilidad restringida (//visibility:private).
    • Incluye una etiqueta manual para evitar la expansión en los destinos comodín (:all, ..., :*, etc.).
  • name solo debe usarse para derivar nombres de destinos definidos por el ni para nada más. Por ejemplo, no uses el nombre para derivar un archivo de entrada o dependencia que la macro no genera.
  • Todos los destinos creados en la macro deberían acoplarse de alguna manera al objetivo principal.
  • Convencionalmente, name debería ser el primer argumento cuando se define una macro.
  • Mantén la coherencia de los nombres de los parámetros de la macro. Si se pasa un parámetro como un valor de atributo para el destino principal, mantén su nombre igual. Si una macro tiene el mismo propósito que un atributo de regla común, como deps, como lo harías para el atributo (consulta a continuación).
  • Cuando llames a una macro, usa solo argumentos de palabras clave. Esto es coherente con reglas de firewall y mejora en gran medida la legibilidad.

Los ingenieros suelen escribir macros cuando la API de Starlark de reglas relevantes se insuficientes para su caso de uso específico, sin importar si la regla está definidos dentro de Bazel en código nativo o en Starlark. Si tienes este pregúntele al autor de la regla si puede extender la API para lograr su y objetivos de tiempo de recuperación.

Como regla general, cuanto más se parezcan las macros a las reglas, mejor.

Consulta también las macros.

Reglas

  • Las reglas, los aspectos y sus atributos deben usar nombres en minúscula (“snake”). ").
  • Los nombres de las reglas son sustantivos que describen el tipo principal de artefacto producido por el desde el punto de vista de sus dependencias (o para las reglas de la hoja, la usuario). No es necesariamente un sufijo de archivo. Por ejemplo, una regla que produce artefactos C++ diseñados para usarse, como podrían llamarse extensiones de Python. py_extension Para la mayoría de los idiomas, estas son algunas de las reglas típicas:
    • *_library: Es una unidad o "módulo" de compilación.
    • *_binary: Es un destino que produce un ejecutable o una unidad de implementación.
    • *_test: Es un objetivo de prueba. Esto puede incluir varias pruebas. Expectativas de todos las pruebas en un objetivo *_test sean variaciones del mismo tema, por por ejemplo, probar una sola biblioteca.
    • *_import: un destino que encapsula un artefacto compilado previamente, como un .jar o un .dll que se usa durante la compilación
  • Usa nombres y tipos coherentes para los atributos. Algunos ejemplos de incluyen los siguientes:
    • srcs: label_list, lo que permite archivos: archivos de origen, por lo general, creado por humanos.
    • deps: label_list, por lo general, no permite archivos: compilación. dependencias.
    • data: label_list, lo que permite archivos, como archivos de datos, como datos de prueba, etcétera
    • runtime_deps: label_list: Son las dependencias del entorno de ejecución que no se necesitan. para la compilación.
  • Para cualquier atributo con comportamiento no evidente (por ejemplo, plantillas de cadenas con sustituciones especiales o herramientas que se invocan ), proporciona documentación con el argumento de palabra clave doc al la declaración del atributo (attr.label_list() o similar).
  • Las funciones de implementación de reglas casi siempre deben ser funciones privadas (llamadas con un guion bajo inicial). Un estilo común es otorgar a la función de implementación para myrule con el nombre _myrule_impl.
  • Pasa información entre tus reglas con una regla provider. Declara y documenta el proveedor .
  • Diseña la regla teniendo en cuenta la extensibilidad. Ten en cuenta que otras reglas podrían desean interactuar con su regla, acceder a sus proveedores y reutilizar el acciones que crees.
  • Sigue los lineamientos de rendimiento en tus reglas.