Bu eğitimde, önceden oluşturulmuş bir Bazel projesi kullanarak kodunuzdaki bağımlılıkları izlemek için Bazel ile nasıl çalışacağınız açıklanmaktadır.
Dil ve --output işareti ayrıntıları için Bazel sorgu referansı ve Bazel cquery referansı kılavuzlarına bakın. Komut satırına bazel help query veya bazel help cquery yazarak IDE'nizde yardım alın.
Hedef
Bu kılavuzda, projenizin dosya bağımlılıkları hakkında daha fazla bilgi edinmek için kullanabileceğiniz bir dizi temel sorgu açıklanmaktadır. Bu doküman, Bazel ve BUILD dosyalarının nasıl çalıştığına dair temel bilgilere sahip yeni Bazel geliştiricileri için hazırlanmıştır.
Ön koşullar
Henüz yapmadıysanız Bazel'i yükleyerek başlayın. Bu eğitimde kaynak kontrolü için Git kullanıldığından en iyi sonuçları elde etmek için Git'i de yükleyin.
Bağımlılık grafiklerini görselleştirmek için Graphviz adlı araç kullanılır. Bu aracı indirerek adımları takip edebilirsiniz.
Örnek projeyi alma
Ardından, tercih ettiğiniz komut satırı aracında aşağıdakileri çalıştırarak Bazel'in örnekler deposundan örnek uygulamayı alın:
git clone https://github.com/bazelbuild/examples.gitBu eğitimdeki örnek proje examples/query-quickstart dizinindedir.
Başlarken
Bazel sorguları nedir?
Sorgular, BUILD dosyaları arasındaki ilişkileri analiz ederek ve sonuçtaki çıktıyı faydalı bilgiler için inceleyerek Bazel kod tabanı hakkında bilgi edinmenize yardımcı olur. Bu kılavuzda bazı temel sorgu işlevleri önizlenir. Daha fazla seçenek için sorgu kılavuzuna bakın. Sorgular, BUILD dosyaları arasında manuel olarak gezinmeden büyük ölçekli projelerdeki bağımlılıklar hakkında bilgi edinmenize yardımcı olur.
Sorgu çalıştırmak için komut satırı terminalinizi açıp şunu girin:
bazel query 'query_function'Senaryo
Cafe Bazel ile şefi arasındaki ilişkiyi ele alan bir senaryo düşünün. Bu kafede yalnızca pizza ve mac & cheese satılıyor. Projenin nasıl yapılandırıldığına dair bilgileri aşağıda bulabilirsiniz:
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
Bu eğitimin tamamında, aksi belirtilmedikçe ihtiyacınız olan bilgileri bulmak için BUILD dosyalarına bakmamaya çalışın ve bunun yerine yalnızca sorgu işlevini kullanın.
Bir proje, bir kafeyi oluşturan farklı paketlerden oluşur. Bunlar restaurant, ingredients, dishes, customers ve reviews olarak ayrılır. Bu paketlerdeki kurallar, çeşitli etiketler ve bağımlılıklarla Cafe'nin farklı bileşenlerini tanımlar.
Derleme çalıştırma
Bu proje, Runner.java içinde bir ana yöntem içerir. Bu yöntemi çalıştırarak kafenin menüsünü yazdırabilirsiniz. bazel build komutuyla Bazel'i kullanarak projeyi oluşturun ve hedefin runner olarak adlandırıldığını belirtmek için : kullanın. Hedeflere nasıl referans vereceğinizi öğrenmek için hedef adlarına bakın.
Bu projeyi oluşturmak için aşağıdaki komutu bir terminale yapıştırın:
bazel build :runnerDerleme başarılı olursa çıkışınız aşağıdaki gibi görünür.
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
Başarıyla oluşturulduktan sonra, bu komutu yapıştırarak uygulamayı çalıştırın:
bazel-bin/runner--------------------- MENU -------------------------
Pizza - Cheesy Delicious Goodness
Macaroni & Cheese - Kid-approved Dinner
----------------------------------------------------
Bu durumda, menü öğelerinin listesi ve kısa açıklamaları gösterilir.
Hedefleri keşfetme
Proje, içerikleri ve yemekleri kendi paketlerinde listeliyor. Bir paketin kurallarını görüntülemek için sorgu kullanmak üzere bazel query package/… komutunu çalıştırın.
Bu durumda, aşağıdaki kodu çalıştırarak bu kafenin malzemelerini ve yemeklerini inceleyebilirsiniz:
bazel query //src/main/java/com/example/dishes/...bazel query //src/main/java/com/example/ingredients/...Malzemeler paketinin hedeflerini sorgularsanız çıkış şu şekilde görünmelidir:
//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
Bağımlılıkları bulma
Çalıştırıcınızın çalışmak için kullandığı hedefler nelerdir?
Örneğin, dosya sistemini incelemeden projenizin yapısını daha ayrıntılı bir şekilde incelemek istiyorsunuz (bu, büyük projeler için uygun olmayabilir). Cafe Bazel hangi kuralları kullanıyor?
Bu örnekteki gibi koşucunuzun hedefi runner ise şu komutu çalıştırarak hedefin temel bağımlılıklarını keşfedin:
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
Çoğu durumda, belirli bir hedefin bağımsız çıkış bağımlılıklarını görmek için sorgu işlevini deps() kullanın.
Bağımlılık grafiğini görselleştirme (isteğe bağlı)
Bu bölümde, belirli bir sorgunun bağımlılık yollarını nasıl görselleştirebileceğiniz açıklanmaktadır. Graphviz, yolu düzleştirilmiş bir liste yerine yönlendirilmiş döngüsüz grafik görüntüsü olarak görmenize yardımcı olur. Çeşitli --output komut satırı seçeneklerini kullanarak Bazel sorgu grafiğinin görünümünü değiştirebilirsiniz. Seçenekler için Çıkış Biçimleri bölümüne bakın.
İstediğiniz sorguyu çalıştırarak başlayın ve gereksiz araç bağımlılıklarını kaldırmak için --noimplicit_deps işaretini ekleyin. Ardından, sorguyu çıkış işaretiyle birlikte kullanın ve grafiğin metin gösterimini oluşturmak için grafiği graph.in adlı bir dosyada saklayın.
Hedef :runner öğesinin tüm bağımlılıklarını aramak ve çıkışı grafik olarak biçimlendirmek için:
bazel query --noimplicit_deps 'deps(:runner)' --output graph > graph.inBu işlem, derleme grafiğinin metin gösterimi olan graph.in adlı bir dosya oluşturur. Graphviz, metni görselleştirmeye dönüştüren bir araç olan dot kullanarak PNG oluşturur:
dot -Tpng < graph.in > graph.pnggraph.png simgesini açtığınızda aşağıdakine benzer bir ekran görürsünüz. Aşağıdaki grafik, bu kılavuzda temel yol ayrıntılarını daha net hale getirmek için basitleştirilmiştir.

Bu, kılavuzdaki farklı sorgu işlevlerinin çıkışlarını görmek istediğinizde işinize yarar.
Ters bağımlılıkları bulma
Bunun yerine, hangi hedeflerin kullandığını analiz etmek istediğiniz bir hedefiniz varsa belirli bir kurala bağlı olan hedefleri incelemek için bir sorgu kullanabilirsiniz. Buna "ters bağımlılık" denir. rdeps(), aşina olmadığınız bir kod tabanındaki dosyaları düzenlerken faydalı olabilir ve kendisine bağlı olan diğer dosyaları bilmeden bozmanızı önleyebilir.
Örneğin, cheese bileşeninde bazı düzenlemeler yapmak istiyorsunuz. Cafe Bazel'de sorun yaşamamak için hangi yemeklerin cheese kullandığını kontrol etmeniz gerekir.
Hangi hedeflerin belirli bir hedefe/pakete bağlı olduğunu görmek için rdeps(universe_scope, target) kullanabilirsiniz. rdeps() sorgu işlevi en az iki bağımsız değişken alır: universe_scope (ilgili dizin) ve target. Bazel, sağlanan universe_scope içinde hedefin ters bağımlılıklarını arar. rdeps() operatörü isteğe bağlı üçüncü bir bağımsız değişkeni kabul eder: arama derinliğinin üst sınırını belirten bir tam sayı değişmezi.
Hedef cheese öğesinin tüm proje kapsamındaki "//…" ters bağımlılıklarını aramak için şu komutu çalıştırın:
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
Sorgu sonucu, hem pizzanın hem de macAndCheese'in peynir kullandığını gösteriyor. Ne sürpriz ama!
Etiketlere göre hedefler bulma
Bazel Cafe'ye iki müşteri giriyor: Amir ve Jenny. Adları dışında haklarında hiçbir bilgi yoktur. Neyse ki siparişleri "müşteriler" BUILD dosyasında etiketlenmiş. Bu etikete nasıl erişebilirsiniz?
Geliştiriciler, genellikle test amacıyla Bazel hedeflerini farklı tanımlayıcılarla etiketleyebilir. Örneğin, testlerdeki etiketler, özellikle çalışma zamanı ek açıklama özelliği olmayan C++ ve Python testleri için bir testin hata ayıklama ve yayınlama sürecindeki rolüne ek açıklamalar ekleyebilir. Etiketleri ve boyut öğelerini kullanmak, bir kod tabanının check-in politikasına göre test paketleri oluşturma konusunda esneklik sağlar.
Bu örnekte, menü öğelerini temsil etmek için etiketler pizza veya macAndCheese'den biri olarak belirlenir. Bu komut, belirli bir pakette tanımlayıcınızla eşleşen etiketlere sahip hedefleri sorgular.
bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)'
Bu sorgu, "pizza" etiketi olan "customers" paketindeki tüm hedefleri döndürür.
Kendinizi test edin
Jenny'nin ne sipariş etmek istediğini öğrenmek için bu sorguyu kullanın.
Yanıtla
Peynirli Makarna
Yeni bağımlılık ekleme
Cafe Bazel menüsünü genişletti. Müşteriler artık smoothie siparişi verebilir. Bu özel smoothie, Strawberry ve Banana malzemelerinden oluşuyor.
Öncelikle smoothie'nin temel malzemelerini ekleyin: Strawberry.java ve Banana.java. Boş Java sınıflarını ekleyin.
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 {
}
Ardından, Smoothie.java öğesini uygun dizine ekleyin: 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";
}
Son olarak, bu dosyaları uygun BUILD dosyalarına kural olarak ekleyin. Adı, herkese açık görünürlüğü ve yeni oluşturulan "src" dosyası da dahil olmak üzere her yeni bileşen için yeni bir Java kitaplığı oluşturun. Sonuç olarak şu güncellenmiş BUILD dosyasına sahip olursunuz:
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"],
)
Yemekler için BUILD dosyasında Smoothie için yeni bir kural eklemek istiyorsunuz. Bu işlem, Smoothie için "src" dosyası olarak oluşturulan Java dosyasını ve smoothie'nin her malzemesi için oluşturduğunuz yeni kuralları içerir.
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",
],
)
Son olarak, smoothie'yi Chef's BUILD dosyasında bağımlı öğe olarak eklemek istiyorsunuz.
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",
],
)
Hata olmadığını onaylamak için cafe öğesini tekrar oluşturun. Başarıyla oluşturulursa tebrikler. "Kafe" için yeni bir bağımlılık eklediniz. Aksi takdirde, yazım hatalarına ve paket adlandırmasına dikkat edin. BUILD dosyaları yazma hakkında daha fazla bilgi için BUILD Stil Kılavuzu'na bakın.
Şimdi, öncekiyle karşılaştırmak için Smoothie simgesini ekleyerek yeni bağımlılık grafiğini görselleştirin. Netlik için grafik girişini graph2.in ve graph2.png olarak adlandırın.
bazel query --noimplicit_deps 'deps(:runner)' --output graph > graph2.indot -Tpng < graph2.in > graph2.pnggraph2.png'ya baktığınızda Smoothie'nın diğer yemeklerle paylaşılan bağımlılıkları olmadığını ancak Chef'nın bağlı olduğu başka bir hedef olduğunu görebilirsiniz.
somepath() ve allpaths()
Bir paketin neden başka bir pakete bağlı olduğunu sorgulamak isterseniz ne yapmanız gerekir? İkisi arasındaki bağımlılık yolunu göstermek yanıtı sağlar.
Bağımlılık yollarını bulmanıza yardımcı olabilecek iki işlev vardır: somepath() ve allpaths(). Başlangıç hedefi S ve bitiş noktası E verildiğinde, somepath(S,E) kullanarak S ile E arasında bir yol bulun.
"Şef" ve "Peynir" hedefleri arasındaki ilişkilere bakarak bu iki işlev arasındaki farkları inceleyin. Bir hedeften diğerine ulaşmak için farklı yollar izleyebilirsiniz:
- Chef → MacAndCheese → Cheese
- Chef → Pizza → Cheese
somepath(), iki seçenekten tek bir yol sunarken "allpaths()" işlevi olası tüm yolları verir.
Cafe Bazel'i örnek olarak kullanarak aşağıdakileri çalıştırın:
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
Çıkış, Cafe → Chef → MacAndCheese → Cheese yolunu izler. Bunun yerine allpaths() kullanırsanız:
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

allpaths() komutunun çıktısı, bağımlılıkların düzleştirilmiş bir listesi olduğundan okunması biraz daha zordur. Bu grafiği Graphviz kullanarak görselleştirmek, ilişkiyi daha net anlamanızı sağlar.
Kendinizi test edin
Cafe Bazel'in müşterilerinden biri, restoranın ilk yorumunu yaptı. Yorumda, yorumcunun kimliği ve hangi yemeğin kastedildiği gibi bazı ayrıntılar eksik. Neyse ki Bazel ile bu bilgilere erişebilirsiniz. reviews paketi, gizemli bir müşterinin yorumunu yazdıran bir program içeriyor. Aşağıdakilerle derleyip çalıştırın:
bazel build //src/main/java/com/example/reviews:reviewbazel-bin/src/main/java/com/example/reviews/reviewYalnızca Bazel sorgularını kullanarak yorumu kimin yazdığını ve hangi yemeği tarif ettiğini bulmaya çalış.
İpucu
Faydalı bilgiler için etiketleri ve bağımlılıkları kontrol edin.
Yanıtla
Bu yorumda pizza anlatılıyor ve yorumu yapan kişi Amir. Bu kuralın hangi bağımlılıkları olduğunu incelerseniz
bazel query --noimplicit\_deps 'deps(//src/main/java/com/example/reviews:review)'
Bu komutun sonucu, incelemeyi yapan kişinin Amir olduğunu gösterir.
Ardından, incelemeyi yapan kişinin Amir olduğunu bildiğiniz için sorgu işlevini kullanarak Amir'in hangi etikete sahip olduğunu bulabilir ve hangi yemeğin olduğunu görebilirsiniz.
bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)' komutunun çıktısı, pizza sipariş eden tek müşterinin Amir olduğunu ve yorumu yapanın da Amir olduğunu göstererek bize yanıtı veriyor.
Özet
Tebrikler! Artık kendi projelerinizde deneyebileceğiniz birkaç temel sorgu çalıştırdınız. Sorgu dili söz dizimi hakkında daha fazla bilgi edinmek için Sorgu referans sayfası'na bakın. Daha gelişmiş sorgular mı istiyorsunuz? Sorgu rehberinde, bu rehberde ele alınanlardan daha fazla kullanım alanının ayrıntılı bir listesi yer almaktadır.
