Panduan memulai kueri

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

Tutorial ini membahas cara bekerja dengan Bazel untuk melacak dependensi dalam kode Anda menggunakan project Bazel siap pakai.

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

Tujuan

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

Prasyarat

Jika belum, mulailah dengan menginstal Bazel. Tutorial ini menggunakan Git untuk kontrol sumber, jadi untuk hasil terbaik, instal juga Git.

Untuk memvisualisasikan grafik dependensi, gunakan alat bernama Graphviz, 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 berada 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 informasi yang berguna. Panduan ini melihat pratinjau 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: posix-terminal bazel query 'query_function'

Skenario

Bayangkan sebuah skenario yang mengungkap hubungan antara Cafe Bazel dan kokinya masing-masing. Kafe ini khusus menjual pizza, mac & amp; keju. Lihat struktur project berikut di bawah ini:

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 ada instruksi lain, cobalah untuk tidak melihat dalam file BUILD untuk menemukan informasi yang Anda butuhkan dan sebagai gantinya menggunakan fungsi kueri.

Project terdiri dari berbagai paket yang membentuk Cafe. Keduanya dipisahkan menjadi: restaurant, ingredients, dishes, customers, dan reviews. Aturan dalam paket ini menentukan berbagai komponen Cafe dengan berbagai tag dan dependensi.

Menjalankan build

Untuk memulai, build project ini menggunakan Bazel untuk membuat file yang dapat dieksekusi.

Berikutnya, jalankan file yang dapat dieksekusi untuk menyediakan menu yang ditawarkan Cafe.

Untuk mem-build project ini, tempel perintah ini ke terminal:

bazel build :runner

Output Anda akan terlihat seperti ini jika build berhasil. bash 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 memberi Anda daftar item menu yang diberikan beserta deskripsi singkat.

Menjelajahi target

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

Dalam hal ini, Anda dapat menggunakannya untuk memeriksa 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 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 oleh pelari Anda untuk berlari?

Misalnya Anda ingin lebih memahami struktur project tanpa harus masuk ke dalam sistem file (yang mungkin tidak dapat dilakukan untuk project besar). Apa saja aturan yang digunakan Cafe Bazel?

Jika, seperti dalam contoh ini, target untuk runner Anda 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 diratakan. Anda dapat mengubah tampilan grafik kueri Bazel menggunakan berbagai opsi command line --output. Lihat Format Output untuk opsi lainnya.

Mulai dengan menjalankan kueri yang diinginkan dan tambahkan flag --noimplicit_deps untuk menghapus dependensi alat yang berlebihan. Kemudian, ikuti kueri dengan tanda output dan simpan grafik ke dalam file yang disebut graph.in untuk membuat representasi teks 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

Jika membuka graph.png, Anda akan melihat tampilan seperti ini. Grafik di bawah telah disederhanakan untuk membuat detail jalur penting lebih jelas dalam panduan ini.

Diagram yang menunjukkan hubungan dari kafe ke chef ke hidangan: pizza dan mac dan keju yang menyimpang ke dalam bahan-bahan yang terpisah: keju, tomat, adonan, dan makaroni.

Hal ini membantu saat Anda ingin melihat output dari berbagai fungsi kueri di seluruh panduan ini.

Menemukan dependensi terbalik

Jika memiliki target yang ingin dianalisis, target apa yang digunakan target lainnya, Anda dapat menggunakan kueri untuk memeriksa target apa yang bergantung pada aturan tertentu. Ini disebut "dependensi terbalik". Penggunaan rdeps() dapat berguna saat mengedit file dalam codebase yang tidak Anda kenal, dan dapat menghindarkan Anda dari merusak file lain yang bergantung padanya tanpa sadar.

Misalnya, Anda ingin mengedit beberapa bahan cheese. Untuk menghindari masalah terkait Cafe Bazel, Anda perlu memeriksa hidangan apa 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 pada kedalaman penelusuran.

Untuk mencari dependensi terbalik 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 macAndCheese. Mengejutkan!

Menemukan target berdasarkan tag

Dua pelanggan berjalan ke Bazel Cafe: Amir dan Jenny. Tidak ada yang diketahui tentang mereka kecuali nama mereka. Untungnya, pesanan mereka telah diberi tag dalam 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 dapat menganotasi peran pengujian dalam proses debug dan rilis, 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 dapat berupa salah satu dari pizza atau macAndCheese untuk mewakili item menu. Perintah ini memproses 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 cari tahu apa yang mau dipesan Jenny.

Jawaban

Mac dan Keju

Menambahkan dependensi baru

Cafe Bazel telah memperluas menunya — pelanggan kini dapat memesan Smoothie! Smoothie spesifik ini terdiri dari bahan-bahan Strawberry dan Banana.

Pertama, tambahkan bahan yang bergantung pada 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. Membuat library Java baru untuk setiap elemen baru, termasuk nama, visibilitas publik, dan file 'src' yang baru dibuat. Anda akan diarahkan dengan 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"],
)

Di file BUILD untuk hidangan, Anda ingin menambahkan aturan baru untuk Smoothie. Cara ini akan 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",
    ],
)

Build 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 informasi selengkapnya tentang penulisan file BUILD, lihat Panduan Gaya BUILD.

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 grafik pertama kecuali sekarang ada pola bicara yang berasal dari target chef 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 antara keduanya akan memberikan jawaban.

Dua fungsi dapat membantu Anda menemukan jalur dependensi: somepath() dan allpaths(). Dengan target 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 beberapa jalur berbeda yang dapat dilalui dari satu target ke target lainnya:

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

somepath() memberi Anda satu jalur dari kedua opsi tersebut, sedangkan 'allpaths()' menghasilkan setiap jalur yang memungkinkan.

Dengan menggunakan Cafe Bazel, jalankan contoh 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

Outputnya mengikuti jalur pertama Cafe → Chef → MacAndCheese → Cheese. Jika 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, koki, pizza, mac, dan keju

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

Uji diri Anda

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

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

Saat menelusuri kueri Bazel saja, cobalah untuk mengetahui siapa yang menulis ulasan, dan hidangan apa yang mereka jelaskan.

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 menggunakan bazel query --noimplicit\_deps 'deps(//src/main/java/com/example/reviews:review)' Hasil perintah ini menunjukkan bahwa Amir adalah peninjau. Selanjutnya, karena Anda tahu pengulas adalah Amir, Anda dapat menggunakan fungsi kueri untuk mencari tag yang dimiliki Amir dalam file `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 piza dan merupakan pengulas yang memberi kita jawaban.

Menyelesaikan

Selamat! Kini Anda telah menjalankan beberapa kueri dasar, yang dapat dicoba pada project Anda sendiri. Untuk mempelajari sintaksis bahasa kueri lebih lanjut, lihat Halaman referensi kueri. Ingin kueri lanjutan lainnya? Panduan kueri menampilkan daftar kasus penggunaan yang lebih mendalam daripada yang dibahas dalam panduan ini.