Aturan Repositori

Halaman ini membahas cara membuat aturan repositori dan memberikan contoh untuk mengetahui detail selengkapnya.

Repositori eksternal adalah aturan yang hanya dapat digunakan dalam file WORKSPACE dan memungkinkan operasi non-hermetik pada fase pemuatan Bazel. Setiap aturan repositori eksternal membuat ruang kerjanya sendiri, dengan file dan artefak BUILD miliknya sendiri. Aturan ini dapat digunakan untuk bergantung pada library pihak ketiga (seperti library yang dikemas Maven), tetapi juga untuk membuat file BUILD yang khusus untuk host tempat Bazel berjalan.

Pembuatan aturan repositori

Dalam file .bzl, gunakan fungsi repository_rule untuk membuat aturan repositori baru dan menyimpannya dalam variabel global.

Aturan repositori kustom dapat digunakan seperti aturan repositori bawaan. Aturan ini memiliki atribut name wajib dan setiap target yang ada dalam file build-nya dapat dirujuk sebagai @<name>//package:target dengan <name> adalah nilai atribut name.

Aturan dimuat saat Anda mem-build-nya secara eksplisit, atau jika aturan tersebut adalah dependensi build. Dalam hal ini, Bazel akan menjalankan fungsi implementation. Fungsi ini menjelaskan cara membuat repositori, kontennya, dan file BUILD.

Atribut

Atribut adalah argumen aturan yang diteruskan sebagai dict ke argumen aturan attrs. Atribut dan jenisnya ditentukan dan dicantumkan saat Anda menentukan aturan repositori. Contoh yang menentukan atribut url dan sha256 sebagai string:

local_repository = repository_rule(
    implementation=_impl,
    local=True,
    attrs={
        "url": attr.string(mandatory=True)
        "sha256": attr.string(mandatory=True)
    }
)

Untuk mengakses atribut dalam fungsi penerapan, gunakan repository_ctx.attr.<attribute_name>:

def _impl(repository_ctx):
    url = repository_ctx.attr.url
    checksum = repository_ctx.attr.sha256

Semua repository_rule memiliki atribut yang ditentukan secara implisit (seperti aturan build). Dua atribut implisit adalah name (seperti untuk aturan build) dan repo_mapping. Nama aturan repositori dapat diakses dengan repository_ctx.name. Arti repo_mapping sama dengan aturan repositori bawaan local_repository dan new_local_repository.

Jika nama atribut dimulai dengan _, atribut tersebut bersifat pribadi dan pengguna tidak dapat menetapkannya.

Fungsi penerapan

Setiap aturan repositori memerlukan fungsi implementation. Fungsi ini berisi logika sebenarnya dari aturan dan dijalankan secara ketat dalam Fase Pemuatan.

Fungsi ini memiliki tepat satu parameter input, repository_ctx. Fungsi ini menampilkan None untuk menandakan bahwa aturan dapat direproduksi dengan parameter yang ditentukan, atau dict dengan kumpulan parameter untuk aturan yang akan mengubah aturan tersebut menjadi aturan yang dapat direproduksi yang menghasilkan repositori yang sama. Misalnya, untuk aturan yang melacak repositori git, hal ini berarti menampilkan ID commit tertentu, bukan cabang floating yang awalnya ditentukan.

Parameter input repository_ctx dapat digunakan untuk mengakses nilai atribut, dan fungsi non-hermetik (menemukan biner, menjalankan biner, membuat file di repositori, atau mendownload file dari Internet). Lihat library untuk mengetahui konteks selengkapnya. Contoh:

def _impl(repository_ctx):
  repository_ctx.symlink(repository_ctx.attr.path, "")

local_repository = repository_rule(
    implementation=_impl,
    ...)

Kapan fungsi penerapan dijalankan?

Fungsi penerapan repositori dijalankan saat Bazel memerlukan target dari repositori tersebut, misalnya saat target lain (di repositori lain) bergantung padanya atau jika disebutkan di command line. Fungsi penerapan kemudian diharapkan untuk membuat repositori dalam sistem file. Hal ini disebut "mengambil" repositori.

Berbeda dengan target reguler, repositori tidak selalu diambil ulang saat ada perubahan yang akan menyebabkan repositori menjadi berbeda. Hal ini karena ada hal-hal yang Bazel tidak dapat mendeteksi perubahannya atau akan menyebabkan terlalu banyak overhead pada setiap build (misalnya, hal-hal yang diambil dari jaringan). Oleh karena itu, repositori hanya diambil ulang jika salah satu hal berikut berubah:

  • Parameter yang diteruskan ke deklarasi repositori dalam file WORKSPACE.
  • Kode Starlark yang terdiri dari penerapan repositori.
  • Nilai variabel lingkungan apa pun yang diteruskan ke repository_ctx's getenv() metode atau dideklarasikan dengan atribut environ dari repository_rule. Nilai variabel lingkungan ini dapat dikodekan secara permanen di command line dengan flag --repo_env.
  • Konten file apa pun yang diteruskan ke metode read(), execute(), dan metode serupa dari repository_ctx yang dirujuk oleh label (misalnya, //mypkg:label.txt, tetapi bukan mypkg/label.txt)
  • Saat bazel sync dijalankan.

Ada dua parameter repository_rule yang mengontrol kapan repositori diambil ulang:

  • Jika flag configure ditetapkan, repositori hanya diambil ulang di bazel sync saat parameter --configure diteruskan ke repositori (jika atribut tidak ditetapkan, perintah ini tidak akan menyebabkan pengambilan ulang)
  • Jika flag local ditetapkan, selain kasus di atas, repositori juga diambil ulang saat server Bazel dimulai ulang atau saat file apa pun yang memengaruhi deklarasi repositori berubah (misalnya, file WORKSPACE atau file yang dimuatnya), terlepas dari apakah perubahan tersebut mengakibatkan perubahan pada deklarasi repositori atau kodenya.

    Repositori non-lokal tidak diambil ulang dalam kasus ini. Hal ini karena repositori ini diasumsikan berkomunikasi dengan jaringan atau mahal.

Memulai ulang fungsi penerapan

Fungsi penerapan dapat dimulai ulang saat repositori diambil jika dependensi yang dimintanya tidak ada. Dalam hal ini, eksekusi fungsi penerapan akan berhenti, dependensi yang tidak ada akan diselesaikan, dan fungsi akan dieksekusi ulang setelah dependensi diselesaikan. Untuk menghindari memulai ulang yang tidak perlu (yang mahal, karena akses jaringan mungkin harus diulang), argumen label akan diambil sebelumnya, asalkan semua argumen label dapat diselesaikan ke file yang ada. Perhatikan bahwa menyelesaikan jalur dari string atau label yang dibuat hanya selama eksekusi fungsi mungkin masih menyebabkan memulai ulang.

Memaksa pengambilan ulang repositori eksternal

Terkadang, repositori eksternal dapat menjadi tidak berlaku tanpa ada perubahan pada definisi atau dependensinya. Misalnya, repositori yang mengambil sumber mungkin mengikuti cabang tertentu dari repositori pihak ketiga, dan commit baru tersedia di cabang tersebut. Dalam hal ini, Anda dapat meminta bazel untuk mengambil ulang semua repositori eksternal tanpa syarat dengan memanggil bazel sync.

Selain itu, beberapa aturan memeriksa mesin lokal dan mungkin menjadi tidak berlaku jika mesin lokal diupgrade. Di sini, Anda dapat meminta bazel untuk hanya mengambil ulang repositori eksternal yang repository_rule definisinya memiliki atribut configure yang ditetapkan, gunakan bazel sync --configure.

Contoh

  • Rantai alat yang dikonfigurasi otomatis C++: menggunakan aturan repositori untuk membuat file konfigurasi C++ secara otomatis untuk Bazel dengan mencari compiler C++ lokal, lingkungan, dan flag yang didukung compiler C++.

  • Repositori Go menggunakan beberapa repository_rule untuk menentukan daftar dependensi yang diperlukan untuk menggunakan aturan Go.

  • rules_jvm_external membuat repositori eksternal yang disebut @maven secara default yang menghasilkan target build untuk setiap artefak Maven di pohon dependensi transitif.