Um rótulo é um identificador de um destino. Um rótulo típico em seu formato canônico completo é semelhante a este:
@@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 no
espaço de trabalho. Rótulos com nomes de repositórios canônicos identificam inequivocamente um destino,
independentemente do contexto em que ele aparece.
Geralmente, o nome do repositório canônico é uma string misteriosa parecida com
@@rules_java~7.1.0~toolchains~local_jdk
. O que é muito mais comumente visto 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
de acordo com o contexto em que o 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 do pacote totalmente qualificado
@@myrepo//my/app/main
. Quando o rótulo se refere ao mesmo
pacote em que ele é 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 gravado 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 sejam importantes de outra forma.
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
relativo à 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, 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
, então 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 comunica claramente que o nome do pacote é absoluto e tem como base o diretório de nível superior do espaço de trabalho.
Não é possível usar rótulos relativos para se referir a destinos em outros pacotes. Nesse caso, o identificador do repositório e o nome do pacote precisam ser sempre especificados.
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 o próprio
arquivo BUILD
), o último pacote conterá um arquivo chamado testdepot.zip
. Aqui
estão duas maneiras (uma errada, 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.zip
Os rótulos que começam com @@//
são referências ao repositório
principal, que ainda funcionará 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 nesse repositório e será usado 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 tenham um significado especial para o shell. Isso ajuda a evitar problemas de citação acidental e facilita a construção de ferramentas e scripts que manipulam rótulos, como a linguagem de consulta do Bazel.
Confira abaixo os detalhes exatos 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 relacionado ao diretório que contém
o arquivo BUILD
.
Os nomes de destino precisam ser compostos inteiramente de caracteres retirados do conjunto a
–z
, A
–Z
, 0
–9
e os símbolos de pontuação !%-@^_"#$&'()*-+,;<=>?[]{|}~/.
.
Os nomes dos arquivos precisam ser nomes de caminho relativos no 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ó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 usar
/
nos nomes das regras. Especialmente quando a forma abreviada de um rótulo é
usada, isso 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á situações em que o uso de uma barra é conveniente ou até mesmo 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 pacote: //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 nos nomes de pacotes são as letras minúsculas de
a
az
, as letras maiúsculasA
aZ
, os dígitos de0
a9
, os caracteres! \"#$%&'()*+,-.;<=>?@[]^_`{|}
(sim, há um caractere de espaço ali) e, claro, a barra/
(porque é o separador do diretório). - Os nomes dos pacotes não podem começar nem terminar com uma barra
/
. - Os nomes dos pacotes não podem conter a substring
//
. Isso não faria sentido. Qual seria o caminho do diretório correspondente? - Nomes de pacotes não podem conter a substring
/./
,/../
,/.../
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, 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 significativa 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 no início 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, bem como as etapas para criá-las. As regras podem ser de vários tipos diferentes (às vezes chamadas de classe de regra), que produzem bibliotecas e executáveis compilados, executáveis de teste e outras saídas com suporte, conforme descrito na enciclopédia de builds.
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",
],
)
Toda invocação de regra tem um atributo name
(que precisa ser um
nome de destino válido), que declara um destino dentro do pacote
do arquivo BUILD
.
Cada regra tem um conjunto de atributos. Os atributos aplicáveis a uma determinada regra e a significância e a semântica de cada atributo são uma função do tipo da 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 e lista de rótulos de saída. Nem todos os atributos precisam ser especificados em todas as regras. Assim, os atributos 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 dele, se presente, é uma lista de rótulos. Cada um é 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, o que é verdadeiro para 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 pelo
build.
Esse gráfico acíclico direcionado sobre os 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 Bazel opera.
Metas | Arquivos BUILD |