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

7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bu eğitimde, hazır bir Bazel projesini 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 sorgusu referansı ve Bazel sorgu 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 temel sorgular açıklanmaktadır. Bu sürüm, Bazel ve BUILD dosyalarının işleyişiyle 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ğiticide kaynak kontrolü için Git kullanıldığından en iyi sonuçlar 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ı, adımları takip etmek için indirebilirsiniz.

Örnek projeyi alma

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

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

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

Başlarken

Bazel sorguları nedir?

Sorgular, BUILD dosyaları arasındaki ilişkileri analiz edip üretilen çıktıyı faydalı bilgiler açısından inceleyerek Bazel kod tabanı hakkında bilgi edinmenize yardımcı olur. Bu kılavuzda bazı temel sorgu işlevleri önizlenebilir. Daha fazla seçenek için sorgu rehberine göz atın. Sorgular, büyük ölçekli projelerdeki bağımlılıklar hakkında bilgi edinmek için BUILD dosyalarında manuel olarak gezinmenize gerek kalmadan size 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 derinlemesine inceleyen bir senaryo düşünün. Bu kafede yalnızca pizza ve makarna satılır. Projenin nasıl yapılandırıldığına aşağıdan göz atabilirsiniz:

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

Proje, bir kafeyi oluşturan farklı paketlerden oluşur. Bunlar restaurant, ingredients, dishes, customers ve reviews olarak ayrılır. Bu paketlerdeki kurallar, farklı etiketlere ve bağımlılıklara sahip farklı kafe bileşenlerini tanımlar.

Derleme çalıştırma

Bu projede, kafenin menüsünü yazdırmak için yürütebileceğiniz Runner.java içinde bir ana yöntem bulunur. Projeyi bazel build komutuyla Bazel'ı kullanarak oluşturun ve hedefin runner olarak adlandırıldığını belirtmek için : yönergesini 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 :runner

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

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

Uygulama başarıyla oluşturulduktan 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

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

Bu işlem, kısa bir açıklamayla birlikte verilen menü öğelerinin listesini gösterir.

Hedefleri keşfetme

Projede, malzemeler ve yemekler kendi paketlerinde listelenir. 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 sorguyu çalıştırarak bu kafenin sunduğu yemekleri ve malzemeleri incelemek için bu özelliği kullanabilirsiniz:

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

İçerik paketinin hedeflerini sorguladığınızda çıkış şu şekilde görünür:

//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şucunuzun koşmak için hangi hedeflere ihtiyacı var?

Dosya sistemine girmeden (büyük projeler için uygun olmayabilir) projenizin yapısına daha ayrıntılı bir şekilde göz atmak istediğinizi varsayalım. Cafe Bazel hangi kuralları kullanıyor?

Bu örnekte olduğu gibi, çalıştırıcınızın hedefi runner ise aşağıdaki 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ı 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 sorgunun bağımlılık yollarını nasıl görselleştirebileceğiniz açıklanmaktadır. Graphviz, yolun düzleştirilmiş liste yerine yönlendirilmiş bir döngüsel grafik resmi olarak görülmesine 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 Çıkış 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ı kaldırmak için --noimplicit_deps işaretini ekleyin. Ardından, çıkış işaretiyle sorguyu takip edin ve grafiğin metin gösterimini oluşturmak için grafiği graph.in adlı bir dosyada depolayın.

Hedef :runner'ün tüm bağımlılıkları için arama yapmak ve çıktıyı grafik olarak biçimlendirmek için:

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

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

dot -Tpng < graph.in > graph.png

graph.png uygulamasını açarsanız şuna benzer bir şey görürsünüz. Bu kılavuzda temel yol ayrıntılarını daha net hale getirmek için aşağıdaki grafik basitleştirilmiştir.

Kafe ile şefin yemekleri arasındaki ilişkiyi gösteren şema. Pizza, macun ve peynir farklı malzemelerle farklı malzemeler kullanılır: peynir, domates, hamur ve makarna.

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

Ters bağımlılıkları bulma

Bunun yerine, hangi diğer hedeflerin kullandığını analiz etmek istediğiniz bir hedefiniz varsa belirli bir kurala bağlı hedefleri incelemek için sorgu kullanabilirsiniz. Buna "ters bağımlılık" denir. Bilmediğiniz bir kod tabanında dosya düzenlerken rdeps() kullanmak yararlı olabilir ve sizi, bağımlı olan diğer dosyaları bilmeden kırmaktan kurtarabilir.

Örneğin, cheese bileşeninde bazı düzenlemeler yapmak istiyorsunuz. Cafe Bazel açısından soruna neden olmaması için cheese kullanılan yemekleri kontrol etmeniz gerekir.

Belirli bir hedefe/pakete bağlı hedefleri görmek için rdeps(universe_scope, target) değerini kullanabilirsiniz. rdeps() sorgu işlevi en az iki bağımsız değişken alır: ilgili dizin olan bir universe_scope 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ü bağımsız değişkeni kabul eder: Aramanın derinliğinin üst sınırını belirten tam sayı bir düz sayı.

cheese hedefinin ters bağımlılıklarını tüm proje "//..." kapsamında 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 makarna için peynirin kullanıldığını gösterir. Ne sürpriz!

Etiketlere dayalı olarak hedef bulma

Bazel Cafe'ye iki müşteri geliyor: Emir ve Jale. Bu kişiler hakkında adları dışında hiçbir bilgi yoktur. Neyse ki siparişleri "customers" BUILD dosyasında etiketlenmiş. Bu etikete nasıl erişebilirsiniz?

Geliştiriciler, genellikle test amacıyla Bazel hedeflerini farklı tanımlayıcılarla etiketleyebilirler. Örneğin, testlerdeki etiketler, çalışma zamanında ek açıklama ekleme yeteneğine sahip olmayan C++ ve Python testlerinde özellikle hata ayıklama ve yayınlama sürecinizde bir testin rolüne ek açıklama ekleyebilir. Etiketlerin ve boyut öğelerinin kullanılması, kod tabanının giriş politikasına dayalı test paketlerinin derlenmesinde 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 sorgulayarak bulur.

bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)'

Bu sorgu, "müşteriler" paketinde "pizza" etiketine sahip tüm hedefleri döndürür.

Kendinizi test etme

Jale'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 smoothie Strawberry ve Banana bileşenlerinden oluşuyor.

İlk olarak, smoothie'nin hangi malzemeleri kullanabileceğini 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 {

}

Sonra, 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. Her yeni bileşen için adı, herkese açık görünürlük ve yeni oluşturulan "src" dosyası da dahil olmak üzere yeni bir Java kitaplığı oluşturun. Şu güncellenmiş BUILD dosyasıyla başlamanı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"],
)

Yemeklerin bulunduğu BUILD dosyasında Smoothie için yeni bir kural eklemek istiyorsunuz. Bu işlem, "src" dosyası olarak Smoothie için oluşturulan Java dosyasını ve smoothie'nin her bir malzemesi için belirlediğiniz 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'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",
    ],
)

Hata olmadığını onaylamak için cafe öğesini tekrar oluşturun. Başarılı bir şekilde oluşturulduysa tebrikler! "Cafe" için yeni bir bağımlılık eklediniz. Sorun çözülmediyse yazım hataları ve paket adı olup olmadığına bakın. BUILD dosyalarını yazma hakkında daha fazla bilgi edinmek için DERLE Stil Kılavuzu'na göz atın.

Şimdi, öncekiyle karşılaştırmak için Smoothie eklenmiş 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.in
dot -Tpng < graph2.in > graph2.png

İlkiyle aynı grafik. Ancak bu sefer smoothie yapan şef hedefinden muz ve çilek hedefine giden bir kol var.

graph2.png'e baktığınızda Smoothie'un diğer yemeklerle ortak bağımlılıkları olmadığını, yalnızca Chef'nin kullandığı 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 olur? İkisi arasındaki bağımlılık yolunu görüntüleyerek yanıtı bulabilirsiniz.

Bağımlılık yollarını bulmanıza yardımcı olabilecek iki işlev vardır: somepath() ve allpaths(). S başlangıç hedefi ve E bitiş noktası 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ı araştırın. Bir hedeften diğerine gidilebilecek farklı yollar vardır:

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

somepath(), size iki seçenek arasından tek bir yol verirken "allpaths()" mümkün olan her yolun çıkışını 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 → Peynir seçiminin ilk yolunu izler. Bunun yerine allpaths() kullanıldığında ş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, makarna ve peynire giden çıkış yolu

Bağımlılıkların düzleştirilmiş bir listesi olduğu için allpaths() işlevinin çıktısının okunması biraz daha zordur. Graphviz'i kullanarak bu grafiği görselleştirmek, ilişkinin daha net anlaşılmasını sağlar.

Kendinizi test edin

Cafe Bazel'in müşterilerinden biri restoranın ilk yorumunu yazdı. Yorumda maalesef yorum sahibinin kimliği ve hangi yemeğe atıfta bulunduğu 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:review
bazel-bin/src/main/java/com/example/reviews/review

Yalnızca Bazel sorgularını kullanarak 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.

Yanıtla

Bu yorumda pizza tarifi açıklanıyordu ve yorumu Amir yazmıştı. Bu kuralın hangi bağımlılıklara sahip olduğunu görmek için bazel query --noimplicit\_deps 'deps(//src/main/java/com/example/reviews:review)' simgesini kullanın. Bu komutun sonucu, Amir'in inceleme uzmanı olduğunu gösterir. Ardından, inceleyenin Emir olduğunu bildiğiniz için sorgu işlevini kullanarak Emir'in "BUILD" (YAPILA) dosyasında hangi etiketi içerdiğini bularak hangi yemeğin olduğunu öğrenebilirsiniz. bazel query 'attr(tags, "pizza", //src/main/java/com/example/customers/...)' komutu, Amir'in pizza sipariş eden tek müşteri olduğunu ve bize yanıt veren yorumcu olduğunu gösterir.

Özet

Tebrikler! Şu anda kendi projelerinizde deneyebileceğiniz birkaç temel sorgu çalıştırıyorsunuz. 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 kapsamlı bir listesini gösterir.