O Bazel cria o software com base no código-fonte organizado em uma árvore de diretórios chamada
espaço de trabalho. Os arquivos de origem no espaço de trabalho são organizados em uma hierarquia aninhada de
pacotes. 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.
Espaço de trabalho
Um espaço de trabalho é uma árvore de diretórios no seu 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.
Diretórios contendo um arquivo chamado WORKSPACE
são considerados a raiz de um
espaço de trabalho. Portanto, o Bazel ignora todas as árvores de diretório em um espaço de trabalho com acesso root em um subdiretório que contém um arquivo WORKSPACE
, porque elas formam outro espaço de trabalho.
Ele também oferece suporte ao 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 de 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 de espaço de trabalho incluídas no Bazel estão documentadas na seção Regras do espaço de trabalho na Enciclopédia de criação e na documentação sobre regras de repositório do Starlark incorporadas.
Como os repositórios externos também são repositórios, eles geralmente contêm um
arquivo WORKSPACE
. No entanto, esses outros arquivos WORKSPACE
são
ignorados pelo Bazel. Em particular, os repositórios que dependem transitivamente não são adicionados automaticamente.
Pacotes
A unidade principal de organização do código em um repositório é o pacote (link em inglês). 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 BUILD
chamado BUILD
ou BUILD.bazel
. Um
pacote inclui todos os arquivos no diretório dele, além de todos os subdiretórios abaixo dele,
exceto os que contêm um arquivo BUILD
. A partir dessa 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
. Observe que 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 das segmentações é de dois tipos principais: arquivos e regras.
Os arquivos são divididos em dois tipos. Os arquivos de origem geralmente são gravados por pessoas e verificados no repositório. Os arquivos gerados, às vezes chamados de arquivos derivados ou de saída, não são verificados, mas são gerados a partir de arquivos de origem.
O segundo tipo de meta é declarado com uma regra. Cada instância de regra especifica o relacionamento entre um conjunto 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 saídas de outras regras.
Se a entrada para uma regra é um arquivo de origem ou um arquivo gerado, na maioria dos casos, o que importa é apenas o conteúdo desse arquivo. Esse fato 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. Nenhuma alteração é necessária para os consumidores desse arquivo. Por outro lado, um arquivo gerado pode ser facilmente substituído por um arquivo de origem apenas com mudanças locais.
As entradas de uma regra também podem incluir outras regras. O significado exato dessas relações geralmente é bastante complexo e depende da linguagem ou da regra, mas de maneira intuitiva é 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 principais 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 ambiente 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 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 são conjuntos de pacotes que têm a finalidade de limitar 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 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
.