Pemformatan file BUILD
mengikuti pendekatan yang sama dengan Go, dengan
menangani sebagian besar masalah pemformatan.
Buildifier adalah alat yang mengurai dan
memunculkan kode sumber dalam gaya standar. Oleh karena itu, setiap BUILD
file
diformat dengan cara otomatis yang sama, sehingga pemformatan tidak menjadi masalah selama
peninjauan kode. Hal ini juga memudahkan {i>tool<i} untuk memahami, mengedit, dan
membuat file BUILD
.
Pemformatan file BUILD
harus cocok dengan output buildifier
.
Contoh pemformatan
# Test code implementing the Foo controller.
package(default_testonly = True)
py_test(
name = "foo_test",
srcs = glob(["*.py"]),
data = [
"//data/production/foo:startfoo",
"//foo",
"//third_party/java/jdk:jdk-k8",
],
flaky = True,
deps = [
":check_bar_lib",
":foo_data_check",
":pick_foo_port",
"//pyglib",
"//testing/pybase",
],
)
Struktur file
Rekomendasi: Gunakan urutan berikut (setiap elemen bersifat opsional):
Deskripsi paket (komentar)
Semua pernyataan
load()
Fungsi
package()
.Panggilan ke aturan dan makro
Buildifier membedakan antara komentar mandiri dan komentar melekat pada suatu elemen. Jika komentar tidak dilampirkan pada elemen tertentu, gunakan baris kosong setelahnya. Perbedaannya penting saat melakukan analisis perubahan (misalnya, untuk menyimpan atau menghapus komentar saat menghapus aturan).
# Standalone comment (such as to make a section in a file)
# Comment for the cc_library below
cc_library(name = "cc")
Referensi ke target dalam paket saat ini
File harus dirujuk oleh jalurnya secara relatif terhadap direktori paket
(tanpa pernah menggunakan referensi naik, seperti ..
). File yang dihasilkan harus
diawali dengan ":
" untuk menunjukkan bahwa mereka bukan sumber. File sumber
tidak boleh diawali dengan :
. Aturan harus diawali dengan :
. Sebagai
contoh, dengan asumsi x.cc
adalah file sumber:
cc_library(
name = "lib",
srcs = ["x.cc"],
hdrs = [":gen_header"],
)
genrule(
name = "gen_header",
srcs = [],
outs = ["x.h"],
cmd = "echo 'int x();' > $@",
)
Penamaan target
Nama target harus deskriptif. Jika target berisi
satu file sumber,
target umumnya harus memiliki nama yang berasal dari sumber tersebut (misalnya,
cc_library
untuk chat.cc
dapat diberi nama chat
, atau java_library
untuk
DirectMessage.java
dapat diberi nama direct_message
).
Target eponim untuk sebuah paket (target dengan nama yang sama dengan yang memuat) harus menyediakan fungsi yang dijelaskan oleh nama direktori. Jika tidak ada target seperti itu, jangan buat eponim target.
Memilih menggunakan nama pendek saat merujuk ke target eponim (//x
bukan //x:x
). Jika Anda menggunakan paket yang sama, lebih baik gunakan paket lokal
(:x
, bukan //x
).
Hindari menggunakan "dicadangkan" nama target yang memiliki arti khusus. Hal ini mencakup
all
, __pkg__
, dan __subpackages__
, nama-nama ini memiliki
semantik dan dapat menyebabkan kebingungan
dan perilaku tak terduga saat digunakan.
Jika tidak ada konvensi tim yang berlaku, beberapa prinsip ini tidak mengikat rekomendasi yang banyak digunakan di Google:
- Secara umum, gunakan "snake_case"
- Untuk
java_library
dengan satusrc
, ini berarti menggunakan nama yang tidak sama dengan nama file tanpa ekstensi - Untuk aturan
*_binary
dan*_test
Java, gunakan "CamelCase Atas". Hal ini memungkinkan nama target cocok dengan salah satusrc
. Sebagaijava_test
, atribut ini memungkinkan atributtest_class
disimpulkan dari nama target.
- Untuk
- Jika ada beberapa varian dari target tertentu, tambahkan akhiran ke
memperjelas (seperti
:foo_dev
,:foo_prod
atau:bar_x86
,:bar_x64
) - Beri akhiran target
_test
dengan_test
,_unittest
,Test
, atauTests
- Hindari akhiran yang tidak bermakna seperti
_lib
atau_library
(kecuali jika diperlukan menghindari konflik antara target_library
dan_binary
yang sesuai) - Untuk target terkait proto:
proto_library
target harus memiliki nama yang diakhiri dengan_proto
- Aturan
*_proto_library
khusus bahasa harus cocok dengan aturan proto, tetapi ganti_proto
dengan akhiran khusus bahasa seperti:cc_proto_library
:_cc_proto
java_proto_library
:_java_proto
java_lite_proto_library
:_java_proto_lite
Visibilitas
Visibilitas harus dibatasi selebar mungkin, sambil tetap mengizinkan akses
oleh pengujian dan dependensi terbalik. Gunakan __pkg__
dan __subpackages__
sebagai
yang sesuai.
Hindari menetapkan paket default_visibility
ke //visibility:public
.
//visibility:public
sebaiknya hanya ditetapkan satu per satu untuk target dalam
API publik project. Ini bisa berupa {i>library<i} yang
dirancang untuk digunakan
oleh project eksternal atau biner yang dapat digunakan oleh project eksternal
proses build project.
Dependensi
Dependensi harus dibatasi ke dependensi langsung (dependensi yang diperlukan oleh sumber yang tercantum dalam aturan). Jangan mencantumkan dependensi transitif.
Dependensi paket-lokal harus dicantumkan terlebih dahulu dan dirujuk dengan cara kompatibel dengan Referensi ke target dalam paket saat ini di atas (bukan berdasarkan nama paketnya yang mutlak).
Pilih untuk mencantumkan dependensi secara langsung, sebagai satu daftar. Menempatkan "umum" dependensi beberapa target ke dalam variabel akan mengurangi kemudahan pemeliharaan, {i>tool<i} tidak mungkin mengubah dependensi target, dan dapat menyebabkan dependensi yang tidak digunakan.
Glob
Menunjukkan "tidak ada target" dengan []
. Jangan gunakan glob yang tidak cocok dengan apa pun: glob
akan lebih rentan terhadap kesalahan
dan tidak terlihat jelas dibandingkan daftar kosong.
Rekursif
Jangan gunakan glob rekursif untuk mencocokkan file sumber (misalnya,
glob(["**/*.java"])
).
Bola rekursif membuat file BUILD
sulit dijelaskan karena dilewati
subdirektori yang berisi file BUILD
.
Bola rekursif umumnya kurang efisien dibandingkan memiliki file BUILD
per
dengan grafik dependensi yang ditentukan di antaranya karena hal ini memungkinkan
{i>caching<i} jarak jauh
dan paralelisme.
Sebaiknya buat file BUILD
di setiap direktori dan menentukan
grafik dependensi di antara
mereka.
Non-rekursif
Gelombang non-rekursif umumnya dapat diterima.
Konvensi lainnya
Gunakan huruf besar dan garis bawah untuk mendeklarasikan konstanta (seperti
GLOBAL_CONSTANT
), gunakan huruf kecil dan garis bawah untuk mendeklarasikan variabel (sepertimy_variable
).Label tidak boleh dipisah, bahkan jika panjangnya lebih dari 79 karakter. Label harus berupa literal string jika memungkinkan. Argumentasi: Hal itu membuat mudah ditemukan dan diganti. Hal ini juga meningkatkan keterbacaan.
Nilai atribut nama harus berupa string konstanta literal (kecuali dalam makro). Alasan: Alat eksternal menggunakan atribut nama untuk merujuk aturan. Mereka perlu menemukan aturan tanpa harus menafsirkan kode.
Saat menetapkan atribut jenis boolean, gunakan nilai boolean, bukan nilai bilangan bulat. Karena alasan lama, aturan masih mengonversi bilangan bulat menjadi boolean sesuai kebutuhan, tapi hal ini tidak disarankan. Argumentasi:
flaky = 1
bisa salah ditafsirkan sebagai mengatakan "deflake target ini dengan menjalankannya kembali sekali".flaky = True
mengatakan dengan jelas "pengujian tidak stabil".
Perbedaan dengan panduan gaya Python
Meskipun kompatibilitas dengan Panduan gaya Python adalah sasaran, ada beberapa perbedaan:
Tidak ada batas panjang baris yang ketat. Komentar yang panjang dan string panjang sering kali dipisahkan hingga 79 kolom, tetapi tidak wajib. Hal ini tidak boleh diterapkan dalam kode meninjau atau mengirimkan skrip. Alasan: Label bisa panjang dan melebihi batas ini batas tersebut. Biasanya file
BUILD
dibuat atau diedit oleh alat, yang tidak sesuai dengan batas panjang garis.Penyambungan string implisit tidak didukung. Gunakan operator
+
. Argumentasi: FileBUILD
berisi banyak daftar string. Sangat mudah untuk melupakan koma, yang mengarah ke hasil yang berbeda sepenuhnya. Hal ini telah menghasilkan banyak bug dari perangkat yang sama atau lokasi yang serupa. Lihat juga diskusi ini.Gunakan spasi di sekitar tanda
=
untuk argumen kata kunci dalam aturan. Argumentasi: Argumen yang dinamai jauh lebih sering daripada di Python dan selalu berada garis terpisah. Spasi meningkatkan keterbacaan. Konvensi ini telah diadakan waktu yang lama, dan membuat semua fileBUILD
yang ada tidak perlu diubah.Secara default, gunakan tanda kutip ganda untuk string. Argumentasi: Hal ini tidak yang ditentukan dalam panduan gaya Python, tetapi merekomendasikan konsistensi. Kita memutuskan untuk hanya menggunakan string dengan tanda kutip ganda. Banyak bahasa menggunakan tanda kutip ganda untuk literal string.
Gunakan satu baris kosong antara dua definisi tingkat atas. Argumentasi: struktur file
BUILD
tidak seperti file Python pada umumnya. Hanya memiliki pernyataan tingkat atas. Menggunakan satu baris kosong akan mempersingkat fileBUILD
.