Reglas de escritura en Windows

Informar un problema Ver fuente

En esta página, se explica cómo escribir reglas compatibles con Windows, problemas comunes de escritura de reglas portátiles y algunas soluciones.

Rutas de acceso

Problemas:

  • Límite de longitud: La ruta de interacciones máxima es de 259 caracteres.

    Si bien Windows también admite rutas de acceso más largas (hasta 32,767 caracteres), muchos programas se compilan con el límite más bajo.

    Ten esto en cuenta sobre los programas que ejecutas en las acciones.

  • Directorio de trabajo: Tiene un límite de 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 mayúsculas de minúsculas, mientras que las de Unix sí lo hacen.

    Ten esto en cuenta cuando crees líneas de comandos para acciones.

  • Separadores de ruta: Son barras inversas (\`), not forward slash (/`).

    Bazel almacena las rutas de acceso de estilo Unix con separadores /. Aunque algunos programas de Windows admiten rutas de acceso de estilo Unix, otros no. Algunos comandos integrados en cmd.exe las 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.

  • Rutas de acceso absolutas: No deben comenzar con una barra diagonal (/).

    Las rutas de acceso absolutas en Windows comienzan con una letra de unidad, como C:\foo\bar.txt. No hay una única raíz de sistema de archivos.

    Ten en cuenta esto si tu regla verifica si una ruta es absoluta. Se deben evitar las rutas absolutas, ya que, a menudo, no son portátiles.

Soluciones:

  • Usa rutas cortas.

    Evita los nombres de directorio largos, las estructuras de directorios profundamente anidadas, los nombres largos de los archivos, los nombres largos de los lugares de trabajo o los nombres de destino largos.

    Todos estos pueden convertirse en componentes de ruta de acceso de los archivos de entrada de acciones y agotar el límite de longitud de la ruta de acceso.

  • Usa una raíz de salida corta.

    Usa la marca --output_user_root=<path> a fin de especificar una ruta corta para los resultados de Bazel. Una buena idea es tener una unidad (o unidad virtual) solo para las salidas de Bazel (como el archivo D:\`), and adding this line to your.bazelrc):

    build --output_user_root=D:/
    

    o

    build --output_user_root=C:/_bzl
    
  • Usa uniones.

    En pocas palabras,[1] las uniones son symlinks de directorio. Las uniones son fáciles de crear y pueden apuntar a directorios (en la misma computadora) con rutas de acceso extensas. 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 límite de rutas cortas pueden acceder a los archivos del directorio de la unión.

    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, a fin de realizar acciones de compilación, puedes considerarlas como vínculos simbólicos de directorio.

  • Reemplaza / por `` en rutas de acceso en acciones / envvars.

    Cuando crees la línea de comandos o las variables de entorno para una acción, crea las rutas de acceso al estilo de Windows. Ejemplo:

    def as_path(p, is_windows):
        if is_windows:
            return p.replace("/", "\\")
        else:
            return p
    

Variables de entorno

Problemas:

  • Distinción entre mayúsculas y minúsculas: Los nombres de las variables de entorno de Windows no distinguen mayúsculas de minúsculas.

    Por ejemplo, en Java, System.getenv("SystemRoot") y System.getenv("SYSTEMROOT") generan el mismo resultado. (Esto también se aplica a otros idiomas).

  • Hermeticidad: Las acciones deben usar la menor cantidad posible de variables de entorno personalizadas.

    Las variables de entorno son parte de la clave de caché de la acción. Si una acción usa variables de entorno que cambian con frecuencia o que son personalizadas para los usuarios, la regla puede almacenarse menos en 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 en ctx.configuration.default_shell_env. Si la acción necesita más variables de entorno, colócalas en un diccionario y pásalas 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

Problemas:

  • Resultados 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 son ejecutables en Windows y no puedes especificarlas como executable de ctx.actions.run. Tampoco hay un permiso +x que los archivos puedan tener, por lo que no puedes ejecutar archivos arbitrarios como en Linux.

  • Comandos de Bash: Para lograr la portabilidad, evita ejecutar comandos de Bash directamente en acciones.

    Bash es muy común en sistemas similares a Unix, pero no suele estar disponible en Windows. En sí, Bazel depende cada vez menos de Bash (MSYS2), por lo que en el futuro será menos probable que los usuarios tengan MSYS2 instalado junto con Bazel. Para facilitar el uso de las reglas en Windows, evita ejecutar comandos de Bash en acciones.

  • Terminaciones de línea: Windows usa CRLF (\r\n), mientras que los sistemas similares a Unix usan LF (\n).

    Ten esto en cuenta cuando compares archivos de texto. Ten en cuenta la configuración de Git, en especial de los extremos de línea cuando realizas la confirmación de la compra o la confirmación. (Consulta la configuración de core.autocrlf de Git).

Soluciones:

  • Usa una regla específica para propósitos específicos sin Bash

    native.genrule() es un wrapper para 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): Fíjate si bazel-skylib tiene una regla específica que se ajuste a tus necesidades. Ninguno de ellos depende de Bash cuando se compila o se prueba en Windows.

    Ejemplos de reglas de compilación:

    • copy_file() (fuente, documentación): Copia un archivo en otro lugar y, de manera opcional, lo hace ejecutable.

    • write_file() (fuente, documentación): Escribe un archivo de texto con los finales de línea deseados (auto, unix o windows) y, de manera opcional, lo hace ejecutable (si es una secuencia de comandos).

    • run_binary() (fuente, documentación): Ejecuta un objeto binario (o regla *_binary) con entradas y salidas determinadas como una acción de compilación (este es un wrapper de reglas de compilación para ctx.actions.run).

    • native_binary() (fuente, documentación): Une un objeto binario nativo en una regla *_binary, que puedes usar bazel run o usar en el atributo tool de run_binary() o el atributo tools de native.genrule()

    Ejemplos de reglas de prueba:

  • En Windows, considera usar secuencias de comandos .bat para tareas triviales.

    En lugar de secuencias de comandos .sh, puedes resolver tareas triviales con secuencias de comandos .bat.

    Por ejemplo, si necesitas una secuencia de comandos que no hace nada, imprime un mensaje o finaliza con un código de error fijo, entonces un archivo .bat simple será suficiente. Si la regla muestra un proveedor DefaultInfo(), el campo executable puede hacer referencia a ese archivo .bat en Windows.

    Además, como las extensiones de archivo no son importantes en macOS y Linux, siempre puedes usar .bat como extensión, incluso para secuencias de comandos de shell.

    Ten en cuenta que no se pueden ejecutar archivos .bat vacíos. Si necesitas una secuencia de comandos vacía, escribe un espacio en ella.

  • Usa Bash con principios.

    En las reglas de compilación y prueba de Starlark, usa ctx.actions.run_shell para ejecutar secuencias de comandos y comandos Bash como acciones.

    En las macros de Starlark, une las secuencias de comandos de Bash y los comandos en un native.sh_binary() o native.genrule(). Bazel verificará si Bash está disponible y ejecutará la secuencia de comandos o el comando mediante Bash.

    En las reglas del repositorio de Starlark, intenta evitar Bash por completo. Por el momento, Bazel no ofrece una manera de ejecutar comandos de Bash de principios en las reglas de repositorio.

Borra archivos

Problemas:

  • No se pueden borrar archivos mientras están abiertos.

    Los archivos abiertos no se pueden borrar (de forma predeterminada); los intentos dan como resultado 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 controlador 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 archivos con anticipación.

    En Java, usa try-with-resources. En Python, usa with open(...) as f:. En principio, intenta cerrar los identificadores lo antes posible.