As seções anteriores descreveram pacotes, destinos, rótulos e o gráfico de dependência de build de forma abstrata. Nesta seção, descrevemos a sintaxe concreta usada para definir um pacote.
Por definição, cada pacote contém um arquivo BUILD
, que é um programa
curto. Os arquivos BUILD
são avaliados usando uma linguagem imperativa,
Starlark.
Elas são interpretadas como uma lista sequencial de instruções.
Em geral, a ordem é importante: por exemplo, as variáveis precisam ser definidas antes de serem
usadas. 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
importante é quais regras foram declaradas e com quais valores até a
conclusão da avaliação do pacote de tempo.
Quando uma função de regra de build, como cc_library
, é executada, ela cria um
novo destino 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 limpa entre código e dados, os arquivos BUILD
não podem
conter definições de função, instruções for
ou instruções if
(mas as compreensões de
lista e expressões if
são permitidas). 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.
É crucial que os programas em Starlark não realizem 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 os builds sejam reproduzíveis.
Para mais detalhes, consulte Hermética.
Arquivos BUILD
precisam ser escritos usando apenas caracteres ASCII, embora
tecnicamente eles sejam interpretados usando o conjunto de caracteres Latin-1.
Como os arquivos BUILD
precisam ser atualizados sempre que as dependências do
código subjacente mudam, eles normalmente são mantidos por várias pessoas em uma
equipe. Os autores de arquivos BUILD
precisam comentar livremente para documentar o papel
de cada destino de build, sendo destinado ou não ao uso público, e para
documentar o papel do próprio pacote.
Como 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. Ele 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. Eles 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 vai ser resolvido em relação ao
pacote (não ao 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, você pode 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.
É possível usar a visibilidade de carregamento 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
idioma. Por exemplo, cc_binary
, cc_library
e cc_test
são as regras de criação para binários, bibliotecas e testes 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 (em inglês), mas é possível
que qualquer pessoa crie novas regras.
As regras
*_binary
criam programas executáveis em determinada linguagem. Após um build, o executável residirá na árvore de saída binária da ferramenta de build no nome correspondente para o rótulo da regra. Portanto,//my:program
apareceria em$(BINDIR)/my/program
, por exemplo.Em algumas linguagens, essas regras também criam um diretório runfiles contendo 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 único local para facilitar a implantação na produção.As regras
*_test
são uma especialização de uma regra*_binary
, usada para testes automatizados. Os testes são simplesmente programas que retornam zero em caso de sucesso.Assim como os binários, os testes também têm árvores de arquivos de execução, e os arquivos abaixo deles são os únicos que um teste pode legitimamente abrir no momento da 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 a 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. A não observação da regra vai causar uma falha no teste quando executado em um host de teste remoto.As regras
*_library
especificam módulos compilados separadamente na linguagem de programação fornecida. As bibliotecas podem depender de outras, e os binários e testes podem depender de bibliotecas, com o comportamento de compilação separada esperado.
Identificadores | Dependências |