En esta página, se explica cómo compilar un programa con Bazel, la sintaxis del comando de compilación y la sintaxis del patrón de destino.
Guía de inicio rápido
Para ejecutar Bazel, ve al directorio base workspace.
o cualquiera de sus subdirectorios, y escribe bazel
. Consulta build si
necesitas hacer un nuevo lugar de trabajo.
bazel help
[Bazel release bazel version]
Usage: bazel command options ...
Comandos disponibles:
analyze-profile
: Analiza los datos del perfil de compilación.aquery
: Ejecuta una consulta en el gráfico de acción posterior al análisis.build
: Compila los destinos especificados.canonicalize-flags
: Canonicaliza marcas de Bazel.clean
: Quita los archivos de salida y, de manera opcional, detiene el servidor.cquery
: Ejecuta una consulta de grafo de dependencia posterior al análisis.dump
: Vuelca el estado interno del proceso del servidor de Bazel.help
: Imprime la ayuda para los comandos o el índice.info
: Muestra información del entorno de ejecución sobre el servidor de Bazel.fetch
: Recupera todas las dependencias externas de un destino.mobile-install
: Instala apps en dispositivos móviles.query
: Ejecuta una consulta de gráfico de dependencia.run
: Ejecuta el destino especificado.shutdown
: Detiene el servidor de Bazel.test
: Compila y ejecuta los destinos de prueba especificados.version
: Imprime información de la versión para Bazel.
Cómo obtener ayuda
bazel help command
: imprime ayuda y opciones paracommand
bazel help
startup_options
: Opciones para la JVM que aloja a Bazelbazel help
target-syntax
: Explica la sintaxis para especificar objetivos.bazel help info-keys
: Muestra una lista de las teclas que usa el comando info.
La herramienta bazel
realiza muchas funciones llamadas comandos. Las más comunes
los usados son bazel build
y bazel test
. Puedes explorar la ayuda en línea
mensajes con bazel help
.
Cómo crear un destino
Antes de iniciar una compilación, necesitas un lugar de trabajo. Un espacio de trabajo de directorio principal que contenga todos los archivos de origen necesarios para compilar tu y mantener la integridad de su aplicación. Bazel te permite compilar a partir de una compilación de solo lectura volumen.
Para compilar un programa con Bazel, escribe bazel build
seguido de la
objetivo que deseas crear.
bazel build //foo
Después de emitir el comando para compilar //foo
, verás un resultado similar al siguiente:
INFO: Analyzed target //foo:foo (14 packages loaded, 48 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 9.905s, Critical Path: 3.25s
INFO: Build completed successfully, 6 total actions
Primero, Bazel carga todos los paquetes en el gráfico de dependencias de tu destino. Esta
Incluye dependencias declaradas, archivos que aparecen directamente en el BUILD
del destino
y las dependencias transitivas, los archivos que aparecen en los archivos BUILD
de tu
las dependencias del destino. Después de identificar todas las dependencias, Bazel analiza.
para asegurarte de que sean correctos y crea las acciones de compilación. Por último, Bazel ejecuta.
los compiladores y otras herramientas de la compilación.
Durante la fase de ejecución de la compilación, Bazel imprime mensajes de progreso. El progreso incluyen el paso de compilación actual (por ejemplo, compilador o vinculador), tal como de inicio y la cantidad completada sobre la cantidad total de acciones de compilación. Como inicios de compilación, la cantidad de acciones totales suele aumentar a medida que Bazel descubre todo el gráfico de acciones, pero el número se estabiliza en unos segundos.
Al final de la compilación, Bazel imprime qué destinos se solicitaron, ya sea que
no, se compilaron con éxito y, de ser así, los archivos de salida se pueden
encontradas. Las secuencias de comandos que ejecutan compilaciones pueden analizar este resultado de manera confiable. ver
--show_result
para obtener más información.
Si vuelves a escribir el mismo comando, la compilación finalizará mucho más rápido.
bazel build //foo
INFO: Analyzed target //foo:foo (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 0.144s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action
Esta es una compilación nula. Como no se modificó nada, no hay paquetes para volver a cargar y no hay pasos de compilación para ejecutar. Si algo cambió en "foo" o su dependencias, Bazel volvería a ejecutar algunas acciones de compilación o completaría un compilación incremental.
Cómo crear varios destinos
Bazel permite varias maneras de especificar los destinos que se compilarán. En conjunto,
estos se conocen como patrones del objetivo. Esta sintaxis se usa en comandos como
build
, test
o query
.
Por su parte, las etiquetas se usan para especificar
objetivos, como la declaración de dependencias en archivos BUILD
, el destino de Bazel
los patrones especifican varios destinos. Los patrones de objetivo son una generalización del
sintaxis de etiquetas para conjuntos de objetivos, con comodines. En el caso más simple, cualquier
etiqueta válida también es un patrón de destino válido, que identifica un conjunto de exactamente un
objetivo.
Todos los patrones de destino que comienzan con //
se resuelven en relación con el valor actual
Workspace.
//foo/bar:wiz |
Solo el //foo/bar:wiz de destino único. |
//foo/bar |
Equivale a //foo/bar:bar . |
//foo/bar:all |
Todos los objetivos de regla en el paquete foo/bar . |
//foo/... |
Todas las reglas objetivo en todos los paquetes debajo del directorio foo |
//foo/...:all |
Todas las reglas objetivo en todos los paquetes debajo del directorio foo |
//foo/...:* |
Todos los objetivos (reglas y archivos) de todos los paquetes del directorio foo |
//foo/...:all-targets |
Todos los objetivos (reglas y archivos) de todos los paquetes del directorio foo |
//... |
Todos los objetivos de la regla en paquetes del repositorio principal. No incluye objetivos desde repositorios externos. |
//:all |
Todas las orientaciones de reglas en el paquete de nivel superior, si hay un archivo "BUILD" en el raíz del lugar de trabajo. |
Los patrones de objetivo que no comienzan con //
se resuelven en relación con el
directorio de trabajo actual. En estos ejemplos, se supone que el directorio de trabajo es foo
:
:foo |
Equivale a //foo:foo . |
bar:wiz |
Equivale a //foo/bar:wiz . |
bar/wiz |
Equivale a:
|
bar:all |
Equivale a //foo/bar:all . |
:all |
Equivale a //foo:all . |
...:all |
Equivale a //foo/...:all . |
... |
Equivale a //foo/...:all . |
bar/...:all |
Equivale a //foo/bar/...:all . |
De forma predeterminada, se siguen los symlinks de directorio para los patrones de destino recursivos. excepto aquellas que apuntan debajo de la base de salida, como la symlinks que se crean en el directorio raíz del lugar de trabajo.
Además, Bazel no sigue estos symlinks cuando evalúa el objetivo recursivo.
patrones en cualquier directorio que contenga un archivo llamado de la siguiente manera:
DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN
foo/...
es un comodín sobre packages (paquetes) que indica todos los paquetes de manera recursiva.
en el directorio foo
(para todas las raíces de la ruta del paquete). :all
es un
comodín sobre targets, que coincide con todas las reglas dentro de un paquete. Estos dos pueden ser
combinados, como en foo/...:all
, y cuando se usan ambos comodines, este puede ser
abreviado como foo/...
.
Además, :*
(o :all-targets
) es un comodín que coincide con todos los destinos.
en los paquetes coincidentes, incluidos los archivos que normalmente no se compilan mediante ninguna regla,
como los archivos _deploy.jar
asociados con las reglas java_binary
.
Esto implica que :*
denota un superconjunto de :all
. y, posiblemente,
confusa, esta sintaxis permite usar el comodín :all
conocido para
compilaciones típicas en las que no se desea compilar destinos como _deploy.jar
.
Además, Bazel permite usar una barra en lugar de los dos puntos requeridos por
la sintaxis de las etiquetas; Esto suele ser conveniente cuando se usa la expansión de nombre de archivo Bash.
Por ejemplo, foo/bar/wiz
es equivalente a //foo/bar:wiz
(si hay un
al paquete foo/bar
) o a //foo:bar/wiz
(si hay un paquete foo
).
Muchos comandos de Bazel aceptan una lista de patrones de destino como argumentos, y todos
debes respetar el operador de negación del prefijo -
. Esto se puede usar para restar un conjunto de
objetivos del conjunto que se especificó en los argumentos anteriores. Ten en cuenta que esto significa
y el orden es importante. Por ejemplo:
bazel build foo/... bar/...
significa "crear todas las orientaciones inferiores a foo
y todas las orientaciones por debajo de bar
", mientras que
bazel build -- foo/... -foo/bar/...
significa "crear todas las segmentaciones inferiores a foo
, excepto aquellas inferiores a foo/bar
". (El
Se requiere el argumento --
para evitar que los argumentos posteriores comiencen con -
.
se interpreten como opciones adicionales).
Es importante señalar que restar objetivos de esta manera no
garantizar que no se compilen, ya que pueden ser dependencias de objetivos
que no se restaron. Por ejemplo, si hubiera un //foo:all-apis
objetivo
que, entre otros, dependía de //foo/bar:api
, este último se compilaría como
de la construcción del primero.
Los destinos con tags = ["manual"]
no se incluyen en los patrones de destino con comodines.
(...
, :*
, :all
, etc.) cuando se especifica en comandos como
bazel build
y bazel test
(pero se incluyen en
los patrones de destino comodín negativos, es decir, se restarán). Deberías
especificar esos destinos de prueba con patrones de destino explícitos en la línea de comandos si
quieres que Bazel las compile y pruebe. Por el contrario, bazel query
no realiza
cualquier filtro de este tipo automáticamente (lo que impediría el propósito de
bazel query
).
Recupera dependencias externas
De forma predeterminada, Bazel descargará dependencias externas y hará un symlink para las dependencias externas durante la
compilar. Sin embargo, esto puede ser
indeseable, ya sea porque quieres saber
cuando se agregan dependencias externas nuevas o porque quieres
“carga previa” dependencias (por ejemplo, antes de un vuelo en el que no tendrás conexión). Si
y deseas evitar que se agreguen nuevas dependencias durante las compilaciones,
puede especificar la marca --fetch=false
. Ten en cuenta que esta marca solo
se aplica a las reglas del repositorio que no apuntan a un directorio en el
un sistema de archivos completo. Los cambios, por ejemplo, a local_repository
,
new_local_repository
y reglas de repositorio del SDK y NDK de Android
siempre tendrá efecto independientemente del valor --fetch
.
Si no permites la recuperación durante las compilaciones y Bazel encuentra ofertas externas dependencias, tu compilación fallará.
Para recuperar dependencias de forma manual, ejecuta bazel fetch
. Si
Si no permites la recuperación durante la compilación, deberás ejecutar bazel fetch
:
- Antes de compilar por primera vez
- Después de agregar una dependencia externa nueva
Una vez ejecutado, no será necesario que lo vuelvas a ejecutar hasta que se ejecute MODULE.bazel cambios en el archivo.
fetch
toma una lista de destinos para los que se recuperarán las dependencias. Para
ejemplo, esto recuperaría las dependencias necesarias para compilar //foo:bar
y //bar:baz
:
bazel fetch //foo:bar //bar:baz
Para recuperar todas las dependencias externas de un lugar de trabajo, ejecuta el siguiente comando:
bazel fetch //...
Con Bazel 7 o una versión posterior, si tienes Bzlmod habilitado, también puedes recuperar todas las dependencias externas ejecutando
bazel fetch
No necesitas ejecutar la recuperación de bazel si tienes todas las herramientas que
(desde los archivos jar de la biblioteca hasta el JDK) en la raíz de tu espacio de trabajo.
Sin embargo, si usas algo fuera del directorio del lugar de trabajo, entonces Bazel
se ejecutará automáticamente bazel fetch
antes de ejecutarse
bazel build
La caché del repositorio
Bazel intenta evitar recuperar el mismo archivo varias veces, incluso si se trata de
un archivo en diferentes lugares de trabajo o si la definición de una
repositorio cambió, pero aún necesita el mismo archivo para descargar. Para ello, sigue estos pasos:
bazel almacena en caché todos los archivos descargados en la caché del repositorio que, de forma predeterminada,
está en ~/.cache/bazel/_bazel_$USER/cache/repos/v1/
. El
la ubicación se puede cambiar con la opción --repository_cache
. El
Se comparte la caché entre todos los lugares de trabajo y las versiones instaladas de Bazel.
Se toma una entrada de la caché si
Bazel sabe con seguridad que tiene una copia del archivo correcto, es decir, si
tiene una suma SHA256 del archivo especificado y un archivo con ese
el hash en la memoria caché. Por lo tanto, especificar un hash para cada archivo externo es
no solo es una buena idea
desde el punto de vista de la seguridad, también ayuda a evitar
descargas innecesarias.
Con cada acierto de caché, la hora de modificación del archivo en la caché se se actualicen. De esta manera, el último uso de un archivo en el directorio de caché puede fácilmente por ejemplo, para limpiar la caché de forma manual. La caché nunca se limpiarse automáticamente, ya que podría contener una copia de un archivo que más tiempo disponible upstream.
[Obsoleto] Directorios de archivos de distribución
Obsoleto: Es preferible usar la caché del repositorio para lograr la compilación sin conexión.
El directorio de distribución es otro mecanismo de Bazel para evitar descargas. Bazel busca directorios de distribución antes de la caché del repositorio. La diferencia principal es que el directorio de distribución y la preparación adecuada.
Con el
--distdir=/path/to-directory
puedes especificar directorios de solo lectura adicionales para buscar archivos
en lugar de recuperarlos. Un archivo se toma de ese directorio si el nombre del archivo
igual al nombre base de la URL y, además, el hash del archivo se
igual al especificado en la solicitud de descarga. Esto solo funciona si
se especifica en la declaración de la regla del repositorio.
Si bien la condición del nombre del archivo no es necesaria para que sea correcta, reduce la cantidad de archivos candidatos a uno por directorio especificado. En este Especificar directorios de archivos de distribución sigue siendo eficiente, incluso si el aumenta la cantidad de archivos en este tipo de directorio.
Ejecución de Bazel en un entorno aislado
Para mantener pequeño el tamaño del objeto binario de Bazel, se recuperan las dependencias implícitas de Bazel. a través de la red mientras se ejecuta por primera vez. Estas dependencias implícitas contienen cadenas de herramientas y reglas que pueden no ser necesarias para todos. Para Por ejemplo, las herramientas de Android se desagrupan y se recuperan solo cuando se compila Android. proyectos.
Sin embargo, estas dependencias implícitas pueden causar problemas al ejecutar Bazel en una un entorno aislado, aunque hayas abastecido todas dependencias. Para resolverlo, puedes preparar una caché de repositorio (con Bazel 7 o posterior) o un directorio de distribución (con Bazel anterior a 7) que contenga estas las dependencias en una máquina con acceso a redes y, luego, transferirlas un entorno aislado con un enfoque sin conexión.
Caché del repositorio (con Bazel 7 o posterior)
Para preparar la caché del repositorio, usa el
--repository_cache
marca. Deberás hacer esto una vez por cada versión nueva de objeto binario de Bazel, ya que
las dependencias implícitas pueden ser diferentes para cada versión.
Para recuperar esas dependencias fuera de su entorno aislado, primero cree un espacio de trabajo vacío:
mkdir empty_workspace && cd empty_workspace
touch MODULE.bazel
Para recuperar dependencias de Bzlmod integradas, ejecuta lo siguiente:
bazel fetch --repository_cache="path/to/repository/cache"
Si aún dependes del archivo WORKSPACE heredado, para recuperar el WORKSPACE integrado las dependencias, puedes ejecutar
bazel sync --repository_cache="path/to/repository/cache"
Por último, cuando uses Bazel en tu entorno con airgapped, pasa el mismo
--repository_cache
. Para mayor comodidad, puedes agregarlo como .bazelrc
.
entrada:
common --repository_cache="path/to/repository/cache"
Además, es posible que también debas clonar
BCR a nivel local y usar
--registry
para apuntar tu copia local a fin de evitar que Bazel acceda a la
BCR a través de Internet Agrega la siguiente línea a tu .bazelrc
:
common --registry="path/to/local/bcr/registry"
Directorio de distribución (con Bazel anterior a la versión 7)
Para preparar el directorio de distribución, usa la
--distdir
marca. Deberás hacer esto una vez por cada versión nueva de objeto binario de Bazel, ya que
las dependencias implícitas pueden ser diferentes para cada versión.
Para compilar estas dependencias fuera de su entorno aislado, primero observa el árbol de fuentes de Bazel en la versión correcta:
git clone https://github.com/bazelbuild/bazel "$BAZEL_DIR"
cd "$BAZEL_DIR"
git checkout "$BAZEL_VERSION"
Luego, compila el archivo tarball que contiene las dependencias implícitas del entorno de ejecución para ese versión específica de Bazel:
bazel build @additional_distfiles//:archives.tar
Exporta este archivo comprimido a un directorio que se pueda copiar en tu Airgapped.
en un entorno de nube. Observa la marca --strip-components
, ya que --distdir
puede ser
bastante complejo con el nivel de anidamiento de directorios:
tar xvf bazel-bin/external/additional_distfiles/archives.tar \
-C "$NEW_DIRECTORY" --strip-components=3
Por último, cuando uses Bazel en tu entorno con airgapped, pasa --distdir
.
marca que apunta al directorio. Para mayor comodidad, puedes agregarlo como .bazelrc
.
entrada:
build --distdir=path/to/directory
Configuraciones de compilación y compilación cruzada
Todas las entradas que especifican el comportamiento y el resultado de una compilación determinada pueden
dividirse en dos categorías distintas. El primer tipo es el de
almacenada en los archivos BUILD
de tu proyecto: la regla de compilación,
valores de sus atributos y el conjunto completo de sus dependencias transitivas.
El segundo tipo corresponde a los datos externos o ambientales que proporciona el usuario o
por la herramienta de compilación: la elección de la arquitectura de destino, la compilación y la vinculación
de la cadena de herramientas y otras opciones de configuración. Nos referimos a un conjunto completo
de datos del entorno como una configuración.
En una compilación determinada, puede haber más de una configuración. Consider a
compilación cruzada, en la que compilas un ejecutable //foo:bin
para un archivo de 64 bits
pero la estación de trabajo es una máquina de 32 bits. Claramente, la compilación
Es necesario compilar //foo:bin
con una cadena de herramientas capaz de crear archivos de 64 bits.
ejecutables, pero el sistema de compilación también debe compilar varias herramientas utilizadas durante la
compilarse a sí mismo, por ejemplo, herramientas que se compilan a partir del código fuente y, luego,
usarse en, por ejemplo, una genrule, que deben compilarse para ejecutarse en tu estación de trabajo. Por lo tanto,
podemos identificar dos configuraciones: la exec configuration, que se usa
para compilar herramientas que se ejecutan durante la compilación, y la configuración de destino
(o la configuración de la solicitud, pero hablamos de "configuración del destino" con más frecuencia,
aunque esa palabra ya tiene muchos significados), que se utiliza para construir la
binario que finalmente solicitaste.
Por lo general, hay muchas bibliotecas que son requisitos previos
el destino de compilación (//foo:bin
) y una o más de las herramientas de ejecución, por ejemplo, algunas
bibliotecas base. Esas bibliotecas se deben compilar dos veces, una para que el comando exec
y otra para la de destino. Bazel se encarga de
garantizando que se compilen ambas variantes y que los archivos derivados se mantengan
separarse para evitar interferencias; por lo general, esos destinos se pueden crear de forma simultánea
ya que son independientes entre sí. Si ves mensajes de progreso
que indica que un destino determinado se construye dos veces, es muy probable que
explicación.
La configuración de ejecución se deriva de la configuración de destino de la siguiente manera:
- Usa la misma versión de Crosstool (
--crosstool_top
) que se especifica en la la configuración de la solicitud, a menos que se especifique--host_crosstool_top
. - Usa el valor de
--host_cpu
para--cpu
(valor predeterminado:k8
). - Usa los mismos valores de estas opciones que se especifican en la solicitud.
configuración:
--compiler
,--use_ijars
y si--host_crosstool_top
es usado, entonces el valor de--host_cpu
se usa para buscar undefault_toolchain
en Crosstool (ignorando--compiler
) para el ejecutivo configuración. - Usa el valor de
--host_javabase
para--javabase
- Usa el valor de
--host_java_toolchain
para--java_toolchain
- Usa compilaciones optimizadas para código C++ (
-c opt
). - No se genera información de depuración (
--copt=-g0
). - Quita la información de depuración de los archivos ejecutables y las bibliotecas compartidas
(
--strip=always
). - Colocar todos los archivos derivados en una ubicación especial, distinta de la usada por cualquier configuración de solicitud posible.
- Elimina el sello de objetos binarios con datos de compilación (consulta las opciones de
--embed_*
). - Todos los demás valores permanecen en su configuración predeterminada.
Hay muchas razones por las que puede ser preferible seleccionar un comando exec distinto de la configuración de la solicitud. Más importante:
En primer lugar, cuando usas objetos binarios optimizados y reducidos, se reduce el tiempo vincular y ejecutar las herramientas, el espacio en disco que ocupan estas y el el tiempo de E/S de la red en compilaciones distribuidas.
Segundo, al separar las configuraciones de ejecución y solicitud en todas las compilaciones, evitar reconstrucciones muy costosas que resultarían de cambios menores en la la configuración de la solicitud (por ejemplo, cambiar las opciones de un vinculador), como se describe anteriormente.
Recompilaciones incrementales correctas
Uno de los principales objetivos del proyecto Bazel es garantizar recompilación. Las herramientas de compilación anteriores, especialmente las basadas en Make, hacen que varias suposiciones ofensivas en la implementación de compilaciones incrementales.
En primer lugar, las marcas de tiempo de los archivos aumentan de forma monótona. Aunque esta es la caso típico, es muy fácil caer en conflicto con esta suposición; sincronizando con una La revisión anterior de un archivo disminuye el tiempo de modificación de ese archivo. Los sistemas basados en Make no se volverán a compilar.
En términos más generales, si bien Make detecta cambios en los archivos, no los detecta.
a los comandos. Si modificas las opciones que se pasan al compilador en una compilación determinada
Make no volverá a ejecutar el compilador, y es necesario descartarlo manualmente
los resultados no válidos de la compilación anterior con make clean
Además, Make no se resiste ante el cierre fallido de una de sus subprocesos después de que el subproceso comienza a escribir en su archivo de salida. Mientras que la ejecución actual de Make fallará, la invocación posterior de Make fallará suponer a ciegas que el archivo de salida truncado es válido (porque es más reciente que sus entradas) y no se volverá a compilar. Del mismo modo, si el proceso Make se matas, puede ocurrir una situación similar.
Bazel evita estas suposiciones y otras. Bazel mantiene una base de datos de todos trabajo realizado anteriormente y solo omitirá un paso de compilación si detecta que el conjunto de archivos de entrada (y sus marcas de tiempo) a ese paso de compilación, y la compilación para ese paso de compilación, debe coincidir exactamente con uno de la base de datos y que un conjunto de archivos de salida (y sus marcas de tiempo) para la entrada de la base de datos las marcas de tiempo de los archivos en el disco. Cualquier cambio en los archivos de entrada o salida o al comando en sí, causará que se vuelva a ejecutar el paso de compilación.
El beneficio para los usuarios de las compilaciones incrementales correctas es: menos tiempo desperdiciado debido a
confusión. Además, se reduce el tiempo de espera de recompilaciones causadas por el uso de make
clean
, ya sea necesario o preventivo.
Compila compilaciones incrementales y coherencia
De manera formal, definimos el estado de una compilación como coherente cuando se cumplen todos los existen archivos de salida y su contenido es correcto, como se especifica en los pasos o las reglas necesarias para crearlos. Cuando editas un archivo fuente, el estado del archivo se dice que la compilación es incoherente y permanece inconsistente hasta la próxima ejecución. la herramienta de compilación hasta que se complete con éxito. Esta situación se describe como inestable incoherencia, ya que es solo temporal, y ejecutando la herramienta de compilación.
Existe otro tipo de inconsistencia perniciosa: estable
incoherencia. Si la compilación alcanza un estado incoherente estable, luego se repite
invocar correctamente la herramienta de compilación no restablece la coherencia: la compilación
quedó “atascado”, por lo que los resultados siguen siendo incorrectos. Estados incoherentes estables
son el motivo principal por el que los usuarios de Make (y otras herramientas de compilación) escriben make clean
.
Descubrir que la herramienta de compilación ha fallado de esta manera (y luego recuperarla
puede llevar mucho tiempo y ser muy frustrante.
Conceptualmente, la forma más sencilla de lograr una compilación coherente es descartar todos los resultados de compilación anteriores y vuelve a comenzar: haz que cada compilación sea una compilación limpia. Es evidente que este enfoque lleva demasiado tiempo para ser práctico (excepto, para los ingenieros de lanzamiento) y, por lo tanto, para ser útil, la herramienta de compilación debe poder para realizar compilaciones incrementales sin comprometer la coherencia.
El análisis correcto de la dependencia incremental es difícil y, como se describió anteriormente, muchos otras herramientas de compilación no hacen un buen trabajo al evitar estados incoherentes estables durante compilaciones incrementales. Por el contrario, Bazel ofrece la siguiente garantía: después de un invocación correcta de la herramienta de compilación durante la cual no realizaste ninguna edición, el compilación estarán en un estado coherente. (Si editas tus archivos fuente durante un , Bazel no garantiza la coherencia del resultado de la compilación actual. Sin embargo, sí garantiza que los resultados de la compilación next restablecer la coherencia).
Como ocurre con todas las garantías, se incluye la letra chica: hay algunas formas conocidas de llegar a un estado incoherente estable con Bazel. No te garantizamos investigar estos problemas derivados de intentos deliberados de encontrar errores en el análisis incremental de la dependencia, pero investigaremos y haremos todo lo posible para solucionarlo todos los estados incoherentes estables que surgen de situaciones normales o “razonables” uso del de compilación.
Si alguna vez detectas un estado incoherente estable con Bazel, informa un error.
Ejecución en zona de pruebas
Bazel usa zonas de pruebas para garantizar que las acciones se ejecuten de forma hermética y
correctamente. Bazel ejecuta generadores (en voz baja: acciones) en zonas de pruebas que
contener únicamente el conjunto mínimo de archivos que la herramienta necesita para hacer su trabajo. Actualmente
La zona de pruebas funciona en Linux 3.12 o versiones posteriores con la opción CONFIG_USER_NS
.
y también en macOS 10.11 o versiones posteriores.
Bazel imprimirá una advertencia si tu sistema no admite la zona de pruebas para alertar
el hecho de que no se garantiza que las construcciones sean herméticas y puedan afectar
el sistema host de maneras desconocidas. Para inhabilitar esta advertencia, puedes pasar el
marca --ignore_unsupported_sandboxing
para Bazel.
En algunas plataformas, como Google Kubernetes
Engine o Debian,
de usuario se desactivan de forma predeterminada debido a políticas
de seguridad en la nube. Esto se puede comprobar si observas el archivo
/proc/sys/kernel/unprivileged_userns_clone
: Si existe y contiene un 0,
los de usuario pueden activarse con
sudo sysctl kernel.unprivileged_userns_clone=1
En algunos casos, la zona de pruebas de Bazel no puede ejecutar reglas debido al sistema
configuración. Por lo general, el síntoma es una falla que genera un mensaje similar al siguiente:
namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory
En ese caso, intenta desactivar la zona de pruebas para genrules con
--strategy=Genrule=standalone
y para otras reglas con
--spawn_strategy=standalone
También informa el error en nuestro
seguimiento de problemas y menciona la distribución de Linux que usas para que
investigar y proporcionar una solución en una versión posterior.
Fases de una compilación
En Bazel, una compilación se produce en tres fases distintas: como usuario, entender el la diferencia entre ellos proporciona información sobre las opciones que controlan una compilación (consulta a continuación).
Fase de carga
El primero es la carga, durante el cual todos los archivos BUILD necesarios para la objetivos iniciales y su cierre transitivo de dependencias, analizarse, evaluarse y almacenarse en caché.
En la primera compilación después de que se inicia un servidor de Bazel, la fase de carga suele tarda varios segundos, ya que se cargan muchos archivos BUILD desde el sistema de archivos. En las compilaciones posteriores, en especial si no cambiaron los archivos de COMPILACIÓN, se producirá la carga. muy rápidamente.
Los errores informados durante esta fase incluyen: paquete no encontrado, destino no encontrado, errores léxicos y gramaticales en un archivo BUILD, y errores de evaluación.
Fase de análisis
La segunda fase, análisis, implica el análisis semántico y la validación de cada regla de compilación, la construcción de un gráfico de dependencia de compilación y el determina exactamente qué trabajo hay que hacer en cada paso de la compilación.
Al igual que cuando se carga, el análisis también tarda varios segundos cuando se calcula en su totalidad. Sin embargo, Bazel almacena en caché el gráfico de dependencias de una compilación a la siguiente y solo vuelve a analizar lo que tiene que hacer, lo que puede hacer que las compilaciones incrementales sean extremadamente rápidas el caso en el que los paquetes no cambiaron desde la compilación anterior.
Los errores informados en esta etapa incluyen dependencias inapropiadas, no válidas las entradas de una regla y todos los mensajes de error específicos de la regla.
Las fases de carga y análisis son rápidas porque Bazel evita el uso de archivos innecesarios. de E/S en esta etapa, solo se leen los archivos de COMPILACIÓN para determinar el trabajo que se debe listo. Esto está pensado, y es una buena base para las herramientas de análisis, como el comando query de Bazel, que se implementa encima de la línea de carga en la fase de desarrollo.
Fase de ejecución
La tercera y última fase de la compilación es la ejecución. Esta fase garantiza que que los resultados de cada paso de la compilación sean coherentes con sus entradas, lo que vuelve a ejecutar compilación, vinculación, etcétera herramientas según sea necesario. En este paso, la compilación la mayor parte de su tiempo, que oscila entre unos pocos segundos y más de una hora para una gran compilar. Los errores informados durante esta fase incluyen: archivos fuente faltantes, errores en una herramienta ejecutada por alguna acción de compilación, o la falla de una herramienta para producir conjunto de resultados esperado.