Como escrever regras no Windows

Reportar um problema Ver a fonte Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Esta página se concentra em escrever regras compatíveis com o Windows, problemas comuns de gravação de regras portáteis e algumas soluções.

Caminhos

Problemas:

  • Limite de comprimento: o comprimento máximo do caminho é de 259 caracteres.

    Embora o Windows também seja compatível com caminhos mais longos (até 32.767 caracteres), muitos programas são criados com o limite inferior.

    Saiba mais sobre os programas que você executa nas ações.

  • Diretório de trabalho: também é limitado a 259 caracteres.

    Os processos não podem cd em um diretório com mais de 259 caracteres.

  • Diferenciação de letras: os caminhos do Windows não diferenciam maiúsculas de minúsculas, mas os do Unix sim.

    Tenha isso em mente ao criar linhas de comando para ações.

  • Separadores de caminho: barra invertida (\`), not forward slash (/`).

    O Bazel armazena caminhos no estilo Unix com separadores /. Embora alguns programas do Windows sejam compatíveis com caminhos no estilo Unix, outros não são. Alguns comandos integrados no cmd.exe são compatíveis, outros não.

    É recomendável sempre usar \` separators on Windows: replace/with ao criar linhas de comando e variáveis de ambiente para ações.

  • Caminhos absolutos: não começam com barra (/).

    Os caminhos absolutos no Windows começam com uma letra de unidade, como C:\foo\bar.txt. Não há uma única raiz do sistema de arquivos.

    Fique atento a isso se a regra verificar se um caminho é absoluto. Caminhos absolutos devem ser evitados, já que geralmente não são portáteis.

Soluções:

  • Mantenha os caminhos curtos.

    Evite nomes de diretórios longos, estruturas de diretórios aninhadas em muitos níveis, nomes de arquivos longos, nomes de espaços de trabalho longos e nomes de destinos longos.

    Todos eles podem se tornar componentes de caminho dos arquivos de entrada das ações e esgotar o limite de comprimento do caminho.

  • Use uma raiz de saída curta.

    Use a flag --output_user_root=<path> para especificar um caminho curto para as saídas do Bazel. Uma boa ideia é ter uma unidade (ou unidade virtual) apenas para saídas do Bazel, como o arquivo D:\`), and adding this line to your.bazelrc:

    build --output_user_root=D:/
    

    ou

    build --output_user_root=C:/_bzl
    
  • Use junções.

    As junções são, em termos gerais[1], links simbólicos de diretório. As junções são fáceis de criar e podem apontar para diretórios (no mesmo computador) com caminhos longos. Se uma ação de build criar uma junção com um caminho curto, mas um destino longo, as ferramentas com limite de caminho curto poderão acessar os arquivos no diretório da junção.

    Em arquivos .bat ou no cmd.exe, é possível criar junções assim:

    mklink /J c:\path\to\junction c:\path\to\very\long\target\path
    

    [1]: estritamente falando, junções não são links simbólicos, mas, para ações de build, você pode considerar junções como links simbólicos de diretório.

  • Substitua / por `` em caminhos em ações / envvars.

    Ao criar a linha de comando ou as variáveis de ambiente para uma ação, use caminhos no estilo Windows. Exemplo:

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

Variáveis de ambiente

Problemas:

  • Diferenciação de letras: os nomes de variáveis de ambiente do Windows não diferenciam maiúsculas de minúsculas.

    Por exemplo, em Java, System.getenv("SystemRoot") e System.getenv("SYSTEMROOT") geram o mesmo resultado. Isso também se aplica a outros idiomas.

  • Hermeticity: as ações precisam usar o mínimo possível de variáveis de ambiente personalizadas.

    As variáveis de ambiente fazem parte da chave de cache da ação. Se uma ação usar variáveis de ambiente que mudam com frequência ou são personalizadas para os usuários, a regra será menos armazenável em cache.

Soluções:

  • Use apenas nomes de variáveis de ambiente em maiúsculas.

    Isso funciona no Windows, macOS e Linux.

  • Minimize os ambientes de ação.

    Ao usar ctx.actions.run, defina o ambiente como ctx.configuration.default_shell_env. Se a ação precisar de mais variáveis de ambiente, coloque todas em um dicionário e transmita isso para a ação. Exemplo:

    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})
    

Ações

Problemas:

  • Saídas executáveis: todo arquivo executável precisa ter uma extensão executável.

    As extensões mais comuns são .exe (arquivos binários) e .bat (scripts em lote).

    Scripts de shell (.sh) NÃO são executáveis no Windows. Não é possível especificá-los como ctx.actions.run executable. Também não há permissão +x para arquivos. Portanto, não é possível executar arquivos arbitrários como no Linux.

  • Comandos Bash: para fins de portabilidade, evite executar comandos Bash diretamente em ações.

    O Bash é comum em sistemas semelhantes ao Unix, mas geralmente não está disponível no Windows. O próprio Bazel depende cada vez menos do Bash (MSYS2). Assim, no futuro, os usuários terão menos chances de ter o MSYS2 instalado com o Bazel. Para facilitar o uso de regras no Windows, evite executar comandos do Bash em ações.

  • Fim de linha: o Windows usa CRLF (\r\n), e sistemas semelhantes ao Unix usam LF (\n).

    Tenha isso em mente ao comparar arquivos de texto. Preste atenção às suas configurações do Git, especialmente às quebras de linha ao fazer check-out ou commit. Consulte a configuração core.autocrlf do Git.

Soluções:

  • Use uma regra criada para uma finalidade específica sem Bash.

    native.genrule() é um wrapper para comandos do Bash e geralmente é usado para resolver problemas simples, como copiar um arquivo ou gravar um arquivo de texto. Você pode evitar depender do Bash (e reinventar a roda): veja se o bazel-skylib tem uma regra feita para suas necessidades. Nenhum deles depende do Bash quando criado/testado no Windows.

    Exemplos de regras de build:

    • copy_file() (source, documentation): copia um arquivo para outro lugar, tornando-o executável (opcional)

    • write_file() (source, documentation): grava um arquivo de texto com as terminações de linha desejadas (auto, unix ou windows), opcionalmente tornando-o executável (se for um script).

    • run_binary() (source, documentation): executa um binário (ou uma regra *_binary) com entradas e saídas esperadas como uma ação de build (este é um wrapper de regra de build para ctx.actions.run)

    • native_binary() (fonte, documentação): encapsula um binário nativo em uma regra *_binary, que pode ser bazel run ou usada no atributo tool do run_binary() ou no atributo tools do native.genrule().

    Exemplos de regras de teste:

    • diff_test() (source, documentation): teste que compara o conteúdo de dois arquivos

    • native_test() (source, documentation): encapsula um binário nativo em uma regra *_test, que pode ser bazel test.

  • No Windows, use scripts .bat para tarefas simples.

    Em vez de scripts .sh, é possível resolver tarefas triviais com scripts .bat.

    Por exemplo, se você precisar de um script que não faça nada, imprima uma mensagem ou saia com um código de erro fixo, um arquivo .bat simples será suficiente. Se a regra retornar um provedor DefaultInfo(), o campo executable poderá se referir a esse arquivo .bat no Windows.

    Como as extensões de arquivo não importam no macOS e no Linux, você pode sempre usar .bat como extensão, mesmo para scripts shell.

    Arquivos .bat vazios não podem ser executados. Se você precisar de um script vazio, escreva um espaço nele.

  • Use o Bash de maneira fundamentada.

    Em regras de build e teste do Starlark, use ctx.actions.run_shell para executar scripts e comandos do Bash como ações.

    Em macros do Starlark, encapsule scripts e comandos do Bash em um native.sh_binary() ou native.genrule(). O Bazel vai verificar se o Bash está disponível e executar o script ou comando usando o Bash.

    Nas regras de repositório do Starlark, tente evitar o Bash completamente. No momento, o Bazel não oferece uma maneira de executar comandos Bash de maneira consistente nas regras do repositório.

Como excluir arquivos

Problemas:

  • Não é possível excluir arquivos abertos.

    Não é possível excluir arquivos abertos (por padrão). As tentativas resultam em erros de "Acesso negado". Se não for possível excluir um arquivo, talvez um processo em execução ainda o mantenha aberto.

  • Não é possível excluir o diretório de trabalho de um processo em execução.

    Os processos têm um identificador aberto para o diretório de trabalho, e o diretório não pode ser excluído até que o processo seja encerrado.

Soluções:

  • No seu código, tente fechar os arquivos assim que possível.

    Em Java, use try-with-resources. Em Python, use with open(...) as f:. Em princípio, tente fechar os identificadores assim que possível.