Modul Bazel adalah project Bazel yang dapat memiliki beberapa versi, masing-masing memublikasikan metadata tentang modul lain yang menjadi dependensinya. Ini analogi dengan konsep yang sudah dikenal dalam sistem pengelolaan dependensi lainnya, seperti artefak Maven, paket npm, modul Go, atau peti Kargo.
Modul harus memiliki file MODULE.bazel
di root repo-nya (di samping
file WORKSPACE
). File ini adalah manifes modul, yang mendeklarasikan nama,
versi, daftar dependensi langsungnya, dan informasi lainnya. Untuk
contoh dasar:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
Lihat daftar lengkap perintah yang tersedia di file MODULE.bazel
.
Untuk menjalankan resolusi modul, Bazel dimulai dengan membaca file MODULE.bazel
modul root, lalu berulang kali meminta file MODULE.bazel
dependensi dari registry Bazel hingga
menemukan seluruh grafik dependensi.
Secara default, Bazel memilih satu versi dari setiap modul yang akan digunakan. Bazel mewakili setiap modul dengan repo, dan berkonsultasi dengan registry lagi untuk mempelajari cara menentukan setiap repo.
Format versi
Bazel memiliki ekosistem yang beragam dan project menggunakan berbagai skema pembuatan versi. Yang
paling populer sejauh ini adalah SemVer, tetapi ada
juga project penting yang menggunakan skema berbeda seperti
Abseil, yang
versinya berbasis tanggal, misalnya 20210324.2
).
Karena alasan ini, Bzlmod mengadopsi versi spesifikasi SemVer yang lebih santai. Perbedaannya meliputi:
- SemVer menentukan bahwa bagian "rilis" versi harus terdiri dari 3
segmen:
MAJOR.MINOR.PATCH
. Di Bazel, persyaratan ini dilonggarkan sehingga semua segmen diizinkan. - Di SemVer, setiap segmen di bagian "rilis" hanya boleh berupa angka. Di Bazel, metode ini dilonggarkan untuk mengizinkan huruf, dan semantik perbandingan cocok dengan "ID" di bagian "pra-rilis".
- Selain itu, semantik peningkatan versi minor, minor, dan patch tidak diberlakukan. Namun, lihat tingkat kompatibilitas untuk mengetahui detail tentang cara kami menunjukkan kompatibilitas mundur.
Semua versi SemVer yang valid adalah versi modul Bazel yang valid. Selain itu, dua
versi Semveer a
dan b
membandingkan a < b
jika dan hanya jika hal yang sama berlaku saat
dibandingkan sebagai versi modul Bazel.
Pemilihan versi
Pertimbangkan masalah dependensi diamond, yang merupakan hal penting dalam ruang pengelolaan dependensi versi. Misalnya Anda memiliki grafik dependensi:
A 1.0
/ \
B 1.0 C 1.1
| |
D 1.0 D 1.1
Versi D
mana yang sebaiknya digunakan? Untuk menjawab pertanyaan ini, Bzlmod menggunakan
algoritme Minimal Version Selection
(MVS) yang diperkenalkan dalam sistem modul Go. MVS mengasumsikan bahwa semua versi baru modul kompatibel dengan versi sebelumnya, sehingga memilih versi tertinggi yang ditentukan oleh dependensi mana pun (D 1.1
dalam contoh kami). Disebut "minimal"
karena D 1.1
adalah versi paling awal yang dapat memenuhi persyaratan kita,
meskipun D 1.2
atau yang lebih baru ada, kita tidak memilihnya. Penggunaan MVS akan menghasilkan
proses pemilihan versi yang memiliki akurasi tinggi dan dapat direproduksi.
Versi Yanking
Registry dapat mendeklarasikan versi tertentu sebagai ditarik jika harus dihindari
(seperti untuk kerentanan keamanan). Bazel menampilkan error saat memilih
versi modul yang ditarik. Untuk memperbaiki error ini, upgrade ke versi yang lebih baru dan tidak ditarik, atau gunakan flag --allow_yanked_versions
untuk mengizinkan versi yang ditarik secara eksplisit.
Tingkat kompatibilitas
Dalam Go, asumsi MVS tentang kompatibilitas mundur berfungsi karena memperlakukan
versi modul mundur yang tidak kompatibel sebagai modul terpisah. Dalam hal
SemVer, artinya A 1.x
dan A 2.x
dianggap sebagai modul yang berbeda, dan dapat
berdampingan dalam grafik dependensi yang telah diselesaikan. Hal ini nantinya, dimungkinkan dengan
mengenkode versi utama di jalur paket di Go, sehingga tidak ada
konflik waktu kompilasi atau waktu penautan.
Namun, Bazel tidak dapat memberikan jaminan tersebut. Oleh karena itu, Bazel memerlukan nomor "versi utama"
untuk mendeteksi versi yang tidak kompatibel dengan versi sebelumnya. Nomor ini disebut
tingkat kompatibilitas, dan ditentukan oleh setiap versi modul dalam
perintah module()
. Dengan informasi ini, Bazel dapat menampilkan error saat
mendeteksi bahwa versi modul yang sama dengan tingkat kompatibilitas yang berbeda
ada di grafik dependensi yang telah diselesaikan.
Mengganti
Menentukan penggantian dalam file MODULE.bazel
untuk mengubah perilaku
resolusi modul Bazel. Hanya penggantian modul root yang akan diterapkan — jika modul
digunakan sebagai dependensi, penggantiannya akan diabaikan.
Setiap penggantian ditentukan untuk nama modul tertentu, yang memengaruhi semua versinya dalam grafik dependensi. Meskipun hanya penggantian modul root yang berlaku, dependensi tersebut dapat digunakan untuk dependensi transitif yang tidak langsung diandalkan modul root.
Penggantian versi tunggal
single_version_override
memiliki beberapa tujuan:
- Dengan atribut
version
, Anda dapat menyematkan dependensi ke versi tertentu, terlepas dari versi dependensi yang diminta dalam grafik dependensi. - Dengan atribut
registry
, Anda dapat memaksa dependensi ini agar berasal dari registry tertentu, bukan mengikuti proses pemilihan registry normal. - Dengan atribut
patch*
, Anda dapat menentukan sekumpulan patch yang akan diterapkan ke modul yang didownload.
Semua atribut ini bersifat opsional dan dapat dicampur dan dicocokkan satu sama lain.
Penggantian beberapa versi
multiple_version_override
dapat ditentukan untuk mengizinkan beberapa versi modul yang sama untuk berdampingan dalam
grafik dependensi yang telah di-resolve.
Anda dapat menentukan daftar eksplisit versi yang diizinkan untuk modul, yang semuanya harus ada di grafik dependensi sebelum menyelesaikan resolusi — harus ada beberapa dependensi transitif, bergantung pada setiap versi yang diizinkan. Setelah penyelesaian, hanya versi modul yang diizinkan yang tetap ada, sedangkan Bazel mengupgrade versi modul lainnya ke versi terdekat yang lebih tinggi yang diizinkan pada tingkat kompatibilitas yang sama. Jika tidak ada versi yang diizinkan di tingkat kompatibilitas yang sama, Bazel akan menampilkan error.
Misalnya, jika versi 1.1
, 1.3
, 1.5
, 1.7
, dan 2.0
ada dalam grafik dependensi sebelum resolusi dan versi utamanya adalah tingkat kompatibilitasnya:
- Penggantian beberapa versi yang memungkinkan
1.3
,1.7
, dan2.0
menyebabkan1.1
diupgrade ke1.3
,1.5
diupgrade ke1.7
, dan versi lainnya tetap sama. - Penggantian beberapa versi yang memungkinkan
1.5
dan2.0
menghasilkan error, karena1.7
tidak memiliki versi yang lebih tinggi di tingkat kompatibilitas yang sama untuk diupgrade. - Penggantian beberapa versi yang memungkinkan
1.9
dan2.0
menghasilkan error, karena1.9
tidak ada dalam grafik dependensi sebelum penyelesaian.
Selain itu, pengguna juga dapat mengganti registry menggunakan atribut registry
, sama dengan penggantian versi tunggal.
Penggantian non-registrasi
Penggantian non-registrasi sepenuhnya menghapus modul dari resolusi versi. Bazel tidak meminta file MODULE.bazel
ini dari registry, melainkan dari repo itu sendiri.
Bazel mendukung penggantian non- registry berikut:
Nama repositori dan dependensi yang ketat
Nama kanonis dari repo yang mendukung
modul adalah module_name~version
(misalnya, bazel_skylib~1.0.3
). Untuk modul dengan
penggantian non- registry, ganti bagian version
dengan string override
. Perhatikan bahwa format nama kanonis bukanlah API
yang harus Anda andalkan dan dapat berubah kapan saja.
Nama jelas repo yang mendukung
modul ke dependensi langsungnya akan ditetapkan secara default ke nama modulnya, kecuali jika
atribut repo_name
dari perintah
bazel_dep
menyatakan sebaliknya. Perlu diketahui bahwa ini berarti modul hanya dapat menemukan dependensi
langsungnya. Hal ini membantu mencegah kerusakan yang tidak disengaja karena perubahan
dependensi transitif.
Ekstensi modul juga dapat memperkenalkan repo tambahan ke dalam cakupan modul yang terlihat.