Tutorial ini membahas cara menggunakan Bazel untuk melacak dependensi dalam kode Anda menggunakan project Bazel siap pakai.
Untuk mengetahui detail bahasa dan --output flag, lihat panduan referensi kueri Bazel dan panduan referensi cquery Bazel. Dapatkan bantuan di IDE Anda dengan mengetik bazel help query atau bazel help cquery di command line.
Tujuan
Panduan ini akan memandu Anda melalui serangkaian kueri dasar yang dapat digunakan untuk mempelajari lebih lanjut dependensi file project Anda. Panduan ini ditujukan untuk developer Bazel baru yang memiliki pengetahuan dasar tentang cara kerja Bazel dan file BUILD.
Prasyarat
Mulai dengan menginstal Bazel, jika Anda belum melakukannya. Tutorial ini menggunakan Git untuk kontrol sumber, jadi untuk mendapatkan hasil terbaik, instal Git juga.
Untuk memvisualisasikan grafik dependensi, alat yang disebut Graphviz digunakan, yang dapat Anda download untuk mengikuti tutorial ini.
Mendapatkan project contoh
Selanjutnya, ambil aplikasi contoh dari repositori Contoh Bazel dengan menjalankan perintah berikut di alat command line pilihan Anda:
git clone https://github.com/bazelbuild/examples.gitProject contoh untuk tutorial ini ada di direktori examples/query-quickstart.
Memulai
Apa yang dimaksud dengan kueri Bazel?
Kueri membantu Anda mempelajari codebase Bazel dengan menganalisis hubungan antara file BUILD dan memeriksa output yang dihasilkan untuk mendapatkan informasi yang berguna. Panduan ini menampilkan pratinjau beberapa fungsi kueri dasar, tetapi untuk opsi lainnya, lihat panduan kueri. Kueri membantu Anda mempelajari dependensi dalam project skala besar tanpa menavigasi file BUILD secara manual.
Untuk menjalankan kueri, buka terminal command line dan masukkan:
bazel query 'query_function'Skenario
Bayangkan skenario yang membahas hubungan antara Cafe Bazel dan koki masing-masing. Kafe ini hanya menjual pizza dan makaroni keju. Lihat di bawah cara project ini disusun:
bazelqueryguide
├── BUILD
├── src
│ └── main
│ └── java
│ └── com
│ └── example
│ ├── customers
│ │ ├── Jenny.java
│ │ ├── Amir.java
│ │ └── BUILD
│ ├── dishes
│ │ ├── Pizza.java
│ │ ├── MacAndCheese.java
│ │ └── BUILD
│ ├── ingredients
│ │ ├── Cheese.java
│ │ ├── Tomatoes.java
│ │ ├── Dough.java
│ │ ├── Macaroni.java
│ │ └── BUILD
│ ├── restaurant
│ │ ├── Cafe.java
│ │ ├── Chef.java
│ │ └── BUILD
│ ├── reviews
│ │ ├── Review.java
│ │ └── BUILD
│ └── Runner.java
└── MODULE.bazel
Selama tutorial ini, kecuali jika diarahkan lain, jangan melihat file BUILD untuk menemukan informasi yang Anda butuhkan dan hanya gunakan fungsi kueri.
Project terdiri dari berbagai paket yang membentuk Kafe. Paket tersebut dipisahkan menjadi: restaurant, ingredients, dishes, customers, dan reviews. Aturan dalam paket ini menentukan berbagai komponen Kafe dengan berbagai tag dan dependensi.
Menjalankan build
Project ini berisi metode utama di dalam Runner.java yang dapat Anda jalankan untuk mencetak menu Kafe. Buat project menggunakan Bazel dengan perintah bazel build dan gunakan : untuk menandakan bahwa target diberi nama runner. Lihat
nama target untuk mempelajari cara
mereferensikan target.
Untuk membuat project ini, tempelkan perintah ini ke terminal:
bazel build :runnerOutput Anda akan terlihat seperti ini jika build berhasil.
INFO: Analyzed target //:runner (49 packages loaded, 784 targets configured).
INFO: Found 1 target...
Target //:runner up-to-date:
bazel-bin/runner.jar
bazel-bin/runner
INFO: Elapsed time: 16.593s, Critical Path: 4.32s
INFO: 23 processes: 4 internal, 10 darwin-sandbox, 9 worker.
INFO: Build completed successfully, 23 total actions
Setelah berhasil dibuat, jalankan aplikasi dengan menempelkan perintah ini:
bazel-bin/runner--------------------- MENU -------------------------
Pizza - Cheesy Delicious Goodness
Macaroni & Cheese - Kid-approved Dinner
----------------------------------------------------
Tindakan ini akan menampilkan daftar item menu yang diberikan beserta deskripsi singkat.
Menjelajahi target
Project ini mencantumkan bahan dan hidangan dalam paketnya sendiri. Untuk menggunakan kueri guna melihat aturan paket, jalankan perintah bazel query package/…
Dalam hal ini, Anda dapat menggunakan perintah ini untuk melihat bahan dan hidangan yang dimiliki Kafe ini dengan menjalankan:
bazel query //src/main/java/com/example/dishes/...bazel query //src/main/java/com/example/ingredients/...Jika Anda membuat kueri untuk target paket bahan, output-nya akan terlihat seperti:
//src/main/java/com/example/ingredients:cheese
//src/main/java/com/example/ingredients:dough
//src/main/java/com/example/ingredients:macaroni
//src/main/java/com/example/ingredients:tomato
Menemukan dependensi
Target apa yang diandalkan runner Anda untuk dijalankan?
Katakanlah Anda ingin mempelajari lebih dalam struktur project Anda tanpa memeriksa sistem file (yang mungkin tidak dapat dipertahankan untuk project besar). Aturan apa yang digunakan Cafe Bazel?
Jika, seperti dalam contoh ini, target untuk runner Anda adalah runner, temukan dependensi yang mendasarinya dengan menjalankan perintah:
bazel query --noimplicit_deps "deps(target)"bazel query --noimplicit_deps "deps(:runner)"//:runner
//:src/main/java/com/example/Runner.java
//src/main/java/com/example/dishes:MacAndCheese.java
//src/main/java/com/example/dishes:Pizza.java
//src/main/java/com/example/dishes:macAndCheese
//src/main/java/com/example/dishes:pizza
//src/main/java/com/example/ingredients:Cheese.java
//src/main/java/com/example/ingredients:Dough.java
//src/main/java/com/example/ingredients:Macaroni.java
//src/main/java/com/example/ingredients:Tomato.java
//src/main/java/com/example/ingredients:cheese
//src/main/java/com/example/ingredients:dough
//src/main/java/com/example/ingredients:macaroni
//src/main/java/com/example/ingredients:tomato
//src/main/java/com/example/restaurant:Cafe.java
//src/main/java/com/example/restaurant:Chef.java
//src/main/java/com/example/restaurant:cafe
//src/main/java/com/example/restaurant:chef
Dalam sebagian besar kasus, gunakan fungsi kueri deps() untuk melihat dependensi output individual dari target tertentu.
Memvisualisasikan grafik dependensi (opsional)
Bagian ini menjelaskan cara memvisualisasikan jalur dependensi untuk kueri tertentu. Graphviz membantu melihat jalur sebagai gambar grafik asiklik terarah, bukan daftar yang diratakan. Anda dapat mengubah tampilan grafik kueri Bazel menggunakan berbagai opsi command line --output. Lihat Format Output untuk mengetahui opsi.
Mulai dengan menjalankan kueri yang diinginkan dan tambahkan flag --noimplicit_deps untuk menghapus dependensi alat yang berlebihan. Kemudian, ikuti kueri dengan flag output dan simpan grafik ke dalam file bernama graph.in untuk membuat representasi teks dari grafik.
Untuk menelusuri semua dependensi target :runner dan memformat output sebagai grafik:
bazel query --noimplicit_deps 'deps(:runner)' --output graph > graph.inTindakan ini akan membuat file bernama graph.in, yang merupakan representasi teks dari grafik build. Graphviz menggunakan dot – alat yang memproses teks menjadi visualisasi — untuk membuat png:
dot -Tpng < graph.in > graph.pngJika membuka graph.png, Anda akan melihat sesuatu seperti ini. Grafik di bawah telah disederhanakan untuk membuat detail jalur penting lebih jelas dalam panduan ini.

Hal ini membantu saat Anda ingin melihat output dari berbagai fungsi kueri di seluruh panduan ini.
Menemukan dependensi terbalik
Jika Anda memiliki target yang ingin dianalisis target lain yang menggunakannya, Anda dapat menggunakan kueri untuk memeriksa target yang bergantung pada aturan tertentu. Hal ini disebut "dependensi terbalik". Menggunakan rdeps() dapat berguna saat mengedit file dalam codebase yang tidak Anda kenal, dan dapat mencegah Anda merusak file lain yang bergantung padanya tanpa disadari.
Misalnya, Anda ingin melakukan beberapa pengeditan pada bahan cheese. Untuk menghindari masalah pada Cafe Bazel, Anda harus memeriksa hidangan yang bergantung pada cheese.
Untuk melihat target yang bergantung pada target/paket tertentu, Anda dapat menggunakan rdeps(universe_scope, target). Fungsi kueri rdeps() menggunakan setidaknya dua argumen: universe_scope — direktori yang relevan — dan target. Bazel menelusuri dependensi terbalik target dalam universe_scope yang disediakan. Operator rdeps() menerima argumen ketiga opsional: literal bilangan bulat yang menentukan batas atas kedalaman penelusuran.
Untuk mencari dependensi terbalik dari target cheese dalam cakupan seluruh project '//…', jalankan perintah:
bazel query "rdeps(universe_scope, target)"ex) bazel query "rdeps(//... , //src/main/java/com/example/ingredients:cheese)"
//:runner
//src/main/java/com/example/dishes:macAndCheese
//src/main/java/com/example/dishes:pizza
//src/main/java/com/example/ingredients:cheese
//src/main/java/com/example/restaurant:cafe
//src/main/java/com/example/restaurant:chef
Hasil kueri menunjukkan bahwa keju diandalkan oleh pizza dan makaroni keju. Sungguh mengejutkan!
Menemukan target berdasarkan tag
Dua pelanggan masuk ke Bazel Cafe: Amir dan Jenny. Tidak ada yang diketahui tentang mereka kecuali nama mereka. Untungnya, pesanan mereka diberi tag dalam file BUILD 'customers'. Bagaimana cara mengakses tag ini?
Developer dapat memberi tag pada target Bazel dengan ID yang berbeda, sering kali untuk tujuan pengujian. Misalnya, tag pada pengujian dapat menganotasi peran pengujian dalam proses debug dan rilis Anda, terutama untuk pengujian C++ dan Python, yang tidak memiliki kemampuan anotasi runtime. Penggunaan tag dan elemen ukuran memberikan fleksibilitas dalam menyusun rangkaian pengujian berdasarkan kebijakan check-in codebase.
Dalam contoh ini, tag adalah salah satu dari pizza atau macAndCheese untuk mewakili item menu. Perintah ini membuat kueri untuk target yang memiliki tag yang cocok dengan ID Anda dalam paket tertentu.
bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)'
Kueri ini menampilkan semua target dalam paket 'customers' yang memiliki tag "pizza".
Uji diri Anda
Gunakan kueri ini untuk mempelajari pesanan Jenny.
Jawaban
Makaroni Keju
Menambahkan dependensi baru
Cafe Bazel telah memperluas menunya — pelanggan kini dapat memesan Smoothie. Smoothie khusus ini terdiri dari bahan Strawberry dan Banana.
Pertama, tambahkan bahan yang menjadi dependensi smoothie: Strawberry.java dan Banana.java. Tambahkan class Java kosong.
src/main/java/com/example/ingredients/Strawberry.java
package com.example.ingredients;
public class Strawberry {
}
src/main/java/com/example/ingredients/Banana.java
package com.example.ingredients;
public class Banana {
}
Selanjutnya, tambahkan Smoothie.java ke direktori yang sesuai: dishes.
src/main/java/com/example/dishes/Smoothie.java
package com.example.dishes;
public class Smoothie {
public static final String DISH_NAME = "Smoothie";
public static final String DESCRIPTION = "Yummy and Refreshing";
}
Terakhir, tambahkan file ini sebagai aturan dalam file BUILD yang sesuai. Buat library java baru untuk setiap bahan baru, termasuk nama, visibilitas publik, dan file 'src' yang baru dibuat. Anda akan mendapatkan file BUILD yang diperbarui ini:
src/main/java/com/example/ingredients/BUILD
java_library(
name = "cheese",
visibility = ["//visibility:public"],
srcs = ["Cheese.java"],
)
java_library(
name = "dough",
visibility = ["//visibility:public"],
srcs = ["Dough.java"],
)
java_library(
name = "macaroni",
visibility = ["//visibility:public"],
srcs = ["Macaroni.java"],
)
java_library(
name = "tomato",
visibility = ["//visibility:public"],
srcs = ["Tomato.java"],
)
java_library(
name = "strawberry",
visibility = ["//visibility:public"],
srcs = ["Strawberry.java"],
)
java_library(
name = "banana",
visibility = ["//visibility:public"],
srcs = ["Banana.java"],
)
Dalam file BUILD untuk hidangan, Anda ingin menambahkan aturan baru untuk Smoothie. Tindakan ini mencakup file Java yang dibuat untuk Smoothie sebagai file 'src', dan aturan baru yang Anda buat untuk setiap bahan smoothie.
src/main/java/com/example/dishes/BUILD
java_library(
name = "macAndCheese",
visibility = ["//visibility:public"],
srcs = ["MacAndCheese.java"],
deps = [
"//src/main/java/com/example/ingredients:cheese",
"//src/main/java/com/example/ingredients:macaroni",
],
)
java_library(
name = "pizza",
visibility = ["//visibility:public"],
srcs = ["Pizza.java"],
deps = [
"//src/main/java/com/example/ingredients:cheese",
"//src/main/java/com/example/ingredients:dough",
"//src/main/java/com/example/ingredients:tomato",
],
)
java_library(
name = "smoothie",
visibility = ["//visibility:public"],
srcs = ["Smoothie.java"],
deps = [
"//src/main/java/com/example/ingredients:strawberry",
"//src/main/java/com/example/ingredients:banana",
],
)
Terakhir, Anda ingin menyertakan smoothie sebagai dependensi dalam file BUILD Chef.
src/main/java/com/example/restaurant/BUILD
java_library(
name = "chef",
visibility = ["//visibility:public"],
srcs = [
"Chef.java",
],
deps = [
"//src/main/java/com/example/dishes:macAndCheese",
"//src/main/java/com/example/dishes:pizza",
"//src/main/java/com/example/dishes:smoothie",
],
)
java_library(
name = "cafe",
visibility = ["//visibility:public"],
srcs = [
"Cafe.java",
],
deps = [
":chef",
],
)
Buat cafe lagi untuk mengonfirmasi bahwa tidak ada error. Jika berhasil dibuat, selamat. Anda telah menambahkan dependensi baru untuk 'Cafe'. Jika tidak, perhatikan kesalahan ejaan dan penamaan paket. Untuk mengetahui informasi selengkapnya tentang cara menulis BUILD file, lihat Panduan Gaya BUILD.
Sekarang, visualisasikan grafik dependensi baru dengan penambahan Smoothie untuk dibandingkan dengan grafik sebelumnya. Agar lebih jelas, beri nama input grafik sebagai graph2.in dan graph2.png.
bazel query --noimplicit_deps 'deps(:runner)' --output graph > graph2.indot -Tpng < graph2.in > graph2.pngDengan melihat graph2.png, Anda dapat melihat bahwa Smoothie tidak memiliki dependensi bersama dengan hidangan lain, tetapi hanya target lain yang diandalkan oleh Chef.
somepath() dan allpaths()
Bagaimana jika Anda ingin membuat kueri mengapa satu paket bergantung pada paket lain? Menampilkan jalur dependensi antara keduanya akan memberikan jawabannya.
Dua fungsi dapat membantu Anda menemukan jalur dependensi: somepath() dan allpaths(). Dengan target awal S dan titik akhir E, temukan jalur antara S dan E menggunakan somepath(S,E).
Pelajari perbedaan antara kedua fungsi ini dengan melihat hubungan antara target 'Chef' dan 'Cheese'. Ada berbagai jalur yang mungkin untuk berpindah dari satu target ke target lainnya:
- Chef → MacAndCheese → Cheese
- Chef → Pizza → Cheese
somepath() memberi Anda satu jalur dari dua opsi, sedangkan 'allpaths()' menampilkan setiap jalur yang memungkinkan.
Dengan menggunakan Cafe Bazel sebagai contoh, jalankan perintah berikut:
bazel query "somepath(//src/main/java/com/example/restaurant/..., //src/main/java/com/example/ingredients:cheese)"//src/main/java/com/example/restaurant:cafe
//src/main/java/com/example/restaurant:chef
//src/main/java/com/example/dishes:macAndCheese
//src/main/java/com/example/ingredients:cheese
Output mengikuti jalur pertama Cafe → Chef → MacAndCheese → Cheese. Jika Anda menggunakan allpaths(), Anda akan mendapatkan:
bazel query "allpaths(//src/main/java/com/example/restaurant/..., //src/main/java/com/example/ingredients:cheese)"//src/main/java/com/example/dishes:macAndCheese
//src/main/java/com/example/dishes:pizza
//src/main/java/com/example/ingredients:cheese
//src/main/java/com/example/restaurant:cafe
//src/main/java/com/example/restaurant:chef

Output allpaths() sedikit lebih sulit dibaca karena merupakan daftar dependensi yang diratakan. Memvisualisasikan grafik ini menggunakan Graphviz akan membuat hubungan lebih mudah dipahami.
Uji diri Anda
Salah satu pelanggan Cafe Bazel memberikan ulasan pertama restoran. Sayangnya, ulasan tersebut tidak memiliki beberapa detail seperti identitas pengulas dan hidangan yang direferensikannya. Untungnya, Anda dapat mengakses informasi ini dengan Bazel. Paket reviews berisi program yang mencetak ulasan dari pelanggan misterius. Buat dan jalankan dengan:
bazel build //src/main/java/com/example/reviews:reviewbazel-bin/src/main/java/com/example/reviews/reviewDengan hanya menggunakan kueri Bazel, coba cari tahu siapa yang menulis ulasan tersebut, dan hidangan apa yang mereka deskripsikan.
Petunjuk
Periksa tag dan dependensi untuk mendapatkan informasi yang berguna.
Jawaban
Ulasan ini mendeskripsikan Pizza dan Amir adalah pengulasnya. Jika Anda melihat dependensi yang dimiliki aturan ini menggunakan
bazel query --noimplicit\_deps 'deps(//src/main/java/com/example/reviews:review)'
hasil perintah ini akan mengungkapkan bahwa Amir adalah pengulasnya.
Selanjutnya, karena Anda mengetahui bahwa pengulasnya adalah Amir, Anda dapat menggunakan fungsi kueri untuk mencari tag yang dimiliki Amir dalam file `BUILD` untuk melihat hidangan apa yang ada di sana.
Output perintah bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)' menunjukkan bahwa Amir adalah satu-satunya pelanggan yang memesan pizza dan merupakan pengulas yang memberi kita jawabannya.
Menyelesaikan
Selamat! Anda kini telah menjalankan beberapa kueri dasar, yang dapat Anda coba di project Anda sendiri. Untuk mempelajari lebih lanjut sintaksis bahasa kueri, lihat halaman Referensi kueri. Ingin kueri yang lebih canggih? Panduan Kueri menampilkan daftar mendalam tentang kasus penggunaan lainnya yang tidak dibahas dalam panduan ini.
