En esta página, se explica cómo escribir reglas compatibles con Windows, los problemas comunes de escribir reglas portátiles y algunas soluciones.
Rutas de acceso
Desventajas:
Límite de longitud: La longitud máxima de la ruta es de 259 caracteres.
Aunque Windows también admite rutas más largas (hasta 32,767 caracteres), muchos programas se compilan con el límite inferior.
Ten en cuenta esto sobre los programas que ejecutas en las acciones.
Directorio de trabajo: También está limitado a 259 caracteres.
Los procesos no pueden
cd
en un directorio de más de 259 caracteres.Distinción entre mayúsculas y minúsculas: Las rutas de acceso de Windows no distinguen entre mayúsculas y minúsculas, mientras que las de Unix sí lo hacen.
Ten en cuenta esto cuando crees líneas de comandos para acciones.
Separadores de ruta: Son barras inversas (
\`), not forward slash (
/`).Bazel almacena las rutas al estilo de Unix con separadores
/
. Si bien algunos programas de Windows admiten rutas de acceso de estilo Unix, otros no. Algunos comandos integrados en cmd.exe los admiten, mientras que otros no.Es mejor usar siempre
\` separators on Windows: replace
/with
cuando creas líneas de comandos y variables de entorno para acciones.Las rutas de acceso absolutas no comienzan con una barra (
/
).Las rutas de acceso absolutas en Windows comienzan con una letra de unidad, como
C:\foo\bar.txt
. No hay una sola raíz del sistema de archivos.Ten en cuenta esto si tu regla verifica si una ruta es absoluta. Se deben evitar las rutas de acceso absolutas, ya que a menudo no son portátiles.
Soluciones:
Mantén las rutas cortas.
Evita los nombres de directorio largos, las estructuras de directorio anidadas, los nombres de archivo largos, los nombres de espacio de trabajo largos y los nombres de destino largos.
Todos estos elementos pueden convertirse en componentes de ruta de los archivos de entrada de las acciones y pueden agotar el límite de longitud de la ruta.
Usa una raíz de salida corta.
Usa la marca
--output_user_root=<path>
para especificar una ruta de acceso corta para los resultados de Bazel. Una buena idea es tener una unidad (o una unidad virtual) solo para los resultados de Bazel (como el archivoD:\`), and adding this line to your
.bazelrc):build --output_user_root=D:/
o
build --output_user_root=C:/_bzl
Usa intersecciones.
En términos generales[1], las uniones son vínculos simbólicos de directorios. Las uniones son fáciles de crear y pueden apuntar a directorios (en la misma computadora) con rutas largas. Si una acción de compilación crea una unión cuya ruta de acceso es corta, pero cuyo destino es largo, las herramientas con un límite de ruta de acceso corto pueden acceder a los archivos en el directorio unido.
En los archivos
.bat
o en cmd.exe, puedes crear uniones de la siguiente manera:mklink /J c:\path\to\junction c:\path\to\very\long\target\path
[1]: En sentido estricto, las uniones no son vínculos simbólicos, pero, para las acciones de compilación, puedes considerarlas como vínculos simbólicos de directorios.
Reemplaza
/
por "" en las rutas de acceso de las acciones o las variables de entorno.Cuando crees la línea de comandos o las variables de entorno para una acción, haz que las rutas tengan el formato de Windows. Ejemplo:
def as_path(p, is_windows): if is_windows: return p.replace("/", "\\") else: return p
Variables de entorno
Desventajas:
Distinción entre mayúsculas y minúsculas: Los nombres de las variables de entorno de Windows no distinguen entre mayúsculas y minúsculas.
Por ejemplo, en Java,
System.getenv("SystemRoot")
ySystem.getenv("SYSTEMROOT")
arrojan el mismo resultado. (Esto también se aplica a otros idiomas).Hermeticity: Las acciones deben usar la menor cantidad posible de variables de entorno personalizadas.
Las variables de entorno forman parte de la clave de caché de la acción. Si una acción usa variables de entorno que cambian con frecuencia o son personalizadas para los usuarios, la regla se puede almacenar menos en la caché.
Soluciones:
Solo usa nombres de variables de entorno en mayúsculas.
Esto funciona en Windows, macOS y Linux.
Minimiza los entornos de acción.
Cuando uses
ctx.actions.run
, establece el entorno enctx.configuration.default_shell_env
. Si la acción necesita más variables de entorno, colócalas todas en un diccionario y pásalo a la acción. Ejemplo:load("@bazel_skylib//lib:dicts.bzl", "dicts") def _make_env(ctx, output_file, is_windows): out_path = output_file.path if is_windows: out_path = out_path.replace("/", "\\") return dicts.add(ctx.configuration.default_shell_env, {"MY_OUTPUT": out_path})
Acciones
Desventajas:
Salidas ejecutables: Cada archivo ejecutable debe tener una extensión ejecutable.
Las extensiones más comunes son
.exe
(archivos binarios) y.bat
(secuencias de comandos por lotes).Ten en cuenta que las secuencias de comandos de shell (
.sh
) NO se pueden ejecutar en Windows. No puedes especificarlas comoexecutable
dectx.actions.run
. Tampoco hay un permiso de+x
que puedan tener los archivos, por lo que no puedes ejecutar archivos arbitrarios como en Linux.Comandos de Bash: Para garantizar la portabilidad, evita ejecutar comandos de Bash directamente en las acciones.
Bash está muy extendido en los sistemas similares a Unix, pero a menudo no está disponible en Windows. Bazel depende cada vez menos de Bash (MSYS2), por lo que, en el futuro, es menos probable que los usuarios tengan MSYS2 instalado junto con Bazel. Para que las reglas sean más fáciles de usar en Windows, evita ejecutar comandos de Bash en las acciones.
Finales de línea: Windows usa CRLF (
\r\n
) y los sistemas similares a Unix usan LF (\n
).Ten en cuenta esto cuando compares archivos de texto. Ten en cuenta la configuración de Git, en especial los finales de línea cuando realices una extracción o una confirmación. (Consulta el parámetro de configuración
core.autocrlf
de Git).
Soluciones:
Usa una regla específica sin Bash.
native.genrule()
es un wrapper para los comandos de Bash y, a menudo, se usa para resolver problemas simples, como copiar un archivo o escribir un archivo de texto. Puedes evitar depender de Bash (y reinventar la rueda): consulta si bazel-skylib tiene una regla hecha a medida para tus necesidades. Ninguno de ellos depende de Bash cuando se compila o prueba en Windows.Ejemplos de reglas de compilación:
copy_file()
(source, documentation): Copia un archivo en otro lugar y, de manera opcional, lo hace ejecutable.write_file()
(source, documentation): Escribe un archivo de texto con los finales de línea deseados (auto
,unix
owindows
) y, de manera opcional, lo hace ejecutable (si es una secuencia de comandos).run_binary()
(source, documentation): Ejecuta un archivo binario (o una regla*_binary
) con entradas y salidas esperadas determinadas como una acción de compilación (este es un wrapper de regla de compilación paractx.actions.run
)native_binary()
(source, documentation): Encapsula un archivo binario nativo en una regla*_binary
, que puedesbazel run
o usar en el atributotool
derun_binary()
o en el atributotools
denative.genrule()
.
Ejemplos de reglas de prueba:
diff_test()
(source, documentation): Prueba que compara el contenido de dos archivosnative_test()
(source, documentation): Encapsula un archivo binario nativo en una regla*_test
, que puedesbazel test
En Windows, considera usar secuencias de comandos
.bat
para tareas triviales.En lugar de usar secuencias de comandos de
.sh
, puedes resolver tareas triviales con secuencias de comandos de.bat
.Por ejemplo, si necesitas una secuencia de comandos que no haga nada, que imprima un mensaje o que salga con un código de error fijo, un archivo
.bat
simple será suficiente. Si tu regla devuelve un proveedorDefaultInfo()
, el campoexecutable
puede hacer referencia a ese archivo.bat
en Windows.Como las extensiones de archivo no son importantes en macOS y Linux, siempre puedes usar
.bat
como extensión, incluso para las secuencias de comandos de shell.Ten en cuenta que los archivos
.bat
vacíos no se pueden ejecutar. Si necesitas un guion vacío, escribe un espacio en él.Usa Bash de forma fundamentada.
En las reglas de compilación y prueba de Starlark, usa
ctx.actions.run_shell
para ejecutar secuencias de comandos y comandos de Bash como acciones.En las macros de Starlark, incluye los comandos y las secuencias de comandos de Bash en un
native.sh_binary()
o unnative.genrule()
. Bazel verificará si Bash está disponible y ejecutará la secuencia de comandos o el comando a través de Bash.En las reglas del repositorio de Starlark, intenta evitar Bash por completo. Actualmente, Bazel no ofrece ninguna forma de ejecutar comandos de Bash de manera fundamentada en las reglas del repositorio.
Borra archivos
Desventajas:
No se pueden borrar los archivos mientras están abiertos.
Los archivos abiertos no se pueden borrar (de forma predeterminada), y los intentos generan errores de "Acceso denegado". Si no puedes borrar un archivo, es posible que un proceso en ejecución lo mantenga abierto.
No se puede borrar el directorio de trabajo de un proceso en ejecución.
Los procesos tienen un identificador abierto para su directorio de trabajo, y el directorio no se puede borrar hasta que finalice el proceso.
Soluciones:
En tu código, intenta cerrar los archivos de forma anticipada.
En Java, usa
try-with-resources
. En Python, usawith open(...) as f:
. En principio, intenta cerrar los identificadores lo antes posible.