Modul Bazel

Laporkan masalah Lihat sumber Per malam · 7,4 kami. 7.3 · 7.2 · 7.1 · 7.0 · 6.5

Modul Bazel adalah project Bazel yang dapat memiliki beberapa versi, masing-masing yang memublikasikan metadata tentang modul lain yang menjadi dependensinya. Ini adalah analog dengan konsep yang sudah dikenal dalam sistem manajemen dependensi lainnya, seperti Artefak Maven, paket npm, modul Go, atau peti Cargo.

Modul harus memiliki file MODULE.bazel di root repo-nya. File ini adalah manifes modul, yang mendeklarasikan nama, versi, daftar dependensi langsung, 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 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 lalu memilih satu versi dari setiap modul untuk digunakan. Bazel merepresentasikan setiap modul dengan repo, dan memeriksa kembali registry untuk mempelajari cara menentukan setiap repo.

Format versi

Bazel memiliki ekosistem yang beragam dan proyek menggunakan berbagai skema pembuatan versi. Tujuan yang paling populer sejauh ini adalah SemVer, tetapi ada juga proyek terkemuka menggunakan berbagai skema seperti Abseil, yang versi berbasis tanggal, misalnya 20210324.2).

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

  • SemVer menetapkan bahwa bagian "rilis" dari versi harus terdiri dari 3 segmen: MAJOR.MINOR.PATCH. Di Bazel, persyaratan ini dilonggarkan sehingga jumlah segmen apa pun diizinkan.
  • Di SemVer, setiap segmen dalam "rilis" bagian harus dalam angka saja. Di Bazel, hal ini dilonggarkan untuk mengizinkan huruf juga, dan semantik perbandingan cocok dengan "ID" di bagian "pra-rilis".
  • Selain itu, semantik peningkatan versi utama, minor, dan patch tidak diterapkan. 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 SemVer a dan b membandingkan a < b jika dan hanya jika nilai yang sama berlaku saat mereka dibandingkan sebagai versi modul Bazel.

Pemilihan versi

Pertimbangkan masalah dependensi berlian, yang merupakan hal umum di 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 menyelesaikan pertanyaan ini, Bzlmod menggunakan algoritma Minimal Version Selection (MVS) yang diperkenalkan dalam sistem modul Go. MVS mengasumsikan bahwa semua versi modulnya kompatibel dengan versi sebelumnya, sehingga memilih versi tertinggi yang ditentukan oleh dependen apa pun (D 1.1 dalam contoh kita). Namanya "minimal" karena D 1.1 adalah versi paling awal yang dapat memenuhi persyaratan kami — meskipun ada D 1.2 atau yang lebih baru, kita tidak memilihnya. Menggunakan MVS akan membuat proses pemilihan versi yang dengan fidelitas tinggi dan dapat direproduksi.

Versi Yanked

Registry dapat mendeklarasikan versi tertentu sebagai dicabut jika harus dihindari (misalnya karena 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

Di Go, asumsi MVS tentang kompatibilitas mundur berfungsi karena memperlakukan versi modul yang tidak kompatibel dengan versi sebelumnya sebagai modul terpisah. Dalam hal SemVer, artinya A 1.x dan A 2.x dianggap sebagai modul yang berbeda, dan dapat bersama-sama ada dalam grafik dependensi yang di-resolve. Hal ini, pada gilirannya, 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, sehingga 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 direktif module()-nya. Dengan informasi ini, Bazel dapat memberikan {i>error<i} saat ia mendeteksi bahwa versi modul yang sama dengan tingkat kompatibilitas yang berbeda ada di grafik dependensi yang di-resolve.

Ganti

Tentukan penggantian dalam file MODULE.bazel untuk mengubah perilaku resolusi modul Bazel. Hanya penggantian modul {i>root<i} yang akan berlaku — 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, penggantian tersebut dapat dilakukan untuk dependensi transitif yang tidak langsung bergantung pada 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 berasal dari registry tertentu, bukan mengikuti proses pemilihan registry normal.
  • Dengan atribut patch*, Anda dapat menentukan kumpulan patch yang akan diterapkan 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 memungkinkan beberapa versi modul yang sama hidup berdampingan dalam menyelesaikan grafik dependensi.

Anda dapat menentukan daftar eksplisit versi yang diizinkan untuk modul, yang semuanya harus ada dalam grafik dependensi sebelum resolusi — harus ada beberapa dependensi transitif bergantung pada setiap versi yang diizinkan. Sesudah hanya versi modul yang diizinkan yang masih ada, sementara Bazel melakukan upgrade versi lain dari modul ke versi terdekat yang diizinkan lebih tinggi secara bersamaan tingkat kompatibilitas. Jika tidak ada versi lebih tinggi yang diizinkan dengan kompatibilitas yang sama Bazel akan menampilkan pesan {i>error<i}.

Misalnya, jika versi 1.1, 1.3, 1.5, 1.7, dan 2.0 ada di grafik dependensi sebelum resolusi dan versi utamanya adalah tingkat:

  • Penggantian beberapa versi yang memungkinkan 1.3, 1.7, dan 2.0 menghasilkan 1.1 sedang diupgrade ke 1.3, 1.5 sedang diupgrade ke 1.7, dan versi tetap sama.
  • Penggantian beberapa versi yang memungkinkan 1.5 dan 2.0 akan menghasilkan error, karena 1.7 tidak memiliki versi yang lebih tinggi pada tingkat kompatibilitas yang sama untuk diupgrade.
  • Penggantian beberapa versi yang memungkinkan 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 registry , mirip dengan penggantian satu versi.

Penggantian non-registry

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

Bazel mendukung penggantian non-registry berikut:

Menentukan repo yang tidak merepresentasikan modul Bazel

Dengan bazel_dep, Anda dapat menentukan repositori yang mewakili modul Bazel lainnya. Terkadang perlu menentukan repo yang tidak merepresentasikan modul Bazel; misalnya, repo yang berisi file JSON biasa untuk dibaca sebagai data.

Dalam hal ini, Anda dapat menggunakan direktif use_repo_rule untuk menentukan repo secara langsung dengan memanggil aturan repo. Repo ini hanya akan terlihat oleh modul tempatnya didefinisikan.

Pada prinsipnya, konfigurasi ini diterapkan menggunakan mekanisme yang sama dengan modul ekstensi, yang memungkinkan Anda menentukan repositori dengan fleksibilitas.

Nama repositori dan dependensi ketat

Nama jelas repo yang mendukung modul ke dependensi langsungnya secara default adalah nama modulnya, kecuali jika atribut repo_name dari bazel_dep perintah tersebut menyatakan sebaliknya. Perhatikan bahwa hal ini berarti modul hanya dapat menemukan dependensi langsungnya. Hal ini membantu mencegah kerusakan yang tidak disengaja karena perubahan dependensi transitif.

Nama kanonis repo yang mendukung modul adalah module_name+version (misalnya, bazel_skylib+1.0.3) atau module_name+ (misalnya, bazel_features+), bergantung pada apakah ada beberapa versi modul di seluruh grafik dependensi (lihat multiple_version_override). Perhatikan bahwa format nama kanonis bukanlah API yang harus Anda andalkan dan dapat berubah kapan saja. Alih-alih melakukan {i>hard-coding<i} nama kanonis, gunakan cara yang didukung untuk mendapatkannya langsung dari Bazel: * Dalam file BUILD dan .bzl, gunakan Label.repo_name pada instance Label dibuat dari string label yang diberikan oleh nama jelas repo, misalnya, Label("@bazel_skylib").repo_name. * Saat mencari runfile, gunakan $(rlocationpath ...) atau salah satu library {i> runfile<i} di @bazel_tools//tools/{bash,cpp,java}/runfiles atau, untuk kumpulan aturan rules_foo, di @rules_foo//foo/runfiles. * Saat berinteraksi dengan Bazel dari alat eksternal seperti IDE atau bahasa server, gunakan perintah bazel mod dump_repo_mapping untuk mendapatkan pemetaan dari nama jelas menjadi nama kanonis untuk sekumpulan repositori tertentu.

Ekstensi modul juga dapat memperkenalkan repo tambahan ke dalam cakupan modul yang terlihat.