Criar variáveis

Reportar um problema Ver a fonte Nightly · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

As variáveis "Make" são uma classe especial de variáveis de string expansíveis disponíveis para atributos marcados como "Sujeito à substituição da variável 'Make'".

Elas podem ser usadas, por exemplo, para injetar caminhos específicos de conjunto de ferramentas em ações de build criadas pelo usuário.

O Bazel fornece variáveis predefinidas, que estão disponíveis para todos os destinos, e variáveis personalizadas, que são definidas em destinos de dependência e estão disponíveis apenas para destinos que dependem delas.

O motivo do termo "Make" é histórico: a sintaxe e a semântica dessas variáveis foram originalmente criadas para corresponder ao GNU Make.

Usar

Atributos marcados como "Sujeito à substituição da variável "Make"" podem referenciar a variável FOO "Make" da seguinte maneira:

my_attr = "prefix $(FOO) suffix"

Em outras palavras, qualquer substring que corresponda a $(FOO) será expandida para o valor de FOO. Se esse valor for "bar", a string final vai ser:

my_attr = "prefix bar suffix"

Se FOO não corresponder a uma variável conhecida pelo destino de consumo, o Bazel falhará com um erro.

Variáveis "Make" com nomes que são símbolos que não são letras, como @, também podem ser referenciadas usando apenas um cifrão, sem parênteses. Exemplo:

my_attr = "prefix $@ suffix"

Para escrever $ como um literal de string (ou seja, para evitar a expansão da variável), escreva $$.

Variáveis predefinidas

As variáveis "Make" predefinidas podem ser referenciadas por qualquer atributo marcado como "Sujeito à substituição da variável "Make"" em qualquer destino.

Para conferir a lista dessas variáveis e os valores delas para um determinado conjunto de opções de build, execute

bazel info --show_make_env [build options]

e observe as linhas de saída principais com letras maiúsculas.

Confira um exemplo de variáveis predefinidas.

Variáveis de opção da cadeia de ferramentas

Variáveis de caminho

  • BINDIR: a base da árvore binária gerada para a arquitetura de destino.

    Uma árvore diferente pode ser usada para programas executados durante o build na arquitetura do host, para oferecer suporte à compilação cruzada.

    Se você quiser executar uma ferramenta em um genrule, a maneira recomendada de acessar o caminho dela é $(execpath toolname), em que toolname precisa estar listado no atributo tools do genrule.

  • GENDIR: A base da árvore de código gerada para a arquitetura de destino.

Variáveis de arquitetura da máquina

  • TARGET_CPU: a CPU da arquitetura de destino, por exemplo, k8.

Variáveis de genrule predefinidas

As informações a seguir estão disponíveis especialmente para o atributo cmd de genrule e são importantes para que esse atributo funcione.

Confira um exemplo de variáveis de genrule predefinidas.

  • OUTS: a lista outs do genrule. Se você tiver apenas um arquivo de saída, também poderá usar $@.
  • SRCS: a lista srcs do genrule (ou, mais precisamente, os nomes de caminho dos arquivos correspondentes aos rótulos na lista srcs). Se você tiver apenas um arquivo de origem, também poderá usar $<.
  • <: SRCS, se for um único arquivo. Caso contrário, um erro de build é acionado.
  • @: OUTS, se for um único arquivo. Caso contrário, um erro de build é acionado.
  • RULEDIR: o diretório de saída do destino, ou seja, o diretório correspondente ao nome do pacote que contém o destino na árvore genfiles ou bin. Para //my/pkg:my_genrule, isso sempre termina em my/pkg, mesmo que as saídas de //my/pkg:my_genrule estejam em subdiretórios.

  • @D: o diretório de saída. Se outs tiver uma entrada, ela será expandida para o diretório que contém esse arquivo. Se tiver várias entradas, isso será expandido para o diretório raiz do pacote na árvore genfiles, mesmo que todos os arquivos de saída estejam no mesmo subdiretório.

    Observação:use RULEDIR em vez de @D porque RULEDIR tem semântica mais simples e se comporta da mesma maneira independentemente do número de arquivos de saída.

    Se a genrule precisar gerar arquivos intermediários temporários (talvez como resultado do uso de outra ferramenta, como um compilador), ela tentará gravá-los em @D (embora /tmp também possa ser gravado) e removê-los antes de terminar.

    Evite gravar em diretórios que contenham entradas. Eles podem estar em sistemas de arquivos somente leitura. Mesmo que não seja, isso destruiria a árvore de origem.

Variáveis de caminho de origem/saída predefinidas

As variáveis predefinidas execpath, execpaths, rootpath, rootpaths, location e locations usam parâmetros de rótulo (por exemplo, $(execpath //foo:bar)) e substituem os caminhos de arquivo indicados por esse rótulo.

Para arquivos de origem, esse é o caminho relativo à raiz do espaço de trabalho. Para arquivos que são saídas de regras, esse é o caminho de saída do arquivo. Consulte a explicação sobre arquivos de saída abaixo.

Confira um exemplo de variáveis de caminho predefinidas.

  • execpath: denota o caminho abaixo do execroot em que o Bazel executa ações de build.

    No exemplo acima, o Bazel executa todas as ações de build no diretório vinculado pelo link simbólico bazel-myproject na raiz do espaço de trabalho. O arquivo de origem empty.source está vinculado no caminho bazel-myproject/testapp/empty.source. Portanto, o caminho de execução (que é o subcaminho abaixo da raiz) é testapp/empty.source. Esse é o caminho que as ações de build podem usar para encontrar o arquivo.

    Os arquivos de saída são organizados de maneira semelhante, mas também têm o prefixo do subcaminho bazel-out/cpu-compilation_mode/bin (ou para as saídas de ferramentas: bazel-out/cpu-opt-exec-hash/bin). No exemplo acima, //testapp:app é uma ferramenta porque aparece no atributo tools de show_app_output. Portanto, o arquivo de saída app é gravado em bazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app. O caminho de execução é bazel-out/cpu-opt-exec-hash/bin/testapp/app. Esse prefixo extra permite criar o mesmo destino para, digamos, duas CPUs diferentes no mesmo build sem que os resultados se sobreponham.

    O rótulo transmitido para essa variável precisa representar exatamente um arquivo. Para rótulos que representam arquivos de origem, isso é automaticamente verdadeiro. Para rótulos que representam regras, a regra precisa gerar exatamente uma saída. Se esse valor for falso ou o rótulo estiver malformado, o build vai falhar com um erro.

  • rootpath: denota o caminho que um binário criado pode usar para encontrar uma dependência no momento da execução em relação ao subdiretório do diretório de arquivos de execução correspondente ao repositório principal. Observação:isso só funciona se o --enable_runfiles estiver ativado, o que não é o caso do Windows por padrão. Use rlocationpath para oferecer suporte a várias plataformas.

    Isso é semelhante a execpath, mas remove os prefixos de configuração descritos acima. No exemplo acima, isso significa que empty.source e app usam caminhos puramente relativos ao espaço de trabalho: testapp/empty.source e testapp/app.

    O rootpath de um arquivo em um repositório externo repo vai começar com ../repo/, seguido pelo caminho relativo ao repositório.

    Ele tem os mesmos requisitos de "apenas uma saída" que execpath.

  • rlocationpath: o caminho que um binário criado pode transmitir para a função Rlocation de uma biblioteca de runfiles para encontrar uma dependência no momento da execução, no diretório de runfiles (se disponível) ou usando o manifesto de runfiles.

    Isso é semelhante a rootpath, porque não contém prefixos de configuração, mas é diferente porque sempre começa com o nome do repositório. No exemplo acima, isso significa que empty.source e app resultam nos seguintes caminhos: myproject/testapp/empty.source e myproject/testapp/app.

    O rlocationpath de um arquivo em um repositório externo repo vai começar com repo/, seguido pelo caminho relativo ao repositório.

    Transmitir esse caminho para um binário e resolvê-lo em um caminho do sistema de arquivos usando as bibliotecas de runfiles é a abordagem preferencial para encontrar dependências no ambiente de execução. Em comparação com rootpath, ele tem a vantagem de funcionar em todas as plataformas e mesmo que o diretório de arquivos de execução não esteja disponível.

    Ele tem os mesmos requisitos de "apenas uma saída" que execpath.

  • location: um sinônimo de execpath ou rootpath, dependendo do atributo que está sendo expandido. Esse é um comportamento legado anterior ao Starlark e não é recomendado, a menos que você realmente saiba o que ele faz para uma regra específica. Consulte #2475 para mais detalhes.

execpaths, rootpaths, rlocationpaths e locations são as variações plurais de execpath, rootpath, rlocationpaths e location, respectivamente. Eles oferecem suporte a rótulos que produzem várias saídas. Nesse caso, cada saída é listada separada por um espaço. Regras de saída zero e rótulos malformados produzem erros de build.

Todos os rótulos referenciados precisam aparecer no srcs, nos arquivos de saída ou no deps do destino consumidor. Caso contrário, o build falha. Os destinos do C++ também podem referenciar rótulos em data.

Os identificadores não precisam estar no formato canônico: foo, :foo e //somepkg:foo são todos aceitáveis.

Variáveis personalizadas

As variáveis "Make" personalizadas podem ser referenciadas por qualquer atributo marcado como "Sujeito à substituição da variável "Make"", mas apenas em segmentos que dependem de outros que definem essas variáveis.

Como prática recomendada, todas as variáveis precisam ser personalizadas, a menos que haja um motivo muito bom para incorporá-las ao núcleo do Bazel. Isso evita que o Bazel precise carregar dependências potencialmente caras para fornecer variáveis que consomem tarets que não se importam.

Variáveis da cadeia de ferramentas do C++

As seguintes regras são definidas nas regras da cadeia de ferramentas C++ e estão disponíveis para qualquer regra que defina toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"]. Algumas regras, como java_binary, incluem implicitamente a cadeia de ferramentas C++ na definição de regras. Elas herdam essas variáveis automaticamente.

As regras integradas do C++ são muito mais sofisticadas do que "executar o compilador nele". Para oferecer suporte a modos de compilação tão diversos quanto *SAN, ThinLTO, com/sem módulos e binários cuidadosamente otimizados, ao mesmo tempo em que executam testes rápidos em várias plataformas, as regras integradas vão longe para garantir que as entradas, saídas e flags de linha de comando corretas sejam definidas em cada uma das ações potencialmente geradas internamente.

Essas variáveis são um mecanismo alternativo para uso por especialistas em linguagem em casos raros. Se você tiver vontade de usá-los, entre em contato com os desenvolvedores do Bazel primeiro.

  • ABI: a versão da ABI do C++.
  • AR: o comando "ar" do crosstool.
  • C_COMPILER: identifica o compilador C/C++, por exemplo, llvm.
  • CC: o comando do compilador C e C++.

    É altamente recomendável usar sempre CC_FLAGS em combinação com CC. Se você não fizer isso, será por sua conta e risco.

  • CC_FLAGS: um conjunto mínimo de flags para que o compilador C/C++ possa ser usado por genrules. Em particular, ele contém flags para selecionar a arquitetura correta se CC for compatível com várias arquiteturas.
  • NM: o comando "nm" do crosstool.
  • OBJCOPY: o comando objcopy do mesmo pacote do compilador C/C++.
  • STRIP: o comando de remoção do mesmo pacote do compilador C/C++.

Variáveis da cadeia de ferramentas do Java

As seguintes regras são definidas nas regras do conjunto de ferramentas Java e estão disponíveis para qualquer regra que defina toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"] (ou "@bazel_tools//tools/jdk:current_host_java_runtime" para o equivalente do conjunto de ferramentas do host).

A maioria das ferramentas do JDK não deve ser usada diretamente. As regras Java integradas usam abordagens muito mais sofisticadas para a compilação e o empacotamento do Java do que as ferramentas upstream podem expressar, como frascos de interface, frascos de interface de cabeçalho e implementações de mesclagem e empacotamento de frascos altamente otimizadas.

Essas variáveis são um mecanismo alternativo para uso por especialistas em linguagem em casos raros. Se você tiver vontade de usá-los, entre em contato com os desenvolvedores do Bazel primeiro.

  • JAVA: o comando "java" (uma máquina virtual Java). Evite isso e use uma regra java_binary sempre que possível. Pode ser um caminho relativo. Se você precisar mudar de diretório antes de invocar java, capture o diretório de trabalho antes de mudar.
  • JAVABASE: o diretório base que contém os utilitários Java. Pode ser um caminho relativo. Ele terá um subdiretório "bin".

Variáveis definidas pelo Starlark

Os criadores de regras e toolchain podem definir variáveis totalmente personalizadas retornando um provedor de TemplateVariableInfo. Qualquer regra que dependa deles pelo atributo toolchains pode ler os valores:

Confira um exemplo de variáveis definidas pelo Starlark.