Rótulos

Informar um problema Acessar fonte

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 az, AZ, 09 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 a z, letras maiúsculas de A a Z, dígitos 0 a 9, 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