Guía de estilo de BUILD

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

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 ausencia de una convención del equipo predominante, estos son algunos recomendaciones que se usan ampliamente en Google:

  • En general, usa "snake_case"
    • Para una java_library con un src, 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 los src. Para java_test, esto permite que se pueda usar el atributo test_class inferido a partir del nombre del destino.
  • 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 o Tests
  • 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 (como my_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 +. Razón: Los archivos 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 archivos BUILD 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 archivos BUILD serán más cortos.