Ringkasan dependensi eksternal

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

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

Dokumen ini memberikan ringkasan sistem sebelum memeriksa beberapa konsep secara lebih mendetail.

Ringkasan sistem

Sistem dependensi eksternal Bazel berfungsi berdasarkan modul Bazel, yang masing-masing adalah project Bazel dengan versi, dan repositori (atau repo), yang merupakan hierarki direktori yang berisi file sumber.

Bazel dimulai dari modul root -- yaitu, project yang sedang Anda kerjakan. Seperti semua modul, modul ini harus memiliki file MODULE.bazel di root direktorinya, yang mendeklarasikan metadata dasar dan dependensi langsungnya. Berikut adalah contoh dasar:

module(name = "my-module", version = "1.0")

bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "platforms", version = "0.0.11")

Dari sana, Bazel akan mencari semua modul dependensi transitif di registry Bazel — secara default, Registry Pusat Bazel. Registry menyediakan file MODULE.bazel dependensi, yang memungkinkan Bazel menemukan seluruh grafik dependensi transitif sebelum melakukan resolusi versi.

Setelah resolusi versi, saat satu versi dipilih untuk setiap modul, Bazel akan memeriksa kembali registry untuk mempelajari cara menentukan repo untuk setiap modul -- yaitu, cara sumber untuk setiap modul dependensi harus diambil. Sering kali, file ini hanyalah arsip yang didownload dari internet dan diekstrak.

Modul juga dapat menentukan potongan data yang disesuaikan yang disebut tag, yang digunakan oleh ekstensi modul setelah resolusi modul untuk menentukan repo tambahan. Ekstensi ini dapat melakukan tindakan seperti I/O file dan mengirim permintaan jaringan. Di antara hal lainnya, hal ini memungkinkan Bazel berinteraksi dengan sistem pengelolaan paket lain sekaligus mematuhi grafik dependensi yang dibuat dari modul Bazel.

Tiga jenis repo -- repo utama (yang merupakan hierarki sumber tempat Anda bekerja), repo yang mewakili modul dependensi transitif, dan repo yang dibuat oleh ekstensi modul -- membentuk ruang kerja secara bersamaan. Repositori eksternal (repositori non-utama) diambil sesuai permintaan, misalnya saat dirujuk oleh label (seperti @repo//pkg:target) dalam file BUILD.

Manfaat

Sistem dependensi eksternal Bazel menawarkan berbagai manfaat.

Resolusi Dependensi Otomatis

  • Resolusi Versi Deterministik: Bazel mengadopsi algoritma resolusi versi MVS deterministik, yang meminimalkan konflik dan mengatasi masalah dependensi berlian.
  • Pengelolaan Dependensi yang Disederhanakan: MODULE.bazel hanya mendeklarasikan dependensi langsung, sedangkan dependensi transitif di-resolve secara otomatis, sehingga memberikan ringkasan yang lebih jelas tentang dependensi project.
  • Visibilitas Dependensi Ketat: Hanya dependensi langsung yang terlihat, sehingga memastikan ketepatan dan prediksi.

Integrasi Ekosistem

  • Bazel Central Registry: Repositori terpusat untuk menemukan dan mengelola dependensi umum sebagai modul Bazel.
  • Adopsi Project Non-Bazel: Saat project non-Bazel (biasanya library C++) diadaptasi untuk Bazel dan tersedia di BCR, hal ini akan menyederhanakan integrasinya untuk seluruh komunitas dan menghilangkan upaya duplikat serta konflik file BUILD kustom.
  • Integrasi Terpadu dengan Pengelola Paket Khusus Bahasa: Kumpulan aturan menyederhanakan integrasi dengan pengelola paket eksternal untuk dependensi non-Bazel, termasuk:

Fitur Lanjutan

  • Ekstensi Modul: Fitur use_repo_rule dan ekstensi modul memungkinkan penggunaan fleksibel aturan repositori kustom dan logika resolusi untuk memperkenalkan dependensi non-Bazel.
  • Perintah bazel mod: Sub-perintah ini menawarkan cara efektif untuk memeriksa dependensi eksternal. Anda tahu persis bagaimana dependensi eksternal ditentukan dan asalnya.
  • Mode Vendor: Mengambil dependensi eksternal yang tepat yang Anda butuhkan untuk memfasilitasi build offline.
  • Lockfile: Lockfile meningkatkan reproduksi build dan mempercepat resolusi dependensi.
  • (Mendatang) Pengesahan Proveniens BCR: Memperkuat keamanan supply chain dengan memastikan dependensi yang terverifikasi.

Konsep

Bagian ini memberikan detail selengkapnya tentang konsep yang terkait dengan dependensi eksternal.

Modul

Project Bazel yang dapat memiliki beberapa versi, yang masing-masing dapat memiliki dependensi pada modul lain.

Di ruang kerja Bazel lokal, modul direpresentasikan oleh repositori.

Untuk mengetahui detail selengkapnya, lihat Modul Bazel.

Repositori

Hierarki direktori dengan file penanda batas di root-nya, yang berisi file sumber yang dapat digunakan dalam build Bazel. Sering disingkat menjadi 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 berdampingan dalam direktori.

Repositori utama

Repositori tempat perintah Bazel saat ini dijalankan.

Root repositori utama juga dikenal sebagai root ruang kerja.

Workspace

Lingkungan yang dibagikan oleh semua perintah Bazel berjalan di repositori utama yang sama. Repositori ini mencakup repo utama dan kumpulan semua repo eksternal yang ditentukan.

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

Nama repositori kanonis

Nama kanonis yang digunakan untuk mengakses repositori. Dalam konteks workspace, setiap repositori memiliki satu nama kanonis. Target di dalam repo yang namanya kanonis adalah canonical_name dapat ditangani oleh label @@canonical_name//package:target (perhatikan @ ganda).

Repositori utama selalu memiliki string kosong sebagai nama kanonis.

Nama repositori yang terlihat

Nama yang dapat digunakan untuk mengakses repositori dalam konteks repo lain tertentu. Hal ini dapat dianggap sebagai "nama panggilan" repo: Repo dengan nama kanonis michael mungkin memiliki nama yang terlihat mike dalam konteks repo alice, tetapi mungkin memiliki nama yang terlihat mickey dalam konteks repo bob. Dalam hal ini, target di dalam michael dapat ditangani oleh label @mike//package:target dalam konteks alice (perhatikan @ tunggal).

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

Aturan repositori

Skema untuk definisi repositori yang memberi tahu Bazel cara mewujudkan repositori. Misalnya, dapat berupa "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 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 membuat symlink direktori lokal yang sudah menjadi repositori Bazel.

Mengambil repositori

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

Perintah fetch dapat digunakan untuk memulai pengambilan awal untuk repositori, target, atau semua repositori yang diperlukan untuk melakukan build apa pun. Kemampuan ini memungkinkan build offline menggunakan opsi --nofetch.

Opsi --fetch berfungsi untuk mengelola akses jaringan. Nilai defaultnya adalah true. Namun, jika disetel ke salah (--nofetch), perintah akan menggunakan versi dependensi yang disimpan dalam cache, dan jika tidak ada, perintah akan mengakibatkan kegagalan.

Lihat opsi pengambilan untuk mengetahui informasi selengkapnya tentang cara mengontrol pengambilan.

Tata letak direktori

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

File REPO.bazel

File REPO.bazel digunakan untuk menandai batas teratas hierarki direktori yang membentuk repo. File ini tidak perlu berisi apa pun untuk 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, kecuali tidak ada pernyataan load yang didukung. Fungsi 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"],
)

Sistem WORKSPACE lama

Pada versi Bazel lama (sebelum 9.0), dependensi eksternal diperkenalkan dengan menentukan repo dalam file WORKSPACE (atau WORKSPACE.bazel). File ini memiliki sintaksis yang mirip dengan file BUILD, yang 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. Di sistem WORKSPACE, secara default, nama kanonis repo juga merupakan nama yang terlihat untuk semua repo lainnya.

Lihat daftar lengkap fungsi yang tersedia dalam file WORKSPACE.

Kekurangan sistem WORKSPACE

Selama beberapa tahun setelah sistem WORKSPACE diperkenalkan, pengguna melaporkan banyak titik masalah, termasuk:

  • Bazel tidak mengevaluasi file WORKSPACE dari 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 menentukan makro yang pada akhirnya menentukan beberapa repo, dan meminta pengguna untuk memanggil makro ini dalam file WORKSPACE mereka.
    • Hal ini memiliki masalah tersendiri: makro tidak dapat load file .bzl lainnya, sehingga project ini harus menentukan dependensi transitifnya dalam makro "deps" ini, atau mengatasi masalah ini dengan meminta pengguna memanggil beberapa makro "deps" 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 andal untuk melakukan resolusi versi dalam kasus dependensi diamond (A bergantung pada B dan C; B dan C keduanya bergantung pada versi D yang berbeda).

Karena kekurangan WORKSPACE, sistem berbasis modul baru (dengan nama kode "Bzlmod") secara bertahap menggantikan sistem WORKSPACE lama antara Bazel 6 dan 9. Baca panduan migrasi Bzlmod tentang cara bermigrasi ke Bzlmod.