Panduan memulai kueri

Tutorial ini membahas cara menggunakan Bazel untuk melacak dependensi dalam kode Anda menggunakan project Bazel yang sudah dibuat sebelumnya.

Untuk detail bahasa dan tanda --output, lihat panduan Referensi kueri Bazel dan Referensi kueri Bazel. Dapatkan bantuan terkait IDE Anda dengan mengetik bazel help query atau bazel help cquery pada command line.

Tujuan

Panduan ini memandu Anda melalui serangkaian kueri dasar yang dapat digunakan untuk mempelajari lebih lanjut tentang dependensi file project Anda. Panduan ini ditujukan bagi developer Bazel baru yang memiliki pengetahuan dasar tentang cara kerja file Bazel dan BUILD.

Prasyarat

Mulailah dengan menginstal Bazel, jika Anda belum melakukannya. Tutorial ini menggunakan Git untuk kontrol sumber. Jadi, instal juga Git untuk mendapatkan hasil terbaik.

Untuk memvisualisasikan grafik dependensi, alat bernama Graphviz digunakan, yang dapat Anda download untuk mengikutinya.

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.git

Project contoh untuk tutorial ini ada di direktori examples/query-quickstart.

Memulai

Apa itu 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 mempratinjau beberapa fungsi kueri dasar, tetapi untuk opsi lainnya, lihat panduan kueri. Kueri membantu Anda mempelajari dependensi dalam project berskala besar tanpa menavigasi file BUILD secara manual.

Untuk menjalankan kueri, buka terminal command line Anda dan masukkan:

bazel query 'query_function'

Skenario

Bayangkan sebuah skenario yang menggali hubungan antara Cafe Bazel dan kokinya masing-masing. Kafe ini menjual pizza, mac & keju secara eksklusif. Lihat di bawah ini bagaimana proyek 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
└── WORKSPACE

Sepanjang tutorial ini, kecuali jika ada arahan lain, cobalah untuk tidak melihat dalam file BUILD guna menemukan informasi yang Anda butuhkan dan sebagai gantinya hanya gunakan fungsi kueri.

Sebuah proyek terdiri dari berbagai paket yang membentuk sebuah Kafe. Semuanya dipisahkan menjadi: restaurant, ingredients, dishes, customers, dan reviews. Aturan dalam paket-paket ini mendefinisikan komponen Cafe yang berbeda dengan berbagai tag dan dependensi.

Menjalankan build

Project ini berisi metode utama di dalam Runner.java yang dapat Anda jalankan untuk mencetak menu Cafe. Build 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, tempel perintah berikut ke terminal:

bazel build :runner

Output 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

----------------------------------------------------

Cara ini akan memberi Anda daftar item menu yang diberikan bersama dengan deskripsi singkat.

Menjelajahi target

Proyek ini mencantumkan bahan dan hidangan dalam paket mereka sendiri. Untuk menggunakan kueri guna melihat aturan suatu paket, jalankan perintah bazel query package/…

Dalam hal ini, Anda dapat menggunakannya 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, outputnya akan terlihat seperti ini:

//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 pelari Anda untuk berlari?

Misalnya, Anda ingin mempelajari lebih dalam struktur project tanpa perlu menambahkan sistem file (yang mungkin tidak dapat digunakan untuk project besar). Aturan apa yang digunakan Cafe Bazel?

Jika, seperti dalam contoh ini, target untuk runner adalah runner, temukan dependensi dasar target 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

Pada umumnya, 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 disatukan. Anda dapat mengubah tampilan grafik kueri Bazel dengan menggunakan berbagai opsi command line --output. Lihat Format Output untuk mengetahui opsinya.

Mulailah dengan menjalankan kueri yang Anda inginkan dan tambahkan flag --noimplicit_deps untuk menghapus dependensi alat yang berlebihan. Kemudian, ikuti kueri dengan tanda output dan simpan grafik ke dalam file bernama graph.in untuk membuat representasi teks dari grafik.

Untuk menelusuri semua dependensi :runner target dan memformat output sebagai grafik:

bazel query --noimplicit_deps 'deps(:runner)' --output graph > graph.in

Tindakan 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.png

Saat membuka graph.png, Anda akan melihat sesuatu seperti ini. Grafik di bawah telah disederhanakan untuk memperjelas detail jalur penting dalam panduan ini.

Diagram yang menunjukkan hubungan dari kafe hingga koki dengan hidangan: pizza, mac, dan keju yang menyatu menjadi bahan terpisah: keju, tomat, adonan, dan makaroni.

Hal ini berguna ketika Anda ingin melihat {i>output<i} dari fungsi kueri yang berbeda di sepanjang panduan ini.

Menemukan dependensi terbalik

Jika Anda memiliki target yang ingin menganalisis apa yang digunakan target lain, Anda dapat menggunakan kueri untuk memeriksa target yang bergantung pada aturan tertentu. Ini disebut “dependensi terbalik”. Menggunakan rdeps() dapat berguna saat mengedit file dalam codebase yang tidak Anda ketahui, dan dapat menghindarkan Anda dari tanpa sadar merusak file lain yang bergantung pada file tersebut.

Misalnya, Anda ingin mengedit bahan cheese. Agar tidak menimbulkan masalah bagi Cafe Bazel, Anda perlu memeriksa hidangan yang mengandalkan 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 balik target dalam universe_scope yang disediakan. Operator rdeps() menerima argumen ketiga opsional: literal bilangan bulat yang menentukan batas atas pada kedalaman penelusuran.

Untuk mencari dependensi terbalik cheese target dalam cakupan keseluruhan 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 macAndCheese. Kejutan yang luar biasa!

Menemukan target berdasarkan tag

Dua pelanggan berjalan ke Bazel Cafe: Amir dan Jenny. Tidak ada yang diketahui tentang mereka kecuali namanya. Untungnya, pesanan mereka diberi tag di file BUILD 'pelanggan'. 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 bisa menganotasi peran pengujian dalam proses debug dan rilis, terutama untuk pengujian C++ dan Python, yang tidak memiliki kemampuan anotasi runtime. Menggunakan 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 mengajukan 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 'pelanggan' yang memiliki tag "pizza".

Uji diri Anda

Gunakan kueri ini untuk mengetahui apa yang ingin dipesan Jenny.

Jawaban

Mac dan 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 diperlukan untuk membuat smoothie: Strawberry.java dan Banana.java. Tambahkan class Java yang 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 telah diupdate 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"],
)

Di file BUILD untuk hidangan, Anda ingin menambahkan aturan baru untuk Smoothie. Tindakan tersebut 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, hati-hati dengan kesalahan ejaan dan penamaan paket. Untuk informasi selengkapnya tentang cara menulis file BUILD, lihat Panduan Gaya BANGUN.

Sekarang, visualisasikan grafik dependensi baru dengan penambahan Smoothie untuk dibandingkan dengan yang sebelumnya. Agar lebih jelas, beri nama input grafik sebagai graph2.in dan graph2.png.

bazel query --noimplicit_deps 'deps(:runner)' --output graph > graph2.in
dot -Tpng < graph2.in > graph2.png

Grafik yang sama dengan yang pertama kecuali sekarang ada jari-jari yang berasal dari target koki dengan smoothie yang mengarah ke pisang dan stroberi

Dengan melihat graph2.png, Anda dapat melihat bahwa Smoothie tidak memiliki dependensi bersama dengan hidangan lain, tetapi hanya merupakan target lain yang diandalkan Chef.

somepath() dan allpaths()

Bagaimana jika Anda ingin bertanya mengapa satu paket bergantung pada paket lain? Menampilkan jalur dependensi di antara keduanya memberikan jawaban.

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).

Jelajahi perbedaan antara kedua fungsi ini dengan melihat hubungan antara target 'Chef' dan 'Cheese'. Ada berbagai kemungkinan jalur untuk berpindah dari satu target ke target lainnya:

  • Chef → MacAndCheese → Keju
  • Koki → Pizza → Keju

somepath() memberi Anda satu jalur dari dua opsi tersebut, sedangkan 'allpaths()' menghasilkan 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-nya 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

Jalur output kafe hingga koki hingga pizza, mac, dan keju hingga keju

Output allpaths() sedikit lebih sulit dibaca karena merupakan daftar dependensi yang disatukan. Memvisualisasikan grafik ini menggunakan Graphviz akan membuat hubungan tersebut lebih jelas untuk dipahami.

Uji diri Anda

Salah satu pelanggan Cafe Bazel memberikan ulasan pertama untuk restoran tersebut! Sayangnya, ulasan tersebut tidak memiliki beberapa detail seperti identitas pengulas dan hidangan yang dirujuk. Untungnya, Anda dapat mengakses informasi ini dengan Bazel. Paket reviews berisi program yang mencetak ulasan dari pelanggan misterius. Bangun dan jalankan dengan:

bazel build //src/main/java/com/example/reviews:review
bazel-bin/src/main/java/com/example/reviews/review

Dengan menjawab pertanyaan Bazel saja, cobalah untuk mencari tahu siapa yang menulis ulasan itu, dan hidangan apa yang mereka gambarkan.

Petunjuk

Periksa tag dan dependensi untuk mendapatkan informasi yang berguna.

Jawaban

Ulasan ini menjelaskan Pizza dan Amir adalah pengulas. Jika Anda melihat dependensi yang dimiliki aturan ini bazel query --noimplicit\_deps 'deps(//src/main/java/com/example/reviews:review)' Hasil perintah ini menunjukkan bahwa Amir adalah peninjaunya. Selanjutnya, karena Anda tahu {i>reviewer<i} adalah Amir, Anda dapat menggunakan fungsi kueri untuk mencari tag yang dimiliki Amir di {i>file<i} `BUILD` untuk melihat hidangan apa yang ada di sana. Perintah bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)' menghasilkan bahwa Amir adalah satu-satunya pelanggan yang memesan pizza dan merupakan pengulas yang memberikan jawabannya.

Menyelesaikan

Selamat! Anda sekarang telah menjalankan beberapa kueri dasar, yang dapat Anda coba pada proyek Anda sendiri. Untuk mempelajari sintaksis bahasa kueri lebih lanjut, lihat halaman Referensi kueri. Ingin kueri tingkat lanjut? Panduan Kueri menampilkan daftar mendalam yang berisi lebih banyak kasus penggunaan daripada yang dibahas dalam panduan ini.