Ringkasan dependensi eksternal

Laporkan masalah Lihat sumber

Bazel mendukung dependensi eksternal, yaitu file sumber (teks dan biner) yang digunakan dalam build yang tidak berasal dari ruang kerja Anda. Misalnya, contoh tersebut dapat berupa kumpulan aturan yang dihosting di repo GitHub, artefak Maven, atau direktori di komputer 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 berfokus pada modul yang lebih baru (bernama kode Bzlmod, dan diaktifkan dengan flag --enable_bzlmod). Kedua sistem tersebut dapat digunakan bersama, tetapi Bzlmod menggantikan sistem WORKSPACE dalam rilis Bazel yang akan datang, baca 10l.mod panduan migrasi dalam panduan migrasi{/10l.mod

Dokumen ini menjelaskan konsep seputar manajemen dependensi eksternal di Bazel, sebelum membahas kedua sistem secara berurutan.

Konsep

Repositori

Hierarki direktori dengan file penanda batas di root-nya, yang berisi file sumber yang dapat digunakan dalam build Bazel. Sering disingkat menjadi hanya 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. Setiap file penanda batas repo akan menandakan batas repo; beberapa file tersebut dapat digunakan berdampingan dalam suatu direktori.

Repositori utama

Repositori tempat perintah Bazel saat ini dijalankan.

Root repositori utama juga dikenal sebagai root workspace.

Workspace

Lingkungan yang digunakan bersama oleh semua perintah Bazel berjalan di repositori utama yang sama. Repositori ini mencakup repo utama dan rangkaian semua repositori 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 menjadi alamat repositori. Dalam konteks ruang kerja, setiap repositori memiliki satu nama kanonis. Target di dalam repositori yang nama kanonisnya adalah canonical_name dapat diberi alamat dengan label @@canonical_name//pac/kage:target (perhatikan @ ganda).

Repositori utama selalu memiliki string kosong sebagai nama kanonis.

Nama repositori yang jelas

Nama repositori yang dapat ditangani dalam konteks repo tertentu lainnya. Hal ini dapat dianggap sebagai "nama panggilan" repo: Repositori dengan nama kanonis michael mungkin memiliki nama jelas mike dalam konteks repo alice, tetapi mungkin memiliki nama jelas mickey dalam konteks repo bob. Dalam hal ini, target di dalam michael dapat ditangani oleh label @mike//pac/kage:target dalam konteks alice (perhatikan satu @).

Sebaliknya, ini dapat dipahami sebagai pemetaan repositori: setiap repo mempertahankan pemetaan dari "nama repo jelas" 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 "symlink direktori lokal". Setiap repo ditentukan dengan memanggil aturan repo beserta jumlah argumen yang sesuai.

Lihat Aturan repositori untuk mengetahui informasi lebih lanjut tentang cara menulis aturan repositori Anda sendiri.

Aturan repo yang paling umum sejauh ini adalah http_archive, yang mendownload arsip dari URL dan mengekstraknya, serta local_repository, yang melakukan symlink pada direktori lokal yang sudah menjadi repositori Bazel.

Mengambil repositori

Tindakan menyediakan repo pada disk lokal dengan menjalankan aturan repo terkaitnya. Repositori 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 repositori sudah diambil sebelumnya, Bazel hanya akan mengambilnya kembali jika definisinya telah berubah.

Perintah fetch dapat digunakan untuk memulai pre-fetching untuk repositori, target, atau semua repositori yang diperlukan untuk menjalankan build apa pun. Kemampuan ini mengaktifkan build offline menggunakan opsi --nofetch.

Opsi --fetch berfungsi untuk mengelola akses jaringan. Nilai defaultnya adalah true (benar). Namun, jika ditetapkan ke salah (--nofetch), perintah akan menggunakan versi dependensi yang di-cache, dan jika tidak ada, perintah tersebut akan menyebabkan kegagalan.

Lihat opsi pengambilan untuk mengetahui informasi selengkapnya tentang mengontrol pengambilan.

Tata letak direktori

Setelah diambil, repo dapat ditemukan di subdirektori external di output base, di bawah 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 hierarki direktori yang membentuk repo. Repositori tidak perlu berisi apa pun agar 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, tetapi tidak ada pernyataan load yang didukung, dan hanya satu fungsi, repo(), yang tersedia. repo() menggunakan argumen yang sama dengan fungsi package() dalam file BUILD; sedangkan package() menentukan atribut umum untuk semua target build di dalam paket, repo() secara analog melakukannya 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 secara langsung berfungsi dengan definisi repo. Sebagai gantinya, class ini membuat grafik dependensi dari modul, menjalankan ekstensi di atas grafik, dan menentukan repo sebagaimana mestinya.

Modul Bazel adalah project Bazel yang dapat memiliki beberapa versi, yang masing-masing memublikasikan metadata tentang modul lain yang menjadi dependensinya. 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 ini menyediakan file MODULE.bazel dependensi, yang memungkinkan Bazel menemukan seluruh grafik dependensi transitif sebelum melakukan penyelesaian versi.

Setelah resolusi versi, saat satu versi dipilih untuk setiap modul, Bazel akan menghubungi registry lagi 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 repositori tambahan. Ekstensi ini memiliki kemampuan yang mirip dengan aturan repo, memungkinkannya melakukan tindakan seperti I/O file dan mengirim permintaan jaringan. Di antara fungsi lainnya, API tersebut memungkinkan Bazel berinteraksi dengan sistem pengelolaan paket lainnya sekaligus mengikuti grafik dependensi yang dibuat dari modul Bazel.

Menentukan repo dengan WORKSPACE

Secara historis, Anda dapat mengelola dependensi eksternal dengan menentukan repositori 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 untuk menggunakan 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 menentukan repo yang nama kanonisnya adalah foo. Dalam sistem WORKSPACE, secara default, nama kanonis repo juga merupakan nama jelasnya dibandingkan semua repo lainnya.

Lihat daftar lengkap fungsi yang tersedia di file WORKSPACE.

Kekurangan sistem WORKSPACE

Selama bertahun-tahun sejak sistem WORKSPACE diperkenalkan, pengguna telah melaporkan banyak titik masalah, termasuk:

  • Bazel tidak mengevaluasi file WORKSPACE dependensi apa pun, sehingga semua dependensi transitif harus ditentukan dalam file WORKSPACE dari repo utama, selain dependensi langsung.
  • Untuk mengatasi hal ini, project telah mengadopsi pola "deps.bzl", yang mana mereka menentukan makro yang kemudian menentukan beberapa repo, dan meminta pengguna untuk memanggil makro ini dalam file WORKSPACE.
    • Hal ini memiliki masalah sendiri: makro tidak dapat load file .bzl lainnya, sehingga project ini harus menentukan dependensi transitifnya dalam makro "dependensi" ini, atau mengatasi masalah ini dengan meminta pengguna memanggil beberapa makro "dependensi" berlapis.
    • Bazel mengevaluasi file WORKSPACE secara berurutan. Selain itu, dependensi ditentukan menggunakan http_archive bersama URL, tanpa informasi versi apa pun. Artinya, tidak ada cara yang andal untuk melakukan resolusi versi dalam kasus dependensi diamond (A bergantung pada B dan C; B dan C bergantung pada versi D yang berbeda).

Karena kelemahan WORKSPACE, Bzlmod akan menggantikan sistem WORKSPACE lama dalam rilis Bazel mendatang. Baca panduan migrasi Bzlmod tentang cara bermigrasi ke Bzlmod.