Crear variables

Denuncia un problema Ver fuente Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Las variables "Make" son una clase especial de variables de cadena expandibles disponibles para los atributos marcados como "Sujeto a la sustitución de "variable Make".

Se pueden usar, por ejemplo, para insertar rutas de herramientas específicas en las acciones de compilación que crea el usuario.

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

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

Usar

Los atributos marcados como “Sujeto a la sustitución de la "variable de Make"” pueden hacer referencia a la variable FOO de "Make" de la siguiente manera:

my_attr = "prefix $(FOO) suffix"

En otras palabras, cualquier subcadena que coincida con $(FOO) se expande al valor de FOO. 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 objetivo consumidor, 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 @, con solo un signo de dólar, sin los paréntesis. Por ejemplo:

my_attr = "prefix $@ suffix"

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

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
) y, luego, usa "$$\{SRCS[@]}" en líneas de comandos posteriores en lugar de $(SRCS). Una opción más sólida es escribir una regla de Starlark.

Variables de ruta de acceso de origen o 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 a los archivos que indica esa etiqueta.

En el caso de los archivos fuente, esta es la ruta de acceso relativa a la raíz de tu espacio de trabajo. En el caso de los archivos que son resultados 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 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 symlink bazel-myproject en la raíz de tu espacio de trabajo. El archivo fuente empty.source está vinculado en la ruta bazel-myproject/testapp/empty.source. Por lo tanto, su ruta de ejecución (que es la subruta debajo de la raíz) es testapp/empty.source. Esta es la ruta de acceso que las acciones de compilación pueden usar para encontrar el archivo.

    Los archivos de salida se implementan de manera similar, pero también tienen el prefijo de la subruta bazel-out/cpu-compilation_mode/bin (o bazel-out/cpu-opt-exec-hash/bin para los resultados de las herramientas). 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 ejecución es bazel-out/cpu-opt-exec-hash/bin/testapp/app. Este prefijo adicional permite compilar el mismo objetivo para, por ejemplo, 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 de origen, esto es verdadero automáticamente. En el caso de las etiquetas que representan reglas, estas deben generar exactamente un resultado. Si es falsa o la etiqueta no tiene el formato correcto, la compilación fallará con un error.

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

    Esto 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 puras relativas al espacio de trabajo: 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 "un solo resultado" 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.

    Esto es similar a rootpath en 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 generan 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 entorno de ejecución. En comparación con rootpath, tiene la ventaja de que funciona en todas las plataformas y, incluso, si el directorio de runfiles no está disponible.

    Tiene los mismos requisitos de "un solo resultado" que execpath.

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

execpaths, rootpaths, rlocationpaths y locations son las variaciones en plural de execpath, rootpath, rlocationpath y location, respectivamente. Admiten etiquetas que producen varios resultados, en cuyo caso cada resultado se muestra separado por un espacio. Las reglas de salida cero y las etiquetas con el formato incorrecto producen errores de compilación.

Todas las etiquetas a las que se hace referencia deben aparecer en el srcs, los archivos de salida o el deps del objetivo de consumo. De lo contrario, la compilación fallará. 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 adecuadas.

Variables personalizadas

Cualquier atributo marcado como "Sujeto a la sustitución de "Make variable" puede hacer referencia a las variables personalizadas de "Make", 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 realmente bueno para incorporarlas en el Bazel principal. Esto evita que Bazel tenga que cargar dependencias potencialmente costosas para proporcionar variables que pueden no ser importantes para los destinos que consumen.

Variables de cadena de herramientas de C++

Los siguientes elementos 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:toolchain_type"]. Algunas reglas, como java_binary, incluyen implícitamente la cadena de herramientas de C++ en su definición de reglas. Heredan estas variables automáticamente.

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

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

  • ABI: Es la versión de la ABI de C++.
  • AR: 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, es bajo tu propia responsabilidad.

  • CC_FLAGS: Es un conjunto mínimo de marcas para que genrules pueda usar el compilador de C/C++. En particular, contiene marcas para seleccionar la arquitectura correcta si CC admite varias arquitecturas.
  • DUMPBIN: Microsoft COFF Binary File Dumper (dumpbin.exe) de Microsoft Visual Studio.
  • NM: El comando "nm" de crosstool.
  • OBJCOPY: El comando objcopy del mismo paquete que el compilador de C/C++.
  • STRIP: El comando strip del mismo paquete que el compilador de C/C++.

Variables de cadena de herramientas de Java

Los siguientes elementos 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 upstream pueden expresar, como los archivos JAR de interfaz, los archivos JAR de interfaz de encabezado y las implementaciones de combinación y empaquetado de archivos JAR altamente optimizados.

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

  • JAVA: El comando “java” (una máquina virtual de Java) Evita esto y usa una regla java_binary en su lugar siempre que 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 subdirectorio "bin".

Variables definidas por Starlark

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

Consulta un ejemplo de variables definidas por Starlark.