Catat Tanggalnya: BazelCon 2023 akan diadakan pada 24-25 Oktober di Google Munich! Pelajari lebih lanjut

Ringkasan dependensi eksternal

Laporkan masalah Lihat sumber

Bazel mendukung dependensi eksternal, file sumber (teks dan biner) yang digunakan dalam build Anda yang bukan dari ruang kerja Anda. Misalnya, instance dapat berupa aturan yang dihosting di repo GitHub, artefak Maven, atau direktori di komputer lokal di luar ruang kerja Anda saat ini.

Sejak 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 (dengan nama kode Bzlmod, dan diaktifkan dengan flag --enable_bzlmod). Kedua sistem tersebut dapat digunakan bersama-sama, tetapi Bzlmod menggantikan sistem WORKSPACE dalam rilis Bazel di masa mendatang.

Artikel ini menjelaskan konsep seputar pengelolaan dependensi eksternal di Bazel, sebelum membahas lebih detail kedua sistem secara berurutan.

Konsep

Repositori

Direktori dengan file WORKSPACE atau WORKSPACE.bazel, yang berisi file sumber yang akan digunakan dalam build Bazel. Sering dipersingkat menjadi hanya repo.

Repositori utama

Repositori tempat perintah Bazel saat ini sedang dijalankan.

Workspace

Lingkungan yang digunakan bersama oleh semua perintah Bazel berjalan di repositori utama yang sama.

Perlu diperhatikan bahwa secara historis konsep "repositori" dan "ruang kerja" telah gabungan; istilah "ruang kerja" sering kali digunakan untuk merujuk ke repositori utama, dan terkadang bahkan digunakan sebagai sinonim dari "repositori".

Nama repositori kanonis

Nama kanonis repositori dapat dialamatkan. Dalam konteks ruang kerja, setiap repositori memiliki satu nama kanonis. Target di dalam repo yang nama kanonisnya adalah canonical_name dapat ditangani oleh label @@canonical_name//pac/kage:target (perhatikan @ ganda).

Repositori utama selalu memiliki string kosong sebagai nama kanonis.

Nama repositori yang jelas

Nama repositori dapat dialamatkan 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 alice repo, 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 @ tunggal).

Sebaliknya, hal ini dapat dipahami sebagai pemetaan repositori: setiap repo mempertahankan pemetaan dari "nama repo yang jelas" ke "nama repo kanonis".

Aturan repositori

Skema untuk definisi repositori yang memberi tahu Bazel cara mewujudkan repositori. Misalnya, file dapat berupa "download arsip zip dari URL tertentu dan mengekstraknya", atau "mengambil artefak Maven tertentu dan membuatnya tersedia sebagai target java_import", atau cukup "symlink direktori lokal". Setiap repo ditentukan dengan memanggil aturan repo dengan jumlah argumen yang sesuai.

Lihat Aturan repositori untuk mengetahui informasi selengkapnya 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 symlink direktori lokal yang sudah menjadi repositori Bazel.

Mengambil repositori

Tindakan membuat repo tersedia di disk lokal dengan menjalankan aturan repo yang terkait. Repositori yang ditentukan dalam ruang kerja tidak tersedia pada disk lokal sebelum diambil.

Biasanya, Bazel hanya akan mengambil repo saat memerlukan sesuatu dari repo, dan repo belum diambil. Jika repo telah diambil sebelumnya, Bazel hanya akan mengambilnya kembali jika definisinya telah berubah.

Tata letak direktori

Setelah diambil, repo dapat ditemukan di subdirektori external di dasar output, 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 

Mengelola dependensi eksternal dengan Bzlmod

Bzlmod, subsistem dependensi eksternal baru, tidak langsung berfungsi dengan definisi repo. Sebaliknya, fitur ini membuat grafik dependensi dari modul, menjalankan ekstensi di atas grafik, dan menentukan repo yang sesuai.

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 dependensinya, di antara 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 menyediakan file MODULE.bazel dependensi, yang memungkinkan Bazel menemukan seluruh grafik dependensi transitif sebelum menjalankan resolusi versi.

Setelah resolusi versi, di mana satu versi dipilih untuk setiap modul, Bazel mempelajari 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 repo tambahan. Ekstensi ini memiliki kemampuan yang mirip dengan aturan repo, sehingga memungkinkan mereka melakukan tindakan seperti file I/O dan mengirim permintaan jaringan. Dengan begitu, Bazel dapat 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 repo 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 di 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 foo. Dalam sistem WORKSPACE, secara default, nama kanonis juga merupakan nama jelasnya untuk semua repo lainnya.

Lihat daftar lengkap fungsi yang tersedia dalam file WORKSPACE.

Kekurangan sistem WORKSPACE

Pada tahun-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 pada repo utama, selain dependensi langsung.
  • Untuk mengatasi hal ini, project telah mengadopsi pola "deps.bzl", yang kemudian menentukan makro yang kemudian menentukan beberapa repo, dan meminta pengguna untuk memanggil makro ini dalam file WORKSPACE.
    • Hal ini memiliki masalahnya 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 dengan URL, tanpa informasi versi apa pun. Artinya, tidak ada cara yang dapat diandalkan untuk melakukan resolusi versi dalam kasus dependensi diamond (A bergantung pada B dan C; B dan C keduanya bergantung pada versi D yang berbeda).