Definições comuns

Informar um problema Ver código-fonte Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Nesta seção, definimos vários termos e conceitos comuns a muitas funções ou regras de compilação.

Conteúdo

Tokenização do shell Bourne

Alguns atributos de string de algumas regras são divididos em várias palavras de acordo com as regras de tokenização do shell Bourne: espaços sem aspas delimitam palavras separadas, e caracteres de aspas simples e duplas e barras invertidas são usados para evitar a tokenização.

Os atributos sujeitos a essa tokenização são indicados explicitamente como tais nas definições deste documento.

Atributos sujeitos à expansão de variáveis "Make" e à tokenização do shell Bourne são normalmente usados para transmitir opções arbitrárias a compiladores e outras ferramentas. Exemplos desses atributos são cc_library.copts e java_library.javacopts. Juntas, essas substituições permitem que uma variável de string seja expandida para uma lista de palavras de opção específica da configuração.

Expansão de rótulos

Alguns atributos de string de poucas regras estão sujeitos à expansão de rótulos: se essas strings contêm um rótulo válido como uma substring, como //mypkg:target, e esse rótulo é um pré-requisito declarado da regra atual, ele é expandido para o caminho do arquivo representado pelo target //mypkg:target.

Exemplos de atributos incluem genrule.cmd e cc_binary.linkopts. Os detalhes podem variar significativamente em cada caso, em questões como: se os rótulos relativos são expandidos; como os rótulos que se expandem para vários arquivos são tratados etc. Consulte a documentação do atributo de regra para detalhes.

Atributos típicos definidos pela maioria das regras de build

Esta seção descreve os atributos que são definidos por muitas regras de build, mas não por todas.

Atributo Descrição
data

Lista de rótulos; o padrão é []

Arquivos necessários para essa regra no momento da execução. Pode listar destinos de arquivos ou regras. Geralmente, permite qualquer destino.

As saídas padrão e os runfiles de destino no atributo data precisam aparecer na área *.runfiles de qualquer executável que seja saída por ou tenha uma dependência de execução nesse destino. Isso pode incluir arquivos de dados ou binários usados quando o srcs do destino é executado. Consulte a seção dependências de dados para mais informações sobre como depender e usar arquivos de dados.

As novas regras precisam definir um atributo data se processarem entradas que possam usar outras entradas no momento da execução. As funções de implementação das regras também precisam preencher os runfiles do destino com as saídas e os runfiles de qualquer atributo data, bem como os runfiles de qualquer atributo de dependência que forneça código-fonte ou dependências de execução.

deps

Lista de rótulos. O padrão é [].

Dependencias para esse destino. Em geral, deve listar apenas destinos de regras. Embora algumas regras permitam que os arquivos sejam listados diretamente em deps, isso deve ser evitado sempre que possível.

As regras específicas de idioma geralmente limitam os destinos listados a aqueles com provedores específicos.

A semântica precisa do que significa um destino depender de outro usando deps é específica para o tipo de regra, e a documentação específica da regra é mais detalhada. Para regras que processam o código-fonte, deps geralmente especifica as dependências usadas pelo código em srcs.

Na maioria das vezes, uma dependência deps é usada para permitir que um módulo use símbolos definidos em outro módulo escrito na mesma linguagem de programação e compilados separadamente. As dependências entre idiomas também são permitidas em muitos casos. Por exemplo, um destino java_library pode depender de um código C++ em um destino cc_library, listando o último no atributo deps. Consulte a definição de dependências para ver mais informações.

licenses

Lista de strings; não configurável; o padrão é ["none"]

Uma lista de strings de tipo de licença a serem usadas para esse destino específico. Isso faz parte de uma API de licenciamento descontinuada que o Bazel não usa mais. Não use isso.

srcs

Lista de rótulos; o padrão é []

Arquivos processados ou incluídos por essa regra. Geralmente, lista arquivos diretamente, mas pode listar destinos de regras (como filegroup ou genrule) para incluir as saídas padrão.

Regras específicas de linguagem geralmente exigem que os arquivos listados tenham extensões de arquivo específicas.

Atributos comuns a todas as regras de build

Esta seção descreve os atributos que são implicitamente adicionados a todas as regras de build.

Atributo Descrição
compatible_with

Lista de rótulos; não configurável; o padrão é []

A lista de ambientes para os quais esse destino pode ser criado, além dos ambientes com suporte padrão.

Isso faz parte do sistema de restrição do Bazel, que permite que os usuários declarem quais alvos podem e não podem depender uns dos outros. Por exemplo, os binários implantáveis externamente não podem depender de bibliotecas com código secreto da empresa. Consulte ConstraintSemantics para mais detalhes.

deprecation

String; não configurável; o padrão é None

Uma mensagem de aviso explicativa associada a esse destino. Normalmente, isso é usado para notificar os usuários de que um destino se tornou obsoleto ou foi substituído por outra regra, é particular a um pacote ou talvez seja considerado nocivo por algum motivo. É uma boa ideia incluir algumas referências (como uma página da Web, um número de bug ou exemplo de CLs de migração) para que seja possível descobrir facilmente quais alterações são necessárias para evitar a mensagem. Se houver um novo destino que possa ser usado como substituição, é recomendado migrar todos os usuários do destino antigo.

Esse atributo não afeta a maneira como as coisas são criadas, mas pode afetar a saída de diagnóstico de uma ferramenta de build. A ferramenta de build emite um aviso quando uma regra com um atributo deprecation depende de um destino em outro pacote.

As dependências intrapacote estão isentas desse aviso. Por exemplo, a criação de testes de uma regra descontinuada não encontra um aviso.

Se um destino descontinuado depender de outro destino descontinuado, nenhuma mensagem de aviso será emitida.

Depois que as pessoas pararem de usá-lo, o alvo poderá ser removido.

distribs

Lista de strings; não configurável; o padrão é []

Uma lista de strings do método de distribuição a serem usadas para esse destino específico. Isso faz parte de uma API de licenciamento descontinuada que o Bazel não usa mais. Não use isso.

exec_compatible_with

Lista de rótulos; não configurável; o padrão é []

Uma lista de constraint_values que precisa estar presente na plataforma de execução para esse destino. Isso é além de qualquer restrição já definida pelo tipo de regra. As restrições são usadas para restringir a lista de plataformas de execução disponíveis. Para mais detalhes, consulte a descrição da resolução do conjunto de ferramentas.

exec_properties

Dicionário de strings. O padrão é {}.

Um dicionário de strings que será adicionado ao exec_properties de uma plataforma selecionada para esse destino. Consulte exec_properties da regra platform.

Se uma chave estiver presente nas propriedades da plataforma e do nível de destino, o valor será retirado do destino.

features

Lista de strings de atributo; o padrão é []

Um recurso é uma tag de string que pode ser ativada ou desativada em um destino. O significado de um recurso depende da própria regra.

Esse atributo features é combinado com o atributo features do nível pacote. Por exemplo, se os recursos ["a", "b"] estiverem ativados no nível do pacote e o atributo features de um destino contiver ["-a", "c"], os recursos ativados para a regra serão "b" e "c". Confira um exemplo.

restricted_to

Lista de rótulos; não configurável; o padrão é []

É a lista de ambientes para os quais o destino pode ser criado, em vez de ambientes compatíveis por padrão.

Isso faz parte do sistema de restrições do Bazel. Consulte compatible_with para mais detalhes.

tags

Lista de strings; não configurável; o padrão é []

As tags podem ser usadas em qualquer regra. As tags nas regras de teste e test_suite são úteis para categorizar os testes. As tags em destinos que não são de teste são usadas para controlar a execução em sandbox de genrules e ações do Starlark e para análise por humanos e/ou ferramentas externas.

O Bazel modifica o comportamento do código de sandbox quando encontra as seguintes palavras-chave no atributo tags de qualquer teste ou destino genrule ou as chaves de execution_requirements para qualquer ação Starlark.

  • A palavra-chave no-sandbox faz com que a ação ou o teste nunca seja colocado em sandbox. Ela ainda pode ser armazenada em cache ou executada remotamente. Use no-cache ou no-remote para impedir que isso aconteça.
  • A palavra-chave no-cache faz com que a ação ou o teste nunca seja armazenado em cache (remotamente ou localmente)
  • A palavra-chave no-remote-cache faz com que a ação ou o teste nunca seja armazenado em cache remotamente, mas pode ser armazenado em cache localmente e executado remotamente. Observação: para os fins desta tag, o cache em disco é considerado local, enquanto o cache HTTP e gRPC é considerado remoto. Se uma combinação de cache de disco local e cache remoto for usada (cache combinado), ela será tratada como um cache remoto e desativada por completo, a menos que --incompatible_remote_results_ignore_disk seja definido. Nesse caso, os componentes locais serão usados.
  • A palavra-chave no-remote-exec faz com que a ação ou o teste nunca sejam executados remotamente, mas podem ser armazenados em cache remotamente.
  • A palavra-chave no-remote impede que a ação ou o teste seja executado remotamente ou armazenado em cache remotamente. Isso é equivalente a usar no-remote-cache e no-remote-exec.
  • A palavra-chave no-remote-cache-upload desativa a parte de upload do armazenamento em cache remoto de um spawn. Ele não desativa a execução remota.
  • A palavra-chave local impede que a ação ou o teste seja armazenado em cache remotamente, executado remotamente ou executado no sandbox. Para regras e testes de geração, marcar a regra com o atributo local = True tem o mesmo efeito.
  • A palavra-chave requires-network permite acesso à rede externa de dentro do sandbox. Essa tag só tem efeito se o sandboxing estiver ativado.
  • A palavra-chave block-network bloqueia o acesso à rede externa dentro do sandbox. Nesse caso, apenas a comunicação com o localhost é permitida. Essa tag só tem efeito se o sandbox estiver ativado.
  • requires-fakeroot executa o teste ou a ação como uid e gid 0 (ou seja, o usuário raiz). Isso só é compatível com Linux. Essa tag tem precedência sobre a opção de linha de comando --sandbox_fake_username.

As tags em testes geralmente são usadas para anotar o papel de um teste no processo de depuração e lançamento. Normalmente, as tags são mais úteis para testes em C++ e Python, que não têm capacidade de anotação de tempo de execução. O uso de tags e elementos de tamanho oferece flexibilidade na montagem de conjuntos de testes com base na política de check-in da base de código.

O Bazel modifica o comportamento de execução do teste se encontrar as seguintes palavras-chave no atributo tags da regra de teste:

  • exclusive força o teste a ser executado no modo "exclusivo", garantindo que nenhum outro teste seja executado ao mesmo tempo. Esses testes serão executados em série depois que todas as atividades de build e testes não exclusivos forem concluídos. A execução remota é desativada para esses testes porque o Bazel não tem controle sobre o que está sendo executado em uma máquina remota.
  • O exclusive-if-local vai forçar a execução do teste no modo "exclusivo" se ele for executado localmente, mas vai executar o teste em paralelo se ele for executado remotamente.
  • A palavra-chave manual excluirá o destino da expansão de caracteres curinga de padrão de destino (..., :*, :all etc.) e regras test_suite que não listam o teste explicitamente ao calcular o conjunto de destinos de nível superior para criar/executar para os comandos build, test e coverage. Ele não afeta o caractere curinga de destino ou a expansão do conjunto de testes em outros contextos, incluindo o comando query. manual não implica que um destino não seja criado/executado automaticamente por sistemas de build/teste contínuos. Por exemplo, pode ser desejável excluir um destino de bazel test ... porque ele exige flags específicas do Bazel, mas ainda assim ele é incluído em execuções de pré-envio ou testes contínuos configurados corretamente.
  • A palavra-chave external força o teste a ser executado incondicionalmente, independentemente do valor de --cache_test_results.
Consulte Convenções de tags na Enciclopédia de testes para conferir mais convenções sobre tags anexadas a destinos de teste.
target_compatible_with

Lista de rótulos. O padrão é [].

Uma lista de constraint_values que precisam estar presentes na plataforma de destino para que ela seja considerada compatível. Isso é além de qualquer restrição já definida pelo tipo de regra. Se a plataforma de destino não atender a todas as restrições listadas, ela será considerada incompatível. Os destinos incompatíveis são ignorados para build e teste quando o padrão de destino é expandido (por exemplo, //..., :all). Quando especificado explicitamente na linha de comando, destinos incompatíveis fazem com que o Bazel imprima um erro e causem um erro de build ou teste.

Os destinos que dependem transitivamente de destinos incompatíveis são considerados incompatíveis. Eles também são pulados na criação e nos testes.

Uma lista vazia (que é o padrão) significa que o destino é compatível com todas as plataformas.

Todas as regras, exceto as regras do Workspace, são compatíveis com esse atributo. Para algumas regras, esse atributo não tem efeito. Por exemplo, especificar target_compatible_with para um cc_toolchain não é útil.

Consulte a página Plataformas para mais informações sobre saltos de destino incompatíveis.

testonly

Booleano; não configurável; o padrão é False, exceto para destinos de teste e de pacote de teste

Se for True, apenas destinos de teste (como testes) poderão depender desse destino.

Igualmente, uma regra que não é testonly não pode depender de nenhuma regra que seja testonly.

Testes (regras *_test) e conjuntos de testes (regras test_suite) são testonly por padrão.

Esse atributo significa que o destino não pode ser contido em binários lançados para produção.

Como o teste é aplicado no momento de build, não de execução, e se propaga de forma viral pela árvore de dependências, ele precisa ser usado com cuidado. Por exemplo, stubs e falsificações que são úteis para testes de unidade também podem ser úteis para testes de integração envolvendo os mesmos binários que serão lançados para produção e, portanto, provavelmente não podem ser marcados como somente teste. Por outro lado, as regras que são perigosas para vincular, talvez porque elas substituem incondicionalmente o comportamento normal, devem ser marcadas como "teste somente".

toolchains

Lista de rótulos; não configuráveis; o padrão é [].

O conjunto de destinos que podem acessar as variáveis Make desta meta. Esses destinos são instâncias de regras que fornecem TemplateVariableInfo ou destinos especiais para tipos de conjunto de ferramentas criados no Bazel. São elas:

  • @bazel_tools//tools/cpp:current_cc_toolchain
  • @bazel_tools//tools/jdk:current_java_runtime

Isso é diferente do conceito de resolução de cadeia de ferramentas usado por implementações de regras para configuração dependente da plataforma. Não é possível usar esse atributo para determinar qual cc_toolchain ou java_toolchain específico um destino vai usar.

visibility

Lista de rótulos; não configuráveis; o padrão é default_visibility do pacote, se especificado, ou "//visibility:private" caso contrário

O atributo visibility em um destino controla se ele pode ser usado em outros pacotes. Consulte a documentação sobre visibilidade.

Atributos comuns a todas as regras de teste (*_test)

Esta seção descreve os atributos comuns a todas as regras de teste.

Atributo Descrição
args

Lista de strings; sujeita à substituição de $(location) e "Make variables" e à tokenização de shell Bourne. O padrão é [].

Argumentos de linha de comando que o Bazel transmite para o destino quando é executado com bazel test.

Esses argumentos são transmitidos antes de qualquer valor --test_arg especificado na linha de comando bazel test.

env

Dicionário de strings. Os valores estão sujeitos à substituição de $(location) e "Make variable". O padrão é [].

Especifica outras variáveis de ambiente a serem definidas quando o teste é executado por bazel test.

Esse atributo se aplica apenas a regras nativas, como cc_test, py_test e sh_test. Ele não se aplica a regras de teste definidas pelo Starlark. Para suas próprias regras do Starlark, adicione um atributo "env" e use-o para preencher um TestEnvironment (link em inglês).

env_inherit

Lista de strings. O padrão é [].

Especifica outras variáveis de ambiente para herdar do ambiente externo quando o teste é executado por bazel test.

Esse atributo se aplica apenas a regras nativas, como cc_test, py_test e sh_test. Ele não se aplica a regras de teste definidas pelo Starlark.

size

String "enormous", "large", "medium" ou "small". Não é possível configurar. O padrão é "medium".

Especifica a "dificuldade" de um destino de teste: quanto tempo/recursos ele precisa para ser executado.

Os testes de unidade são considerados "pequenos", os testes de integração são "médios" e os testes completos são "grandes" ou "enormes". O Bazel usa o tamanho para determinar um tempo limite padrão, que pode ser substituído usando o atributo timeout. O tempo limite é para todos os testes no destino BUILD, não para cada teste individual. Quando o teste é executado localmente, o size também é usado para fins de programação. O Bazel tenta respeitar --local_{ram,cpu}_resources e não sobrecarregar a máquina local executando muitos testes pesados ao mesmo tempo.

Os tamanhos de teste correspondem aos seguintes tempos limite padrão e aos usos de recursos locais de pico presumidos:

Tamanho RAM (em MB) CPU (em núcleos de CPU) Tempo limite padrão
pequeno 20 1 curto (1 minuto)
médio 100 1 moderada (5 minutos)
grande 300 1 longo (15 minutos)
enorme 800 1 eterno (60 minutos)

A variável de ambiente TEST_SIZE será definida como o valor desse atributo ao gerar o teste.

timeout

String "short", "moderate", "long" ou "eternal"; não configurável; o padrão é derivado do atributo size do teste

Tempo de execução esperado do teste antes do retorno.

Embora o atributo de tamanho de um teste controle a estimativa de recursos, o tempo limite dele pode ser definido de forma independente. Se não for especificado explicitamente, o tempo limite será baseado no tamanho do teste. O tempo limite do teste pode ser substituído pela sinalização --test_timeout, por exemplo, para execução sob certas condições que são conhecidas por serem lentas. Os valores de tempo limite do teste correspondem aos seguintes períodos:

Valor de tempo limite Período
short 1 minuto
moderada 5 minutos
long 15 minutos
eterno 60 minutos

Para outros tempos, o tempo limite do teste pode ser substituído com a flag --test_timeout do Bazel, por exemplo, para execução manual em condições que são conhecidas por serem lentas. Os valores de --test_timeout são em segundos. Por exemplo, --test_timeout=120 definirá o tempo limite do teste como dois minutos.

A variável de ambiente TEST_TIMEOUT será definida como o tempo limite do teste (em segundos) ao gerar o teste.

flaky

Booleano; não configurável; o padrão é False.

Marca o teste como instável.

Se definido, executa o teste até três vezes, marcando-o como falha apenas em caso de falha. Por padrão, esse atributo é definido como "False", e o teste é executado apenas uma vez. O uso desse atributo geralmente não é recomendado. Os testes precisam ser confiáveis quando as declarações são mantidas.

shard_count

Número inteiro não negativo menor ou igual a 50. O padrão é -1

Especifica o número de fragmentos paralelos a serem usados para executar o teste.

Se definido, esse valor substituirá qualquer heurística usada para determinar o número de fragmentos paralelos com que executar o teste. Para algumas regras de teste, esse parâmetro pode ser necessário para ativar o sharding. Consulte também --test_sharding_strategy.

Se o sharding de teste estiver ativado, a variável de ambiente TEST_TOTAL_SHARDS será definida como esse valor ao gerar o teste.

A fragmentação exige que o executor de teste ofereça suporte ao protocolo de fragmentação de teste. Caso contrário, provavelmente ele vai executar todos os testes em todos os fragmentos, o que não é o que você quer.

Consulte Test Sharding na Enciclopédia de testes para saber mais detalhes sobre o sharding.

local

Booleano, não configurável. O padrão é False

Força o teste a ser executado localmente, sem sandbox.

Definir esse valor como "True" equivale a fornecer "local" como uma tag (tags=["local"]).

Atributos comuns a todas as regras binárias (*_binary)

Esta seção descreve os atributos comuns a todas as regras binárias.

Atributo Descrição
args

Lista de strings; sujeita a $(location) e "Make variable" substituição e tokenização de shell Bourne; não configurável; o padrão é []

Argumentos de linha de comando que o Bazel passa para o destino quando é executado pelo comando run ou como um teste. Esses argumentos são transmitidos antes dos especificados na linha de comando bazel run ou bazel test.

Observação: os argumentos não são transmitidos quando você executa o destino fora do Bazel (por exemplo, executando manualmente o binário em bazel-bin/).

env

Dicionário de strings. Os valores estão sujeitos à substituição de $(location) e "Make variable". O padrão é {}.

Especifica variáveis de ambiente adicionais a serem definidas quando o destino é executado por bazel run.

Esse atributo se aplica apenas a regras nativas, como cc_binary, py_binary e sh_binary. Ele não se aplica às regras executáveis definidas pelo Starlark.

OBSERVAÇÃO: as variáveis de ambiente não são definidas quando você executa o destino fora do Bazel (por exemplo, executando manualmente o binário em bazel-bin/).

output_licenses

Lista de strings. O padrão é [].

As licenças dos arquivos de saída que esse binário gera. Isso faz parte de uma API de licenciamento descontinuada que o Bazel não usa mais. Não use isso.

Atributos configuráveis

A maioria dos atributos é "configurável", ou seja, os valores deles podem mudar quando o destino é criado de maneiras diferentes. Especificamente, os atributos configuráveis podem variar com base nas flags transmitidas para a linha de comando do Bazel ou em qual dependência downstream está solicitando o destino. Isso pode ser usado, por exemplo, para personalizar o destino para várias plataformas ou modos de compilação.

O exemplo a seguir declara fontes diferentes para diferentes arquiteturas de destino. A execução de bazel build :multiplatform_lib --cpu x86 vai criar o destino usando x86_impl.cc, enquanto a substituição de --cpu arm fará com que ele use arm_impl.cc.

cc_library(
    name = "multiplatform_lib",
    srcs = select({
        ":x86_mode": ["x86_impl.cc"],
        ":arm_mode": ["arm_impl.cc"]
    })
)
config_setting(
    name = "x86_mode",
    values = { "cpu": "x86" }
)
config_setting(
    name = "arm_mode",
    values = { "cpu": "arm" }
)

A função select() escolhe entre diferentes valores alternativos para um atributo configurável com base nos critérios de config_setting ou constraint_value que a configuração do destino atende.

O Bazel avalia os atributos configuráveis após processar macros e antes de processar regras (tecnicamente, entre as fases de carregamento e análise). Qualquer processamento antes da avaliação de select() não sabe qual ramificação o select() escolhe. As macros, por exemplo, não podem mudar o comportamento com base na ramificação escolhida, e o bazel query só pode fazer estimativas conservadoras sobre as dependências configuráveis de um destino. Consulte estas perguntas frequentes para saber mais sobre como usar select() com regras e macros.

Os atributos marcados como nonconfigurable na documentação não podem usar esse recurso. Geralmente, um atributo não é configurável porque o Bazel precisa saber internamente o valor dele antes de determinar como resolver um select().

Consulte Atributos de build configuráveis para conferir uma visão geral detalhada.

Alvos de saída implícitos

As saídas implícitas em C++ foram descontinuadas. Evite usá-lo em outros idiomas, quando possível. Ainda não temos um caminho de descontinuação, mas eles serão descontinuados em algum momento.

Ao definir uma regra de build em um arquivo BUILD, você declara explicitamente um novo destino de regra nomeado em um pacote. Muitas funções de regra de build também implicitamente implicam um ou mais destinos de arquivo de saída, cujo conteúdo e significado são específicos da regra. Por exemplo, ao declarar explicitamente uma regra java_binary(name='foo', ...), você também declara implicitamente um arquivo de saída foo_deploy.jar como membro do mesmo pacote. Esse destino específico é um arquivo Java independente adequado para implantação.

Os destinos de saída implícitos são membros de primeira classe do gráfico de destino global. Assim como outros destinos, eles são criados sob demanda, quando especificados no comando de build de nível superior ou quando são pré-requisitos necessários para outros destinos de build. Elas podem ser referenciadas como dependências em arquivos BUILD e observadas na saída de ferramentas de análise, como bazel query.

Para cada tipo de regra de build, a documentação da regra contém uma seção especial que detalha os nomes e o conteúdo de todas as saídas implícitas envolvidas por uma declaração desse tipo de regra.

Uma distinção importante, mas um tanto sutil, entre os dois namespaces usados pelo sistema de build: os rótulos identificam alvos, que podem ser regras ou arquivos, e os alvos de arquivo podem ser divididos em alvos de arquivo de origem (ou de entrada) e alvos de arquivo derivados (ou de saída). Estas são as coisas que você pode mencionar em arquivos BUILD, criar na linha de comando ou examinar usando bazel query. Esse é o namespace de destino. Cada destino de arquivo corresponde a um arquivo real no disco (o "namespace do sistema de arquivos"). Cada destino de regra pode corresponder a zero, um ou mais arquivos reais no disco. Talvez haja arquivos no disco que não tenham um destino correspondente. Por exemplo, os arquivos de objeto .o produzidos durante a compilação em C++ não podem ser referenciados nos arquivos BUILD ou na linha de comando. Dessa forma, a ferramenta de build pode ocultar certos detalhes de implementação de como ela faz o trabalho dela. Isso é explicado mais detalhadamente na Referência de conceito do BUILD.