Etiquetas

Informar un problema Ver fuente

Una etiqueta es un identificador para un destino. Una etiqueta típica en su forma canónica completa se ve de la siguiente manera:

@@myrepo//my/app/main:app_binary

La primera parte de la etiqueta es el nombre del repositorio, @@myrepo. La sintaxis de doble @ indica que este es un nombre del repositorio canónico, que es único dentro del lugar de trabajo. Las etiquetas con nombres de repositorios canónicos identifican de manera inequívoca un destino sin importar el contexto en el que aparezcan.

A menudo, el nombre del repositorio canónico es una cadena arcana similar a @@rules_java~7.1.0~toolchains~local_jdk. Lo que más se observa son las etiquetas con un nombre de repositorio aparente, que se ve de la siguiente manera:

@myrepo//my/app/main:app_binary

La única diferencia es que el nombre del repositorio tiene un prefijo con un @ en lugar de dos. Esto hace referencia a un repositorio con el nombre aparente myrepo, que podría ser diferente según el contexto en el que aparece esta etiqueta.

En el caso típico en que una etiqueta hace referencia al mismo repositorio en el que se usa, se puede omitir la parte del nombre del repositorio. Por lo general, dentro de @@myrepo, la primera etiqueta se escribe como

//my/app/main:app_binary

La segunda parte de la etiqueta es el nombre del paquete no calificado my/app/main, la ruta al paquete relacionada con la raíz del repositorio. Juntos, el nombre del repositorio y el nombre del paquete sin calificar forman el nombre del paquete completamente calificado @@myrepo//my/app/main. Cuando la etiqueta hace referencia al mismo paquete en el que se usa, se puede omitir el nombre del paquete (y, opcionalmente, los dos puntos). Por lo tanto, dentro de @@myrepo//my/app/main, esta etiqueta se puede escribir de las siguientes maneras:

app_binary
:app_binary

Es una cuestión de convención que los dos puntos se omitan en los archivos, pero se conserven para las reglas, pero no tienen importancia en otros aspectos.

La parte de la etiqueta después de los dos puntos, app_binary es el nombre de destino no calificado. Cuando coincide con el último componente de la ruta del paquete, este y los dos puntos se pueden omitir. Por lo tanto, estas dos etiquetas son equivalentes:

//my/app/lib
//my/app/lib:lib

El nombre de un destino de archivo en un subdirectorio del paquete es la ruta del archivo relativa a la raíz del paquete (el directorio que contiene el archivo BUILD). Por lo tanto, este archivo se encuentra en el subdirectorio my/app/main/testdata del repositorio:

//my/app/main:testdata/input.txt

Las cadenas como //my/app y @@some_repo//my/app tienen dos significados según el contexto en el que se usan: cuando Bazel espera una etiqueta, significan //my/app:app y @@some_repo//my/app:app, respectivamente. Sin embargo, cuando Bazel espera un paquete (p.ej., en las especificaciones package_group), hace referencia al paquete que contiene esa etiqueta.

Un error común en los archivos BUILD es usar //my/app para hacer referencia a un paquete, o a todos los destinos de un paquete, pero no lo hace. Recuerda que es equivalente a //my/app:app, por lo que nombra el destino app en el paquete my/app del repositorio actual.

Sin embargo, se recomienda el uso de //my/app para hacer referencia a un paquete en la especificación de un package_group o en los archivos .bzl, ya que comunica claramente que el nombre del paquete es absoluto y tiene raíz en el directorio de nivel superior del lugar de trabajo.

Las etiquetas relativas no se pueden usar para hacer referencia a destinos en otros paquetes; el identificador del repositorio y el nombre del paquete siempre deben especificarse en este caso. Por ejemplo, si el árbol de fuentes contiene el paquete my/app y el paquete my/app/testdata (cada uno de estos dos directorios tiene su propio archivo BUILD), el último paquete contiene un archivo llamado testdepot.zip. Hay dos maneras (una incorrecta y una correcta) de referirse a este archivo dentro de //my/app:BUILD:

Incorrecto: testdata es un paquete diferente, por lo que no puedes usar una ruta de acceso relativa

testdata/testdepot.zip

Correcto: Consulta testdata con su ruta completa.

//my/app/testdata:testdepot.zip

Las etiquetas que comienzan con @@// son referencias al repositorio principal, que seguirá funcionando incluso desde repositorios externos. Por lo tanto, @@//a/b/c es diferente de //a/b/c cuando se hace referencia a él desde un repositorio externo. El primero hace referencia al repositorio principal, mientras que el segundo busca //a/b/c en el repositorio externo. Esto es especialmente relevante cuando se escriben reglas en el repositorio principal que hacen referencia a destinos en el repositorio principal y se usarán desde repositorios externos.

Para obtener más información sobre las diferentes formas en las que puedes hacer referencia a los destinos, consulta Patrones de objetivos.

Especificación léxica de una etiqueta

La sintaxis de las etiquetas desalienta el uso de metacaracteres que tienen un significado especial en el shell. Esto ayuda a evitar problemas de citas involuntarios y facilita la construcción de herramientas y secuencias de comandos que manipulan etiquetas, como el lenguaje de consulta de Bazel.

A continuación, se incluyen los detalles precisos de los nombres de destino permitidos.

Nombres de destino: package-name:target-name

target-name es el nombre del destino dentro del paquete. El nombre de una regla es el valor del atributo name en la declaración de la regla en un archivo BUILD; el nombre de un archivo es su nombre de ruta en relación con el directorio que contiene el archivo BUILD.

Los nombres de destino deben estar compuestos en su totalidad por caracteres extraídos del conjunto az, AZ, 09 y los símbolos de puntuación !%-@^_"#$&'()*-+,;<=>?[]{|}~/..

Los nombres de archivo deben ser nombres de rutas de acceso relativos en formato normal, lo que significa que no deben comenzar ni terminar con una barra (por ejemplo, se prohíben /foo y foo/) ni contener varias barras consecutivas como separadores de ruta de acceso (por ejemplo, foo//bar). De manera similar, están prohibidas las referencias de nivel superior (..) y las referencias del directorio actual (./).

Incorrecto: No uses .. para hacer referencia a archivos de otros paquetes

Correcto: Usa //package-name:filename.

Si bien es común usar / en el nombre de un destino de archivo, evita usar / en los nombres de las reglas. Esto puede confundir al lector, en especial cuando se usa la forma abreviada de una etiqueta. La etiqueta //foo/bar/wiz siempre es una abreviatura de //foo/bar/wiz:wiz, incluso si no existe el paquete foo/bar/wiz; nunca hace referencia a //foo:bar/wiz, incluso si ese destino existe.

Sin embargo, hay algunas situaciones en las que el uso de una barra es conveniente o, a veces, incluso necesario. Por ejemplo, el nombre de ciertas reglas debe coincidir con su archivo de origen principal, que puede residir en un subdirectorio del paquete.

Nombres de paquetes: //package-name:target-name

El nombre de un paquete es el nombre del directorio que contiene su archivo BUILD, en relación con el directorio de nivel superior del repositorio que lo contiene. Por ejemplo: my/app.

A nivel técnico, Bazel aplica lo siguiente:

  • Los caracteres permitidos en los nombres de paquetes son las letras minúsculas a a z, las letras mayúsculas de A a Z, los dígitos 0 a 9, los caracteres ! \"#$%&'()*+,-.;<=>?@[]^_`{|} (sí, hay un carácter de espacio allí) y, por supuesto, la barra diagonal / (ya que es el separador de directorio).
  • Los nombres de paquetes no pueden comenzar ni terminar con un carácter de barra diagonal /.
  • Los nombres de los paquetes no pueden contener la subcadena //. Esto no tiene sentido, ¿cuál sería la ruta de acceso al directorio correspondiente?
  • Los nombres de paquetes no pueden contener la substring /./, /../ o /.../, etc. Esta aplicación se realiza para evitar confusiones cuando se traduce entre un nombre de paquete lógico y un nombre de directorio físico, según el significado semántico del carácter de punto en las strings de ruta de acceso.

A nivel práctico:

  • En el caso de un lenguaje con una estructura de directorios que es significativa para el sistema de módulos (por ejemplo, Java), es importante elegir nombres de directorio que sean identificadores válidos en el lenguaje. Por ejemplo, no comiences con un dígito inicial y evita los caracteres especiales, en especial los guiones bajos y guiones.
  • Aunque Bazel admite destinos en el paquete raíz del lugar de trabajo (por ejemplo, //:foo), es mejor dejar ese paquete vacío para que todos los paquetes significativos tengan nombres descriptivos.

Reglas

Una regla especifica la relación entre las entradas y salidas, y los pasos para compilar las salidas. Las reglas pueden ser de uno de muchos tipos diferentes (a veces llamado clase de regla), que produce ejecutables y bibliotecas compilados, ejecutables de prueba y otros resultados compatibles, como se describe en la Enciclopedia de compilación.

Los archivos BUILD declaran destinos invocando reglas.

En el siguiente ejemplo, vemos la declaración del my_app de destino con la regla cc_binary.

cc_binary(
    name = "my_app",
    srcs = ["my_app.cc"],
    deps = [
        "//absl/base",
        "//absl/strings",
    ],
)

Cada invocación de reglas tiene un atributo name (que debe ser un nombre de destino válido), que declara un destino dentro del paquete del archivo BUILD.

Cada regla tiene un conjunto de atributos; los atributos aplicables para una regla determinada, y la importancia y semántica de cada atributo son una función del tipo de regla. Consulta la Enciclopedia de compilaciones para obtener una lista de reglas y sus atributos correspondientes. Cada atributo tiene un nombre y un tipo. Algunos de los tipos comunes que puede tener un atributo son números enteros, etiquetas, listas de etiquetas, strings, listas de strings, etiquetas de salida y listas de etiquetas de salida. No es necesario especificar todos los atributos en todas las reglas. Por lo tanto, los atributos forman un diccionario que va desde claves (nombres) hasta valores escritos opcionales.

El atributo srcs presente en muchas reglas tiene el tipo “list of labels”; su valor, si está presente, es una lista de etiquetas, cada una de las cuales es el nombre de un objetivo que es una entrada a esta regla.

En algunos casos, el nombre del tipo de regla es un poco arbitrario y los nombres de los archivos que genera la regla son más interesantes, y esto es cierto para las genrules. Para obtener más información, consulta Reglas generales: genrule.

En otros casos, el nombre es significativo: para las reglas *_binary y *_test, por ejemplo, el nombre de la regla determina el nombre del archivo ejecutable que produjo la compilación.

Este grafo acíclico dirigido sobre los destinos se denomina gráfico de destino o gráfico de dependencia de compilación y es el dominio sobre el que opera la Herramienta de consultas de Bazel.

Objetivos Archivos BUILD