As seções anteriores descreveram pacotes, destinos e rótulos, além do gráfico de dependência de build de forma abstrata. Esta seção descreve a sintaxe concreta usada para definir um pacote.
Por definição, todo pacote contém um arquivo BUILD
, que é um programa curto.
Os arquivos BUILD
são avaliados usando uma linguagem imperativa, o Starlark.
Elas são interpretadas como uma lista sequencial de instruções.
Em geral, a ordem é importante: as variáveis precisam ser definidas antes de serem usadas, por exemplo. No entanto, a maioria dos arquivos BUILD
consiste apenas em declarações de regras de build, e a ordem relativa dessas instruções é irrelevante. O que importa é quais regras foram declaradas e com quais valores até a conclusão da avaliação do pacote.
Quando uma função de regra de build, como cc_library
, é executada, ela cria uma
nova meta no gráfico. Esse destino pode ser referenciado mais tarde usando um rótulo.
Em arquivos BUILD
simples, as declarações de regras podem ser reordenadas livremente sem mudar o comportamento.
Para incentivar uma separação clara entre código e dados, os arquivos BUILD
não podem conter definições de função, instruções for
ou if
. No entanto, são permitidas compreensões de lista e expressões if
. As funções podem ser declaradas em arquivos
.bzl
. Além disso, os argumentos *args
e **kwargs
não são permitidos em arquivos BUILD
. Em vez disso, liste todos os argumentos explicitamente.
É importante lembrar que os programas em Starlark não podem realizar E/S arbitrárias. Essa invariante torna a interpretação de arquivos BUILD
hermética, dependente apenas de um conjunto conhecido de entradas, o que é essencial para garantir que as builds sejam reproduzíveis.
Para mais detalhes, consulte Hermeticity.
Como os arquivos BUILD
precisam ser atualizados sempre que as dependências do
código subjacente mudam, eles geralmente são mantidos por várias pessoas em uma
equipe. Os autores de arquivos BUILD
devem comentar livremente para documentar a função de cada destino de build, seja ou não destinado ao uso público, e para documentar a função do próprio pacote.
Carregar uma extensão
As extensões do Bazel são arquivos que terminam em .bzl
. Use a instrução load
para importar
um símbolo de uma extensão.
load("//foo/bar:file.bzl", "some_library")
Esse código carrega o arquivo foo/bar/file.bzl
e adiciona o símbolo some_library
ao ambiente. Isso pode ser usado para carregar novas regras, funções ou constantes (por exemplo, uma string ou uma lista). Vários símbolos podem ser importados usando
argumentos adicionais na chamada para load
. Os argumentos precisam ser literais de string (sem variável), e as instruções load
precisam aparecer no nível superior. Elas não podem estar no corpo de uma função.
O primeiro argumento de load
é um rótulo que identifica um arquivo .bzl
. Se for um rótulo relativo, ele será resolvido em relação ao
pacote (não diretório) que contém o arquivo bzl
atual. Os rótulos relativos em instruções load
precisam usar um :
inicial.
O load
também aceita aliases. Portanto, é possível atribuir nomes diferentes aos símbolos importados.
load("//foo/bar:file.bzl", library_alias = "some_library")
É possível definir vários aliases em uma instrução load
. Além disso, a lista de argumentos pode conter aliases e nomes de símbolos regulares. O exemplo a seguir é perfeitamente legal. Observe quando usar aspas.
load(":my_rules.bzl", "some_rule", nice_alias = "some_other_rule")
Em um arquivo .bzl
, os símbolos que começam com _
não são exportados e não podem ser carregados de outro arquivo.
Use load visibility para restringir
quem pode carregar um arquivo .bzl
.
Tipos de regras de build
A maioria das regras de build vem em famílias, agrupadas por linguagem. Por exemplo, cc_binary
, cc_library
e cc_test
são as regras de build para binários,
bibliotecas e testes em C++, respectivamente. Outras linguagens usam o mesmo
esquema de nomenclatura, com um prefixo diferente, como java_*
para
Java. Algumas dessas funções estão documentadas na Build Encyclopedia, mas qualquer pessoa pode criar novas regras.
As regras
*_binary
criam programas executáveis em uma determinada linguagem. Depois de uma compilação, o executável vai ficar na árvore de saída binária da ferramenta de build com o nome correspondente ao rótulo da regra. Assim,//my:program
apareceria em (por exemplo)$(BINDIR)/my/program
.Em algumas linguagens, essas regras também criam um diretório de runfiles que contém todos os arquivos mencionados em um atributo
data
pertencente à regra ou qualquer regra no fechamento transitivo de dependências. Esse conjunto de arquivos é reunido em um só lugar para facilitar a implantação na produção.As regras
*_test
são uma especialização de uma regra*_binary
, usadas para testes automatizados. Os testes são apenas programas que retornam zero em caso de sucesso.Assim como os binários, os testes também têm árvores de runfiles, e os arquivos abaixo dela são os únicos que um teste pode abrir legitimamente durante a execução. Por exemplo, um programa
cc_test(name='x', data=['//foo:bar'])
pode abrir e ler$TEST_SRCDIR/workspace/foo/bar
durante a execução. Cada linguagem de programação tem sua própria função utilitária para acessar o valor de$TEST_SRCDIR
, mas todas são equivalentes ao uso direto da variável de ambiente. Se a regra não for seguida, o teste vai falhar quando for executado em um host de teste remoto.As regras
*_library
especificam módulos compilados separadamente na linguagem de programação indicada. As bibliotecas podem depender de outras bibliotecas, e os binários e testes podem depender de bibliotecas, com o comportamento esperado de compilação separada.
Rótulos | Dependências |
Codificação de arquivo
Os arquivos BUILD
e .bzl
precisam ser codificados em UTF-8, em que ASCII é um subconjunto válido. Sequências de bytes arbitrárias são permitidas atualmente, mas podem deixar de ser compatíveis no futuro.