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 repo GitHub, artefak Maven, atau direktori di mesin lokal Anda di luar ruang kerja Anda 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 lebih baru dan berfokus pada modul (dengan nama kode Bzlmod,
dan diaktifkan dengan flag --enable_bzlmod). Kedua sistem dapat digunakan
bersama-sama, tetapi Bzlmod menggantikan sistem WORKSPACE dalam rilis Bazel
mendatang. Lihat panduan migrasi Bzlmod untuk mengetahui cara
bermigrasi.
Dokumen ini menjelaskan konsep seputar pengelolaan dependensi eksternal di Bazel, sebelum membahas lebih detail tentang kedua sistem tersebut secara berurutan.
Konsep
Repositori
Struktur 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. File penanda batas repo akan menandai batas repo; beberapa file tersebut dapat berada bersama dalam satu direktori.
Repositori utama
Repositori tempat perintah Bazel saat ini dijalankan.
Root repositori utama juga dikenal sebagai root ruang kerja.
Ruang kerja
Lingkungan yang digunakan bersama oleh semua perintah Bazel yang dijalankan di repositori utama yang sama. Lingkungan ini mencakup repo utama dan kumpulan semua repo eksternal yang ditentukan.
Perhatikan bahwa secara historis, konsep "repositori" dan "ruang kerja" telah digabungkan; istilah "ruang kerja" sering digunakan untuk merujuk ke repositori utama, dan terkadang bahkan digunakan sebagai sinonim dari "repositori".
Nama repositori kanonis
Nama kanonis yang dapat digunakan untuk merujuk ke repositori. Dalam konteks ruang kerja, setiap repositori memiliki satu nama kanonis. Target di dalam repo
yang nama kanonisnya adalah canonical_name dapat dirujuk 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 merujuk ke repositori dalam konteks repo lain tertentu.
Nama 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 dirujuk 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, "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, dan
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 terkait. Repo 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 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 default-nya adalah true.
Namun, jika ditetapkan 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 cara mengontrol pengambilan.
Tata letak direktori
Setelah diambil, repo dapat ditemukan di subdirektori external di
basis output, dengan 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 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 bahwa tidak ada pernyataan load yang didukung, dan hanya satu fungsi, repo(), yang tersedia. repo() menggunakan argumen yang sama dengan package()
fungsi dalam file BUILD; sedangkan package()
menentukan atribut umum untuk semua target build di dalam paket, repo()
secara analog melakukan hal yang sama 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 langsung dengan definisi repo. Sebagai gantinya, Bzlmod 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 bergantung
padanya. 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 dasarnya:
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, Bazel Central
Registry. Registry menyediakan file MODULE.bazel dependensi, yang memungkinkan Bazel menemukan seluruh grafik dependensi transitif sebelum melakukan resolusi versi.
Setelah resolusi versi, yang memilih satu versi untuk setiap modul, Bazel akan berkonsultasi lagi dengan registry untuk mempelajari cara menentukan repo untuk setiap modul (dalam sebagian besar kasus, menggunakan http_archive).
Modul juga dapat menentukan bagian 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 memungkinkan mereka melakukan tindakan seperti I/O file dan mengirim permintaan jaringan. Selain hal lainnya, ekstensi 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
- Bazel External Dependencies Overhaul (dokumen desain Bzlmod asli)
- Pembicaraan BazelCon 2021 tentang Bzlmod
- Pembicaraan Bazel Community Day tentang Bzlmod
Menentukan repo 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, 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 ini menentukan repo yang nama kanonisnya adalah foo. Dalam sistem WORKSPACE, secara default, nama kanonis repo juga merupakan nama yang terlihat untuk semua repo lainnya.
Lihat daftar lengkap fungsi yang tersedia dalam
WORKSPACE file.
Kekurangan sistem WORKSPACE
Selama bertahun-tahun sejak sistem WORKSPACE diperkenalkan, pengguna telah melaporkan banyak masalah, termasuk:
- Bazel tidak mengevaluasi file
WORKSPACEdari dependensi apa pun, sehingga semua dependensi transitif harus ditentukan dalam fileWORKSPACErepo utama, selain dependensi langsung. - Untuk mengatasi hal ini, project telah mengadopsi pola "deps.bzl", yang menentukan makro yang pada gilirannya menentukan beberapa repo, dan meminta pengguna untuk memanggil makro ini dalam file
WORKSPACEmereka.- Hal ini memiliki masalah tersendiri: makro tidak dapat
loadfile.bzllainnya, 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
WORKSPACEsecara berurutan. Selain itu, dependensi ditentukan menggunakanhttp_archivedengan URL, tanpa informasi versi apa pun. Artinya, tidak ada cara yang andal untuk melakukan resolusi versi dalam kasus dependensi berlian (Abergantung padaBdanC;BdanCbergantung pada versiDyang 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.