Um rótulo é um identificador de um destino. Um rótulo típico na forma canônica completa é assim:
@@myrepo//my/app/main:app_binary
A primeira parte do rótulo é o nome do repositório, @@myrepo. A sintaxe @
dupla significa que esse é um nome de repositório canônico, que é exclusivo no
espaço de trabalho. Os rótulos com nomes de repositório canônicos identificam um destino de forma inequívoca
não importa em qual contexto eles apareçam.
Muitas vezes, o nome do repositório canônico é uma string arcana que se parece com
@@rules_java++toolchains+local_jdk. O que é muito mais comum são
rótulos com um aparente nome de repositório,
que se parece com:
@myrepo//my/app/main:app_binary
A única diferença é que o nome do repositório tem um prefixo com um @ em vez de dois.
Isso se refere a um repositório com o nome aparente myrepo, que pode ser diferente
com base no contexto em que esse rótulo aparece.
No caso típico em que um rótulo se refere ao mesmo repositório em que
é usado, a parte do nome do repositório pode ser omitida. Portanto, dentro de @@myrepo o primeiro
rótulo geralmente é escrito como
//my/app/main:app_binary
A segunda parte do rótulo é o nome do pacote não qualificado
my/app/main, o caminho para o pacote
em relação à raiz do repositório. Juntos, o nome do repositório e o
nome do pacote não qualificado formam o nome do pacote totalmente qualificado
@@myrepo//my/app/main. Quando o rótulo se refere ao mesmo
pacote em que é usado, o nome do pacote (e, opcionalmente, os dois pontos)
pode ser omitido. Portanto, dentro de @@myrepo//my/app/main,
esse rótulo pode ser escrito de uma das seguintes maneiras:
app_binary
:app_binary
É uma questão de convenção que os dois pontos sejam omitidos para arquivos, mas mantidos para regras, mas não é significativo.
A parte do rótulo após os dois pontos, app_binary, é o nome do destino não qualificado. Quando ele corresponde ao último componente do caminho do pacote, ele e os
dois pontos podem ser omitidos. Portanto, esses dois rótulos são equivalentes:
//my/app/lib
//my/app/lib:lib
O nome de um destino de arquivo em um subdiretório do pacote é o caminho do arquivo
em relação à raiz do pacote (o diretório que contém o arquivo BUILD). Portanto,
esse arquivo está no subdiretório my/app/main/testdata do repositório:
//my/app/main:testdata/input.txt
Strings como //my/app e @@some_repo//my/app têm dois significados, dependendo do
contexto em que são usadas: quando o Bazel espera um rótulo, elas significam
//my/app:app e @@some_repo//my/app:app, respectivamente. No entanto, quando o Bazel
espera um pacote (por exemplo, em package_group especificações), eles referenciam o
pacote que contém esse rótulo.
Um erro comum em BUILD arquivos é usar //my/app para se referir a um pacote, ou
para todos os destinos em um pacote. Isso não acontece. Lembre-se de que ele é
equivalente a //my/app:app, então ele nomeia o destino app no my/app
pacote do repositório atual.
No entanto, o uso de //my/app para se referir a um pacote é incentivado na
especificação de um package_group ou em .bzl arquivos, porque ele comunica claramente
que o nome do pacote é absoluto e está enraizado no diretório de nível superior
do espaço de trabalho.
Os rótulos relativos não podem ser usados para se referir a destinos em outros pacotes. O
identificador do repositório e o nome do pacote precisam sempre ser especificados nesse caso.
Por exemplo, se a árvore de origem contiver o pacote my/app e o
pacote my/app/testdata (cada um desses dois diretórios tem seu próprio
BUILD arquivo), o último pacote contém um arquivo chamado testdepot.zip. Confira duas maneiras (uma errada e uma correta) de se referir a esse arquivo em
//my/app:BUILD:
Errado: testdata é um pacote diferente, então não é possível usar um caminho relativo
testdata/testdepot.zip
Correto: consulte testdata com o caminho completo
//my/app/testdata:testdepot.zipOs rótulos que começam com @@// são referências ao repositório principal, que ainda funciona mesmo em repositórios externos.
Portanto, @@//a/b/c é diferente de
//a/b/c quando referenciado de um repositório externo.
O primeiro se refere ao repositório principal, enquanto o segundo
procura //a/b/c no próprio repositório externo.
Isso é especialmente relevante ao escrever regras no repositório principal
que se referem a destinos no repositório principal e serão
usadas em repositórios externos.
Para informações sobre as diferentes maneiras de se referir a destinos, consulte Padrões de destino.
Especificação léxica de um rótulo
A sintaxe de rótulo desencoraja o uso de metacaracteres que têm um significado especial para o shell. Isso ajuda a evitar problemas de cotação inadvertidos e facilita a criação de ferramentas e scripts que manipulam rótulos, como a linguagem de consulta do Bazel.
Confira abaixo os detalhes precisos dos nomes de destino permitidos.
Nomes de destino: package-name:target-name
target-name é o nome do destino no pacote. O nome de uma regra
é o valor do atributo name na declaração da regra em um arquivo BUILD
; o nome de um arquivo é o nome do caminho relativo ao diretório que contém
o arquivo BUILD.
Os nomes de destino precisam ser compostos inteiramente de caracteres extraídos do conjunto a–z,
A–Z, 0–9, e dos símbolos de pontuação !%-@^_"#$&'()*-+,;<=>?[]{|}~/..
Os nomes de arquivos precisam ser nomes de caminho relativos na forma normal, o que significa que eles não podem
começar nem terminar com uma barra (por exemplo, /foo e foo/ são
proibidos) nem conter várias barras consecutivas como separadores de caminho
(por exemplo, foo//bar). Da mesma forma, referências de nível superior (..) e
referências de diretório atual (./) são proibidas.
Errado: não use .. para se referir a arquivos em outros pacotes
Correto: Use
//package-name:filename
Embora seja comum usar / no nome de um destino de arquivo, evite o uso de
/ nos nomes das regras. Especialmente quando a forma abreviada de um rótulo é
usada, ela pode confundir o leitor. O rótulo //foo/bar/wiz é sempre uma abreviação
para //foo/bar/wiz:wiz, mesmo que não haja um pacote foo/bar/wiz. Ele
nunca se refere a //foo:bar/wiz, mesmo que esse destino exista.
No entanto, há algumas situações em que o uso de uma barra é conveniente ou até necessário. Por exemplo, o nome de determinadas regras precisa corresponder ao arquivo de origem principal, que pode residir em um subdiretório do pacote.
Nomes de pacotes: //package-name:target-name
O nome de um pacote é o nome do diretório que contém o arquivo BUILD,
relativo ao diretório de nível superior do repositório que o contém.
Por exemplo: my/app.
Em um nível técnico, o Bazel aplica o seguinte:
- Os caracteres permitidos em nomes de pacotes são as letras minúsculas
aaz, as letras maiúsculasAaZ, os dígitos0a9, os caracteres! \"#$%&'()*+,-.;<=>?@[]^_`{|}(sim, há um caractere de espaço aí!), e é claro, a barra/(já que é o separador de diretório). - Os nomes de pacotes não podem começar nem terminar com um caractere de barra
/. - Os nomes de pacotes não podem conter a substring
//. Isso não faria sentido. Qual seria o caminho do diretório correspondente? - Os nomes de pacotes não podem conter a substring
/./ou/../ou/.../etc. Essa aplicação é feita para evitar confusão ao traduzir entre um nome de pacote lógico e um nome de diretório físico, considerando o significado semântico do caractere de ponto em strings de caminho.
Em um nível prático:
- Para uma linguagem com uma estrutura de diretório significativa para o sistema de módulos (por exemplo, Java), é importante escolher nomes de diretório que sejam identificadores válidos na linguagem. Por exemplo, não comece com um dígito inicial e evite caracteres especiais, especialmente sublinhados e hífens.
- Embora o Bazel ofereça suporte a destinos no pacote raiz do espaço de trabalho (por exemplo,
//:foo), é melhor deixar esse pacote vazio para que todos os pacotes significativos tenham nomes descritivos.
Regras
Uma regra especifica a relação entre entradas e saídas e as etapas para criar as saídas. As regras podem ser de vários tipos diferentes (às vezes chamadas de classe de regra), que produzem executáveis e bibliotecas compilados , executáveis de teste e outras saídas com suporte , conforme descrito na Enciclopédia de build.
Os arquivos BUILD declaram destinos invocando regras.
No exemplo abaixo, vemos a declaração do destino my_app
usando a regra cc_binary.
cc_binary(
name = "my_app",
srcs = ["my_app.cc"],
deps = [
"//absl/base",
"//absl/strings",
],
)
Cada invocação de regra tem um atributo name (que precisa ser um
nome de destino válido) que declara um destino no pacote
do arquivo BUILD.
Cada regra tem um conjunto de atributos. Os atributos aplicáveis a uma determinada regra, e a importância e a semântica de cada atributo são uma função do tipo de regra. Consulte a Enciclopédia de build para conferir uma lista de regras e os atributos correspondentes. Cada atributo tem um nome e um tipo. Alguns dos tipos comuns que um atributo pode ter são número inteiro, rótulo, lista de rótulos, string, lista de strings, rótulo de saída, lista de rótulos de saída. Nem todos os atributos precisam ser especificados em todas as regras. Os atributos formam um dicionário de chaves (nomes) para valores opcionais e digitados.
O atributo srcs presente em muitas regras tem o tipo "lista de rótulos". O
valor dele, se presente, é uma lista de rótulos, cada um sendo o nome de um destino que é
uma entrada para essa regra.
Em alguns casos, o nome do tipo de regra é um pouco arbitrário, e mais interessantes são os nomes dos arquivos gerados pela regra, e isso é verdadeiro para genrules. Para mais informações, consulte Regras gerais: genrule.
Em outros casos, o nome é significativo: para regras *_binary e *_test,
por exemplo, o nome da regra determina o nome do executável produzido pelo
build.
Esse gráfico acíclico direcionado sobre destinos é chamado de gráfico de destino ou gráfico de dependência de build e é o domínio em que a ferramenta de consulta do Bazel opera.
| Destinos | Arquivos BUILD |