A formatação do arquivo BUILD
segue a mesma abordagem do Go, em que uma interface
cuida da maioria dos problemas de formatação.
O Buildifier é uma ferramenta que analisa e
emite o código-fonte em um estilo padrão. Portanto, cada arquivo BUILD
é
formatados da mesma maneira automatizada, o que faz com que a formatação não seja um problema durante
revisões de código. Também torna mais fácil para as ferramentas entender, editar e
gerar arquivos BUILD
.
A formatação do arquivo BUILD
precisa corresponder à saída de buildifier
.
Exemplo de formatação
# Test code implementing the Foo controller.
package(default_testonly = True)
py_test(
name = "foo_test",
srcs = glob(["*.py"]),
data = [
"//data/production/foo:startfoo",
"//foo",
"//third_party/java/jdk:jdk-k8",
],
flaky = True,
deps = [
":check_bar_lib",
":foo_data_check",
":pick_foo_port",
"//pyglib",
"//testing/pybase",
],
)
Estrutura do arquivo
Recomendação: use a seguinte ordem (cada elemento é opcional):
Descrição do pacote (um comentário)
Todas as instruções de
load()
A função
package()
.Chamadas para regras e macros
O buildificador faz distinção entre um comentário independente e um comentário anexada a um elemento. Se um comentário não estiver anexado a um elemento específico, use uma linha vazia depois dele. A distinção é importante ao realizar processos alterações (por exemplo, para manter ou remover um comentário ao excluir uma regra).
# Standalone comment (such as to make a section in a file)
# Comment for the cc_library below
cc_library(name = "cc")
Referências a destinos no pacote atual
Os arquivos devem ser referenciados pelos caminhos em relação ao diretório do pacote.
(sem nunca usar referências crescentes, como ..
). Os arquivos gerados devem ser
com o prefixo ":
" para indicar que eles não são fontes. Arquivos de origem
não pode ter o prefixo :
. As regras precisam ter o prefixo :
. Para
exemplo, supondo que x.cc
seja um arquivo de origem:
cc_library(
name = "lib",
srcs = ["x.cc"],
hdrs = [":gen_header"],
)
genrule(
name = "gen_header",
srcs = [],
outs = ["x.h"],
cmd = "echo 'int x();' > $@",
)
Nomenclatura do destino
Os nomes dos destinos devem ser descritivos. Se um destino tiver um arquivo de origem,
o destino geralmente deve ter um nome derivado dessa origem (por exemplo, um
O cc_library
para chat.cc
pode ser nomeado como chat
ou java_library
para
DirectMessage.java
pode ser chamado de direct_message
).
O destino de mesmo nome de um pacote (o destino com o mesmo nome do que contém o diretório) deve fornecer a funcionalidade descrita pelo do diretório atual. Se não houver uma segmentação desse tipo, não crie uma alvo.
Prefiro usar o nome curto ao se referir a um destino com o mesmo nome (//x
em vez de //x:x
). Se você estiver no mesmo pacote, prefira a versão local
referência (:x
em vez de //x
).
Evite usar "reservado" nomes de destino com um significado especial. Isso inclui
all
, __pkg__
e __subpackages__
, esses nomes têm
semântica e podem causar confusão e comportamentos inesperados quando usados.
Na ausência de uma convenção de equipe predominante, estas são algumas formas não vinculativas Recomendações amplamente usadas no Google:
- Em geral, use "snake_case"
- Para uma
java_library
com umsrc
, isso significa usar um nome que não seja é igual ao nome do arquivo sem a extensão - Para as regras
*_binary
e*_test
do Java, use "CaelCase maiúsculas". Isso permite que o nome do destino corresponda a um dossrc
s. Parajava_test
, isso possibilita que o atributotest_class
seja inferida do nome do destino.
- Para uma
- Se houver diversas variantes de um destino específico, adicione um sufixo
sem ambiguidade (como
:foo_dev
,:foo_prod
ou:bar_x86
,:bar_x64
) - Destinos de sufixo
_test
com_test
,_unittest
,Test
ouTests
- Evite sufixos sem sentido, como
_lib
ou_library
(a menos que seja necessário para evitar conflitos entre um destino_library
e o_binary
correspondente - Para destinos relacionados a proto:
proto_library
destinos precisam ter nomes que terminam em_proto
- As regras
*_proto_library
específicas de idiomas precisam corresponder às proto, mas substitua_proto
por um sufixo específico da linguagem, como:cc_proto_library
:_cc_proto
java_proto_library
:_java_proto
java_lite_proto_library
:_java_proto_lite
Visibilidade
A visibilidade precisa ter o escopo mais definido possível, sem deixar de permitir o acesso
com testes e dependências reversas. Usar __pkg__
e __subpackages__
como
apropriados.
Evite definir o pacote default_visibility
como //visibility:public
.
//visibility:public
deve ser definido individualmente apenas para metas na
API pública do projeto. Podem ser bibliotecas projetadas para depender
por projetos externos ou binários que poderiam ser usados por um
o processo de build.
Dependências
As dependências devem ser restritas a dependências diretas (dependências necessário para as origens listadas na regra). Não liste dependências transitivas.
As dependências do pacote local precisam ser listadas primeiro e referenciadas de forma compatível com Referências a destinos no pacote atual acima (não pelo nome absoluto do pacote).
Prefira listar as dependências diretamente, como uma única lista. Colocar o "comum" dependências de vários destinos em uma variável reduz a capacidade de manutenção, é impossível que as ferramentas mudem as dependências de um alvo dependências não utilizadas.
Globs
Indicar "sem metas" com []
. Não use um glob que não corresponda a nada:
é mais propensa a erros e menos óbvia do que uma lista vazia.
Recursivo
Não use globs recursivos para corresponder a arquivos de origem (por exemplo,
glob(["**/*.java"])
).
Os globs recursivos tornam os arquivos BUILD
difíceis de entender porque eles ignoram
subdiretórios que contêm arquivos BUILD
.
Os globs recursivos geralmente são menos eficientes do que ter um arquivo BUILD
por
com um gráfico de dependência definido entre eles, permitindo um melhor
armazenamento em cache remoto
e paralelismo.
É recomendável criar um arquivo BUILD
em cada diretório e definir um
gráfico de dependência entre eles.
Não recursiva
Em geral, globs não recursivos são aceitáveis.
Outras convenções
Use letras maiúsculas e sublinhados para declarar constantes (como
GLOBAL_CONSTANT
). use minúsculas e sublinhados para declarar variáveis (comomy_variable
).Os rótulos nunca devem ser divididos, mesmo que tenham mais de 79 caracteres. Os rótulos precisam ser literais de string sempre que possível. Justificativa: faz localizar e substituir facilmente. Isso também melhora a legibilidade.
O valor do atributo name deve ser uma string constante literal (exceto em macros). Lógica: as ferramentas externas usam o atributo "name" para se referir a uma regra de firewall. Eles precisam encontrar regras sem ter que interpretar o código.
Ao definir atributos do tipo booleano, use valores booleanos em vez de números inteiros. Por motivos legados, as regras ainda convertem números inteiros em booleanos conforme necessário. mas isso não é recomendado. Justificativa: a expressão
flaky = 1
pode ser interpretada incorretamente "desbotar este destino executando-o novamente uma vez".flaky = True
diz claramente "este teste é instável".
Diferenças com o guia de estilo do Python
Embora a compatibilidade com Guia de estilo do Python é uma meta, há algumas diferenças:
Não há um limite rígido de comprimento de linha. Comentários e strings longos geralmente são divididos 79, mas isso não é obrigatório. Ela não deve ser aplicada no código revisões ou pré-envio de scripts. Lógica: os rótulos podem ser longos e exceder esse ou ao atingir um limite estabelecido. É comum que os arquivos
BUILD
sejam gerados ou editados por ferramentas. o que não funciona bem com um limite de comprimento de linha.A concatenação implícita de strings não é compatível. Use o operador
+
. Lógica: os arquivosBUILD
contêm muitas listas de strings. É fácil esquecer um vírgula, o que leva a um resultado completamente diferente. Isso criou muitos bugs que já assisti. Confira também esta discussão.Use espaços ao redor do sinal
=
para argumentos de palavra-chave nas regras. Justificativa: Argumentos nomeados são muito mais frequentes do que em Python e estão sempre em uma linha separada. Os espaços melhoram a legibilidade. Essa convenção surgiu muito tempo, e não vale a pena modificar todos os arquivosBUILD
já existentes.Por padrão, use aspas duplas para as strings. Justificativa: não é especificada no guia de estilo Python, mas recomenda consistência. Então nós decidiu usar apenas strings entre aspas duplas. Muitos idiomas usam aspas duplas para literais de string.
Use uma única linha em branco entre duas definições de nível superior. Justificativa: a de um arquivo
BUILD
não é como um arquivo Python típico. Ele tem apenas declarações de alto nível. Usar uma única linha em branco torna os arquivosBUILD
mais curtos.