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
- Usa Buildifier. como formateador y linter.
- Sigue los lineamientos para realizar pruebas.
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_]*
), comocc_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).
Usar impresión solo para depuración
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.).
- Tienen sus nombres con el prefijo
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.
- 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éteraruntime_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.