Halaman ini menjawab beberapa pertanyaan umum (FAQ) tentang dependensi eksternal di Bazel.
MODULE.bazel
Mengapa MODULE.bazel tidak mendukung load
?
Selama resolusi dependensi, file MODULE.bazel dari semua dependensi eksternal
yang direferensikan diambil dari registry. Pada tahap ini, arsip sumber
dependensi belum diambil; jadi, jika file MODULE.bazel load
adalah file lain, tidak ada cara bagi Bazel untuk benar-benar mengambil file tersebut tanpa
mengambil seluruh arsip sumber. Perhatikan bahwa file MODULE.bazel itu sendiri bersifat khusus, karena dihosting langsung di registry.
Ada beberapa kasus penggunaan yang umumnya diminati oleh orang yang meminta load
di MODULE.bazel, dan kasus tersebut dapat diselesaikan tanpa load
:
- Memastikan bahwa versi yang tercantum di MODULE.bazel konsisten dengan metadata
build yang disimpan di tempat lain, misalnya dalam file .bzl: Hal ini dapat dilakukan
dengan menggunakan
metode
native.module_version
dalam file .bzl yang dimuat dari file BUILD. - Membagi file MODULE.bazel yang sangat besar menjadi beberapa bagian yang dapat dikelola,
terutama untuk monorepo: Modul root dapat menggunakan
perintah
include
untuk membagi file MODULE.bazel menjadi beberapa segmen. Karena alasan yang sama, kami tidak mengizinkanload
dalam file MODULE.bazel,include
tidak dapat digunakan dalam modul non-root. - Pengguna sistem WORKSPACE lama mungkin ingat mendeklarasikan repo, lalu
langsung
load
dari repo tersebut untuk menjalankan logika yang kompleks. Kemampuan ini telah diganti dengan ekstensi modul.
Dapatkah saya menentukan rentang SemVer untuk bazel_dep
?
Tidak. Beberapa pengelola paket lain seperti npm dan Cargo mendukung rentang versi (secara implisit atau eksplisit), dan hal ini sering kali memerlukan pemecah batasan (sehingga output lebih sulit diprediksi bagi pengguna) dan membuat resolusi versi tidak dapat direproduksi tanpa file kunci.
Sebagai gantinya, Bazel menggunakan Minimal Version Selection seperti Go, yang justru membuat output mudah diprediksi dan menjamin reproducibilitas. Ini adalah kompromi yang cocok dengan sasaran desain Bazel.
Selain itu, versi modul Bazel adalah superset SemVer, sehingga hal yang masuk akal dalam lingkungan SemVer yang ketat tidak selalu diterapkan ke versi modul Bazel.
Dapatkah saya otomatis mendapatkan versi terbaru untuk bazel_dep
?
Beberapa pengguna terkadang meminta kemampuan untuk menentukan bazel_dep(name = "foo",
version = "latest")
guna mendapatkan versi terbaru dep secara otomatis. Hal ini
mirip dengan pertanyaan tentang rentang
SemVer, dan jawabannya juga
tidak.
Solusi yang direkomendasikan di sini adalah dengan menggunakan otomatisasi untuk menanganinya. Misalnya, Renovate mendukung modul Bazel.
Terkadang, pengguna yang mengajukan pertanyaan ini benar-benar mencari cara untuk melakukan iterasi
dengan cepat selama pengembangan lokal. Hal ini dapat dicapai dengan menggunakan
local_path_override
.
Mengapa ada banyak use_repo
?
Penggunaan ekstensi modul dalam file MODULE.bazel terkadang disertai dengan perintah
use_repo
besar. Misalnya, penggunaan umum
ekstensi go_deps
dari gazelle
mungkin terlihat seperti:
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(
go_deps,
"com_github_gogo_protobuf",
"com_github_golang_mock",
"com_github_golang_protobuf",
"org_golang_x_net",
... # potentially dozens of lines...
)
Perintah use_repo
yang panjang mungkin tampak berlebihan, karena informasi tersebut
mungkin sudah ada dalam file go.mod
yang dirujuk.
Alasan Bazel memerlukan perintah use_repo
ini adalah karena Bazel menjalankan ekstensi
modul secara lambat. Artinya, ekstensi modul hanya dijalankan jika hasilnya
diamati. Karena "output" ekstensi modul adalah definisi repo, ini berarti
kita hanya menjalankan ekstensi modul jika repo yang ditentukan diminta (misalnya, jika target @org_golang_x_net//:foo
di-build, dalam contoh
di atas). Namun, kita tidak tahu repo mana yang akan ditentukan oleh ekstensi modul hingga
setelah kita menjalankannya. Di sinilah perintah use_repo
berperan; pengguna dapat
memberi tahu Bazel repo mana yang diharapkan akan dihasilkan oleh ekstensi, dan Bazel kemudian
hanya akan menjalankan ekstensi saat repo tertentu ini digunakan.
Untuk membantu mempertahankan perintah use_repo
ini, ekstensi modul dapat menampilkan
objek extension_metadata
dari fungsi implementasinya. Pengguna dapat menjalankan perintah bazel mod tidy
untuk memperbarui perintah use_repo
untuk ekstensi modul ini.
Migrasi Bzlmod
Manakah yang dievaluasi terlebih dahulu, MODULE.bazel atau WORKSPACE?
Jika --enable_bzlmod
dan --enable_workspace
ditetapkan, wajar saja jika
Anda bertanya-tanya sistem mana yang dikonsultasikan terlebih dahulu. Jawaban singkatnya adalah MODULE.bazel
(Bzlmod) dievaluasi terlebih dahulu.
Jawaban panjangnya adalah "yang dievaluasi terlebih dahulu" bukanlah pertanyaan yang tepat untuk
diajukan; pertanyaan yang tepat untuk diajukan adalah: dalam konteks repo dengan
nama kanonis @@foo
, apa yang di-resolve oleh nama repo
yang terlihat @bar
? Atau, apa
pemetaan repo @@base
?
Label dengan nama repo yang jelas (satu @
utama) dapat merujuk ke hal
yang berbeda berdasarkan konteks tempatnya di-resolve. Saat melihat label
@bar//:baz
dan bertanya-tanya apa yang sebenarnya ditunjuknya, Anda harus terlebih dahulu mencari tahu
repo konteks: misalnya, jika label berada dalam file BUILD yang terletak
di repo @@foo
, maka repo konteksnya adalah @@foo
.
Kemudian, bergantung pada repo konteks, tabel"visibilitas repositori" dalam panduan migrasi dapat digunakan untuk mengetahui repo mana yang sebenarnya me-resolve nama yang terlihat.
- Jika repo konteks adalah repo utama (
@@
):- Jika
bar
adalah nama repo yang jelas yang diperkenalkan oleh file MODULE.bazel modul root (melaluibazel_dep
,use_repo
,module
,use_repo_rule
),@bar
akan me-resolve ke apa yang diklaim file MODULE.bazel tersebut. - Jika tidak, jika
bar
adalah repo yang ditentukan di WORKSPACE (yang berarti nama kanonisnya adalah@@bar
),@bar
akan di-resolve ke@@bar
. - Jika tidak,
@bar
akan di-resolve ke sesuatu seperti@@[unknown repo 'bar' requested from @@]
, dan hal ini pada akhirnya akan menyebabkan error.
- Jika
- Jika repo konteks adalah repo dunia Bzlmod (yaitu, sesuai dengan
modul Bazel non-root, atau dibuat oleh ekstensi modul), repo tersebut
hanya akan melihat repo dunia Bzlmod lainnya, dan tidak ada repo dunia WORKSPACE.
- Secara khusus, hal ini mencakup repo apa pun yang diperkenalkan dalam ekstensi modul
seperti
non_module_deps
di modul root, atau pembuatan instanceuse_repo_rule
di modul root.
- Secara khusus, hal ini mencakup repo apa pun yang diperkenalkan dalam ekstensi modul
seperti
- Jika repo konteks ditentukan di WORKSPACE:
- Pertama, periksa apakah definisi repo konteks memiliki atribut
repo_mapping
ajaib. Jika ya, lihat pemetaan terlebih dahulu (jadi untuk repo yang ditentukan denganrepo_mapping = {"@bar": "@baz"}
, kita akan melihat@baz
di bawah). - Jika
bar
adalah nama repo yang jelas yang diperkenalkan oleh file MODULE.bazel modul root,@bar
akan di-resolve ke apa yang diklaim oleh file MODULE.bazel tersebut. (Ini sama dengan item 1 dalam kasus repo utama.) - Jika tidak,
@bar
akan di-resolve ke@@bar
. Hal ini kemungkinan besar akan mengarah kebar
repo yang ditentukan di WORKSPACE; jika repo tersebut tidak ditentukan, Bazel akan menampilkan error.
- Pertama, periksa apakah definisi repo konteks memiliki atribut
Untuk versi yang lebih ringkas:
- Repositori Bzlmod-world (tidak termasuk repositori utama) hanya akan melihat repositori Bzlmod-world.
- Repositori dunia WORKSPACE (termasuk repo utama) akan melihat terlebih dahulu modul root di dunia Bzlmod, lalu kembali melihat repo dunia WORKSPACE.
Perlu diperhatikan, label di command line Bazel (termasuk flag Starlark, nilai flag berjenis label, dan pola target build/pengujian) diperlakukan seolah-olah memiliki repo utama sebagai repo konteks.
Lainnya
Bagaimana cara menyiapkan dan menjalankan build offline?
Gunakan perintah bazel fetch
untuk melakukan pengambilan data repo. Anda dapat menggunakan flag --repo
(seperti bazel fetch --repo @foo
) untuk hanya mengambil repo @foo
(di-resolve dalam
konteks repo utama, lihat pertanyaan
di atas), atau menggunakan pola
target (seperti bazel fetch @foo//:bar
) untuk mengambil semua dependensi transitif
@foo//:bar
(ini setara dengan bazel build --nobuild @foo//:bar
).
Pastikan tidak ada pengambilan yang terjadi selama build, gunakan --nofetch
. Lebih tepatnya, hal ini membuat setiap upaya untuk menjalankan aturan repositori non-lokal gagal.
Jika Anda ingin mengambil repo dan memodifikasinya untuk diuji secara lokal, pertimbangkan untuk menggunakan perintah bazel vendor
.
Bagaimana cara menggunakan proxy HTTP?
Bazel mematuhi variabel lingkungan http_proxy
dan HTTPS_PROXY
yang umumnya
diterima oleh program lain, seperti
curl.
Bagaimana cara membuat Bazel lebih memilih IPv6 dalam penyiapan IPv4/IPv6 stack ganda?
Pada mesin khusus IPv6, Bazel dapat mendownload dependensi tanpa perubahan. Namun,
pada mesin IPv4/IPv6 stack ganda, Bazel mengikuti konvensi yang sama dengan Java,
yang lebih memilih IPv4 jika diaktifkan. Dalam beberapa situasi, misalnya saat jaringan IPv4
tidak dapat me-resolve/menjangkau alamat eksternal, hal ini dapat menyebabkan pengecualian Network
unreachable
dan kegagalan build. Dalam kasus ini, Anda dapat mengganti
perilaku Bazel untuk memilih IPv6 menggunakan
properti sistem
java.net.preferIPv6Addresses=true
.
Khususnya:
Gunakan opsi startup
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
, misalnya dengan menambahkan baris berikut di file.bazelrc
:startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
Saat menjalankan target build Java yang perlu terhubung ke internet (seperti untuk pengujian integrasi), gunakan flag alat
--jvmopt=-Djava.net.preferIPv6Addresses=true
. Misalnya, sertakan dalam file.bazelrc
:build --jvmopt=-Djava.net.preferIPv6Addresses
Jika Anda menggunakan
rules_jvm_external
untuk resolusi versi dependensi, tambahkan juga-Djava.net.preferIPv6Addresses=true
ke variabel lingkunganCOURSIER_OPTS
untuk memberikan opsi JVM untuk Coursier.
Dapatkah aturan repo dijalankan dari jarak jauh dengan eksekusi jarak jauh?
Tidak; atau setidaknya, belum. Pengguna yang menggunakan layanan eksekusi jarak jauh untuk mempercepat
build mungkin melihat bahwa aturan repo masih berjalan secara lokal. Misalnya, http_archive
akan didownload terlebih dahulu ke komputer lokal (menggunakan cache
download lokal jika ada), diekstrak, lalu setiap file sumber akan
diupload ke layanan eksekusi jarak jauh sebagai file input. Wajar jika Anda bertanya
mengapa layanan eksekusi jarak jauh tidak hanya mendownload dan mengekstrak arsip tersebut,
sehingga menghemat perjalanan bolak-balik yang tidak berguna.
Salah satu alasannya adalah aturan repo (dan ekstensi modul) mirip dengan "skrip" yang dijalankan oleh Bazel itu sendiri. Eksekutor jarak jauh tidak harus menginstal Bazel.
Alasan lainnya adalah Bazel sering kali memerlukan file BUILD dalam arsip yang didownload dan diekstrak untuk melakukan pemuatan dan analisis, yang dilakukan secara lokal.
Ada ide awal untuk memecahkan masalah ini dengan membayangkan ulang aturan repo sebagai
aturan build, yang secara alami akan memungkinkannya dijalankan dari jarak jauh, tetapi sebaliknya
menimbulkan masalah arsitektur baru (misalnya, perintah query
berpotensi perlu menjalankan tindakan, yang mempersulit desainnya).
Untuk pembahasan sebelumnya tentang topik ini, lihat Cara mendukung repositori yang memerlukan Bazel untuk diambil.