Variáveis de quot;Make"

Informar um problema Ver código-fonte

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

Eles podem ser usados, por exemplo, para injetar caminhos de conjunto de ferramentas específicos em ações de versão 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 deles.

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

Uso

Atributos marcados como "Substituição pela variável 'Tornar variável'" podem fazer referência à variável "Make" FOO da seguinte forma:

my_attr = "prefix $(FOO) suffix"

Em outras palavras, qualquer substring correspondente a $(FOO) é expandida para o valor de FOO. Se o valor for "bar", a string final vai ficar:

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.

As variáveis "Make" com nomes que não são letras, como @, também podem ser referenciadas usando um cifrão, sem os 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 a substituição de 'Make variável'" em qualquer destino.

Para ver 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 com letras maiúsculas.

Veja um exemplo de variáveis predefinidas.

Variáveis de opção do conjunto de ferramentas

Variáveis de caminho

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

    Observe que uma árvore diferente pode ser usada para programas executados durante a compilação 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 é $(execpath toolname), em que toolname precisa ser listado no atributo tools do genrule.

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

Variáveis de arquitetura de máquina

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

Variáveis de regra predefinidas

Os itens a seguir estão disponíveis especialmente para o atributo cmd de genrule e são importantes para que esse atributo funcione.

Veja um exemplo de variáveis de regra geral 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 dos caminhos 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, aciona um erro de build.
  • @: OUTS, se for um único arquivo. Caso contrário, um erro de compilação será 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, isso expandirá para o diretório que contém esse arquivo. Se tiver várias entradas, ela vai ser expandida 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 uma semântica mais simples e se comporta da mesma forma, independentemente do número de arquivos de saída.

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

    Evite especialmente gravar em diretórios que contenham entradas. Eles podem estar em sistemas de arquivos somente leitura. Mesmo que não tenha feito isso, a árvore de origem seria enviada para a lixeira.

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

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, é o caminho relativo para a raiz do espaço de trabalho. Para arquivos que são saídas de regras, esse é o caminho de saída do arquivo (veja a explicação de arquivos de saída abaixo).

Veja um exemplo de variáveis de caminho predefinidas.

  • execpath: indica o caminho abaixo do execroot em que o Bazel executa ações de compilação.

    No exemplo acima, o Bazel executa todas as ações de versão 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 ao caminho bazel-myproject/testapp/empty.source. Portanto, o caminho executivo, 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 são prefixados com o 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. Portanto, o caminho executivo é bazel-out/cpu-opt-exec-hash/bin/testapp/app. Esse prefixo extra possibilita criar o mesmo destino para, por exemplo, duas CPUs diferentes no mesmo build, sem que os resultados sejam movidos em conjunto.

    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 os rótulos que representam regras, a regra precisa gerar exatamente uma saída. Se for falso ou o rótulo estiver incorreto, o build falhará com um erro.

  • rootpath: indica o caminho que um binário criado pode usar para encontrar uma dependência em tempo de execução em relação ao subdiretório do diretório de runfiles correspondente ao repositório principal. Observação:isso só funciona se o --enable_runfiles estiver ativado, o que não é o caso no Windows por padrão. Use rlocationpath para compatibilidade com 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 puros relativos ao espaço de trabalho: testapp/empty.source e testapp/app.

    O rootpath de um arquivo em um repositório externo repo 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 runfiles para encontrar uma dependência no ambiente de execução, seja no diretório runfiles (se disponível) ou usando o manifesto 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 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 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 runfiles 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 anterior ao Starlark e não é recomendado, a menos que você realmente saiba o que ele faz em uma regra específica. Consulte 2475 para mais detalhes.

execpaths, rootpaths, rlocationpaths e locations são as variações de plural de execpath, rootpath, rlocationpaths e location, respectivamente. Elas são compatíveis com rótulos que produzem várias saídas. Nesse caso, cada uma é listada separadamente por um espaço. Regras de saída zero e rótulos malformados produzem erros de build.

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

Os rótulos não precisam estar na forma canônica: foo, :foo e //somepkg:foo são aceitas.

Variáveis personalizadas

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

Como prática recomendada, todas as variáveis devem ser personalizadas, a não ser que haja um bom motivo para as colocar no núcleo do Bazel. Assim, o Bazel não precisa carregar dependências potencialmente caras para fornecer variáveis de consumo.

Variáveis do conjunto de ferramentas em C++

Os itens a seguir são definidos nas regras do conjunto de ferramentas do C++ e disponíveis para qualquer regra que defina toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"] (ou "@bazel_tools//tools/cpp:current_cc_host_toolchain" para o equivalente do conjunto de ferramentas do host). Algumas regras, como java_binary, incluem implicitamente o conjunto de ferramentas do C++ na definição das regras. Elas herdam essas variáveis automaticamente.

As regras C++ integradas são muito mais sofisticadas do que "executam 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 que testes de execução rápida em várias plataformas, as regras integradas fazem grandes esforços para garantir que as entradas, saídas e sinalizações de linha de comando corretas sejam definidas em cada uma das várias ações geradas internamente.

Essas variáveis são um mecanismo substituto usado por especialistas em idiomas em casos raros. Se você quiser usá-las, entre em contato com os desenvolvedores do Bazel primeiro.

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

    É altamente recomendável usar CC_FLAGS em combinação com CC. Você não será responsável por fazer isso.

  • CC_FLAGS: um conjunto mínimo de sinalizações para que o compilador C/C++ possa ser usado por regras gerais. Ele contém sinalizações 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 que o compilador C/C++.
  • STRIP: o comando de remoção do mesmo pacote que o compilador C/C++.

Variáveis do conjunto de ferramentas Java

Os itens a seguir são definidos 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 no JDK não pode ser usada diretamente. As regras integradas do Java usam abordagens muito mais sofisticadas para compilação e empacotamento do Java do que as ferramentas upstream podem expressar, como JARs de interface, Jarses de interface de cabeçalho e implementações de empacotamento e mesclagem de JAR altamente otimizadas.

Essas variáveis são um mecanismo substituto usado por especialistas em idiomas em casos raros. Se você quiser usá-las, 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, será necessário capturar o diretório de trabalho antes da mudança.
  • JAVABASE: o diretório base que contém os utilitários do Java. Pode ser um caminho relativo. Ele terá um subdiretório "bin".

Variáveis definidas pelo Starlark

Os gravadores de regras e conjuntos de ferramentas podem definir variáveis completamente personalizadas retornando um provedor TemplateVariableInfo. Qualquer regra que dependa delas com o atributo toolchains pode ler os valores:

Veja um exemplo de variáveis definidas pelo Starlark.