Guia de estilo do arquivo .bzl

Informar um problema Mostrar fonte Por noite · 7,4 do Google. 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Esta página aborda as diretrizes de estilo básicas do Starlark e também inclui informações sobre macros e regras.

O Starlark é uma linguagem que define como o software é criado e, como tal, é uma linguagem de programação e de configuração.

Você vai usar o Starlark para escrever arquivos BUILD, macros e regras de build. Macros e são essencialmente metalinguagens. Elas definem como os arquivos BUILD são escritos. Os arquivos BUILD são simples e repetitivos.

Todo software é lido com mais frequência do que escrito. Isso é especialmente verdadeiro para o Starlark, já que os engenheiros leem arquivos BUILD para entender as dependências dos alvos e os detalhes dos builds. Essa leitura geralmente acontece rapidamente, com pressa ou em paralelo a outra tarefa. Consequentemente, simplicidade e legibilidade são muito importantes para que os usuários possam analisar e compreender arquivos BUILD rapidamente.

Quando um usuário abre um arquivo BUILD, ele quer saber rapidamente a lista de destinos no arquivo, revisar a lista de origens da biblioteca C++ ou remover uma dependência desse binário Java. Cada vez que você adiciona uma camada de abstração, dificultam a realização dessas tarefas por parte do usuário.

Os arquivos BUILD também são analisados e atualizados por muitas ferramentas diferentes. As ferramentas podem não conseguir editar o arquivo BUILD se ele usar abstrações. A BUILD vai ser mantida arquivos simples permitirão ferramentas melhores. À medida que a base de código cresce, ela se torna cada vez mais frequente fazer alterações em muitos arquivos BUILD, a fim de atualizar uma biblioteca ou fazer uma limpeza.

Recomendações gerais

Estilo

Estilo Python

Em caso de dúvida, siga o guia de estilo PEP 8 sempre que possível. Em particular, use quatro espaços em vez de dois para o recuo para seguir a convenção do Python.

Como o Starlark não é Python, alguns aspectos do estilo Python não se aplicam. Por exemplo, a PEP 8 recomenda que as comparações com Singletons sejam feitas com is, que não é um operador em Starlark.

String de documento

Documente arquivos e funções usando docstrings. Use um docstring na parte superior de cada arquivo .bzl e um docstring para cada arquivo público. função.

Documentar regras e aspectos

As regras e os aspectos, junto com os atributos, bem como os provedores e os campos, precisam ser documentados usando o argumento doc.

Convenção de nomenclatura

  • As variáveis e os nomes de funções usam letras minúsculas com palavras separadas por sublinhados ([a-z][a-z0-9_]*), como cc_library.
  • Os valores privados de nível superior começam com um sublinhado. O Bazel exige que valores privados não possam ser usados em outros arquivos. As variáveis locais não podem usar o prefixo de sublinhado.

Comprimento da linha

Assim como nos arquivos BUILD, não há um limite estrito de comprimento de linha, já que os rótulos podem ser longos. Quando possível, tente usar no máximo 79 caracteres por linha (seguindo guia de estilo, PEP 8). Essa diretriz não deve ser aplicada de forma rígida: os editores devem mostrar mais de 80 colunas, as mudanças automáticas vão introduzir linhas mais longas com frequência, e as pessoas não devem gastar tempo dividindo linhas que já são legíveis.

Argumentos de palavra-chave

Em argumentos de palavra-chave, é preferível usar espaços em torno do sinal de igual:

def fct(name, srcs):
    filtered_srcs = my_filter(source = srcs)
    native.cc_library(
        name = name,
        srcs = filtered_srcs,
        testonly = True,
    )

Valores booleanos

Prefira os valores True e False (em vez de 1 e 0) para valores booleanos, como ao usar um atributo booleano em uma regra.

Não use a função print() no código de produção. ele é destinado apenas a depuração e vai enviar spam para todos os usuários diretos e indiretos de seu arquivo .bzl. O A única exceção é que você pode enviar um código que use print() se ele estiver desativado por padrão e só podem ser ativados ao editar a fonte. Por exemplo, se todos os usos de print() são protegidos por if DEBUG:, em que DEBUG é fixado no código para False. Saiba se essas declarações são úteis o suficiente para justificar o impacto na legibilidade.

Macros

Uma macro é uma função que instancia uma ou mais regras durante o carregamento fase de testes. Em geral, use regras sempre que possível em vez de macros. O build gráfico visto pelo usuário não é o mesmo usado pelo Bazel durante a build: as macros são expandidas antes de o Bazel fazer qualquer análise de gráfico de build.

Por isso, quando algo dá errado, o usuário precisa entender a implementação da macro para resolver problemas de build. Além disso, os resultados de bazel query podem ser difíceis de interpretar porque as metas mostradas nos resultados vêm da expansão de macros. Por fim, os aspectos não reconhecem as macros, então as ferramentas dependendo de aspectos (IDEs e outros), pode falhar.

Um uso seguro das macros é definir destinos adicionais para serem referenciados diretamente na CLI do Bazel ou nos arquivos BUILD: nesse caso, apenas o Os usuários finais desses destinos precisam conhecê-los e quaisquer problemas de compilação. introduzidos por macros nunca estão longe de seu uso.

Para macros que definem destinos gerados (detalhes de implementação da macro que não devem ser referenciados na CLI ou depender de destinos não instanciados por essa macro), siga estas práticas recomendadas:

  • Uma macro precisa usar um argumento name e definir um destino com esse nome. Esse destino se torna o destino principal da macro.
  • Os destinos gerados, ou seja, todos os outros destinos definidos por uma macro, precisam:
    • Ter o nome prefixado por <name> ou _<name>. Por exemplo, usar name = '%s_bar' % (name):
    • Ter visibilidade restrita (//visibility:private);
    • Tenha uma tag manual para evitar a expansão em destinos com caracteres curinga (:all, ..., :* etc.).
  • O name só deve ser usado para derivar nomes de destinos definidos pela macro, e não para qualquer outra coisa. Por exemplo, não use o nome para derivar uma dependência ou um arquivo de entrada que não seja gerado pela própria macro.
  • Todos os destinos criados na macro devem ser acoplados de alguma forma ao alvo principal.
  • Mantenha a consistência dos nomes dos parâmetros na macro. Se um parâmetro for passado como um valor de atributo para o destino principal, mantenha seu nome igual. Se uma macro tem a mesma finalidade de um atributo de regra comum, como deps, nome que você usaria para o atributo (veja abaixo).
  • Ao chamar uma macro, use apenas argumentos de palavra-chave. Isso é consistente com as regras e melhora muito a legibilidade.

Os engenheiros geralmente escrevem macros quando a API Starlark de regras relevantes é insuficientes para o caso de uso específico, independentemente de a regra ser definidos no Bazel em código nativo ou no Starlark. Se você estiver enfrentando esse problema, pergunte ao autor da regra se ele pode estender a API para alcançar suas metas.

Como regra geral, quanto mais macros se assemelham às regras, melhor.

Consulte também macros.

Regras

  • Regras, aspectos e seus atributos devem usar nomes em minúsculas ("snake", em inglês) caso).
  • Os nomes de regras são substantivos que descrevem o tipo principal de artefato produzido pela regra, do ponto de vista das dependências dela (ou, no caso de regras de folha, do usuário). Não é necessariamente um sufixo de arquivo. Por exemplo, uma regra que produz artefatos C++ para serem usados, já que extensões Python podem ser chamadas py_extension: Para a maioria das linguagens, as regras típicas incluem:
    • *_library: uma unidade de compilação ou "módulo".
    • *_binary: um destino que produz um executável ou uma unidade de implantação.
    • *_test: um destino de teste. Isso pode incluir vários testes. Espere todos em um destino *_test como variações do mesmo tema, para por exemplo, testar uma única biblioteca.
    • *_import: um destino que encapsula um artefato pré-compilado, como um .jar ou um .dll usado durante a compilação.
  • Use nomes e tipos consistentes para os atributos. Algumas configurações incluem:
    • srcs: label_list, permitindo arquivos: arquivos de origem, normalmente de autoria humana.
    • deps: label_list, normalmente não permite arquivos: compilação dependências.
    • data: label_list, permitindo arquivos: arquivos de dados, como dados de teste etc.
    • runtime_deps: label_list: dependências de tempo de execução que não são necessárias para a compilação.
  • Para atributos com comportamento não óbvio (por exemplo, modelos de string) com substituições especiais ou ferramentas que são invocadas com comandos requisitos), forneça a documentação usando o argumento de palavra-chave doc para o declaração do atributo (attr.label_list() ou similar).
  • As funções de implementação de regras devem ser quase sempre funções privadas (nomeado com um sublinhado no início). Um estilo comum é dar função de implementação de myrule com o nome _myrule_impl.
  • Transmita informações entre suas regras usando uma interface de provedor bem definida. Declarar e documentar o provedor campos.
  • Crie sua regra com a extensibilidade em mente. Considere que outras regras podem interagir com a regra, acessar os provedores e reutilizar os e as ações criadas por você.
  • Siga as diretrizes de desempenho nas suas regras.