Bazel dapat bergantung pada target dari project lain. Dependensi dari project lain ini disebut dependensi eksternal.
File WORKSPACE (atau file WORKSPACE.bazel) di
direktori ruang kerja
memberi tahu Bazel cara mendapatkan sumber project lain. Project lain ini dapat berisi satu atau beberapa file BUILD dengan targetnya sendiri. File BUILD dalam project utama dapat bergantung pada target eksternal ini dengan menggunakan namanya dari file WORKSPACE.
Misalnya, anggap ada dua project di sistem:
/
home/
user/
project1/
WORKSPACE
BUILD
srcs/
...
project2/
WORKSPACE
BUILD
my-libs/
Jika project1 ingin bergantung pada target, :foo, yang ditentukan di
/home/user/project2/BUILD, project tersebut dapat menentukan bahwa repositori bernama
project2 dapat ditemukan di /home/user/project2. Kemudian, target di /home/user/project1/BUILD dapat bergantung pada @project2//:foo.
File WORKSPACE memungkinkan pengguna bergantung pada target dari bagian lain sistem file atau yang didownload dari internet. File ini menggunakan sintaksis yang sama dengan file BUILD, tetapi memungkinkan kumpulan aturan yang berbeda yang disebut aturan repositori (terkadang juga dikenal sebagai aturan ruang kerja). Bazel dilengkapi dengan beberapa
aturan repositori bawaan dan kumpulan
aturan repositori Starlark tersemat.
Pengguna juga dapat menulis aturan repositori kustom
untuk mendapatkan perilaku yang lebih kompleks.
Jenis dependensi eksternal yang didukung
Beberapa jenis dasar dependensi eksternal dapat digunakan:
- Dependensi pada project Bazel lainnya
- Dependensi pada project non-Bazel
- Dependensi pada paket eksternal
Bergantung pada project Bazel lainnya
Jika ingin menggunakan target dari project Bazel kedua, Anda dapat
menggunakan
local_repository,
git_repository
atau http_archive
untuk membuat symlink dari sistem file lokal, mereferensikan repositori git, atau mendownload
nya (masing-masing).
Misalnya, Anda sedang mengerjakan project, my-project/, dan Anda ingin bergantung pada target dari project rekan kerja Anda, coworkers-project/. Kedua project menggunakan Bazel, sehingga Anda dapat menambahkan project rekan kerja Anda sebagai dependensi eksternal, lalu menggunakan target apa pun yang telah ditentukan rekan kerja Anda dari file BUILD Anda sendiri. Anda akan menambahkan hal berikut ke my_project/WORKSPACE:
local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
)
Jika rekan kerja Anda memiliki target //foo:bar, project Anda dapat merujuknya sebagai
@coworkers_project//foo:bar. Nama project eksternal harus berupa
nama ruang kerja yang valid.
Bergantung pada project non-Bazel
Aturan yang diawali dengan new_, seperti
new_local_repository,
memungkinkan Anda membuat target dari project yang tidak menggunakan Bazel.
Misalnya, Anda sedang mengerjakan project, my-project/, dan Anda ingin bergantung pada project rekan kerja Anda, coworkers-project/. Project rekan kerja Anda menggunakan make untuk mem-build, tetapi Anda ingin bergantung pada salah satu file .so yang dihasilkannya. Untuk melakukannya, tambahkan hal berikut ke my_project/WORKSPACE:
new_local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
build_file = "coworker.BUILD",
)
build_file menentukan file BUILD yang akan di-overlay pada project yang ada, misalnya:
cc_library(
name = "some-lib",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
Kemudian, Anda dapat bergantung pada @coworkers_project//:some-lib dari file BUILD project Anda.
Bergantung pada paket eksternal
Artefak dan repositori Maven
Gunakan kumpulan aturan rules_jvm_external
untuk mendownload artefak dari repositori Maven dan membuatnya tersedia sebagai dependensi Java.
Mengambil dependensi
Secara default, dependensi eksternal diambil sesuai kebutuhan selama bazel build. Jika
Anda ingin mengambil dependensi yang diperlukan untuk kumpulan target tertentu, gunakan
bazel fetch.
Untuk mengambil semua dependensi eksternal tanpa syarat, gunakan
bazel sync.
Karena repositori yang diambil disimpan di basis output, pengambilan
terjadi per ruang kerja.
Dependensi bayangan
Jika memungkinkan, sebaiknya gunakan kebijakan versi tunggal di project Anda. Hal ini diperlukan untuk dependensi yang Anda kompilasi dan berakhir di biner akhir Anda. Namun, untuk kasus yang tidak benar, dependensi dapat dibayangi. Pertimbangkan skenario berikut:
myproject/WORKSPACE
workspace(name = "myproject")
local_repository(
name = "A",
path = "../A",
)
local_repository(
name = "B",
path = "../B",
)
A/WORKSPACE
workspace(name = "A")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "...",
)
B/WORKSPACE
workspace(name = "B")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
Dependensi A dan B bergantung pada testrunner, tetapi bergantung pada versi testrunner yang berbeda. Tidak ada alasan mengapa pelari pengujian ini tidak dapat hidup berdampingan dengan tenang dalam myproject, tetapi keduanya akan bertentangan karena memiliki nama yang sama. Untuk mendeklarasikan kedua dependensi, perbarui myproject/WORKSPACE:
workspace(name = "myproject")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner-v1",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "..."
)
http_archive(
name = "testrunner-v2",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
local_repository(
name = "A",
path = "../A",
repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
name = "B",
path = "../B",
repo_mapping = {"@testrunner" : "@testrunner-v2"}
)
Mekanisme ini juga dapat digunakan untuk menggabungkan berlian. Misalnya, jika A dan B memiliki dependensi yang sama tetapi memanggilnya dengan nama yang berbeda, dependensi tersebut dapat digabungkan di myproject/WORKSPACE.
Mengganti repositori dari command line
Untuk mengganti repositori yang dideklarasikan dengan repositori lokal dari command line,
gunakan
--override_repository
flag. Menggunakan flag ini akan mengubah konten repositori eksternal tanpa mengubah kode sumber Anda.
Misalnya, untuk mengganti @foo ke direktori lokal /path/to/local/foo,
teruskan flag --override_repository=foo=/path/to/local/foo.
Beberapa kasus penggunaan mencakup:
- Masalah proses debug. Misalnya, Anda dapat mengganti repositori
http_archiveke direktori lokal tempat Anda dapat melakukan perubahan dengan lebih mudah. - Vendor. Jika Anda berada di lingkungan tempat Anda tidak dapat melakukan panggilan jaringan, ganti aturan repositori berbasis jaringan untuk mengarah ke direktori lokal.
Menggunakan proxy
Bazel akan mengambil alamat proxy dari variabel lingkungan HTTPS_PROXY dan HTTP_PROXY, lalu menggunakannya untuk mendownload file HTTP/HTTPS (jika ditentukan).
Dukungan untuk IPv6
Di mesin khusus IPv6, Bazel akan dapat mendownload dependensi tanpa perubahan. Namun, di mesin IPv4/IPv6 stack ganda, Bazel mengikuti konvensi yang sama dengan Java: jika IPv4 diaktifkan, IPv4 akan lebih diutamakan. 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 lebih memilih IPv6
dengan menggunakan java.net.preferIPv6Addresses=true properti sistem.
Khususnya:
Gunakan opsi startup
--host_jvm_args=-Djava.net.preferIPv6Addresses=true, misalnya dengan menambahkan baris berikut di file.bazelrcAnda:startup --host_jvm_args=-Djava.net.preferIPv6Addresses=trueJika Anda menjalankan target build Java yang juga perlu terhubung ke internet serta (pengujian integrasi terkadang memerlukannya), gunakan juga
--jvmopt=-Djava.net.preferIPv6Addresses=trueflag alat, misalnya dengan memiliki baris berikut di file.bazelrcAnda:build --jvmopt=-Djava.net.preferIPv6AddressesJika Anda menggunakan rules_jvm_external, misalnya, untuk resolusi versi dependensi, tambahkan juga
-Djava.net.preferIPv6Addresses=truekeCOURSIER_OPTSvariabel lingkungan untuk memberikan opsi JVM untuk Coursier
Dependensi transitif
Bazel hanya membaca dependensi yang tercantum dalam file WORKSPACE Anda. Jika project Anda
(A) bergantung pada project lain (B) yang mencantumkan dependensi pada project ketiga
project (C) dalam file WORKSPACE, Anda harus menambahkan B
dan C ke file WORKSPACE project Anda. Persyaratan ini dapat meningkatkan ukuran file
WORKSPACE, tetapi membatasi kemungkinan satu library
menyertakan C di versi 1.0 dan library lain menyertakan C di 2.0.
Caching dependensi eksternal
Secara default, Bazel hanya akan mendownload ulang dependensi eksternal jika definisinya berubah. Perubahan pada file yang direferensikan dalam definisi (seperti patch atau file BUILD) juga diperhitungkan oleh bazel.
Untuk memaksa download ulang, gunakan bazel sync.
Tata Letak
Semua dependensi eksternal didownload ke direktori di bawah subdirektori
external di basis output. Jika repositori
lokal, symlink akan dibuat
di sana, bukan membuat direktori baru.
Anda dapat melihat direktori external dengan menjalankan:
ls $(bazel info output_base)/externalPerhatikan bahwa menjalankan bazel clean tidak akan benar-benar menghapus direktori eksternal. Untuk menghapus semua artefak eksternal, gunakan bazel clean --expunge.
Build offline
Terkadang, Anda mungkin ingin atau perlu menjalankan build secara offline. Untuk
kasus penggunaan sederhana, seperti bepergian dengan pesawat,
prefetching repositori yang diperlukan dengan bazel fetch atau bazel sync mungkin sudah cukup. Selain itu, dengan
menggunakan opsi --nofetch, pengambilan repositori lebih lanjut dapat dinonaktifkan
selama build.
Untuk build offline yang sebenarnya, tempat penyediaan file yang diperlukan dilakukan oleh entity yang berbeda dari bazel, bazel mendukung opsi --distdir. Setiap kali aturan repositori meminta bazel untuk mengambil file melalui
ctx.download atau
ctx.download_and_extract
dan memberikan jumlah hash file
yang diperlukan, bazel akan terlebih dahulu melihat direktori yang ditentukan oleh opsi tersebut untuk
file yang cocok dengan nama dasar URL pertama yang diberikan, dan menggunakan salinan lokal
tersebut jika hash cocok.
Bazel sendiri menggunakan teknik ini untuk melakukan bootstrap offline dari artefak distribusi.
Hal ini dilakukan dengan mengumpulkan semua dependensi eksternal yang diperlukan
dalam
internaldistdir_tar.
Namun, bazel memungkinkan eksekusi perintah arbitrer dalam aturan repositori, tanpa mengetahui apakah perintah tersebut memanggil jaringan. Oleh karena itu, bazel tidak memiliki opsi untuk menerapkan build yang sepenuhnya offline. Jadi, pengujian apakah build berfungsi dengan benar secara offline memerlukan pemblokiran jaringan eksternal, seperti yang dilakukan bazel dalam pengujian bootstrap-nya.
Praktik terbaik
Aturan repositori
Aturan repositori umumnya harus bertanggung jawab untuk:
- Mendeteksi setelan sistem dan menuliskannya ke file.
- Menemukan resource di tempat lain dalam sistem.
- Mendownload resource dari URL.
- Membuat atau membuat symlink file BUILD ke direktori repositori eksternal.
Hindari penggunaan repository_ctx.execute jika memungkinkan. Misalnya, saat menggunakan library C++ non-Bazel
yang memiliki build menggunakan Make, sebaiknya gunakan repository_ctx.download() lalu
tulis file BUILD yang mem-build-nya, bukan menjalankan ctx.execute(["make"]).
Sebaiknya gunakan http_archive daripada git_repository dan
new_git_repository. Alasannya adalah:
- Aturan repositori Git bergantung pada sistem
git(1), sedangkan downloader HTTP dibuat ke dalam Bazel dan tidak memiliki dependensi sistem. http_archivemendukung daftarurlssebagai mirror, dangit_repositoryhanya mendukung saturemote.http_archiveberfungsi dengan cache repositori, tetapi tidakgit_repository. Lihat #5116 untuk mengetahui informasi selengkapnya.
Jangan gunakan bind(). Lihat "Pertimbangkan untuk menghapus
bind" untuk diskusi panjang
tentang masalah dan alternatifnya.