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 ele alınmaktadı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 bir dizi temel sorgu 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. Aracı 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, BUILD dosyalarında manuel olarak gezinmeden büyük ölçekli projelerdeki bağımlılıkları öğrenmenize 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 aşçısı arasındaki ilişkiyi ele alan bir senaryo düşünün. Bu kafede özellikle pizza ve macun satılıyor peynir. Projenin nasıl yapılandırıldığına aşağıdan 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 yönde bir talimat olmadığı sürece, ihtiyacınız olan bilgileri bulmak için BUILD dosyalarına bakmamaya çalışın. Bunun yerine yalnızca sorgu işlevini kullanın.

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

Derleme çalıştırma

Bu proje, Runner.java içinde yürütebileceğiniz bir ana yöntem içerir menünün çıktısını alıyorum. Şu komutu kullanarak Bazel'ı kullanarak projeyi derleme: bazel build ve hedefin runner olarak adlandırıldığını belirtmek için : politikasını kullanın. Görüntüleyin hedef adları referans hedefleridir.

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 ş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

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

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

Böylece menü öğelerinin listesini, kısa bir açıklamayla birlikte görebilirsiniz.

Hedefleri keşfetme

Projede kullanılan 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 bu kafenin malzemelerini ve yemeklerini incelemek için şunu kullanabilirsiniz:

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

Malzeme paketinin hedeflerini sorgularsanız çıkış 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 hangi hedeflere ulaşmaya çalışıyor?

Örneğin, dosya sisteminde üretim yapmadan projenizin yapısını daha ayrıntılı bir şekilde incelemek istediğinizi düşünelim (bu, büyük projeler için etkinleştirilmeyebilir). Cafe Bazel hangi kuralları kullanıyor?

Bu örnekte olduğu gibi koşucu hedefiniz 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 çıktı bağımlılıklarını tek tek 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, 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ünümünü değiştirebilirsiniz. Seçenekler için Çıktı Biçimleri bölümüne bakın.

İlk olarak istediğiniz sorguyu çalıştırın, ardından aşırı araç bağımlılıkları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.

:runner hedefinin 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 işleyip görselleştiren 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. Bu kılavuzdaki 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 işlem, bu kılavuz boyunca farklı sorgu işlevlerinin çıktılarını görmek istediğinizde işinize yarayacaktır.

Ters bağımlılıkları bulma

Bunun yerine, diğer hedeflerin hangi hedefleri kullandığını analiz etmek isterseniz, hangi hedeflerin belirli bir kurala bağlı olduğunu incelemek için bir sorgu kullanabilirsiniz. Buna "ters bağımlılık" denir. rdeps() kullanmak, aşina olmadığınız bir kod tabanında dosya düzenlerken yararlı olabilir ve sizi, ona bağlı olan diğer dosyaları bilmeden kırmaktan kurtarabilir.

Örneğin, cheese adlı malzemede bazı düzenlemeler yapmak istiyorsunuz. Cafe Bazel açısından soruna neden olmaması için cheese kullanılan yemekleri 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: 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ü 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

Döndürülen sorgu, hem pizza hem de macAndCheese'in peynir için kullanıldığını gösterir. Muhteşem bir sürpriz!

Etiketlere dayalı olarak hedef bulma

Bazel Cafe'ye iki müşteri geliyor: Emir ve Jale. Adları dışında bilinen bir şey yok. Neyse ki siparişleri "müşteriler" BUILD dosyası yükleyin. 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 eden 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" içindeki tüm hedefleri döndürür "pizza" etiketine sahip bir pakettir.

Kendinizi test edin

Jale'nin 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 özel smoothie, Strawberry ve Banana malzemelerinden 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ı ilgili BUILD dosyalarına kural olarak ekleyin. Adı, herkese açık görünürlüğü ve yeni oluşturulan "src" özelliği dahil olmak üzere her yeni malzeme için yeni bir Java kitaplığı oluşturun dosyası olarak kaydedebilirsiniz. Ş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"],
)

Yemeklere ilişkin BUILD dosyasında Smoothie için yeni bir kural eklemek istiyorsunuz. Bu işlem, Smoothie için oluşturulan Java dosyasını bir 'src' olarak ekler. dosyası ve smoothie'nin her bir malzemesi için belirlediğiniz yeni kurallar.

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! "Kafe" 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 yeni bağımlılık grafiğini Smoothie ekleyerek 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

Grafikte birincisi ile aynı, ancak şu anda şefin hedefinden smoothie içeren, muz ve çileliğe giden bir uç var.

graph2.png incelediğinizde Smoothie öğesinin diğer yemeklere olan ortak bağımlılığı olmadığını, ancak Chef için temel alınan 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? Bu ikisi arasında bir bağımlılık yolunu göstermek cevabı 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 ile bir bitiş noktası E arasında, somepath(S,E) kullanarak S ile E arasında bir yol bulun.

"Şef" arasındaki ilişkilere bakarak bu iki işlev arasındaki farkları araştırın ve "Cheese" belirler. 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 sunar ve "allpaths()" kullanır her olası yolu çıkarır.

Örnek olarak Cafe Bazel'ı 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 → 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, pizza, Mac, peynirden peynire uzanan çıkış yolu

Bağımlılıkların birleştirilmiş bir listesi olduğundan allpaths() çıktısını okumak biraz daha zordur. Bu grafiği Graphviz kullanarak görselleştirmek, ilişkiyi daha net bir şekilde anlamamızı sağlar.

Kendinizi test edin

Cafe Bazel'in müşterilerinden biri, restoranın ilk incelemesini yaptı. Maalesef yorumda, inceleyenin kimliği ve hangi yemeğe atıfta bulunduğu gibi bazı bilgiler eksik. Neyse ki, Bazel ile bu bilgilere erişebilirsiniz. reviews paketi, gizemli bir müşterinin yorumunu yazdıran bir program içeriyor. Şunlarla 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 dışında, 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 Pizza ile ilgili bilgiler yer alıyordu. Yorumcu ise Emir'di. Bu kuralın kullandığı bağımlılıklara bakarsanız bazel query --noimplicit\_deps 'deps(//src/main/java/com/example/reviews:review)'. Bu komutun sonucu, incelemecinin Emir olduğunu ortaya çıkarır. 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, Emir'in pizza sipariş eden tek müşteri olduğunu ve yanıtı bize inceleyen kişi olduğunu belirtir.

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