O Bazel cria software com base em código-fonte organizado em uma árvore de diretórios chamada de
espaço de trabalho. Os arquivos de origem no espaço de trabalho são organizados em uma hierarquia aninhada de
pacotes, em que cada pacote é um diretório que contém um conjunto de arquivos de origem
relacionados e um arquivo BUILD
. O arquivo BUILD
especifica quais saídas de software
podem ser criadas com base na origem.
Espaço de trabalho
Um espaço de trabalho é uma árvore de diretórios no sistema de arquivos que contém os arquivos
de origem do software que você quer criar. Cada espaço de trabalho tem um arquivo de texto chamado
WORKSPACE
, que pode estar vazio ou conter referências a dependências
externas necessárias para criar as saídas.
Os diretórios que contêm um arquivo chamado WORKSPACE
são considerados a raiz de um
espaço de trabalho. Portanto, o Bazel ignora as árvores de diretórios em um espaço de trabalho com raiz em um subdiretório que contém um arquivo WORKSPACE
, já que eles formam outro espaço de trabalho.
O Bazel também aceita o arquivo WORKSPACE.bazel
como um alias do arquivo WORKSPACE
. Se os dois arquivos existirem, WORKSPACE.bazel
será usado.
Repositórios
O código é organizado em repositórios. O diretório que contém o arquivo WORKSPACE
é a raiz do repositório principal, também chamado de @
. Outros repositórios (externos) são definidos no arquivo WORKSPACE
usando regras do espaço de trabalho ou gerados de módulos e extensões no sistema Bzlmod. Consulte a visão geral das dependências externas para mais informações.
As regras do espaço de trabalho agrupadas com o Bazel estão documentadas na seção Regras do espaço de trabalho da Enciclopédia de build e na documentação sobre regras de repositório Starlark incorporadas.
Como os repositórios externos são repositórios, eles geralmente contêm um arquivo WORKSPACE
também. No entanto, esses arquivos WORKSPACE
extras são ignorados pelo Bazel. Em particular, os repositórios de que dependem transitivamente não são adicionados automaticamente.
Pacotes
A principal unidade de organização de código em um repositório é o pacote. Um pacote é uma coleção de arquivos relacionados e uma especificação de como eles podem ser usados para produzir artefatos de saída.
Um pacote é definido como um diretório que contém um arquivo chamado BUILD
(ou
BUILD.bazel
). Ele inclui todos os arquivos no diretório, além de todos os
subdiretórios abaixo dele, exceto aqueles que contêm um arquivo BUILD
.
Com base nessa definição, nenhum arquivo ou diretório pode fazer parte de dois pacotes diferentes.
Por exemplo, na árvore de diretórios a seguir, há dois pacotes, my/app
e o subpacote my/app/tests
. my/app/data
não é um pacote, mas um diretório pertencente ao pacote my/app
.
src/my/app/BUILD
src/my/app/app.cc
src/my/app/data/input.txt
src/my/app/tests/BUILD
src/my/app/tests/test.cc
Destinos
Um pacote é um contêiner de destinos, que são definidos no arquivo
BUILD
do pacote. A maioria dos destinos é de um dos dois tipos principais: arquivos e regras.
Os arquivos são divididos em dois tipos. Os arquivos de origem geralmente são escritos por pessoas e armazenados no repositório. Arquivos gerados, às vezes chamados de arquivos derivados ou de saída, não são verificados, mas são gerados de arquivos de origem.
O segundo tipo de segmentação é declarado com uma regra. Cada instância de regra especifica a relação entre um conjunto de arquivos de entrada e um conjunto de arquivos de saída. As entradas de uma regra podem ser arquivos de origem, mas também podem ser as saídas de outras regras.
Na maioria dos casos, não importa se a entrada de uma regra é um arquivo de origem ou um arquivo gerado. O que importa é apenas o conteúdo desse arquivo. Isso facilita a substituição de um arquivo de origem complexo por um arquivo gerado por uma regra, como acontece quando o trabalho de manter manualmente um arquivo altamente estruturado se torna muito cansativo e alguém escreve um programa para derivá-lo. Não é necessário fazer mudanças nos consumidores desse arquivo. Por outro lado, um arquivo gerado pode ser facilmente substituído por um arquivo de origem com apenas mudanças locais.
As entradas de uma regra também podem incluir outras regras. O significado preciso dessas relações costuma ser bastante complexo e dependente de linguagem ou regra, mas intuitivamente é simples: uma regra A de biblioteca C++ pode ter outra regra B de biblioteca C++ para uma entrada. O efeito dessa dependência é que os arquivos de cabeçalho de B ficam disponíveis para A durante a compilação, os símbolos de B ficam disponíveis para A durante a vinculação, e os dados de tempo de execução de B ficam disponíveis para A durante a execução.
Uma invariante de todas as regras é que os arquivos gerados por uma regra sempre pertencem ao mesmo pacote da regra. Não é possível gerar arquivos em outro pacote. No entanto, não é incomum que as entradas de uma regra venham de outro pacote.
Os grupos de pacotes são conjuntos de pacotes que limitam a acessibilidade de
determinadas regras. Os grupos de pacotes são definidos pela função package_group
. Eles têm três propriedades: a lista de pacotes que contêm, o nome e outros grupos de pacotes que incluem. As únicas maneiras permitidas de se referir a eles são pelo atributo visibility
das regras ou pelo atributo default_visibility
da função package
. Eles não geram nem consomem arquivos. Para mais
informações, consulte a documentação
package_group
.