Criar variáveis

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 de variável 'Make'".

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

O Bazel oferece 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 só estão disponíveis para destinos que dependem delas.

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

Usar

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

my_attr = "prefix $(FOO) suffix"

Em outras palavras, qualquer substring correspondente a $(FOO) é expandida para FOO's valor. Se esse valor for "bar", a string final se tornará:

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" cujos nomes são símbolos não alfabéticos, como @, também podem ser referenciadas usando apenas um cifrão, sem os parênteses. Por exemplo:

my_attr = "prefix $@ suffix"

Para gravar $ como um literal de string (ou seja, para evitar a expansão de variáveis), grave $$.

Predefined variables

Predefined "Make" variables can be referenced by any attribute marked as "Subject to 'Make variable' substitution" on any target.

To see the list of these variables and their values for a given set of build options, run

bazel info --show_make_env [build options]

and look at the top output lines with capital letters.

See an example of predefined variables.

Toolchain option variables

Path variables

  • BINDIR: The base of the generated binary tree for the target architecture.

    Note that a different tree may be used for programs that run during the build on the host architecture, to support cross-compiling.

    If you want to run a tool from within a genrule, the recommended way to get its path is $(execpath toolname), where toolname must be listed in the genrule's tools attribute.

  • GENDIR: The base of the generated code tree for the target architecture.

Machine architecture variables

  • TARGET_CPU: The target architecture's CPU, e.g. k8.

Predefined genrule variables

The following are specially available to genrule's cmd attribute and are generally important for making that attribute work.

See an example of predefined genrule variables.

  • OUTS: The genrule's outs list. If you have only one output file, you can also use $@.
  • SRCS: The genrule's srcs list (or more precisely: the path names of the files corresponding to labels in the srcs list). If you have only one source file, you can also use $<.
  • <: SRCS, if it is a single file. Else triggers a build error.
  • @: OUTS, if it is a single file. Else triggers a build error.
  • RULEDIR: The output directory of the target, that is, the directory corresponding to the name of the package containing the target under the genfiles or bin tree. For //my/pkg:my_genrule this always ends in my/pkg, even if //my/pkg:my_genrule's outputs are in subdirectories.

  • @D: The output directory. If outs has one entry, this expands to the directory containing that file. If it has multiple entries, this expands to the package's root directory in the genfiles tree, even if all output files are in the same subdirectory!

    Note: Use RULEDIR over @D because RULEDIR has simpler semantics and behaves the same way regardless of the number of output files.

    If the genrule needs to generate temporary intermediate files (perhaps as a result of using some other tool like a compiler), it should attempt to write them to @D (although /tmp will also be writable) and remove them before finishing.

    Especially avoid writing to directories containing inputs. They may be on read-only filesystems. Even if not, doing so would trash the source tree.

Note: If the filenames corresponding to the input labels or the output filenames contain spaces, ', or other special characters (or your genrule is part of a Starlark macro which downstream users may invoke on such files), then $(SRCS) and $(OUTS) are not suitable for interpolation into a command line, as they do not have the semantics that "${@}" would in Bash.

One workaround is to convert to a Bash array, with

mapfile SRCS <<< "$$(sed -e 's/ /\\n/g' <<'genrule_srcs_expansion'
$(SRC)
genrule_srcs_expansion
)
e use "$$\{SRCS[@]}" em linhas de comando subsequentes no lugar
de $(SRCS). Uma opção mais robusta é gravar uma regra do Starlark
em vez disso.

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 dos arquivos de saída abaixo).

Consulte um exemplo de variáveis de caminho predefinidas.

  • execpath: indica 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 por 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 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 preparados 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. Assim, 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 a essa variável precisa representar exatamente um arquivo. Para rótulos que representam arquivos de origem, isso é verdadeiro automaticamente. Para rótulos que representam regras, a regra precisa gerar exatamente uma saída. Se isso for falso ou o rótulo estiver malformado, o build falhará com um erro.

  • rootpath: indica o caminho que um binário criado pode usar para encontrar uma dependência no ambiente de 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 --enable_runfiles estiver ativado, o que não acontece no Windows por padrão. Use rlocationpath para oferecer suporte multiplataforma.

    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 relativos ao espaço de trabalho puro: 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 arquivos de execução para encontrar uma dependência no ambiente de execução, no diretório de arquivos de execução (se disponível) ou usando o manifesto de arquivos de execução.

    Isso é semelhante a rootpath pois não contém prefixos de configuração, mas difere 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 para um caminho do sistema de arquivos usando as bibliotecas de arquivos de execução é a abordagem preferida para encontrar dependências no ambiente de execução. Em comparação com rootpath, ele tem a vantagem de que funciona 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 é comportamento legado pré-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, rlocationpath, elocation, respectivamente. Eles oferecem suporte a rótulos que produzem várias saídas, em que 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 em srcs, arquivos de saída ou deps do destino de consumo. Caso contrário, o build falhará. Os destinos do C++ também podem referenciar rótulos em data.

Os rótulos não precisam estar no formato canônico: foo, :foo e //somepkg:foo são válidos.

Variáveis personalizadas

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

Como prática recomendada, todas as variáveis precisam ser personalizadas, a menos que haja um bom motivo para incorporá-las ao Bazel principal. Isso evita que o Bazel precise carregar dependências potencialmente caras para fornecer variáveis que os destinos de consumo talvez não se importem.

Variáveis da cadeia de ferramentas do C++

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

As regras de C++ integradas 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 que testes de execução rápida em várias plataformas, as regras integradas fazem o possível para garantir que as entradas, saídas e flags de linha de comando corretas sejam definidas em cada uma das várias ações geradas internamente.

Essas variáveis são um mecanismo de fallback a ser usado por especialistas em idiomas em casos raros. Se você quiser usá-las, por favor, 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: O identificador do compilador C/C++, por exemplo, llvm.
  • CC: o comando do compilador C e C++.

    Recomendamos sempre usar CC_FLAGS em combinação com CC. Não fazer isso é 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 oferecer suporte a várias arquiteturas.
  • DUMPBIN: Microsoft COFF Binary File Dumper (dumpbin.exe) from do Microsoft Visual Studio.
  • NM: o comando "nm" do crosstool.
  • OBJCOPY: o comando objcopy do mesmo pacote que o compilador C/C++
  • STRIP: o comando strip do mesmo pacote que o compilador C/C++

Variáveis da cadeia de ferramentas Java

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

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

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

  • JAVA: o comando "java" (uma máquina virtual Java). Evite isso e use uma java_binary regra em vez disso, 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 "bin" subdiretório.

Variáveis definidas pelo Starlark

Os autores de regras e cadeias de ferramentas podem definir variáveis totalmente personalizadas retornando um TemplateVariableInfo. Todas as regras que dependem delas pelo toolchains atributo podem ler os valores:

Consulte um exemplo de variáveis definidas pelo Starlark.