Um rótulo é um identificador de uma meta. 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 de @
duplo significa que este é um nome de repositório canônico, que é exclusivo no espaço de trabalho. Os rótulos com nomes canônicos de repositórios identificam um destino de forma inequívoca, não importa em qual contexto eles apareçam.
Muitas vezes, o nome canônico do repositório é uma string arcana que se parece com
@@rules_java++toolchains+local_jdk
. O que é muito mais comum são
rótulos com um nome de repositório aparente,
que se parece com isto:
@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 dependendo do contexto em que esse rótulo aparece.
No caso típico em que um rótulo se refere ao mesmo repositório de onde
ele é usado, a parte do nome do repositório pode ser omitida. Então, 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 totalmente qualificado do pacote @@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)
podem ser omitidos. Portanto, dentro de @@myrepo//my/app/main
,
esse rótulo pode ser escrito de uma destas maneiras:
app_binary
:app_binary
Por convenção, o dois-pontos é omitido para arquivos, mas mantido para regras, mas não é significativo de outra forma.
A parte do rótulo após os dois pontos, app_binary
, é o nome de destino não qualificado. Quando ele corresponde ao último componente do caminho do pacote, ele e os dois-pontos podem ser omitidos. Portanto, estes 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. Mas, quando o Bazel
espera um pacote (por exemplo, em especificações de 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 todas as metas em um pacote, o que não acontece. Lembre-se de que ele é equivalente a //my/app:app
, então 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 é recomendado na especificação de um package_group
ou em arquivos .bzl
, porque comunica claramente que o nome do pacote é absoluto e está 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 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
arquivo BUILD
), o último pacote vai conter um arquivo chamado testdepot.zip
. Confira
duas maneiras (uma errada e outra certa) 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 vai 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 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 lexical de um rótulo
A sintaxe de rótulos desencoraja o uso de metacaracteres que têm um significado especial para o shell. Isso ajuda a evitar problemas de inclusão de aspas 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 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 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 arquivo precisam ser nomes de caminhos relativos na forma normal, o que significa que 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. Principalmente 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 um 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 algumas regras precisa corresponder ao arquivo de origem principal, que pode estar 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
dele,
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 as letras minúsculas de
a
az
, as letras maiúsculas deA
aZ
, os dígitos de0
a9
, os caracteres! \"#$%&'()*+,-.;<=>?@[]^_`{|}
(sim, há um espaço aí!) e, claro, a barra/
(já que é o separador de diretório). - Os nomes de 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 de pacotes não podem conter a substring
/./
,/../
,/.../
etc. Essa restriçã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.
Na prática:
- 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 inicial e evite caracteres especiais, principalmente 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 chamados de classe de regra), que produzem executáveis e bibliotecas compilados, executáveis de teste e outras saídas compatíveis, conforme descrito na Build Encyclopedia.
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, bem como a importância e a semântica de cada atributo, são uma função do tipo da regra. Consulte a Build Encyclopedia para ver 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) para valores opcionais e tipados.
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, o que é verdade 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 dirigido 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.
Metas | Arquivos BUILD |