Una etiqueta es un identificador de un objetivo. Una etiqueta típica en su forma canónica completa se ve así:
@@myrepo//my/app/main:app_binary
La primera parte de la etiqueta es el nombre del repositorio, @@myrepo
. La sintaxis de doble @
indica que se trata de un nombre de repo canónico, que es único dentro del espacio de trabajo. Las etiquetas con nombres de repositorios canónicos identifican de forma inequívoca un destino, sin importar el contexto en el que aparezcan.
A menudo, el nombre canónico del repo es una cadena arcana que se ve como @@rules_java++toolchains+local_jdk
. Lo que se ve con mucha más frecuencia son etiquetas con un nombre de repo aparente, que se ve de la siguiente manera:
@myrepo//my/app/main:app_binary
La única diferencia es que el nombre del repo tiene un prefijo con un @
en lugar de dos.
Esto hace referencia a un repo con el nombre aparente myrepo
, que podría ser diferente según el contexto en el que aparezca esta etiqueta.
En el caso típico en que una etiqueta hace referencia al mismo repositorio desde el que se usa, se puede omitir la parte del nombre del repositorio. Por lo tanto, dentro de @@myrepo
, la primera etiqueta suele escribirse como
//my/app/main:app_binary
La segunda parte de la etiqueta es el nombre de paquete no calificado my/app/main
, la ruta de acceso al paquete relativa a la raíz del repositorio. En conjunto, el nombre del repositorio y el nombre del paquete no calificado 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, de forma opcional, los dos puntos). Por lo tanto, dentro de @@myrepo//my/app/main
, esta etiqueta se puede escribir de cualquiera de las siguientes maneras:
app_binary
:app_binary
Por convención, se omite el signo de dos puntos en los archivos, pero se conserva en las reglas. Sin embargo, no tiene otro significado.
La parte de la etiqueta que se encuentra después de los dos puntos, app_binary
, es el nombre del destino sin calificar. Cuando coincide con el último componente de la ruta del paquete, se puede omitir, junto con los dos puntos. 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 de acceso 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 de 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 es así. 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 usar //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 se basa en el directorio de nivel superior del espacio de trabajo.
Las etiquetas relativas no se pueden usar para hacer referencia a destinos en otros paquetes; en este caso, siempre se deben especificar el identificador del repositorio y el nombre del paquete.
Por ejemplo, si el árbol de origen 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
. A continuación, se muestran dos formas (una incorrecta y otra correcta) de hacer referencia 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: Haz referencia a testdata
con su ruta de acceso 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 información sobre las diferentes formas en que puedes hacer referencia a los destinos, consulta patrones de destino.
Especificación léxica de una etiqueta
La sintaxis de las etiquetas desaconseja el uso de metacaracteres que tienen un significado especial para el shell. Esto ayuda a evitar problemas de comillas involuntarios y facilita la creación de herramientas y secuencias de comandos que manipulan etiquetas, como el lenguaje de consultas de Bazel.
A continuación, se indican 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 ruta de acceso relativa al directorio que contiene el archivo BUILD
.
Los nombres de destino deben estar compuestos en su totalidad por caracteres del conjunto a
–z
, A
–Z
, 0
–9
y los símbolos de puntuación !%-@^_"#$&'()*-+,;<=>?[]{|}~/.
.
Los nombres de archivo deben ser nombres de ruta de acceso relativos en formato normal, lo que significa que no deben comenzar ni terminar con una barra (por ejemplo, /foo
y foo/
están prohibidos) ni contener varias barras consecutivas como separadores de ruta de acceso (por ejemplo, foo//bar
). Del mismo modo, se prohíben las referencias de nivel superior (..
) y las referencias de directorio actual (./
).
Incorrecto: No uses ..
para hacer referencia a archivos en 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. Especialmente cuando se usa la forma abreviada de una etiqueta, puede confundir al lector. La etiqueta //foo/bar/wiz
siempre es una abreviatura de //foo/bar/wiz:wiz
, incluso si no existe ese paquete foo/bar/wiz
; nunca hace referencia a //foo:bar/wiz
, incluso si existe ese destino.
Sin embargo, en algunas situaciones, es conveniente o, incluso, necesario usar una barra. Por ejemplo, el nombre de ciertas reglas debe coincidir con su archivo fuente 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
, relativo al 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 en minúscula de la
a
a laz
, las letras en mayúscula de laA
a laZ
, los dígitos del0
al9
, el carácter! \"#$%&'()*+,-.;<=>?@[]^_`{|}
(sí, hay un carácter de espacio allí) y, por supuesto, la barra/
(ya que es el separador de directorios). - 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 tendría sentido. ¿Cuál sería la ruta de acceso del directorio correspondiente? - Los nombres de paquetes no pueden contener las subcadenas
/./
,/../
,/.../
, etcétera. Esta aplicación se realiza para evitar confusiones al traducir entre un nombre de paquete lógico y un nombre de directorio físico, dado el significado semántico del carácter de punto en las cadenas de ruta de acceso.
A nivel práctico, haz lo siguiente:
- En el caso de un lenguaje con una estructura de directorios significativa para su sistema de módulos (por ejemplo, Java), es importante elegir nombres de directorios 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 los guiones.
- Si bien Bazel admite destinos en el paquete raíz del espacio 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 las salidas, y los pasos para generar las salidas. Las reglas pueden ser de muchos tipos diferentes (a veces, se denominan clase de regla), que producen ejecutables y bibliotecas compilados, ejecutables de prueba y otros resultados admitidos, como se describe en la Enciclopedia de compilación.
Los archivos BUILD
declaran objetivos invocando reglas.
En el siguiente ejemplo, vemos la declaración del destino my_app
con la regla cc_binary
.
cc_binary(
name = "my_app",
srcs = ["my_app.cc"],
deps = [
"//absl/base",
"//absl/strings",
],
)
Cada invocación de regla 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, así como la importancia y la semántica de cada atributo, son una función del tipo de regla. Consulta la Enciclopedia de compilación para obtener una lista de las 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úmero entero, etiqueta, lista de etiquetas, cadena, lista de cadenas, etiqueta de salida y lista de etiquetas de salida. No es necesario especificar todos los atributos en cada regla. Por lo tanto, los atributos forman un diccionario de claves (nombres) a valores opcionales con tipo.
El atributo srcs
presente en muchas reglas tiene el tipo "lista de etiquetas"; su valor, si está presente, es una lista de etiquetas, cada una de las cuales es el nombre de un destino que es una entrada para esta regla.
En algunos casos, el nombre del tipo de regla es algo arbitrario, y los nombres de los archivos que genera la regla son más interesantes, y esto se aplica a las genrules. Para obtener más información, consulta Reglas generales: genrule.
En otros casos, el nombre es importante: por ejemplo, para las reglas *_binary
y *_test
, el nombre de la regla determina el nombre del ejecutable que produce la compilación.
Este gráfico acíclico dirigido sobre los destinos se denomina gráfico de destinos o gráfico de dependencias de compilación, y es el dominio sobre el que opera la herramienta Bazel Query.
Objetivos | Archivos BUILD |