El formato de archivo BUILD
sigue el mismo enfoque que Go, en el que se aplica
se encarga de la mayoría de los problemas de formato.
Buildifier es una herramienta que analiza y
emite el código fuente en un estilo estándar. Por lo tanto, cada archivo BUILD
se
de la misma manera automatizada, lo que hace que formatear no sea un problema durante
revisiones de código. También facilita que las herramientas entiendan, editen y
generar archivos BUILD
El formato de archivo BUILD
debe coincidir con el resultado de buildifier
.
Ejemplo de formato
# Test code implementing the Foo controller.
package(default_testonly = True)
py_test(
name = "foo_test",
srcs = glob(["*.py"]),
data = [
"//data/production/foo:startfoo",
"//foo",
"//third_party/java/jdk:jdk-k8",
],
flaky = True,
deps = [
":check_bar_lib",
":foo_data_check",
":pick_foo_port",
"//pyglib",
"//testing/pybase",
],
)
Estructura de archivos
Recomendación: Usa el siguiente orden (cada elemento es opcional):
Descripción del paquete (un comentario)
Todos los estados de cuenta
load()
La función
package()
Llamadas a reglas y macros
Buildifier distingue entre un comentario independiente y un comentario se adjuntan a un elemento. Si no se adjunta un comentario a un elemento específico, usa una línea vacía después del nombre. La distinción es importante cuando se usan procesos cambios (por ejemplo, conservar o quitar un comentario al borrar una regla).
# Standalone comment (such as to make a section in a file)
# Comment for the cc_library below
cc_library(name = "cc")
Referencias a los destinos en el paquete actual
Se debe hacer referencia a los archivos por sus rutas de acceso en relación con el directorio del paquete
(sin usar referencias ascendentes, como ..
). Los archivos generados deben tener
con el prefijo “:
” para indicar que no son fuentes. Archivos de origen
no debe tener el prefijo :
. Las reglas deben tener el prefijo :
. Para
Ejemplo, si x.cc
es un archivo de origen:
cc_library(
name = "lib",
srcs = ["x.cc"],
hdrs = [":gen_header"],
)
genrule(
name = "gen_header",
srcs = [],
outs = ["x.h"],
cmd = "echo 'int x();' > $@",
)
Nomenclatura de objetivos
Los nombres de los destinos deben ser descriptivos. Si un destino contiene un archivo de origen,
el destino generalmente debe tener un nombre derivado de esa fuente (por ejemplo,
cc_library
para chat.cc
podría llamarse chat
o un java_library
para
DirectMessage.java
podría llamarse direct_message
).
El objetivo eónimo de un paquete (el objetivo con el mismo nombre que el que contiene) deben proporcionar la funcionalidad que se describe en el nombre de directorio. Si no existe tal objetivo, no crees un nombre epónima. objetivo.
Prefieres usar el nombre corto para hacer referencia a un objetivo eónimo (//x
)
en lugar de //x:x
). Si formas parte del mismo paquete, prioriza la local
referencia (:x
en lugar de //x
).
Evita utilizar la palabra "reservado" nombres de objetivos que tienen un significado especial. Esto incluye
all
, __pkg__
y __subpackages__
, estos nombres tienen valores especiales
y pueden causar confusión y comportamientos inesperados cuando se usan.
Ante la falta de una convención predominante del equipo, estos son algunos recomendaciones que se usan ampliamente en Google:
- En general, usa "snake_case"
- Para una
java_library
con unsrc
, esto significa que debes usar un nombre que no sea ser el mismo que el nombre del archivo, sin la extensión - Para las reglas
*_binary
y*_test
de Java, usa “Upper CamelCase”. Esto permite que el nombre del destino coincida con uno de lossrc
. Parajava_test
, esto permite que se pueda usar el atributotest_class
inferido a partir del nombre del destino.
- Para una
- Si hay múltiples variantes de un objetivo en particular, agrega un sufijo a
eliminar la ambigüedad (por ejemplo,
:foo_dev
,:foo_prod
o:bar_x86
,:bar_x64
) - Sufija los objetivos
_test
con_test
,_unittest
,Test
oTests
- Evita los sufijos sin sentido, como
_lib
o_library
(a menos que sea necesario para Evita conflictos entre un objetivo de_library
y su_binary
correspondiente) - Para destinos relacionados con proto:
proto_library
destinos deben tener nombres que terminen en_proto
- Las reglas de
*_proto_library
específicas de los lenguajes deben coincidir con las reglas subyacentes proto, pero reemplaza_proto
por un sufijo específico de lenguaje, como el siguiente:cc_proto_library
:_cc_proto
java_proto_library
:_java_proto
java_lite_proto_library
:_java_proto_lite
Visibilidad
El alcance de la visibilidad debe ser lo más restringido posible y, al mismo tiempo, permitir el acceso.
y revertir las dependencias. Utiliza __pkg__
y __subpackages__
como
lo que sea apropiado.
No configures el paquete default_visibility
como //visibility:public
.
//visibility:public
debe configurarse de forma individual solo para objetivos en el
la API pública del proyecto. Podrían ser bibliotecas diseñadas para depender de
por proyectos externos u objetos binarios que podrían usarse en la interfaz
de compilación.
Dependencias
Las dependencias deben restringirse a dependencias directas (las que necesiten las fuentes indicadas en la regla). No incluyas dependencias transitivas.
Las dependencias del paquete local deben aparecer primero y se debe hacer referencia a ellas de manera compatibles con el Referencias a destinos en el paquete actual en la sección anterior (no por su nombre absoluto de paquete).
Prefieres enumerar las dependencias directamente, como una sola lista. Si ponemos lo «común» dependencias de varios objetivos en una variable reduce la capacidad de mantenimiento, hace que las herramientas no puedan cambiar las dependencias de un objetivo, las dependencias sin usar.
Globs
Indicar "sin orientaciones" con []
. No uses un glob que no coincida con nada, ya que
es más propensa a errores y menos obvia que una lista vacía.
Recursiva
No uses globs recursivos para hacer coincidir los archivos de origen (por ejemplo,
glob(["**/*.java"])
).
Los globs recursivos dificultan el razonamiento de los archivos BUILD
porque se omiten
subdirectorios que contienen archivos BUILD
.
Los globs recursivos suelen ser menos eficientes que tener un archivo BUILD
por
con un gráfico de dependencias definido entre ellos, ya que esto permite una mejor
el paralelismo y el almacenamiento en caché remoto.
Se recomienda crear un archivo BUILD
en cada directorio y definir un
gráfico de dependencias entre ellas.
No recursivo
Por lo general, se aceptan los globs no recursivos.
Otras convenciones
Usa mayúsculas y guiones bajos para declarar constantes (como
GLOBAL_CONSTANT
). usa minúsculas y guiones bajos para declarar variables (comomy_variable
).Las etiquetas nunca se deben dividir, incluso si tienen más de 79 caracteres. Las etiquetas deben ser literales de cadena siempre que sea posible. Razón: Hace que es muy fácil buscar y reemplazar. También mejora la legibilidad.
El valor del atributo de nombre debe ser una cadena literal constante (excepto en macros). Razón: Las herramientas externas usan el atributo de nombre para hacer referencia a un . Necesitan encontrar reglas sin tener que interpretar el código.
Cuando establezca atributos de tipo booleano, use valores booleanos, no valores enteros. Por motivos heredados, las reglas siguen convirtiendo números enteros en booleanos según sea necesario, pero no es aconsejable. Razón: Es posible que
flaky = 1
no se interprete correctamente como dicho “deflake este destino volviendo a ejecutarlo una vez”.flaky = True
dice sin ambigüedades "esta prueba es inestable".
Diferencias con la guía de estilo de Python
Si bien la compatibilidad con Guía de estilo de Python es un objetivo, existen algunas diferencias:
No hay un límite estricto de longitud de línea. Los comentarios largos y las cadenas largas suelen dividirse a 79 columnas, pero no es obligatorio. No se debe aplicar en el código. revisiones o secuencias de comandos del envío previo. Razón: Las etiquetas pueden ser largas y superar este límite límite. Es común que las herramientas generen o editen los archivos
BUILD
, lo que no va bien con un límite de longitud de línea.No se admite la concatenación de cadenas implícitas. Usa el operador
BUILD
contienen muchas listas de cadenas. Es fácil olvidar un coma, lo que lleva a un resultado completamente diferente. Esto ha creado muchos errores en el pasado. Consulta también este debate.Usa espacios alrededor del signo
=
para los argumentos de palabras clave en las reglas. Motivos: Los argumentos con nombre son mucho más frecuentes que en Python y siempre están en un línea separada. Los espacios mejoran la legibilidad. Esta convención se desarrolló durante mucho tiempo, por lo que no vale la pena modificar todos los archivosBUILD
existentes.De forma predeterminada, usa comillas dobles para las cadenas. Motivo: Esto no es especificada en la guía de estilo de Python, pero recomienda coherencia. Entonces, decidió usar solo cadenas entre comillas dobles. Muchos idiomas usan comillas dobles. para literales de cadena.
Usa una sola línea en blanco entre dos definiciones de nivel superior. Razón: La de un archivo
BUILD
no es como un archivo típico de Python. Solo tiene declaraciones de nivel superior. Si usas una sola línea en blanco, los archivosBUILD
serán más cortos.