Sorgu hızlı başlangıç kılavuzu

Bu eğitimde, önceden hazırlanmış bir Bazel projesi kullanarak kodunuzdaki bağımlılıkları izlemek için Bazel ile nasıl çalışabileceğiniz ele alınmaktadır.

Dil ve --output işaret ayrıntıları için Bazel sorgu referansı ve Bazel BigQuery referansı kılavuzlarına bakın. Komut satırına bazel help query veya bazel help cquery yazarak IDE'nizle ilgili 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çıklanmıştır. Bu program, Bazel ve BUILD dosyalarının nasıl çalıştığıyla ilgili temel bilgilere sahip yeni Bazel geliştiricileri için tasarlanmıştır.

Ön koşullar

Henüz yapmadıysanız Bazel'i yükleyerek başlayın. Bu eğitim, kaynak kontrolü için Git kullanır. Bu nedenle, 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. Daha sonra bu aracı indirebilirsiniz.

Örnek projeyi alma

Daha sonra, seçtiğiniz komut satırı aracında aşağıdaki kodu çalıştırarak Bazel's Örnekler deposundan örnek uygulamayı alın:

git clone https://github.com/bazelbuild/examples.git

Bu eğitim için örnek proje, examples/query-quickstart dizinindedir.

Kullanmaya başlama

Bazel sorguları nedir?

Sorgular, BUILD dosyaları arasındaki ilişkileri analiz ederek ve elde edilen çıkışı faydalı bilgiler açısından inceleyerek Bazel kod tabanı hakkında bilgi edinmenize yardımcı olur. Bu kılavuzda bazı temel sorgu işlevleri önizlenmektedir. Ancak daha fazla seçenek için sorgu kılavuzuna göz atın. Sorgular, BUILD dosyalarında manuel olarak gezinmeden büyük ölçekli projelerde bağımlılıklar hakkında bilgi edinmenize yardımcı olur.

Sorgu çalıştırmak için komut satırı terminalinizi açın ve şunu girin:

bazel query 'query_function'

Senaryo

Cafe Bazel ile şefi arasındaki ilişkinin ayrıntılarına inen bir senaryo hayal edin. Bu kafede özel olarak pizza, mac ve peynir satılıyor. Projenin nasıl yapılandırıldığına göz atın:

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ğitim boyunca, aksi belirtilmediği sürece ihtiyacınız olan bilgileri bulmak için BUILD dosyalarına bakmayı deneyin, bunun yerine yalnızca sorgu işlevini kullanın.

Proje, bir kafeyi oluşturan farklı paketlerden oluşur. Bunlar şu şekilde ayrılmıştır: restaurant, ingredients, dishes, customers ve reviews. Bu paketlerdeki kurallar, çeşitli etiketler ve bağımlılıklarla birlikte kafenin farklı bileşenlerini tanımlar.

Derleme çalıştırma

Bu proje, Runner.java içinde bir kafe menüsünü yazdırmak için çalıştırabileceğiniz bir ana yöntem içerir. bazel build komutunu kullanarak Bazel'i kullanarak projeyi oluşturun ve hedefin runner olarak adlandırıldığını belirtmek için : kodunu kullanın. Hedeflere nasıl başvuracağınızı öğrenmek için hedef adlarına bakın.

Bu projeyi derlemek için şu komutu bir terminale yapıştırın:

bazel build :runner

Derleme başarılı olursa çıktınız aşağıdaki gibi görünmelidir.

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 derlendikten sonra aşağıdaki komutu yapıştırarak uygulamayı çalıştırın:

bazel-bin/runner
--------------------- MENU -------------------------

Pizza - Cheesy Delicious Goodness
Macaroni & Cheese - Kid-approved Dinner

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

Böylece kısa bir açıklamayla birlikte menü öğelerinin bir listesi size sunulur.

Hedefleri keşfetme

Projede, malzemeler ve yemekler kendi paketlerinde listeleniyor. Paketin kurallarını görüntülemek amacıyla sorgu kullanmak için bazel query package/… komutunu çalıştırın.

Bu durumda, aşağıdaki komutu çalıştırarak kafedeki malzemeler ve yemeklere göz atabilirsiniz:

bazel query //src/main/java/com/example/dishes/...
bazel query //src/main/java/com/example/ingredients/...

Malzeme paketinin hedeflerini sorgularsanız çıktı ş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

Koşucunuz koşmak için hangi hedeflere güveniyor?

Dosya sistemine geçmeden projenizin yapısını daha ayrıntılı olarak incelemek istediğinizi varsayalım (büyük projeler için bu ayar etkinleştirilemeyebilir). Cafe Bazel hangi kuralları kullanıyor?

Bu örnekte olduğu gibi, çalıştırıcınızın 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 deps() sorgu işlevini kullanın.

Bağımlılık grafiğini görselleştirme (isteğe bağlı)

Bu bölümde, belirli bir sorgu için bağımlılık yollarını nasıl görselleştirebileceğiniz açıklanmaktadır. Grafik grafiği, yolu düzleştirilmiş bir liste yerine yönlendirilmiş çembersel bir grafik resmi olarak görmeye yardımcı olur. Çeşitli --output komut satırı seçeneklerini kullanarak Bazel sorgu grafiğinin görüntüsünü değiştirebilirsiniz. Seçenekler için Çıktı Biçimleri bölümüne bakın.

İstediğiniz sorguyu çalıştırarak başlayın ve aşırı sayıda araç bağımlılığını kaldırmak için --noimplicit_deps işaretini ekleyin. Ardından, çıktı işaretiyle sorguyu izleyin ve grafiğin metin şeklinde temsilini oluşturmak için grafiği graph.in adlı bir dosyaya kaydedin.

Hedef :runner öğesinin tüm bağımlılıklarını aramak ve çıktıyı grafik olarak biçimlendirmek için:

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

Bu işlem, yapı grafiğinin metin gösterimi olan graph.in adlı bir dosya oluşturur. Graphviz, png oluşturmak için metni görselleştirmeye dönüştüren dot aracını kullanır:

dot -Tpng < graph.in > graph.png

graph.png uygulamasını açarsanız şunun gibi bir şey görürsünüz. Aşağıdaki grafik, bu kılavuzdaki temel yol ayrıntılarını daha net hale getirmek için basitleştirilmiştir.

Pizza ve mac ve peynir; peynir, domates, hamur ve makarna gibi farklı malzemeleriyle kafeden şefi ve yemekler arasındaki ilişkiyi gösteren şema.

Bu kılavuz, farklı sorgu işlevlerinin çıkışlarını görmek istediğinizde işinize yarayacaktır.

Ters bağımlılıkları bulma

Bunun yerine, başka hangi hedeflerin onu kullandığını analiz etmek istediğiniz bir hedefiniz varsa, hangi hedeflerin belirli bir kurala bağlı olduğunu incelemek için bir sorgu kullanabilirsiniz. Buna "ters bağımlılık" denir. rdeps() kullanımı, aşina olmadığınız bir kod tabanında dosya düzenlerken faydalı olabilir ve sizi buna bağlı olan diğer dosyaları farkında olmadan bozmaktan kurtarabilir.

Örneğin, cheese malzemesinde bazı düzenlemeler yapmak istiyorsunuz. Cafe Bazel ile ilgili sorun yaşamamak için hangi yemeklerin cheese güvenilir olduğunu kontrol etmeniz gerekir.

Hangi hedeflerin belirli bir hedefe/pakete bağlı olduğunu görmek için rdeps(universe_scope, target) öğesini kullanabilirsiniz. rdeps() sorgu işlevi en az iki bağımsız değişken alır: bir universe_scope - ilgili dizin - ve bir 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: Aramanın derinliğindeki üst sınırı belirten bir tam sayı değişmez değeri.

"//..." projesinin tamamı kapsamında cheese hedefinin 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 pizza hem de macAndCheese'de peynirin kullanıldığını gösterir. Ne sürpriz!

Etiketlere göre hedefler bulma

İki müşteri Bazel Cafe'ye giriyor: Emir ve Canan. Adları dışında bilinen hiçbir şey yoktur. Neyse ki, müşterilerinin siparişleri "müşteriler" BUILD dosyasında etiketlenmiştir. Bu etikete nasıl erişebilirsiniz?

Geliştiriciler, genellikle test amacıyla Bazel hedeflerini farklı tanımlayıcılarla etiketleyebilirler. Örneğin, testlerdeki etiketler, hata ayıklama ve yayınlama sürecinizde, özellikle de çalışma zamanı notu özelliği olmayan C++ ve Python testlerinde testin rolüne ek açıklama ekleyebilir. Etiketlerin ve boyut öğelerinin kullanılması, test paketlerinin bir kod tabanının check-in politikasına göre derlenmesinde esneklik sağlar.

Bu örnekte etiketler, menü öğelerini temsil etmek için pizza veya macAndCheese etiketlerinden biridir. 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, "müşteriler" paketinde bulunan ve "pizza" etiketine sahip tüm hedefleri döndürür.

Kendinizi test edin

Ceyda'nın ne sipariş etmek istediğini öğrenmek için bu sorguyu kullanın.

Yanıtla

Mac ve Peynir

Yeni bir bağımlılık ekleme

Cafe Bazel menüsünü genişletti; müşteriler artık Smoothie sipariş edebilir. Bu smoothie, Strawberry ve Banana malzemelerinden oluşur.

Öncelikle smoothie'nin bağlı olduğu malzemeleri 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 dosyasını 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. Her yeni bileşen için adı, herkese açık görünürlüğü ve yeni oluşturulan 'src' dosyasını içeren yeni bir Java kitaplığı oluşturun. Şu güncellenmiş BUILD dosyasıyla çalışmanız gerekir:

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"],
)

Yemeklerle ilgili BUILD dosyasında Smoothie için yeni bir kural eklemek istiyorsunuz. Bu işlem sonucunda, Smoothie için oluşturulan Java dosyası "src" dosyası olarak ve smoothie'nin her bir malzemesi için oluşturduğunuz yeni kurallar dahil edilir.

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'in BUILD dosyasına bir bağımlılık 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",
    ],
)

Herhangi bir hata olmadığını onaylamak için cafe uygulamasını tekrar oluşturun. Başarıyla oluşturulduysa tebrikler! "Kafe" için yeni bir bağımlılık eklediniz. Doğru değilse yazım hatalarına ve paket adlandırma kurallarına dikkat edin. BUILD dosyalarını yazma hakkında daha fazla bilgi için DERLEME Stil Kılavuzu'na bakın.

Şimdi, öncekiyle karşılaştırmak için yeni bağımlılık grafiğini, eklenen Smoothie ile görselleştirin. Anlaşılır olması için, grafik girişini graph2.in ve graph2.png olarak adlandırın.

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

İlkiyle aynı grafik ancak şu anda smoothie içeren şefin hedefinden çıkan ve muz ile çilek getiren bir konuşma metni var

graph2.png verilerine baktığınızda, Smoothie adlı müşterinin diğer yemeklerle ortak bağımlılıkları olmadığını, ancak Chef için kullanılan başka bir hedefin olduğunu görebilirsiniz.

somepath() ve allpaths()

Bir paketin neden başka bir pakete bağlı olduğunu sorgulamak isterseniz ne olur? İkisi arasında bir bağımlılık yolu görüntülemek cevabı sağlar.

Şu iki işlev bağımlılık yollarını bulmanıza yardımcı olabilir: somepath() ve allpaths(). Bir başlangıç hedefi S ve bir bitiş noktası E verildiğinde, somepath(S,E) işlevini 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 gitmek için kullanılabilecek farklı yollar vardır:

  • Şef → MacAndCheese → Peynir
  • Şef → Pizza → Peynir

somepath() size iki seçenekten tek bir yol sunarken "allpaths()" olası her yolu sağlar.

Örnek olarak Cafe Bazel'i kullanarak aşağıdaki komutu ç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 bölümünün ilk yolunu izler. Bunun yerine allpaths() kullanırsanız şu avantajları elde edersiniz:

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

Kafeden şefe, pizzaya, maca, peynire ve peynire doğru çıkış yolu

Bağımlılıkların birleştirilmiş bir listesi olduğundan allpaths() çıktısının okunması biraz daha zordur. Bu grafiği Graphviz kullanarak görselleştirmek, ilişkinin anlaşılmasını daha net hale getirir.

Kendinizi test edin

Restoranın ilk yorumunu Cafe Bazel'in müşterilerinden biri yaptı. Maalesef yorumda, yorumcunun kimliği ve hangi yemeğe atıfta bulunduğu gibi bazı ayrıntılar eksik. Neyse ki, bu bilgilere Bazel ile erişebilirsiniz. reviews paketi, gizli bir müşterinin yorumunu yazdıran bir program içerir. Şununla derleyin ve çalıştırın:

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

Yalnızca Bazel sorgularından çıkarak yorumu kimin yazdığını ve hangi yemeği açıkladığını öğrenmeye çalışın.

İpucu

Faydalı bilgiler için etiketleri ve bağımlılıkları kontrol edin.

Yanıtla

Bu yorumda Pizzacı, yorumcunun Emir olduğu açıklanıyor. Bu kuralın bazel query --noimplicit\_deps 'deps(//src/main/java/com/example/reviews:review)' kullanarak sahip olduğu bağımlılıklara bakarsanız Bu komutun sonucu Emir'in incelemeci olduğunu gösterir. Ardından, yorumcunun Emir olduğunu bildiğiniz için sorgu işlevini kullanarak Emir'in "BUILD" dosyasındaki hangi etikete sahip olduğunu araştırarak orada hangi yemeğin olduğunu görebilirsiniz. bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)' komutu, Emir'in pizza siparişi veren tek müşteri olduğunu ve yanıtı inceleyen kişi olduğunu söyler.

Ö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 kılavuzu, bu kılavuzda ele alınandan daha fazla kullanım alanının ayrıntılı bir listesini gösterir.