Panduan Gaya BUILD

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.
Laporkan masalah Lihat sumber

Format file BUILD mengikuti pendekatan yang sama dengan Go, tempat alat standar menangani sebagian besar masalah pemformatan. Buildifier adalah alat yang mengurai dan membuat kode sumber dengan gaya standar. Oleh karena itu, setiap file BUILD diformat dengan cara yang sama otomatis, yang membuat pemformatan bukan masalah selama peninjauan kode. Hal ini juga memudahkan alat untuk memahami, mengedit, dan membuat file BUILD.

Pemformatan file BUILD harus sesuai 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 membuat perbedaan antara komentar yang berdiri sendiri dan komentar yang dilampirkan pada elemen. Jika komentar tidak dilampirkan ke elemen tertentu, gunakan baris kosong setelahnya. Perbedaan ini penting saat melakukan perubahan otomatis (misalnya, untuk mempertahankan 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 yang relatif terhadap direktori paket (tanpa pernah menggunakan referensi ke atas, seperti ..). File yang dihasilkan harus diawali dengan ":" untuk menunjukkan bahwa itu bukan sumber. File sumber tidak boleh diawali dengan :. Aturan harus diawali dengan :. Misalnya, 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 biasanya 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 paket (target dengan nama yang sama seperti direktori yang memuatnya) harus menyediakan fungsi yang dijelaskan oleh nama direktori. Jika tidak ada target seperti itu, jangan buat target eponim.

Lebih baik menggunakan nama pendek saat merujuk ke target yang sama (//x, bukan //x:x). Jika Anda menggunakan paket yang sama, pilih referensi lokal (:x, bukan //x).

Hindari penggunaan nama target "yang dicadangkan" yang memiliki makna khusus. Ini mencakup all, __pkg__, dan __subpackages__, nama-nama ini memiliki semantik khusus dan dapat menyebabkan kebingungan dan perilaku yang tidak terduga saat digunakan.

Jika tidak ada konvensi tim yang berlaku, berikut beberapa rekomendasi non-binding yang digunakan secara luas di Google:

  • Secara umum, gunakan "snake_case"
    • Untuk java_library dengan satu src, ini berarti menggunakan nama yang tidak sama dengan nama file tanpa ekstensi
    • Untuk aturan *_binary dan *_test Java, gunakan "Upper CamelCase". Hal ini memungkinkan nama target cocok dengan salah satu src. Untuk java_test, hal ini memungkinkan atribut test_class disimpulkan dari nama target.
  • Jika ada beberapa varian dari target tertentu, tambahkan akhiran untuk membedakan (seperti :foo_dev, :foo_prod, atau :bar_x86, :bar_x64)
  • Akhiran _test target dengan _test, _unittest, Test, atau Tests
  • Hindari akhiran yang tidak bermakna seperti _lib atau _library (kecuali jika perlu untuk menghindari konflik antara target _library dan _binary terkaitnya)
  • Untuk target terkait proto:
    • proto_library target harus memiliki nama yang diakhiri dengan _proto
    • Aturan bahasa *_proto_library tertentu harus cocok dengan prototipe yang mendasarinya 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 dicakup sedekat mungkin, sekaligus tetap mengizinkan akses dengan pengujian dan dependensi terbalik. Gunakan __pkg__ dan __subpackages__ sebagaimana mestinya.

Hindari menyetel paket default_visibility ke //visibility:public. //visibility:public harus ditetapkan satu per satu hanya untuk target dalam API publik project. Library ini dapat berupa library yang dirancang untuk diandalkan oleh project eksternal atau biner yang dapat digunakan oleh proses build project eksternal.

Dependensi

Dependensi harus dibatasi pada dependensi langsung (dependensi yang diperlukan oleh sumber yang tercantum dalam aturan). Jangan cantumkan dependensi transitif.

Dependensi lokal paket harus dicantumkan terlebih dahulu dan dirujuk dengan cara yang kompatibel dengan bagian Referensi ke target dalam paket saat ini di atas (bukan dengan nama paket absolutnya).

Memilih untuk mencantumkan dependensi secara langsung, sebagai satu daftar. Menempatkan dependensi "common" beberapa target ke dalam variabel akan mengurangi pemeliharaan, membuat alat tidak dapat mengubah dependensi target, dan dapat menyebabkan dependensi yang tidak digunakan.

Globs

Tunjukkan "tidak ada target" dengan []. Jangan gunakan glob yang tidak cocok apa pun: glob lebih rentan terhadap error dan kurang jelas dibandingkan daftar kosong.

Rekursif

Jangan gunakan glob rekursif untuk mencocokkan file sumber (misalnya, glob(["**/*.java"])).

glob rekursif membuat file BUILD sulit untuk dipertimbangkan karena melewati subdirektori yang berisi file BUILD.

glob rekursif umumnya kurang efisien daripada memiliki file BUILD per direktori dengan grafik dependensi yang ditentukan di antaranya karena ini memungkinkan cache jarak jauh dan paralelisme yang lebih baik.

Sebaiknya buat file BUILD di setiap direktori dan tentukan grafik dependensi di antara direktori tersebut.

Tidak berulang

glob non-rekursif secara umum 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 (seperti my_variable).

  • Label tidak boleh dipisahkan, meskipun lebih dari 79 karakter. Label harus berupa string literal jika memungkinkan. Rationale: Menemukan dan mengganti dengan mudah. Hal ini juga meningkatkan keterbacaan.

  • Nilai atribut nama harus berupa string konstan literal (kecuali dalam makro). Rasional: Alat eksternal menggunakan atribut nama untuk merujuk aturan. Mereka harus menemukan aturan tanpa harus menafsirkan kode.

  • Saat menetapkan atribut jenis boolean, gunakan nilai boolean, bukan nilai bilangan bulat. Karena alasan lama, aturan tetap mengonversi bilangan bulat menjadi boolean sesuai kebutuhan, tetapi tidak disarankan. Dasar rasional: flaky = 1 bisa salah dibaca sebagai "deflake target ini dengan menjalankannya kembali". flaky = True tanpa ambigu mengatakan "pengujian ini tidak stabil".

Perbedaan dengan panduan gaya Python

Meskipun kompatibilitas dengan panduan gaya Python adalah sebuah sasaran, ada beberapa perbedaan:

  • Tanpa batas panjang baris yang ketat. Komentar panjang dan string panjang sering dibagi menjadi 79 kolom, tetapi tidak wajib. Ini tidak boleh diterapkan dalam peninjauan kode atau skrip pra-pengiriman. Rasional: Label bisa panjang dan melebihi batas ini. File BUILD biasanya dibuat atau diedit oleh alat, yang tidak sesuai dengan batas panjang baris.

  • Penyambungan string implisit tidak didukung. Gunakan operator +. Rasional: File BUILD berisi banyak daftar string. Sangat mudah untuk melupakan koma, yang menyebabkan hasil yang berbeda sepenuhnya. Hal ini menyebabkan banyak bug di masa lalu. Lihat juga diskusi ini.

  • Gunakan spasi di sekitar tanda = untuk argumen kata kunci dalam aturan. Rasional: Argumen bernama jauh lebih sering daripada di Python dan selalu berada di baris terpisah. Spasi meningkatkan keterbacaan. Konvensi ini telah ada sejak lama, dan tidak ada baiknya Anda mengubah semua file BUILD yang ada.

  • Secara default, gunakan tanda petik ganda untuk string. Rasional: Ini tidak ditentukan dalam panduan gaya Python, tetapi merekomendasikan konsistensi. Jadi, kami memutuskan untuk hanya menggunakan string dengan tanda kutip ganda. Banyak bahasa menggunakan tanda kutip ganda untuk literal string.

  • Gunakan satu baris kosong di antara dua definisi level teratas. Rasional: Struktur file BUILD tidak seperti file Python biasa. Laporan ini hanya memiliki pernyataan tingkat atas. Penggunaan baris kosong tunggal akan membuat file BUILD lebih pendek.