Bazel mendukung dependensi eksternal, file sumber (teks dan biner) yang digunakan dalam build Anda yang bukan berasal dari ruang kerja Anda. Misalnya, file tersebut dapat berupa kumpulan aturan yang dihosting di repo GitHub, artefak Maven, atau direktori di komputer lokal Anda di luar ruang kerja saat ini.
Mulai Bazel 6.0, ada dua cara untuk mengelola dependensi eksternal dengan Bazel:
sistem WORKSPACE
tradisional yang berfokus pada repositori, dan
sistem MODULE.bazel
yang berfokus pada modul yang lebih baru (bernama kode Bzlmod,
dan diaktifkan dengan flag --enable_bzlmod
). Kedua sistem tersebut dapat digunakan
bersama-sama, tetapi Bzlmod akan menggantikan sistem WORKSPACE
dalam rilis
Bazel mendatang. Lihat panduan migrasi Bzlmod tentang cara
melakukan migrasi.
Dokumen ini menjelaskan konsep seputar pengelolaan dependensi eksternal di Bazel, sebelum membahas kedua sistem secara berurutan.
Konsep
Repositori
Hierarki 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
mewakili modul Bazel), REPO.bazel
(lihat di bawah), atau dalam
konteks lama, WORKSPACE
atau WORKSPACE.bazel
. Setiap file penanda batas repo
akan menandakan batas repo; beberapa file tersebut dapat berdampingan dalam
direktori.
Repositori utama
Repositori tempat perintah Bazel saat ini dijalankan.
Root repositori utama juga dikenal sebagai root ruang kerja.
Workspace
Lingkungan yang dibagikan 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 dicampuradukkan; istilah "ruang kerja" sering digunakan untuk merujuk ke repositori utama, dan terkadang bahkan digunakan sebagai sinonim dari "repositori".
Nama repositori kanonis
Nama kanonis yang digunakan untuk mengakses repositori. Dalam konteks workspace, setiap repositori memiliki satu nama kanonis. Target di dalam repo
yang namanya kanonis adalah canonical_name
dapat ditangani oleh label
@@canonical_name//package:target
(perhatikan @
ganda).
Repositori utama selalu memiliki string kosong sebagai nama kanonis.
Nama repositori yang terlihat
Nama yang dapat digunakan untuk mengakses repositori dalam konteks repo lain tertentu.
Hal 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 ditangani oleh label
@mike//package:target
dalam konteks alice
(perhatikan @
tunggal).
Sebaliknya, hal ini dapat dipahami sebagai pemetaan repositori: setiap repo mempertahankan pemetaan dari "nama repo yang terlihat" ke "nama repo kanonis".
Aturan repositori
Skema untuk definisi repositori yang memberi tahu Bazel cara mewujudkan
repositori. Misalnya, dapat berupa "download arsip zip dari URL tertentu
dan ekstrak", atau "ambil artefak Maven tertentu dan sediakan sebagai
target java_import
", atau cukup "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 sejauh ini 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 menyediakan repo di disk lokal dengan menjalankan aturan repo terkait. 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 telah diambil sebelumnya, Bazel hanya akan mengambilnya kembali jika definisinya telah berubah.
Perintah fetch
dapat digunakan untuk memulai pengambilan 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 true.
Namun, jika disetel ke salah (--nofetch
), perintah akan menggunakan versi dependensi yang disimpan dalam cache, dan jika tidak ada, perintah akan mengakibatkan kegagalan.
Lihat opsi pengambilan untuk mengetahui informasi selengkapnya tentang cara mengontrol pengambilan.
Tata letak direktori
Setelah diambil, repo dapat ditemukan di subdirektori external
di
basis output, di bawah nama kanonisnya.
Anda dapat menjalankan perintah berikut untuk melihat konten repo dengan
nama kanonis canonical_name
:
ls $(bazel info output_base)/external/ canonical_name
File REPO.bazel
File REPO.bazel
digunakan untuk menandai batas teratas hierarki 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, dan hanya satu fungsi, repo()
, yang
tersedia. repo()
menggunakan argumen yang sama dengan fungsi
package()
dalam file BUILD
; sedangkan package()
menentukan atribut umum untuk semua target build di dalam paket, repo()
secara analog melakukannya 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"],
)
Mengelola dependensi eksternal dengan Bzlmod
Bzlmod, subsistem dependensi eksternal baru, tidak berfungsi secara langsung dengan definisi repo. Sebagai gantinya, alat ini membuat grafik dependensi dari modul, menjalankan ekstensi di atas grafik, dan menentukan repo yang sesuai.
Modul Bazel adalah project Bazel yang dapat memiliki beberapa
versi, yang masing-masing memublikasikan metadata tentang modul lain yang menjadi dependensinya. 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, dan informasi lainnya. Berikut adalah 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")
Modul hanya boleh mencantumkan dependensi langsungnya, yang dicari Bzlmod di
registry Bazel — secara default, Registry Pusat
Bazel. Registry menyediakan
file MODULE.bazel
dependensi, yang memungkinkan Bazel menemukan seluruh
grafik dependensi transitif sebelum melakukan resolusi versi.
Setelah resolusi versi, saat satu versi dipilih untuk setiap modul,
Bazel akan memeriksa kembali registry untuk mempelajari cara menentukan repo untuk setiap modul
(dalam sebagian besar kasus, menggunakan http_archive
).
Modul juga dapat menentukan potongan data yang disesuaikan yang disebut tag, yang digunakan oleh ekstensi modul setelah resolusi modul untuk menentukan repo tambahan. Ekstensi ini memiliki kemampuan yang mirip dengan aturan repo, sehingga dapat melakukan tindakan seperti I/O file dan mengirim permintaan jaringan. Di antara hal lainnya, hal ini memungkinkan Bazel berinteraksi dengan sistem pengelolaan paket lain sekaligus mematuhi grafik dependensi yang dibuat dari modul Bazel.
Link eksternal di Bzlmod
- Contoh penggunaan bzlmod di bazelbuild/examples
- Pembaruan Dependensi Eksternal Bazel (dokumen desain Bzlmod asli)
- Presentasi BazelCon 2021 tentang Bzlmod
- Presentasi Bazel Community Day tentang Bzlmod
Menentukan repositori dengan WORKSPACE
Secara historis, Anda dapat mengelola dependensi eksternal dengan menentukan repo dalam
file WORKSPACE
(atau WORKSPACE.bazel
). File ini memiliki sintaksis yang mirip dengan file BUILD
, yang menggunakan aturan repo, bukan aturan build.
Cuplikan berikut adalah contoh untuk menggunakan 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 untuk
semua repo lainnya.
Lihat daftar lengkap fungsi yang tersedia dalam
file WORKSPACE
.
Kekurangan sistem WORKSPACE
Selama bertahun-tahun sejak sistem WORKSPACE
diperkenalkan, pengguna telah melaporkan
banyak poin masalah, termasuk:
- Bazel tidak mengevaluasi file
WORKSPACE
dari dependensi apa pun, sehingga semua dependensi transitif harus ditentukan dalam fileWORKSPACE
dari repo utama, selain dependensi langsung. - Untuk mengatasi hal ini, project telah mengadopsi pola "deps.bzl", yang
menentukan makro yang pada akhirnya menentukan beberapa repo, dan meminta pengguna untuk
memanggil makro ini dalam file
WORKSPACE
mereka.- Hal ini memiliki 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 resolusi versi dalam kasus dependensi diamond (A
bergantung padaB
danC
;B
danC
keduanya bergantung pada versiD
yang berbeda).
- Hal ini memiliki masalah tersendiri: makro tidak dapat
Karena kekurangan WORKSPACE, Bzlmod akan menggantikan sistem WORKSPACE lama dalam rilis Bazel mendatang. Baca panduan migrasi Bzlmod tentang cara bermigrasi ke Bzlmod.