Um rótulo é um identificador de um destino. Um rótulo típico em sua forma canônica completa tem a seguinte aparência:
@@myrepo//my/app/main:app_binary
A primeira parte do rótulo é o nome do repositório, @@myrepo
. A sintaxe de @
duplo significa que esse é um nome de repositório canônico, que é exclusivo dentro do espaço de trabalho. Os rótulos com nomes de repositório canônicos identificam inequivocamente um destino,
independentemente do contexto em que aparecem.
Muitas vezes, o nome do repositório canônico é uma string secreta parecida com
@@rules_java~7.1.0~toolchains~local_jdk
. O que é muito mais comum são
rótulos com um nome de repositório aparente,
que tem esta aparência:
@myrepo//my/app/main:app_binary
A única diferença é que o nome do repositório é prefixado 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 de um rótulo se referir ao mesmo repositório em que ele é usado, a parte do nome do repositório pode ser omitida. 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
relativo à raiz do repositório. Juntos, o nome do repositório e o
nome do pacote não qualificado formam o nome de pacote totalmente qualificado
@@myrepo//my/app/main
. Quando o rótulo se refere ao mesmo
pacote em que é usado, o nome dele e, opcionalmente, os dois-pontos
podem ser omitidos. Portanto, em @@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 retidos para regras, mas não são significativos.
A parte do rótulo após os dois-pontos, app_binary
é o nome do destino
não qualificado. Quando 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, ou seja, 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, nas especificações package_group
), ele faz referência ao
pacote que contém esse rótulo.
Um erro comum em arquivos BUILD
é usar //my/app
para se referir a um pacote ou
a todos os destinos em um pacote. Isso não acontece. Lembre-se de que ele é
equivalente a //my/app:app
. Portanto, ele nomeia o destino app
no pacote
my/app
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 arquivos .bzl
, porque informa claramente
que o nome do pacote é absoluto e tem acesso root no diretório de nível
superior do espaço de trabalho.
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 ser sempre especificados nesse caso.
Por exemplo, se a árvore de origem contiver os pacotes my/app
e
my/app/testdata
(cada um desses dois diretórios tem o próprio arquivo
BUILD
), o último pacote conterá um arquivo chamado testdepot.zip
. Veja
duas maneiras (uma errada e outra correta) de se referir a esse arquivo em
//my/app:BUILD
:
Errado: testdata
é um pacote diferente, por isso não é possível usar um caminho relativo.
testdata/testdepot.zip
Correto: consulte testdata
com o caminho completo.
//my/app/testdata:testdepot.zip
Os rótulos que começam com @@//
são referências ao repositório principal, que ainda funciona até 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 que 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 do rótulo desencoraja o uso de metacaracteres que têm um significado especial para o shell. Isso ajuda a evitar problemas de cotações acidentais e facilita a construção de ferramentas e scripts que manipulam rótulos, como a Linguagem de consulta Bazel.
Veja abaixo os detalhes exatos dos nomes de destinos 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 dele em relação ao diretório que contém
o arquivo BUILD
.
Os nomes dos destinos precisam ser compostos inteiramente de caracteres extraídos do conjunto a
–z
,
A
–Z
, 0
–9
e os símbolos de pontuação !%-@^_"#$&'()*-+,;<=>?[]{|}~/.
.
Os nomes de arquivos precisam ser nomes de caminho relativos em formato 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órios atuais (./
) são proibidas.
Incorreto: 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 usar /
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
de //foo/bar/wiz:wiz
, mesmo que não haja esse 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 e, às vezes, 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 dos pacotes: //package-name:target-name
O nome de um pacote é o nome do diretório que contém o arquivo BUILD
,
em relação 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: letras minúsculas de
a
az
, letras maiúsculas deA
aZ
, dígitos0
a9
, caracteres! \"#$%&'()*+,-.;<=>?@[]^_`{|}
(sim, há um caractere de espaço aí!) e, claro, barra/
(já que é o separador de diretório). - Os nomes dos pacotes não podem começar ou terminar com uma 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 dos pacotes não podem conter a substring
/./
,/../
ou/.../
etc. Essa aplicação é feita para evitar confusão na conversão entre um nome de pacote lógico e um nome de diretório físico, dado o significado semântico do caractere de ponto nas strings de caminho.
Em termos práticos:
- Para uma linguagem com uma estrutura de diretórios importante para o sistema de módulos (por exemplo, Java), é importante escolher nomes de diretórios que sejam identificadores válidos na linguagem. Por exemplo, não comece com um dígito e evite caracteres especiais, especialmente sublinhados e hifens.
- 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 muitos tipos diferentes (às vezes chamadas de classe de regras), 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 my_app
de destino usando a regra cc_binary
.
cc_binary(
name = "my_app",
srcs = ["my_app.cc"],
deps = [
"//absl/base",
"//absl/strings",
],
)
Toda 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 o significado e a semântica de cada atributo são funções do tipo da regra. Consulte a Enciclopédia de criação para ver uma lista de regras e os atributos correspondentes. Cada atributo tem um nome e um tipo. Alguns dos tipos comuns de um atributo são: inteiro, rótulo, lista de rótulos, string, lista de strings, rótulo de saída e lista de rótulos de saída. Nem todos os atributos precisam ser especificados em todas as regras. Os atributos, portanto, formam um dicionário de chaves (nomes) a valores digitados opcionais.
O atributo srcs
, presente em muitas regras, tem o tipo "lista de rótulos". O
valor, se presente, é uma lista de rótulos, sendo cada um o nome de um destino
que é uma entrada da regra.
Em alguns casos, o nome do tipo da regra é um pouco arbitrário, e mais interessantes são os nomes dos arquivos gerados pela regra, e isso é verdade para as regras gerais. 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
pela compilação.
Esse gráfico acíclico direcionado sobre destinos é chamado de gráfico de destino ou gráfico de dependência do build e é o domínio em que a ferramenta de consulta Bazel opera.
Destinos | Arquivos BUILD |