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

Bu eğiticide, önceden hazırlanmış bir Bazel projesi kullanarak kodunuzdaki bağımlılıkları izlemek için Bazel ile nasıl çalışabileceğiniz 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'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 bulabilirsiniz. Bu program, Bazel ve BUILD dosyalarının nasıl çalıştığıyla ilgili temel bilgilere sahip yeni Bazel geliştiricileri içindir.

Ön koşullar

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

Örnek projeyi alma

Ardından, istediğiniz komut satırı aracında aşağıdaki kodu çalıştırarak Bazel'ın Örnekler deposundan örnek uygulamayı alın:

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

Bu eğitim için örnek proje examples/query-quickstart dizininde yer alıyor.

Başlarken

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. Daha fazla seçenek için sorgu kılavuzuna göz atabilirsiniz. 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şkiyi ele alan bir senaryo düşünün. Bu kafede özel olarak pizza, mak ve peynir satılır. Aşağıda 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
└── WORKSPACE

Bu eğitim süresince, aksi belirtilmediği sürece, ihtiyacınız olan bilgileri bulmak için BUILD dosyalarına bakmayıp yalnızca sorgu işlevini kullanmayı deneyin.

Proje, bir kafeyi oluşturan farklı paketlerden oluşur. Bunlar restaurant, ingredients, dishes, customers ve reviews olarak ayrılmıştır. Bu paketlerdeki kurallar, kafenin çeşitli etiketleri ve bağımlılıklarıyla 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 ana bir yöntem içermektedir. Projeyi, bazel build komutuyla Bazel kullanarak oluşturun ve hedefin runner olarak adlandırıldığını belirtmek için : ifadesini 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 şuna benzer bir görünümde olacaktı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 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 size menü öğelerinin bir listesi sunulur.

Hedefleri keşfetme

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

Bu durumda, aşağıdaki kodu çalıştırarak bu kafenin malzemelerine ve yemeklerine göz atabilirsiniz:

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

Bileşenler paketinin hedeflerini sorgularsanız çıktı aşağıdaki gibi 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 hedefleri temel alıyor?

Dosya sistemini üretmeden projenizin yapısını derinlemesine incelemek istediğinizi düşünelim (büyük projelerde kullanılamayabilir). Cafe Bazel hangi kuralları kullanır?

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. Graphviz, yolu düzleştirilmiş bir liste yerine yönlendirilmiş dairesel bir grafik resmi olarak görmeye 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 Çıktı Biçimleri bölümüne bakın.

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

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

Bu işlem, yapı grafiğinin metin temsili olan graph.in adında 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 şuna benzer bir şey 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.

Peynir, domates, hamur ve makarna gibi farklı malzemelere ayrılan pizza ve mac ve peynir gibi kafeden şefe ve yemeklere olan ilişkiyi gösteren diyagram.

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

Tersine bağımlılıkları bulma

Bunun yerine, diğer hedeflerin hangi hedefleri 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" adı verilir. rdeps() kullanımı, aşina olmadığınız bir kod tabanında dosya düzenlerken yararlı olabilir ve sizi ilgili kod tabanına bağımlı olan diğer dosyaları farkında olmadan bozmanızı önler.

Örneğin, cheese bileşeninde bazı düzenlemeler yapmak istiyorsunuz. Cafe Bazel ile ilgili bir sorun oluşmasını önlemek 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ı.

Tüm "//..." projesi 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 döndürmesi, hem pizza hem de macAndCheese'in peyniri kullandığını gösterir. Sürpriz!

Etiketlere dayalı olarak 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, çoğu zaman 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ı ek açıklaması yeteneğine sahip olmayan C++ ve Python testlerinde testin rolüne ek açıklama ekleyebilir. Etiket ve boyut öğelerinin kullanılması, test paketlerini bir kod tabanının check-in politikasına göre derlerken esneklik sağlar.

Bu örnekte etiketler, menü öğelerini temsil etmek için pizza veya macAndCheese değerlerinden 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

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

Cevap

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 ihtiyaç duyduğ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. Bu güncellenmiş BUILD dosyasıyla yola çıkın:

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ına Smoothie için yeni bir kural eklemek istiyorsunuz. Bu işlem, Smoothie için oluşturulan Java dosyasını "src" dosyası olarak ve smoothie'nin her bir bileşeni 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, Şefin BUILD dosyasına smoothie'yi bağımlılık olarak dahil etmek istersiniz.

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 öğesini yeniden oluşturun. Başarıyla oluşturulduysa tebrikler! "Kafe" için yeni bir bağımlılık eklediniz. 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 Kılavuzu'na bakın.

Şimdi de Smoothie öğesinin eklendiği ve öncekiyle karşılaştırmak için yeni bağımlılık grafiğini 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

İlki ile aynı grafiktir. Şu anda şefin hedefinden çıkan, smoothie içeren ve muz ile çilek çıkan bir küpe vardır

graph2.png metriğine baktığınızda, Smoothie adlı yerin diğer yemeklerle ortak bir bağımlılığı olmadığını, ancak Chef için kullanılan bir başka hedef olduğunu görebilirsiniz.

somepath() ve allpaths()

Bir paketin neden başka bir pakete bağlı olduğunu sorgulamak isterseniz ne olur? Yanıt, ikisi arasında bir bağımlılık yolu göstermektir.

Şu iki işlev bağımlılık yollarını bulmanıza yardımcı olabilir: somepath() ve allpaths(). Başlangıç hedefi S ve varış noktası E verildiğinde S ile E arasındaki yolu somepath(S,E) kullanarak bulun.

"Şef" ve "Peynir" hedefleri arasındaki ilişkilere bakarak bu iki işlev arasındaki farkları keşfedin. Bir hedeften diğerine gitmek için olası farklı yollar vardır:

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

somepath() size iki seçenekten tek bir yol sağlar, "allpaths()" ise olası tüm yolları sunar.

Ö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 yolunun ilk yolunu izler. Bunun yerine allpaths() kullanırsanız şu avantajlardan yararlanırsını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

Kafeden şefe, pizza, mac, peynirden peynire giden çı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

Restoranla ilgili ilk yorumu Cafe Bazel'in müşterilerinden biri yapmıştır. 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. Şunu kullanarak derleyip ç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ının önüne geçerseniz yorumu kimin yazdığını ve hangi yemeği tarif ettiğini bulmaya çalışın.

İpucu

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

Cevap

Bu yorumda Pizza ile ilgiliydi ve Emir'in yorumcu olduğuydu. 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ğinizden, Emir'in "BUILD" dosyasındaki hangi etikete sahip olduğunu bulmak için sorgu işlevini kullanarak 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 sorunu inceleyen kişi olduğunu belirtir.

Ö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ını inceleyin. 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.