Bazel dapat bergantung pada target dari project lain. Dependensi dari project lain ini disebut dependensi eksternal.
File WORKSPACE
(atau file WORKSPACE.bazel
) dalam
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 nama dari
file WORKSPACE
.
Misalnya, anggaplah ada dua project pada suatu sistem:
/
home/
user/
project1/
WORKSPACE
BUILD
srcs/
...
project2/
WORKSPACE
BUILD
my-libs/
Jika project1
ingin bergantung pada target, :foo
, yang ditentukan dalam
/home/user/project2/BUILD
, fungsi ini dapat menentukan bahwa repositori bernama
project2
dapat ditemukan di /home/user/project2
. Selanjutnya, target di /home/user/project1/BUILD
dapat bergantung pada @project2//:foo
.
File WORKSPACE
memungkinkan pengguna bergantung pada target dari bagian lain
sistem file atau didownload dari internet. Ini menggunakan sintaksis yang sama dengan file BUILD
, tetapi memungkinkan serangkaian aturan berbeda yang disebut aturan repositori (terkadang
juga dikenal sebagai aturan ruang kerja). Bazel dilengkapi dengan beberapa aturan repositori
bawaan dan kumpulan aturan repositori
Starlark yang disematkan. 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
Tergantung pada project Bazel lainnya
Jika ingin menggunakan target dari project Bazel kedua, Anda dapat
menggunakan
local_repository
,
git_repository
,
atau http_archive
untuk melakukan symlink dari sistem file lokal, mereferensikan repositori git, atau
mendownloadnya (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 sebagai dependensi eksternal, lalu menggunakan target apa pun yang telah ditentukan rekan kerja 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 //foo:bar
target, project Anda dapat menyebutnya 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 membuat build, tetapi Anda harus bergantung pada salah satu file .so yang dihasilkannya. Untuk melakukannya, tambahkan kode 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
untuk ditempatkan pada project yang ada, misalnya:
cc_library(
name = "some-lib",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
Selanjutnya, 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 menyediakannya sebagai dependensi
Java.
Mengambil dependensi
Secara default, dependensi eksternal diambil sesuai kebutuhan selama bazel build
. Jika
Anda ingin mengambil data 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 buat satu kebijakan versi di project Anda. Ini diperlukan untuk dependensi yang Anda kompilasi dan berakhir di biner akhir Anda. Namun, untuk kasus yang tidak benar, Anda dapat membayangi dependensi. Pertimbangkan skenario berikut:
projectsaya/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/Ruang Kerja
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 bagi runner pengujian ini untuk
tidak hidup berdampingan dengan damai dalam myproject
, tetapi keduanya akan saling berbenturan
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 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
tanda
--override_repository
. 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:
- Men-debug masalah. Misalnya, Anda dapat mengganti repositori
http_archive
ke direktori lokal tempat Anda dapat membuat perubahan dengan lebih mudah. - Vendor. Jika Anda berada di lingkungan yang tidak dapat melakukan panggilan jaringan, ganti aturan repositori berbasis jaringan agar 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
Pada komputer khusus IPv6, Bazel akan dapat mendownload dependensi tanpa
perubahan. Namun, pada mesin IPv4/IPv6 dual-stack, Bazel mengikuti konvensi yang sama dengan Java: jika IPv4 diaktifkan, IPv4 akan lebih disukai. Dalam beberapa situasi, misalnya jika jaringan IPv4 tidak dapat menyelesaikan/menjangkau alamat eksternal, hal ini dapat menyebabkan pengecualian Network unreachable
dan kegagalan build.
Dalam hal ini, Anda dapat mengganti perilaku Bazel untuk memilih IPv6
menggunakan properti sistem java.net.preferIPv6Addresses=true
.
Khususnya:
Gunakan
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
opsi startup, misalnya dengan menambahkan baris berikut di file.bazelrc
Anda:startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
Jika Anda menjalankan target build Java yang juga perlu terhubung ke internet (pengujian integrasi terkadang memerlukannya), gunakan juga flag alat
--jvmopt=-Djava.net.preferIPv6Addresses=true
, misalnya dengan mencantumkan baris berikut di file.bazelrc
Anda:build --jvmopt=-Djava.net.preferIPv6Addresses
Jika Anda menggunakan rules_jvm_external, misalnya untuk resolusi versi dependensi, tambahkan juga
-Djava.net.preferIPv6Addresses=true
ke variabel lingkunganCOURSIER_OPTS
untuk menyediakan 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 (C
) dalam file WORKSPACE
, Anda harus menambahkan B
dan C
ke file WORKSPACE
project Anda. Persyaratan ini dapat menggelembungkan
ukuran file WORKSPACE
, tetapi membatasi kemungkinan satu library
menyertakan C
di versi 1.0 dan library lainnya menyertakan C
di versi 2.0.
Menyimpan cache dependensi eksternal
Secara default, Bazel hanya akan mendownload ulang dependensi eksternal jika
definisinya berubah. Perubahan pada file yang dirujuk dalam definisi (seperti patch
atau file BUILD
) juga dipertimbangkan oleh bazel.
Untuk mendownload ulang secara paksa, gunakan bazel sync
.
Tata Letak
Semua dependensi eksternal didownload ke direktori di bawah subdirektori
external
di output base. Untuk
repositori lokal, symlink akan dibuat
di sana, bukan membuat direktori baru.
Anda dapat melihat direktori external
dengan menjalankan:
ls $(bazel info output_base)/external
Perhatikan bahwa menjalankan bazel clean
tidak akan benar-benar menghapus direktori
eksternal. Untuk menghapus semua artefak eksternal, gunakan bazel clean --expunge
.
Build offline
Terkadang memang lebih baik atau perlu untuk menjalankan build secara offline. Untuk
kasus penggunaan sederhana, seperti bepergian di pesawat terbang,
melakukan pengambilan data repositori
yang diperlukan dengan bazel fetch
atau bazel sync
sudah cukup; selain itu, penggunaan opsi --nofetch
, pengambilan repositori lebih lanjut dapat dinonaktifkan
selama build.
Untuk build offline sebenarnya, dengan penyediaan file yang diperlukan dilakukan
oleh entity yang berbeda dengan 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, lalu menggunakan salinan lokal tersebut
jika hash-nya cocok.
Bazel sendiri menggunakan teknik ini untuk melakukan bootstrap offline dari artefak
distribusi.
Hal ini dilakukan dengan mengumpulkan semua dependensi eksternal
yang diperlukan
dalam distdir_tar
internal.
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, menguji apakah build berfungsi dengan benar secara offline memerlukan pemblokiran eksternal jaringan, seperti yang dilakukan bazel dalam pengujian bootstrap-nya.
Praktik terbaik
Aturan repositori
Aturan repositori secara umum harus bertanggung jawab untuk:
- Mendeteksi setelan sistem dan menulisnya ke file.
- Mencari resource di tempat lain pada sistem.
- Mendownload referensi dari URL.
- Membuat atau melakukan 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"])
.
Pilih http_archive
ke git_repository
dan new_git_repository
. Alasannya adalah:
- Aturan repositori Git bergantung pada
git(1)
sistem, sedangkan downloader HTTP terintegrasi ke Bazel dan tidak memiliki dependensi sistem. http_archive
mendukung daftarurls
sebagai cermin, dangit_repository
hanya mendukung saturemote
.http_archive
berfungsi dengan cache repositori, tetapi tidakgit_repository
. Lihat #5116 untuk informasi selengkapnya.
Jangan gunakan bind()
. Lihat "Mempertimbangkan penghapusan
ikat" untuk diskusi
panjang tentang masalah dan alternatifnya.