Halaman ini berfokus pada penulisan aturan yang kompatibel dengan Windows, masalah umum penulisan aturan portabel, dan beberapa solusi.
Jalur
Masalah:
Batas panjang: panjang jalur maksimum adalah 259 karakter.
Meskipun Windows juga mendukung jalur yang lebih panjang (hingga 32767 karakter), banyak program dibuat dengan batas yang lebih rendah.
Perhatikan program ini yang Anda jalankan dalam tindakan.
Direktori kerja: juga dibatasi hingga 259 karakter.
Proses tidak dapat
cd
ke dalam direktori yang lebih dari 259 karakter.Peka 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: garis miring terbalik (
\`), not forward slash (
/`).Bazel menyimpan jalur bergaya Unix dengan pemisah
/
. Meskipun beberapa program Windows mendukung jalur bergaya Unix, program lainnya tidak. Beberapa perintah bawaan dalam cmd.exe 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 di Windows dimulai dengan huruf drive, seperti
C:\foo\bar.txt
. Tidak ada root sistem file tunggal.Perhatikan hal ini jika aturan Anda memeriksa apakah jalur bersifat absolut. Jalur absolut harus dihindari karena sering kali tidak portabel.
Solusi:
Buat jalur yang pendek.
Hindari nama direktori yang panjang, struktur direktori bertingkat yang dalam, nama file yang panjang, nama ruang kerja yang panjang, nama target yang panjang.
Semua ini dapat menjadi komponen jalur file input tindakan, dan dapat menghabiskan batas panjang jalur.
Gunakan root output singkat.
Gunakan flag
--output_user_root=<path>
untuk menentukan jalur pendek untuk output Bazel. Anda disarankan memiliki drive (atau drive virtual) hanya untuk output Bazel (seperti fileD:\`), and adding this line to your
.bazelrc`:build --output_user_root=D:/
atau
build --output_user_root=C:/_bzl
Gunakan persimpangan.
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 koneksi yang jalurnya pendek tetapi targetnya panjang, alat dengan batas jalur pendek dapat mengakses file di direktori persimpangan.
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]: Singkatnya, Junction bukanlah Symbolic Links, tetapi untuk tindakan build, Anda dapat menganggap Junction sebagai Directory Symlinks.
Ganti
/
dengan `` dalam jalur dalam tindakan/envvars.Saat Anda membuat command line atau variabel lingkungan untuk tindakan, buat jalur bergaya Windows. Contoh:
def as_path(p, is_windows): if is_windows: return p.replace("/", "\\") else: return p
Variabel lingkungan
Masalah:
Sensitivitas huruf besar/kecil: Nama variabel lingkungan Windows tidak peka huruf besar/kecil.
Misalnya, di Java,
System.getenv("SystemRoot")
danSystem.getenv("SYSTEMROOT")
memberikan hasil yang sama. (Ini juga berlaku untuk bahasa lain.)Hermeticity: tindakan harus menggunakan sesedikit mungkin variabel lingkungan kustom.
Variabel lingkungan adalah bagian dari kunci cache tindakan. Jika tindakan menggunakan variabel lingkungan yang sering berubah atau kustom untuk pengguna, aturan tersebut menjadi kurang dapat disimpan dalam cache.
Solusi:
Hanya gunakan nama variabel lingkungan huruf besar.
Ini berfungsi di Windows, macOS, dan Linux.
Minimalkan lingkungan tindakan.
Saat menggunakan
ctx.actions.run
, tetapkan lingkungan kectx.configuration.default_shell_env
. Jika tindakan tersebut 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
Masalah:
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 sebagaiexecutable
ctx.actions.run
. Selain itu, tidak ada izin+x
yang dapat dimiliki file, sehingga Anda tidak dapat menjalankan file arbitrer seperti pada Linux.Perintah bash: Agar portabilitas mudah, hindari menjalankan perintah Bash secara langsung dalam tindakan.
Bash tersebar luas pada sistem yang menyerupai Unix, tetapi sering kali tidak tersedia di Windows. Bazel sendiri lebih jarang mengandalkan Bash (MSYS2), sehingga di masa mendatang pengguna kemungkinan tidak akan 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 setelan Git Anda, terutama akhiran baris saat melakukan check out atau commit. (Lihat setelan
core.autocrlf
Git.)
Solusi:
Gunakan aturan yang dibuat tanpa tujuan Bash.
native.genrule()
adalah wrapper untuk perintah Bash, dan sering kali digunakan untuk menyelesaikan masalah sederhana seperti menyalin file atau menulis file teks. Anda tidak perlu mengandalkan Bash (dan menciptakan kembali roda): lihat apakah bazel-skylib memiliki aturan yang dibuat khusus untuk kebutuhan Anda. Tidak satu pun bergantung pada Bash saat di-build/diuji di Windows.Contoh aturan build:
copy_file()
(sumber, dokumentasi): menyalin file di tempat lain, secara opsional membuatnya dapat dieksekusiwrite_file()
(sumber, dokumentasi): menulis file teks, dengan akhiran baris yang diinginkan (auto
,unix
, atauwindows
), secara opsional menjadi dapat dieksekusi (jika berupa skrip)run_binary()
(sumber, dokumentasi): menjalankan biner (atau aturan*_binary
) dengan input yang diberikan dan output yang diharapkan sebagai tindakan build (ini adalah wrapper aturan build untukctx.actions.run
)native_binary()
(source, dokumentasi): menggabungkan biner native dalam aturan*_binary
, yang dapatbazel run
atau gunakan di atributtool
run_binary()
atau atributtools
native.genrule()
Contoh aturan pengujian:
diff_test()
(sumber, dokumentasi): pengujian yang membandingkan konten dua filenative_test()
(sumber, dokumentasi): menggabungkan biner native dalam aturan*_test
, yang dapat Andabazel test
Di Windows, pertimbangkan untuk menggunakan skrip
.bat
untuk hal-hal sederhana.Sebagai ganti skrip
.sh
, Anda dapat menyelesaikan tugas sederhana dengan skrip.bat
.Misalnya, jika Anda memerlukan skrip yang tidak melakukan apa pun, atau mencetak pesan, atau keluar dengan kode error tetap, maka file
.bat
sederhana sudah cukup. Jika aturan Anda menampilkan penyediaDefaultInfo()
, kolomexecutable
dapat merujuk ke file.bat
tersebut di Windows.Selain itu, karena ekstensi file tidak berpengaruh pada macOS dan Linux, Anda dapat menggunakan
.bat
sebagai ekstensi kapan saja, bahkan untuk skrip shell.Perlu diketahui bahwa file
.bat
kosong tidak dapat dijalankan. 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.Dalam makro Starlark, gabungkan skrip dan perintah Bash dalam
native.sh_binary()
ataunative.genrule()
. Bazel akan memeriksa apakah Bash tersedia dan menjalankan skrip atau perintah melalui Bash.Di aturan repositori Starlark, coba hindari Bash sepenuhnya. Bazel saat ini tidak menawarkan cara untuk menjalankan perintah Bash dengan cara berprinsip dalam aturan repositori.
Menghapus file
Masalah:
File tidak dapat dihapus saat terbuka.
File yang terbuka tidak dapat dihapus (secara default), upaya menghasilkan error "Akses Ditolak". Jika Anda tidak dapat menghapus file, mungkin proses yang sedang berjalan masih membekukannya.
Direktori kerja proses yang sedang berjalan tidak dapat dihapus.
Proses memiliki handle terbuka terhadap direktori kerjanya, dan direktori tidak bisa dihapus sampai proses berhenti.
Solusi:
Dalam kode Anda, coba tutup file dengan segera.
Di Java, gunakan
try-with-resources
. Dalam Python, gunakanwith open(...) as f:
. Pada prinsipnya, coba tutup handle sesegera mungkin.