O Bazel cria softwares a partir do código-fonte organizado em árvores de diretórios chamadas
de repositórios. Um conjunto definido de repositórios compõe o espaço de trabalho. Os arquivos
de origem em repositórios 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 a partir
da origem.
Repositórios
Os arquivos de origem usados em um build do Bazel são organizados em repositórios (muitas vezes
abreviados para repos). Um repositório é uma árvore de diretórios com um arquivo de marcador de limite na
raiz. Esse arquivo pode ser MODULE.bazel
, REPO.bazel
ou, em contextos legados, WORKSPACE
ou WORKSPACE.bazel
.
O repositório em que o comando atual do Bazel está sendo executado é chamado de repositório principal. Outros repos (externos) são definidos por regras de repos. Consulte Visão geral das dependências externas para mais informações.
Espaço de trabalho
Um espaço de trabalho é o ambiente compartilhado por todos os comandos do Bazel executados no mesmo repositório principal. Ele abrange o repositório principal e o conjunto de todos os repositórios externos definidos.
Historicamente, os conceitos de "repositório" e "espaço de trabalho" foram confundidos. O termo "espaço de trabalho" foi usado com frequência para se referir ao repositório principal e, às vezes, até como sinônimo de "repositório".
Pacotes
A unidade principal de organização de código em um repositório é o pacote. Um pacote é um conjunto 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 BUILD
chamado BUILD
ou BUILD.bazel
. Um
pacote 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 que pertence 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 alvos, que são definidos no arquivo
BUILD
do pacote. A maioria dos destinos é de 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 enviados para o repositório. Os arquivos gerados, às vezes chamados de arquivos derivados ou de saída, não são enviados, mas são gerados a partir 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 entradas 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 fardo de manter manualmente um arquivo altamente estruturado se torna muito cansativo e alguém escreve um programa para extrair esse arquivo. Não é necessário fazer nenhuma mudança nos consumidores desse arquivo. Por outro lado, um arquivo gerado pode ser facilmente substituído por um arquivo de origem com apenas alterações locais.
As entradas de uma regra também podem incluir outras regras. O significado preciso dessas relacionamentos geralmente é bastante complexo e depende da linguagem ou da regra, mas intuitivamente é simples: uma regra de biblioteca A do C++ pode ter outra regra de biblioteca B do C++ para uma entrada. O efeito dessa dependência é que os arquivos de cabeçalho de B estão disponíveis para A durante a compilação, os símbolos de B estão disponíveis para A durante a vinculação e os dados de execução de B estão 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 que a própria 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 com o objetivo de limitar a acessibilidade de
certas regras. Os grupos de pacotes são definidos pela função package_group
. Elas
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 elas são pelo
atributo visibility
das regras ou pelo atributo default_visibility
da
função package
. Elas não geram nem consomem arquivos. Para mais
informações, consulte a documentação
package_group
.