Bazel mendukung dependensi eksternal, file sumber (teks dan biner) yang digunakan dalam build Anda yang bukan dari ruang kerja Anda. Misalnya, file tersebut dapat berupa kumpulan aturan yang dihosting di repositori GitHub, artefak Maven, atau direktori di komputer lokal Anda di luar ruang kerja saat ini.
Dokumen ini memberikan ringkasan sistem sebelum memeriksa beberapa konsep secara lebih mendetail.
Ringkasan sistem
Sistem dependensi eksternal Bazel berfungsi berdasarkan modul Bazel, yang masing-masing merupakan project Bazel yang diberi versi, dan repositori (atau repositori), yang merupakan hierarki direktori yang berisi file sumber.
Bazel dimulai dari modul root, yaitu project yang sedang Anda kerjakan.
Seperti semua modul, modul ini harus memiliki file MODULE.bazel
di root direktorinya,
yang mendeklarasikan metadata dasar dan dependensi langsungnya. Berikut adalah contoh
dasar:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "platforms", version = "0.0.11")
Dari sana, Bazel akan mencari semua modul dependensi transitif di
registry Bazel — secara default, Bazel Central
Registry. Registry menyediakan file MODULE.bazel
dependensi, yang memungkinkan Bazel menemukan seluruh grafik dependensi transitif sebelum melakukan penyelesaian versi.
Setelah penyelesaian versi, yang memilih satu versi untuk setiap modul, Bazel berkonsultasi dengan registry lagi untuk mempelajari cara menentukan repo untuk setiap modul -- yaitu, cara mengambil sumber untuk setiap modul dependensi. Sebagian besar waktu, file ini hanyalah arsip yang didownload dari internet dan diekstrak.
Modul juga dapat menentukan potongan data yang disesuaikan yang disebut tag, yang digunakan oleh ekstensi modul setelah penyelesaian modul untuk menentukan repositori tambahan. Ekstensi ini dapat melakukan tindakan seperti I/O file dan mengirim permintaan jaringan. Selain itu, mereka memungkinkan Bazel berinteraksi dengan sistem pengelolaan paket lain sekaligus mematuhi grafik dependensi yang dibuat dari modul Bazel.
Tiga jenis repositori -- repositori utama (yang merupakan pohon sumber tempat Anda
bekerja), repositori yang merepresentasikan modul dependensi transitif, dan repositori
yang dibuat oleh ekstensi modul -- membentuk ruang kerja bersama-sama.
Repositori eksternal (repositori non-utama) diambil sesuai permintaan, misalnya saat
dirujuk oleh label (seperti @repo//pkg:target
) dalam file BUILD.
Manfaat
Sistem dependensi eksternal Bazel menawarkan berbagai manfaat.
Resolusi Dependensi Otomatis
- Penyelesaian Versi Deterministik: Bazel mengadopsi algoritma penyelesaian versi MVS deterministik, yang meminimalkan konflik dan mengatasi masalah dependensi berlian.
- Pengelolaan Dependensi yang Disederhanakan:
MODULE.bazel
hanya mendeklarasikan dependensi langsung, sementara dependensi transitif diselesaikan secara otomatis, sehingga memberikan ringkasan yang lebih jelas tentang dependensi project. - Visibilitas Dependensi Ketat: Hanya dependensi langsung yang terlihat, sehingga memastikan kebenaran dan prediktabilitas.
Integrasi Ekosistem
- Bazel Central Registry: Repositori terpusat untuk menemukan dan mengelola dependensi umum sebagai modul Bazel.
- Adopsi Project Non-Bazel: Saat project non-Bazel (biasanya library C++) diadaptasi untuk Bazel dan tersedia di BCR, integrasinya akan dipermudah untuk seluruh komunitas dan menghilangkan upaya duplikat serta konflik file BUILD kustom.
- Integrasi Terpadu dengan Pengelola Paket Khusus Bahasa: Ruleset menyederhanakan integrasi dengan pengelola paket eksternal untuk dependensi non-Bazel, termasuk:
- rules_jvm_external untuk Maven,
- rules_python untuk PyPi,
- bazel-gazelle untuk Modul Go,
- rules_rust untuk Cargo.
Fitur Lanjutan
- Ekstensi Modul: Fitur
use_repo_rule
dan ekstensi modul memungkinkan penggunaan fleksibel aturan repositori kustom dan logika penyelesaian untuk memperkenalkan dependensi non-Bazel. - Perintah
bazel mod
: Sub-perintah ini menawarkan cara yang efektif untuk memeriksa dependensi eksternal. Anda tahu persis bagaimana dependensi eksternal ditentukan dan dari mana asalnya. - Mode Vendor: Melakukan pengambilan data awal dependensi eksternal yang tepat yang Anda butuhkan untuk memfasilitasi build offline.
- Lockfile: Lockfile meningkatkan kemampuan reproduksi build dan mempercepat resolusi dependensi.
- (Segera Hadir) Pengesahan Asal-Usul BCR: Memperkuat keamanan supply chain dengan memastikan asal-usul dependensi yang terverifikasi.
Konsep
Bagian ini memberikan detail lebih lanjut tentang konsep yang terkait dengan dependensi eksternal.
Modul
Project Bazel yang dapat memiliki beberapa versi, yang masing-masing dapat memiliki dependensi pada modul lain.
Di ruang kerja Bazel lokal, modul direpresentasikan oleh repositori.
Untuk mengetahui detail selengkapnya, lihat Modul Bazel.
Repositori
Pohon direktori dengan file penanda batas di root-nya, yang berisi file sumber yang dapat digunakan dalam build Bazel. Sering disingkat menjadi repo.
File penanda batas repo dapat berupa MODULE.bazel
(menandakan bahwa repo ini merepresentasikan modul Bazel), REPO.bazel
(lihat di bawah), atau dalam konteks lama, WORKSPACE
atau WORKSPACE.bazel
. File penanda batas repo apa pun akan menandakan batas repo; beberapa file tersebut dapat berada bersama dalam direktori.
Repositori utama
Repositori tempat perintah Bazel saat ini dijalankan.
Root repositori utama juga dikenal sebagai root ruang kerja.
Ruang kerja
Lingkungan yang digunakan oleh semua perintah Bazel berjalan di repositori utama yang sama. Repositori ini mencakup repo utama dan kumpulan semua repo eksternal yang ditentukan.
Perhatikan bahwa secara historis konsep "repositori" dan "ruang kerja" telah disamakan; istilah "ruang kerja" sering digunakan untuk merujuk ke repositori utama, dan terkadang bahkan digunakan sebagai sinonim dari "repositori".
Nama repositori kanonis
Nama yang selalu dapat digunakan untuk mengakses repositori. Dalam konteks ruang kerja, setiap repositori memiliki satu nama kanonis. Target di dalam repo
yang nama kanonisnya adalah canonical_name
dapat diakses dengan label
@@canonical_name//package:target
(perhatikan @
ganda).
Repositori utama selalu memiliki string kosong sebagai nama kanonis.
Nama repositori yang terlihat
Nama yang digunakan untuk memanggil repositori dalam konteks repositori lain tertentu. Ini dapat dianggap sebagai "nama panggilan" repo: Repo dengan nama kanonis michael
mungkin memiliki nama yang terlihat mike
dalam konteks repo alice
, tetapi mungkin memiliki nama yang terlihat mickey
dalam konteks repo bob
. Dalam hal ini, target di dalam michael
dapat diakses oleh label
@mike//package:target
dalam konteks alice
(perhatikan @
tunggal).
Sebaliknya, ini dapat dipahami sebagai pemetaan repositori: setiap repositori mempertahankan pemetaan dari "nama repositori yang terlihat" ke "nama repositori kanonis".
Aturan repositori
Skema untuk definisi repositori yang memberi tahu Bazel cara mewujudkan repositori. Misalnya, "download arsip zip dari URL tertentu
dan ekstrak", atau "ambil artefak Maven tertentu dan sediakan sebagai target
java_import
", atau cukup "buat symlink direktori lokal". Setiap repo ditentukan dengan memanggil aturan repo dengan jumlah argumen yang sesuai.
Lihat Aturan repositori untuk mengetahui informasi selengkapnya tentang cara menulis aturan repositori Anda sendiri.
Aturan repo yang paling umum adalah
http_archive
, yang mendownload arsip
dari URL dan mengekstraknya, serta
local_repository
, yang membuat symlink
direktori lokal yang sudah menjadi repositori Bazel.
Mengambil repositori
Tindakan membuat repo tersedia di disk lokal dengan menjalankan aturan repo terkaitnya. Repositori yang ditentukan di ruang kerja tidak tersedia di disk lokal sebelum diambil.
Biasanya, Bazel hanya mengambil repo saat memerlukan sesuatu dari repo, dan repo belum diambil. Jika repo sudah diambil sebelumnya, Bazel hanya akan mengambilnya kembali jika definisinya telah berubah.
Perintah fetch
dapat digunakan untuk memulai pengambilan data awal untuk repositori, target, atau semua repositori yang diperlukan untuk melakukan build apa pun. Kemampuan ini memungkinkan build offline menggunakan opsi --nofetch
.
Opsi --fetch
berfungsi untuk mengelola akses jaringan. Nilai defaultnya adalah benar (true).
Namun, jika disetel ke false (--nofetch
), perintah akan menggunakan versi dependensi yang di-cache, dan jika tidak ada, perintah akan gagal.
Lihat opsi pengambilan untuk mengetahui informasi selengkapnya tentang mengontrol pengambilan.
Tata letak direktori
Setelah diambil, repo dapat ditemukan di subdirektori external
di
output base, dengan nama kanonisnya.
Anda dapat menjalankan perintah berikut untuk melihat konten repositori dengan
nama kanonis canonical_name
:
ls $(bazel info output_base)/external/ canonical_name
File REPO.bazel
File REPO.bazel
digunakan untuk menandai batas
paling atas dari struktur direktori yang membentuk repo. File ini tidak perlu berisi apa pun untuk berfungsi sebagai file batas repo; namun, file ini juga dapat digunakan untuk menentukan beberapa atribut umum untuk semua target build di dalam repo.
Sintaksis file REPO.bazel
mirip dengan file BUILD
, kecuali tidak ada pernyataan
load
yang didukung. Fungsi repo()
mengambil argumen yang sama dengan fungsi package()
dalam file BUILD
; sedangkan package()
menentukan atribut umum untuk semua target build di dalam paket, repo()
melakukannya secara analog untuk semua target build di dalam repo.
Misalnya, Anda dapat menentukan lisensi umum untuk semua target di repo dengan memiliki file REPO.bazel
berikut:
repo(
default_package_metadata = ["//:my_license"],
)
Sistem WORKSPACE lama
Pada versi Bazel yang lebih lama (sebelum 9.0), dependensi eksternal diperkenalkan dengan
menentukan repositori dalam file WORKSPACE
(atau WORKSPACE.bazel
). File ini memiliki sintaksis yang serupa dengan file BUILD
, menggunakan aturan repo, bukan aturan build.
Cuplikan berikut adalah contoh penggunaan aturan repo http_archive
dalam
file WORKSPACE
:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
Cuplikan menentukan repo yang nama kanonisnya adalah foo
. Di sistem WORKSPACE
, secara default, nama kanonis repo juga merupakan nama yang terlihat oleh semua repo lainnya.
Lihat daftar lengkap fungsi yang tersedia dalam file
WORKSPACE
.
Kekurangan sistem WORKSPACE
Pada tahun-tahun setelah sistem WORKSPACE
diperkenalkan, pengguna melaporkan banyak masalah, termasuk:
- Bazel tidak mengevaluasi file
WORKSPACE
dari dependensi apa pun, sehingga semua dependensi transitif harus ditentukan dalam fileWORKSPACE
repositori utama, selain dependensi langsung. - Untuk mengatasi hal ini, project telah mengadopsi pola "deps.bzl", yang di dalamnya
project menentukan makro yang pada gilirannya menentukan beberapa repo, dan meminta pengguna untuk
memanggil makro ini dalam file
WORKSPACE
mereka.- Hal ini menimbulkan masalah tersendiri: makro tidak dapat
load
file.bzl
lainnya, sehingga project ini harus menentukan dependensi transitifnya dalam makro "deps" ini, atau mengatasi masalah ini dengan meminta pengguna memanggil beberapa makro "deps" berlapis. - Bazel mengevaluasi file
WORKSPACE
secara berurutan. Selain itu, dependensi ditentukan menggunakanhttp_archive
dengan URL, tanpa informasi versi apa pun. Artinya, tidak ada cara yang andal untuk melakukan penyelesaian versi dalam kasus dependensi berlian (A
bergantung padaB
danC
;B
danC
bergantung pada versiD
yang berbeda).
- Hal ini menimbulkan masalah tersendiri: makro tidak dapat
Karena kekurangan WORKSPACE, sistem berbasis modul baru (dengan nama kode "Bzlmod") secara bertahap menggantikan sistem WORKSPACE lama antara Bazel 6 dan 9. Baca panduan migrasi Bzlmod tentang cara bermigrasi ke Bzlmod.