Crear variables

Las variables "Make" son una clase especial de variables de cadena expandibles disponibles para los atributos marcados como "Subject to 'Make variable' substitution".

Se pueden usar, por ejemplo, para insertar rutas de acceso específicas de la cadena de herramientas en acciones de compilación construidas por el usuario.

Bazel proporciona variables predefinidas, que están disponibles para todos los destinos, y variables personalizadas, que se definen en los destinos de dependencia y solo están disponibles para los destinos que dependen de ellos.

El motivo del término "Make" es histórico: la sintaxis y la semántica de estas variables se diseñaron originalmente para que coincidieran con GNU Make.

Usar

Los atributos marcados como "Subject to 'Make variable' substitution" pueden hacer referencia a la variable "Make" FOO de la siguiente manera:

my_attr = "prefix $(FOO) suffix"

En otras palabras, cualquier subcadena que coincida con $(FOO) se expande a FOO's value. Si ese valor es "bar", la cadena final se convierte en lo siguiente:

my_attr = "prefix bar suffix"

Si FOO no corresponde a una variable conocida por el destino de consumo, Bazel falla con un error.

También se puede hacer referencia a las variables "Make" cuyos nombres son símbolos que no son letras, como @, usando solo un signo de dólar, sin los paréntesis. Por ejemplo:

my_attr = "prefix $@ suffix"

Para escribir $ como un literal de cadena (es decir, para evitar la expansión de variables ), escribe $$.

Variables predefinidas

Se puede hacer referencia a las variables "Make" predefinidas con cualquier atributo marcado como "Subject to 'Make variable' substitution" en cualquier destino.

Para ver la lista de estas variables y sus valores para un conjunto determinado de opciones de compilación, ejecuta lo siguiente:

bazel info --show_make_env [build options]

y observa las líneas de salida superiores con letras mayúsculas.

Consulta un ejemplo de variables predefinidas.

Variables de opciones de la cadena de herramientas

Variables de ruta de acceso

  • BINDIR: Es la base del árbol binario generado para la arquitectura de destino.

    Ten en cuenta que se puede usar un árbol diferente para los programas que se ejecutan durante la compilación en la arquitectura del host para admitir la compilación cruzada.

    Si deseas ejecutar una herramienta desde una genrule, la forma recomendada de obtener su ruta de acceso es $(execpath toolname), en la que toolname debe aparecer en el atributo tools de genrule.

  • GENDIR: Es la base del árbol de código generado para la arquitectura de destino.

Variables de arquitectura de la máquina

  • TARGET_CPU: Es la CPU de la arquitectura de destino, p.ej., k8.

Variables genrule predefinidas

Las siguientes están disponibles especialmente para el atributo genrule's cmd y, por lo general, son importantes para que ese atributo funcione.

Consulta un ejemplo de variables genrule predefinidas.

  • OUTS: Es la lista outs de genrule. Si solo tienes un archivo de salida, también puedes usar $@.
  • SRCS: Es la lista srcs de genrule (o, más precisamente, los nombres de ruta de acceso de los archivos correspondientes a las etiquetas de la lista srcs). Si solo tienes un archivo fuente, también puedes usar $<.
  • <: SRCS, si es un solo archivo. De lo contrario, se activa un error de compilación.
  • @: OUTS, si es un solo archivo. De lo contrario, se activa un error de compilación.
  • RULEDIR: Es el directorio de salida del destino, es decir, el directorio correspondiente al nombre del paquete que contiene el destino en el árbol genfiles o bin. Para //my/pkg:my_genrule siempre termina en my/pkg, incluso si las salidas de //my/pkg:my_genrule's están en subdirectorios.

  • @D: Es el directorio de salida. Si outs tiene una entrada, se expande al directorio que contiene ese archivo. Si tiene varias entradas, se expande al directorio raíz del paquete en el genfiles árbol, incluso si todos los archivos de salida están en el mismo subdirectorio.

    Nota: Usa RULEDIR en lugar de @D, ya que RULEDIR tiene una semántica más simple y se comporta de la misma manera, independientemente de la cantidad de archivos de salida.

    Si la genrule necesita generar archivos intermedios temporales (quizás como resultado de usar alguna otra herramienta como un compilador), debe intentar escribirlos en @D (aunque /tmp también se podrá escribir) y quitarlos antes de terminar.

    En especial, evita escribir en directorios que contengan entradas. Es posible que estén en sistemas de archivos de solo lectura. Incluso si no es así, hacerlo destruiría el árbol de origen.

Variables de ruta de acceso de origen/salida predefinidas

Las variables predefinidas execpath, execpaths, rootpath, rootpaths, location, y locations toman parámetros de etiqueta (p.ej., $(execpath //foo:bar)) y sustituyen las rutas de acceso de los archivos que denota esa etiqueta.

Para los archivos fuente, esta es la ruta de acceso relativa a la raíz de tu espacio de trabajo. Para los archivos que son salidas de reglas, esta es la ruta de acceso de salida del archivo (consulta la explicación de los archivos de salida a continuación).

Consulta un ejemplo de variables de ruta de acceso predefinidas.

  • execpath: Denota la ruta de acceso debajo de execroot donde Bazel ejecuta acciones de compilación.

    En el ejemplo anterior, Bazel ejecuta todas las acciones de compilación en el directorio vinculado por el vínculo simbólico bazel-myproject en la raíz de tu espacio de trabajo. El archivo fuente empty.source está vinculado en la ruta de acceso bazel-myproject/testapp/empty.source. Por lo tanto, su ruta de acceso de ejecución (que es la subruta debajo de la raíz) es testapp/empty.source. Esta es la ruta de acceso que pueden usar las acciones de compilación para encontrar el archivo.

    Los archivos de salida se organizan de manera similar, pero también tienen el prefijo de la subruta bazel-out/cpu-compilation_mode/bin (o para las salidas de herramientas: bazel-out/cpu-opt-exec-hash/bin). En el ejemplo anterior, //testapp:app es una herramienta porque aparece en el atributo tools de show_app_output. Por lo tanto, su archivo de salida app se escribe en bazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app. Por lo tanto, la ruta de acceso de ejecución es bazel-out/cpu-opt-exec-hash/bin/testapp/app. Este prefijo adicional permite compilar el mismo destino, por ejemplo, para dos CPUs diferentes en la misma compilación sin que los resultados se superpongan.

    La etiqueta que se pasa a esta variable debe representar exactamente un archivo. Para las etiquetas que representan archivos fuente, esto es automáticamente verdadero. Para las etiquetas que representan reglas, la regla debe generar exactamente una salida. Si esto es falso o la etiqueta no tiene el formato correcto, la compilación falla con un error.

  • rootpath: Denota la ruta de acceso que un objeto binario compilado puede usar para encontrar una dependencia en el tiempo de ejecución en relación con el subdirectorio de su directorio de runfiles correspondiente al repositorio principal. Nota: Esto solo funciona si --enable_runfiles está habilitado, lo que no sucede en Windows de forma predeterminada. Usa rlocationpath en su lugar para la compatibilidad multiplataforma.

    Es similar a execpath pero quita los prefijos de configuración descritos anteriormente. En el ejemplo anterior, esto significa que tanto empty.source como app usan rutas de acceso relativas al espacio de trabajo puras: testapp/empty.source y testapp/app.

    El rootpath de un archivo en un repositorio externo repo comenzará con ../repo/, seguido de la ruta de acceso relativa al repositorio.

    Tiene los mismos requisitos de "una sola salida" que execpath.

  • rlocationpath: Es la ruta de acceso que un objeto binario compilado puede pasar a la función Rlocation de una biblioteca de runfiles para encontrar una dependencia en el tiempo de ejecución, ya sea en el directorio de runfiles (si está disponible) o con el manifiesto de runfiles.

    Es similar a rootpath en el sentido de que no contiene prefijos de configuración, pero difiere en que siempre comienza con el nombre del repositorio. En el ejemplo anterior, esto significa que empty.source y app dan como resultado las siguientes rutas de acceso: myproject/testapp/empty.source y myproject/testapp/app.

    El rlocationpath de un archivo en un repositorio externo repo comenzará con repo/, seguido de la ruta de acceso relativa al repositorio.

    Pasar esta ruta de acceso a un objeto binario y resolverla en una ruta de acceso del sistema de archivos con las bibliotecas de runfiles es el enfoque preferido para encontrar dependencias en el tiempo de ejecución. En comparación con rootpath, tiene la ventaja de que funciona en todas las plataformas, incluso si el directorio de runfiles no está disponible.

    Tiene los mismos requisitos de "una sola salida" que execpath.

  • location: Es un sinónimo de execpath o rootpath, según el atributo que se expanda. Este es comportamiento heredado anterior a Starlark y no se recomienda, a menos que sepas lo que hace para una regla en particular. Consulta #2475 para obtener más detalles.

execpaths, rootpaths, rlocationpaths, y locations son las variaciones plurales de execpath, rootpath, rlocationpaths ylocation, respectivamente. Admiten etiquetas que producen varias salidas, en cuyo caso cada salida se muestra separada por un espacio. Las reglas de salida cero y las etiquetas con formato incorrecto producen errores de compilación.

Todas las etiquetas a las que se hace referencia deben aparecer en srcs, los archivos de salida o deps. De lo contrario, la compilación falla. Los destinos de C++ también pueden hacer referencia a etiquetas en data.

Las etiquetas no tienen que estar en formato canónico: foo, :foo y //somepkg:foo son correctas.

Variables personalizadas

Se puede hacer referencia a las variables "Make" personalizadas con cualquier atributo marcado como "Subject to 'Make variable' substitution", pero solo en los destinos que dependen de otros destinos que definen estas variables.

Como práctica recomendada, todas las variables deben ser personalizadas, a menos que haya un motivo muy bueno para incorporarlas a Bazel principal. Esto evita que Bazel tenga que cargar dependencias potencialmente costosas para proporcionar variables que los destinos de consumo no puedan usar.

Variables de la cadena de herramientas de C++

Las siguientes se definen en las reglas de la cadena de herramientas de C++ y están disponibles para cualquier regla que establezca toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"] Algunas reglas, como java_binary, incluyen implícitamente la cadena de herramientas de C++ en su definición de regla. Heredan estas variables automáticamente.

Las reglas integradas de C++ son mucho más sofisticadas que "ejecutar el compilador en ellas". Para admitir modos de compilación tan diversos como *SAN, ThinLTO, con o sin módulos, y objetos binarios cuidadosamente optimizados al mismo tiempo que pruebas de ejecución rápida en varias plataformas, las reglas integradas hacen todo lo posible para garantizar que las entradas, las salidas y las marcas de la línea de comandos correctas se establezcan en cada una de las acciones generadas internamente.

Estas variables son un mecanismo de resguardo que los expertos en lenguajes deben usar en casos excepcionales. Si tienes la tentación de usarlas, comunícate primero con los desarrolladores de Bazel.

  • ABI: Es la versión de ABI de C++.
  • AR: Es el comando "ar" de crosstool.
  • C_COMPILER: Es el identificador del compilador de C/C++, p.ej., llvm.
  • CC: Es el comando del compilador de C y C++.

    Te recomendamos que siempre uses CC_FLAGS en combinación con CC. Si no lo haces, será bajo tu propia responsabilidad.

  • CC_FLAGS: Es un conjunto mínimo de marcas para que las genrules puedan usar el compilador de C/C++. En particular, contiene marcas para seleccionar la arquitectura correcta si CC admite varias arquitecturas.
  • NM: Es el comando "nm" de crosstool.
  • OBJCOPY: Es el comando objcopy del mismo paquete que el compilador de C/C++
  • STRIP: Es el comando strip del mismo paquete que el compilador de C/C++

Variables de la cadena de herramientas de Java

Las siguientes se definen en las reglas de la cadena de herramientas de Java y están disponibles para cualquier regla que establezca toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"] (o "@bazel_tools//tools/jdk:current_host_java_runtime" para el equivalente de la cadena de herramientas del host).

La mayoría de las herramientas del JDK no deben usarse directamente. Las reglas integradas de Java usan enfoques mucho más sofisticados para la compilación y el empaquetado de Java que las herramientas ascendentes pueden expresar, como los Jars de interfaz, los Jars de interfaz de encabezado y las implementaciones de empaquetado y combinación de Jars altamente optimizadas.

Estas variables son un mecanismo de resguardo que los expertos en lenguajes deben usar en casos excepcionales. Si tienes la tentación de usarlas, comunícate primero con los desarrolladores de Bazel.

  • JAVA: Es el comando "java" (una máquina virtual de Java ). Evita esto y usa una regla java_binary en su lugar cuando sea posible. Puede ser una ruta de acceso relativa. Si debes cambiar directorios antes de invocar java, debes capturar el directorio de trabajo antes de cambiarlo.
  • JAVABASE: Es el directorio base que contiene las utilidades de Java. Puede ser una ruta de acceso relativa. Tendrá un "bin" subdirectorio.

Variables definidas por Starlark

Los escritores de reglas y cadenas de herramientas pueden definir variables completamente personalizadas si muestran un TemplateVariableInfo. Cualquier regla que dependa de estas a través del toolchains atributo puede leer sus valores:

Consulta un ejemplo de variables definidas por Starlark.