Pertanyaan umum (FAQ)

Laporkan masalah Lihat sumber Nightly · 8.2 · 8.1 · 8.0 · 7.6 · 7.5

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 mengizinkan load 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 (@@):
    1. Jika bar adalah nama repo yang jelas yang diperkenalkan oleh file MODULE.bazel modul root (melalui bazel_dep, use_repo, module, use_repo_rule), @bar akan me-resolve ke apa yang diklaim file MODULE.bazel tersebut.
    2. Jika tidak, jika bar adalah repo yang ditentukan di WORKSPACE (yang berarti nama kanonisnya adalah @@bar), @bar akan di-resolve ke @@bar.
    3. Jika tidak, @bar akan di-resolve ke sesuatu seperti @@[unknown repo 'bar' requested from @@], dan hal ini pada akhirnya akan menyebabkan error.
  • 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 instance use_repo_rule di modul root.
  • Jika repo konteks ditentukan di WORKSPACE:
    1. Pertama, periksa apakah definisi repo konteks memiliki atribut repo_mapping ajaib. Jika ya, lihat pemetaan terlebih dahulu (jadi untuk repo yang ditentukan dengan repo_mapping = {"@bar": "@baz"}, kita akan melihat @baz di bawah).
    2. 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.)
    3. Jika tidak, @bar akan di-resolve ke @@bar. Hal ini kemungkinan besar akan mengarah ke bar repo yang ditentukan di WORKSPACE; jika repo tersebut tidak ditentukan, Bazel akan menampilkan error.

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 lingkungan COURSIER_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.