Menulis Aturan di Windows

Laporkan masalah Lihat sumber

Halaman ini berfokus pada penulisan aturan yang kompatibel dengan Windows, masalah umum dalam penulisan aturan portabel, dan beberapa solusi.

Jalur

Permasalahan:

  • Batas panjang: panjang jalur maksimum adalah 259 karakter.

    Meskipun Windows juga mendukung jalur yang lebih panjang (hingga 32.767 karakter), banyak program dibuat dengan batas bawah.

    Perhatikan hal ini tentang program yang Anda jalankan dalam tindakan.

  • Working directory: juga dibatasi hingga 259 karakter.

    Proses tidak dapat cd ke dalam direktori yang lebih dari 259 karakter.

  • Kepekaan huruf besar-kecil: Jalur Windows tidak peka huruf besar/kecil, jalur Unix peka huruf besar/kecil.

    Perhatikan hal ini saat membuat command line untuk tindakan.

  • Pemisah jalur: adalah garis miring terbalik (\`), not forward slash (/`).

    Bazel menyimpan jalur bergaya Unix dengan pemisah /. Meskipun beberapa program Windows mendukung jalur gaya Unix, sebagian lainnya tidak. Beberapa perintah bawaan di {i>cmd.exe<i} mendukungnya, beberapa tidak.

    Sebaiknya selalu gunakan \` separators on Windows: replace/with` saat Anda membuat command line dan variabel lingkungan untuk tindakan.

  • Jalur absolut: jangan diawali dengan garis miring (/).

    Jalur absolut pada Windows dimulai dengan huruf drive, seperti C:\foo\bar.txt. Tidak ada {i>root<i} sistem file tunggal.

    Perhatikan hal ini jika aturan Anda memeriksa apakah suatu jalur bersifat absolut. Jalur absolut harus dihindari karena sering kali tidak portabel.

Solusi:

  • Buat jalur yang singkat.

    Hindari nama direktori yang panjang, struktur direktori bertingkat yang dalam, nama file yang panjang, nama ruang kerja yang panjang, nama target panjang.

    Semua ini dapat menjadi komponen jalur file input tindakan, dan dapat menghabiskan batas panjang jalur.

  • Gunakan root output pendek.

    Gunakan flag --output_user_root=<path> untuk menentukan jalur pendek bagi output Bazel. Sebaiknya Anda memiliki drive (atau drive virtual) hanya untuk output Bazel (seperti file D:\`), and adding this line to your.bazelrc`:

    build --output_user_root=D:/
    

    atau

    build --output_user_root=C:/_bzl
    
  • Gunakan junction.

    Persimpangan adalah, secara longgar[1], symlink direktori. Persimpangan mudah dibuat dan dapat mengarah ke direktori (di komputer yang sama) dengan jalur yang panjang. Jika tindakan build membuat junction yang jalurnya pendek, tetapi targetnya panjang, alat dengan batas jalur pendek dapat mengakses file dalam direktori junction'ed tersebut.

    Di file .bat atau di cmd.exe, Anda dapat membuat persimpangan seperti berikut:

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

    [1]: Sebenarnya, Junctions bukan Link Simbolis, tetapi untuk tindakan build, Anda dapat menganggap Junction sebagai Directory Symlink.

  • Ganti / dengan `` di jalur dalam tindakan / envvars.

    Saat Anda membuat variabel command line atau lingkungan untuk suatu tindakan, buat jalur tersebut bergaya Windows. Contoh:

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

Variabel lingkungan

Permasalahan:

  • Kepekaan huruf besar/kecil: Nama variabel lingkungan Windows tidak peka huruf besar/kecil.

    Misalnya, dalam Java, System.getenv("SystemRoot") dan System.getenv("SYSTEMROOT") memberikan hasil yang sama. (Ini juga berlaku untuk bahasa lain.)

  • Hermetisitas: tindakan harus menggunakan sesedikit mungkin variabel lingkungan kustom.

    Variabel lingkungan adalah bagian dari kunci cache tindakan. Jika suatu tindakan menggunakan variabel lingkungan yang sering berubah, atau bersifat khusus untuk pengguna, hal tersebut membuat aturan kurang dapat disimpan dalam cache.

Solusi:

  • Hanya gunakan nama variabel lingkungan dalam huruf besar.

    Ini berfungsi di Windows, macOS, dan Linux.

  • Minimalkan lingkungan tindakan.

    Saat menggunakan ctx.actions.run, setel lingkungan ke ctx.configuration.default_shell_env. Jika tindakan memerlukan lebih banyak variabel lingkungan, masukkan semuanya ke dalam kamus dan teruskan ke tindakan. Contoh:

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

Tindakan

Permasalahan:

  • Output yang dapat dieksekusi: Setiap file yang dapat dieksekusi harus memiliki ekstensi yang dapat dieksekusi.

    Ekstensi yang paling umum adalah .exe (file biner) dan .bat (skrip Batch).

    Perlu diketahui bahwa skrip shell (.sh) TIDAK dapat dieksekusi di Windows; Anda tidak dapat menentukannya sebagai executable dari ctx.actions.run. Selain itu, tidak ada izin +x yang dapat dimiliki file, sehingga Anda tidak dapat mengeksekusi file arbitrer seperti di Linux.

  • Perintah Bash: Demi portabilitas, hindari menjalankan perintah Bash secara langsung dalam tindakan.

    Bash tersebar luas di sistem yang mirip Unix, tetapi sering kali tidak tersedia di Windows. Bazel sendiri semakin tidak mengandalkan Bash (MSYS2), sehingga di masa mendatang pengguna akan cenderung tidak menginstal MSYS2 bersama dengan Bazel. Untuk mempermudah penggunaan aturan di Windows, hindari menjalankan perintah Bash dalam tindakan.

  • Akhiran baris: Windows menggunakan CRLF (\r\n), sistem seperti Unix menggunakan LF (\n).

    Perhatikan hal ini saat membandingkan file teks. Perhatikan pengaturan Git Anda, terutama akhir baris saat {i>check out<i} atau {i>commit<i}. (Lihat setelan core.autocrlf Git.)

Solusi:

  • Gunakan aturan yang dibuat khusus tanpa Bash.

    native.genrule() adalah wrapper untuk perintah Bash, dan sering digunakan untuk menyelesaikan masalah sederhana seperti menyalin file atau menulis file teks. Anda dapat menghindari mengandalkan Bash (dan menciptakan kembali sesuatu yang sudah ada): lihat apakah bazel-skylib memiliki aturan yang dibuat khusus untuk kebutuhan Anda. Tidak satu pun dari mereka yang bergantung pada Bash ketika di-build/diuji di Windows.

    Contoh aturan build:

    • copy_file() (source, dokumentasi): menyalin file di tempat lain, dan secara opsional menjadikannya dapat dieksekusi

    • write_file() (sumber, dokumentasi): menulis file teks, dengan akhiran baris yang diinginkan (auto, unix, atau windows), secara opsional membuatnya dapat dieksekusi (jika berupa skrip)

    • run_binary() (source, dokumentasi): menjalankan biner (atau aturan *_binary) dengan input tertentu dan output yang diharapkan sebagai tindakan build (ini adalah wrapper aturan build untuk ctx.actions.run)

    • native_binary() (sumber, dokumentasi): menggabungkan biner native dalam aturan *_binary, yang dapat Anda gunakan bazel run atau gunakan dalam atribut tool run_binary() atau atribut tools native.genrule()

    Contoh aturan pengujian:

    • diff_test() (sumber, dokumentasi): pengujian yang membandingkan konten dua file

    • native_test() (sumber, dokumentasi): menggabungkan biner native dalam aturan *_test, yang dapat Anda bazel test

  • Di Windows, pertimbangkan untuk menggunakan skrip .bat untuk hal-hal kecil.

    Daripada menggunakan skrip .sh, Anda dapat menyelesaikan tugas sederhana dengan skrip .bat.

    Misalnya, jika Anda memerlukan skrip yang tidak melakukan apa pun, mencetak pesan, atau keluar dengan kode error tetap, file .bat sederhana sudah cukup. Jika aturan Anda menampilkan penyedia DefaultInfo(), kolom executable mungkin merujuk ke file .bat tersebut di Windows.

    Dan karena ekstensi file tidak penting di macOS dan Linux, Anda selalu dapat menggunakan .bat sebagai ekstensi, bahkan untuk skrip shell.

    Perlu diketahui bahwa file .bat kosong tidak dapat dieksekusi. Jika Anda memerlukan skrip kosong, tulis satu spasi di dalamnya.

  • Gunakan Bash dengan cara yang berprinsip.

    Dalam aturan build dan pengujian Starlark, gunakan ctx.actions.run_shell untuk menjalankan skrip Bash dan perintah Bash sebagai tindakan.

    Di makro Starlark, gabungkan skrip dan perintah Bash dalam native.sh_binary() atau native.genrule(). Bazel akan memeriksa apakah Bash tersedia dan menjalankan skrip atau perintah melalui Bash.

    Dalam aturan repositori Starlark, coba hindari Bash sepenuhnya. Bazel saat ini tidak menawarkan cara untuk menjalankan perintah Bash dengan cara yang sesuai dalam aturan repositori.

Menghapus file

Permasalahan:

  • File tidak dapat dihapus saat terbuka.

    File yang terbuka tidak dapat dihapus (secara default), percobaan yang dilakukan akan menghasilkan error "Akses Ditolak". Jika Anda tidak dapat menghapus file, mungkin proses yang sedang berjalan masih menahan file tersebut.

  • Direktori kerja dari proses yang sedang berjalan tidak dapat dihapus.

    Proses memiliki handle terbuka untuk direktori kerjanya, dan direktori tersebut tidak dapat dihapus sampai proses dihentikan.

Solusi:

  • Di kode Anda, coba tutup file dengan segera.

    Di Java, gunakan try-with-resources. Di Python, gunakan with open(...) as f:. Pada prinsipnya, coba tutup tuas sesegera mungkin.