Modul Bazel

Laporkan masalah Lihat sumber

Modul Bazel adalah project Bazel yang dapat memiliki beberapa versi, yang masing-masing memublikasikan metadata tentang modul lain yang menjadi dependensinya. Hal ini analog dengan konsep umum dalam sistem pengelolaan dependensi lainnya, seperti artefak Maven, paket npm, modul Go, atau peti Cargo.

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 langsung, dan informasi lainnya. 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")

Untuk melakukan resolusi modul, Bazel memulai 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 kemudian memilih satu versi dari setiap modul untuk digunakan. Bazel mewakili setiap modul dengan repo, dan berkonsultasi lagi dengan registry untuk mempelajari cara menentukan setiap repositori.

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 terkemuka yang menggunakan skema berbeda seperti Abseil, yang versinya berbasis tanggal, misalnya 20210324.2).

Karena alasan ini, Bzlmod mengadopsi versi spesifikasi SemVer yang lebih longgar. Perbedaannya meliputi:

  • SemVer menentukan bahwa bagian "rilis" dari versi harus terdiri dari 3 segmen: MAJOR.MINOR.PATCH. Di Bazel, persyaratan ini dilonggarkan sehingga sejumlah segmen diizinkan.
  • Di SemVer, tiap segmen dalam bagian "rilis" harus berupa digit saja. Di Bazel, hal ini dilonggarkan untuk memungkinkan huruf juga, dan semantik perbandingan cocok dengan "ID" di bagian "prarilis".
  • Selain itu, semantik peningkatan versi utama, minor, dan patch tidak diterapkan. Namun, lihat tingkat kompatibilitas untuk mengetahui detail cara kami menunjukkan kompatibilitas mundur.

Semua versi SemVer yang valid adalah versi modul Bazel yang valid. Selain itu, dua versi SemVer a dan b membandingkan a < b jika dan hanya jika terdapat pemberlakuan yang sama saat dibandingkan sebagai versi modul Bazel.

Pemilihan versi

Pertimbangkan masalah dependensi diamond, yaitu masalah pokok dalam ruang pengelolaan dependensi berversi. Misalkan Anda memiliki grafik dependensi:

       A 1.0
      /     \
   B 1.0    C 1.1
     |        |
   D 1.0    D 1.1

Versi D mana yang harus digunakan? Untuk mengatasi pertanyaan ini, Bzlmod menggunakan algoritma Minimal Version Selection (MVS) yang diperkenalkan dalam sistem modul Go. MVS mengasumsikan bahwa semua versi baru modul kompatibel dengan versi lama, sehingga memilih versi tertinggi yang ditentukan oleh dependen mana pun (D 1.1 dalam contoh kami). Elemen ini disebut "minimal" karena D 1.1 adalah versi paling awal yang dapat memenuhi persyaratan — meskipun D 1.2 atau yang lebih baru ada, kita tidak memilihnya. Penggunaan MVS akan menghasilkan proses pemilihan versi yang berkualitas tinggi dan dapat direproduksi.

Versi Yanked

Registry dapat mendeklarasikan versi tertentu sebagai yanked jika harus dihindari (misalnya untuk kerentanan keamanan). Bazel menampilkan error saat memilih versi modul yang ditarik. Untuk memperbaiki error ini, upgrade ke versi yang lebih baru dan tidak dibatalkan, atau gunakan flag --allow_yanked_versions untuk mengizinkan versi yanked secara eksplisit.

Tingkat kompatibilitas

Dalam Go, asumsi MVS tentang kompatibilitas mundur berfungsi karena akan memperlakukan versi modul yang tidak kompatibel dengan versi sebelumnya sebagai modul terpisah. Dalam SemVer, itu berarti A 1.x dan A 2.x dianggap modul yang berbeda, dan dapat berdampingan dalam grafik dependensi yang di-resolve. Hal ini pada akhirnya dapat dilakukan dengan mengenkode versi utama dalam jalur paket di Go, sehingga tidak ada konflik waktu kompilasi atau waktu penautan.

Namun, Bazel tidak dapat memberikan jaminan tersebut, sehingga memerlukan nomor "versi utama" untuk mendeteksi versi yang tidak kompatibel dengan versi sebelumnya. Angka ini disebut tingkat kompatibilitas, dan ditentukan oleh setiap versi modul dalam perintah module()-nya. Dengan informasi ini, Bazel dapat menampilkan error saat mendeteksi bahwa versi modul yang sama dengan tingkat kompatibilitas yang berbeda ada dalam grafik dependensi yang di-resolve.

Mengganti

Tentukan penggantian dalam file MODULE.bazel untuk mengubah perilaku resolusi modul Bazel. Hanya penggantian modul root yang berlaku — jika modul digunakan sebagai dependensi, penggantiannya akan diabaikan.

Setiap penggantian ditetapkan untuk nama modul tertentu, sehingga memengaruhi semua versinya dalam grafik dependensi. Meskipun hanya penggantian modul root yang berlaku, penggantian ini dapat berlaku untuk dependensi transitif yang tidak langsung bergantung secara langsung oleh modul root.

Penggantian versi tunggal

single_version_override memiliki beberapa tujuan:

  • Dengan atribut version, Anda dapat menyematkan dependensi ke versi tertentu, apa pun versi dependensi yang diminta dalam grafik dependensi.
  • Dengan atribut registry, Anda dapat memaksa dependensi ini berasal dari registry tertentu, bukan mengikuti proses pemilihan registry normal.
  • Dengan atribut patch*, Anda dapat menentukan serangkaian patch untuk diterapkan ke modul yang didownload.

Semua atribut ini bersifat opsional dan dapat dicampur dan dicocokkan satu sama lain.

Penggantian multi-versi

multiple_version_override dapat ditentukan untuk memungkinkan beberapa versi modul yang sama hidup berdampingan dalam grafik dependensi yang telah di-resolve.

Anda dapat menentukan daftar eksplisit versi yang diizinkan untuk modul, yang semuanya harus ada dalam grafik dependensi sebelum penyelesaian — harus ada beberapa dependensi transitif yang bergantung pada setiap versi yang diizinkan. Setelah selesai, hanya versi modul yang diizinkan yang tersisa, sedangkan Bazel mengupgrade versi lain modul ke versi terdekat yang diizinkan dan lebih tinggi pada tingkat kompatibilitas yang sama. Jika tidak ada versi yang lebih tinggi yang diizinkan pada 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 kompatibilitas:

  • Penggantian multi-versi yang mengizinkan 1.3, 1.7, dan 2.0 menyebabkan 1.1 diupgrade ke 1.3, 1.5 diupgrade ke 1.7, dan versi lainnya tetap sama.
  • Penggantian multi-versi yang mengizinkan 1.5 dan 2.0 akan menghasilkan error karena 1.7 tidak memiliki versi yang lebih tinggi dengan tingkat kompatibilitas yang sama untuk diupgrade.
  • Penggantian multi-versi yang mengizinkan 1.9 dan 2.0 akan menghasilkan error, karena 1.9 tidak ada dalam grafik dependensi sebelum resolusi.

Selain itu, pengguna juga dapat mengganti registry menggunakan atribut registry, sama seperti penggantian versi tunggal.

Penggantian non-registry

Penggantian non-registry sepenuhnya menghapus modul dari resolusi versi. Bazel tidak meminta file MODULE.bazel ini dari registry, tetapi dari repo itu sendiri.

Bazel mendukung penggantian non-registry berikut:

Nama repositori dan dependensi ketat

Nama kanonis 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. Perlu diperhatikan bahwa format nama kanonis bukanlah API yang harus Anda gunakan dan dapat berubah sewaktu-waktu.

Nama jelas repo yang mendukung modul ke dependen langsungnya secara default ditetapkan ke nama modul, kecuali jika atribut repo_name dari perintah bazel_dep menentukan sebaliknya. Perlu diperhatikan bahwa ini berarti modul hanya dapat menemukan dependensi langsungnya. Hal ini membantu mencegah kerusakan yang tidak disengaja karena perubahan pada dependensi transitif.

Ekstensi modul juga dapat memasukkan repositori tambahan ke dalam cakupan modul yang terlihat.