Yapılandırılabilir Sorgu (cquery)

Sorun bildir Kaynağı göster Gece · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

cquery, query varyantının doğru şekilde işleyen bir varyantıdır select() ve derleme seçenekleri yapı üzerindeki etkileri grafiğe dönüştürülebilir.

Bunu, Bazel'in analizinin sonuçları üzerinden aşamasında entegre eder. Buna karşılık query, Bazel'in seçenekler değerlendirilmeden önceki yükleme aşaması.

Örneğin:

$ cat > tree/BUILD <<EOF
sh_library(
    name = "ash",
    deps = select({
        ":excelsior": [":manna-ash"],
        ":americana": [":white-ash"],
        "//conditions:default": [":common-ash"],
    }),
)
sh_library(name = "manna-ash")
sh_library(name = "white-ash")
sh_library(name = "common-ash")
config_setting(
    name = "excelsior",
    values = {"define": "species=excelsior"},
)
config_setting(
    name = "americana",
    values = {"define": "species=americana"},
)
EOF
# Traditional query: query doesn't know which select() branch you will choose,
# so it conservatively lists all of possible choices, including all used config_settings.
$ bazel query "deps(//tree:ash)" --noimplicit_deps
//tree:americana
//tree:ash
//tree:common-ash
//tree:excelsior
//tree:manna-ash
//tree:white-ash

# cquery: cquery lets you set build options at the command line and chooses
# the exact dependencies that implies (and also the config_setting targets).
$ bazel cquery "deps(//tree:ash)" --define species=excelsior --noimplicit_deps
//tree:ash (9f87702)
//tree:manna-ash (9f87702)
//tree:americana (9f87702)
//tree:excelsior (9f87702)

Her sonuçta benzersiz bir tanımlayıcı (9f87702) yapılandırmayı temelini oluşturur.

cquery, yapılandırılan hedef grafiğin üzerinde çalıştığı için. analiz içermiyor derleme işlemleri veya test_suite erişimi gibi yapılara kuralları yapılandırılmamış hedefler. Birincisi için aquery sayfasını inceleyin.

Temel söz dizimi

Basit bir cquery çağrısı şu şekilde görünür:

bazel cquery "function(//target)"

"function(//target)" sorgu ifadesi şunlardan oluşur:

  • function(...), hedefte çalıştırılacak işlevdir. cquery. çoğu öğeyi destekler query işlevlerinin yanı sıra bir yenilerini oluşturabilirsiniz.
  • //target, işleve aktarılan ifadedir. Bu örnekte ifade, basit bir hedeftir. Ancak sorgu dili, işlevlerin iç içe yerleştirilmesine de olanak tanır. Örnekler için Sorgu rehberine bakın.

cquery, yükleme ve analiz sürecini tamamlaması için bir hedef gerektirir aşamalar. Aksi belirtilmedikçe cquery, sorgu ifadesinden farklıdır. Bkz. --universe_scope üst düzey derleme hedeflerinin bağımlılıklarını sorgulamak için kullanılır.

Yapılandırmalar

Satır:

//tree:ash (9f87702)

//tree:ash ürününün, 9f87702 kimliğine sahip bir yapılandırmada oluşturulduğu anlamına gelir. Çoğu Bu, yapılandırma.

Yapılandırmanın tüm içeriğini görmek için şu komutu çalıştırın:

$ bazel config 9f87702

9f87702, tam kimliğin ön ekidir. Bunun nedeni, tam kimliklerin Uzun ve takip edilmesi zor SHA-256 karmaları. cquery, geçerli tüm tam bir kimliğin önekine benzer, Git kısa karmalar. Kimliklerin tamamını görmek için $ bazel config komutunu çalıştırın.

Hedef kalıp değerlendirmesi

//foo, cquery için query dilinden farklı bir anlama sahiptir. Çünkü cquery, yapılandırılmış hedefleri değerlendirir ve derleme grafiğinde birden fazla yapılandırılmış //foo sürümleri.

cquery için sorgu ifadesindeki hedef kalıbı bu kalıpla eşleşen bir etikete sahip her yapılandırılmış hedefe uygulanır. Çıkış (şimdiki değeri) deterministik, ancak cquery temel sorgu siparişi sözleşmesi.

Bu, sorgu ifadeleri için query ile karşılaştırıldığında daha ince sonuçlar üretir. Örneğin, aşağıdakiler birden fazla sonuç üretebilir:

# Analyzes //foo in the target configuration, but also analyzes
# //genrule_with_foo_as_tool which depends on an exec-configured
# //foo. So there are two configured target instances of //foo in
# the build graph.
$ bazel cquery //foo --universe_scope=//foo,//genrule_with_foo_as_tool
//foo (9f87702)
//foo (exec)

Hangi örneğin üzerinde sorgu yapılacağını kesin olarak belirtmek istiyorsanız config işlevini kullanın.

query adlı kullanıcının hedef kalıbına bakın dokümanlarına göz atın.

İşlevler

İşlev kümesinin query tarafından desteklenir, cquery şunun hariç tümünü destekler: allrdeps, buildfiles rbuildfiles, siblings, tests ve visible.

cquery aşağıdaki yeni işlevleri de kullanıma sunuyor:

yapılandırma

expr ::= config(expr, word)

config operatörü, şunun için yapılandırılmış hedefi bulmaya çalışır: ilk bağımsız değişken ve yapılandırmanın belirttiği kullanabilirsiniz.

İkinci bağımsız değişken için geçerli değerler null veya bir özel yapılandırma karmasını kullanın. Karmalar, $ bazel config veya önceki bir cquery çıkışından alınabilir.

Örnekler:

$ bazel cquery "config(//bar, 3732cc8)" --universe_scope=//foo
$ bazel cquery "deps(//foo)"
//bar (exec)
//baz (exec)

$ bazel cquery "config(//baz, 3732cc8)"

İlk bağımsız değişkenin tüm sonuçları belirtilen yalnızca bulunabilenler döndürülür. Sonuç yoksa belirtilen yapılandırmada bulunursa sorgu başarısız olur.

Seçenekler

Derleme seçenekleri

cquery, normal bir Bazel derlemesi üzerinde çalışır ve böylece seçenekleri geliştirmenize yardımcı olur.

Sorgu seçeneklerini kullanma

--universe_scope (virgülle ayrılmış liste)

Yapılandırılmış hedeflerin bağımlılıkları genellikle geçişler Bu da yapılandırmalarının bağlı olduklarından farklı olmasına neden olur. Bu işaret , bir hedefi bağımlılık veya geçişli olarak oluşturulmuş gibi sorgulamanıza olanak tanır. bağımlılığı olabilir. Örneğin:

# x/BUILD
genrule(
     name = "my_gen",
     srcs = ["x.in"],
     outs = ["x.cc"],
     cmd = "$(locations :tool) $< >$@",
     tools = [":tool"],
)
cc_binary(
    name = "tool",
    srcs = ["tool.cpp"],
)

Genrules, araçlarını exec yapılandırması Bu nedenle aşağıdaki sorgular şu çıktıları üretir:

Sorgu Hedef Oluşturuldu Çıkış
bazel cquery "//x:tool" //x:tool //x:tool(targetconfig)
bazel cquery "//x:tool" --universe_scope=&quot;//x:my_gen&quot; //x:my_gen //x:tool(execconfig)

Bu işaret ayarlanırsa içeriği oluşturulur. Belirlenmezse tüm hedefler belirtilenlerin yerine oluşturmanız gerekir. İşletmenin geçişli olarak kapatılması oluşturulan hedefler sorgunun evreni olarak kullanılır. Her iki durumda da hedefler üst düzeyde oluşturulabilmelidir (yani üst düzey seçenekleri). cquery, bunların geçişli olarak kapatılmasıyla sonuçlanıyor üst düzey hedeflerdir.

Üst kısımdaki bir sorgu ifadesinde tüm hedefleri oluşturmak mümkün olsa bile bu tür bir eylemde bulunmamak yararlı olabilir. Örneğin, --universe_scope, şurada hedef oluşturmayı birden çok kez engelleyebilir: yapılandırmalarına yardımcı olur. Ayrıca, bir dosyanın yapılandırma sürümünün (şu anda mümkün olmadığı için) aradığınız her şeyi (bunu başka bir şekilde tam olarak belirtme) gerekir). Bu işareti ayarlamalısınız (sorgu ifadeniz deps(//foo) ifadesinden daha karmaşıksa).

--implicit_deps (boole, varsayılan=Doğru)

Bu işareti false (yanlış) olarak ayarlamak, şurada açıkça belirtilmeyen tüm sonuçları filtreler: BuILD dosyasını kullanır ve bunun yerine Bazel tarafından başka bir yere ayarlanır. Buna çözümlenmiş filtrelemeler dahildir araç zincirleri olarak düşünebilirsiniz.

--tool_deps (boole, varsayılan=Doğru)

Bu işaretin yanlış değerine ayarlanması, sorgulanan hedeften bunlara giden yolun hedef ile ve hedeflenmeyen yapılandırmalar. Sorgulanan hedef hedef yapılandırmadaysa --notool_deps ayarı şunları yapar: yalnızca hedef yapılandırmada bulunan hedefleri döndürür. Sorgulanan hedef, hedef olmayan bir yapılandırmada. --notool_deps ayarı yalnızca şu sonucu döndürür: hedeflenmeyen yapılandırmalarda da kullanılabilir. Bu ayar genellikle filtrelemeyi etkilemez. çok basit bir örneğidir.

--include_aspects (boole, varsayılan=Doğru)

Yönler ile eklenen bağımlılıkları dahil edin.

Bu işaret devre dışı bırakılırsa cquery somepath(X, Y) ve X yalnızca bir yönüyle bağımlıysa cquery deps(X) | grep 'Y' Y'yi atlayın.

Çıkış biçimleri

Varsayılan olarak Cquery çıkışları, bağımlılık sıralı bir etiket ve yapılandırma çifti listesiyle sonuçlanır. Sonuçları göstermek için başka seçenekler de vardır.

Geçişler

--transitions=lite
--transitions=full

Yapılandırma geçişleri farklı sektörlerdeki üst düzey hedeflerin altında hedefler oluşturmak için kullanılır. üst düzey hedeflere göre daha fazla yapılandırmaları ortaya çıkarıyor.

Örneğin bir hedef, yönetici yapılandırmasına geçişin tamamını bağımlılıklarını tools özelliğinde belirtir. Bunlar, oluşturabilirsiniz. Kurallar, kendi yapılandırmalarında geçişler de uygulayabilir. Bunlar, kural sınıfı geçişleri olarak adlandırılır. Bu çıkış biçimi, şunun hakkında bilgi verir: bunların ne tür olduğu ve bunların derleme üzerindeki etkisi gibi seçenekleri vardır.

Bu çıkış biçimi, varsayılan olarak --transitions işareti tarafından tetiklenir. NONE olarak ayarlandı. FULL veya LITE moduna ayarlanabilir. FULL modu çıkışı kural sınıfı geçişleri ve özellik geçişleri hakkında bilgi: geçişten önceki ve sonraki seçeneklerin ayrıntılı farklarını gösterir. LITE modu aynı bilgileri seçenek farkı olmadan çıkarır.

Protokol mesajı çıkışı

--output=proto

Bu seçenek, sonuçta elde edilen hedeflerin ikili program protokolünde yazdırılmasına neden olur bir şablondur. Protokol arabelleğinin tanımı şu adreste bulunabilir: src/main/protobuf/analysis_v2.proto.

CqueryResult, sorgu sonuçlarını içeren üst düzey mesajdır. Google ConfiguredTarget mesaj ve Configuration mesajdan oluşan bir listeye sahip mesaj. Her ConfiguredTarget, değeri eşit olan bir configuration_id içeriyor (ilgili Configuration mesajındaki id alanının aynısı).

--[no]proto:include_configurations

Varsayılan olarak, Cquery sonuçları her yapılandırılmış hedef. Bu bilgiyi hariç tutup proto çıktısı almak istiyorsanız bu işareti "false" (yanlış) olarak ayarlayın.

Sorgunun proto çıkışı belgelerine bakın. seçenekleri sunar.

Grafik çıkışı

--output=graph

Bu seçenek, çıktıyı Graphviz uyumlu bir .dot dosyası olarak oluşturur. Bkz. query grafik çıktısı dokümanlarına göz atın. cquery. Ayrıca --graph:node_limit ve --graph:factored.

Dosya çıkışı

--output=files

Bu seçenek, eşleşen her hedefin ürettiği çıkış dosyalarının listesini yazdırır bazel build etiketinin sonunda yazdırılan listeye benzer sorgu ile çağrılacaktır. Çıkış yalnızca istekte tanıtılan dosyaları içerir proje yöneticileri tarafından belirlenen çıkış --output_groups işareti. Kaynak dosyalar bu kapsama girer.

Bu çıkış biçimi tarafından yayınlanan tüm yollar execroot bazel info execution_root üzerinden. bazel-out kolaylık sembolü bağlantısı varsa ana depodaki dosyaların yolları da çalışma alanına göre çözümleniyor dizin.

Starlark'ı kullanarak çıkış biçimini tanımlama

--output=starlark

Bu çıkış biçimi bir Starlark çağırır işlevini yerine getirir ve çağrı tarafından geri döndü. --starlark:file işareti Tek parametreli format adlı bir işlevi tanımlayan Starlark dosyası target. Bu işlev, her bir Hedef yazar. Alternatif olarak, kolaylık olması açısından yalnızca def format(target): return expr olarak bildirilen bir fonksiyonun gövdesi --starlark:expr işareti.

"cquery" Starlark lehçesi

Sorgu Starlark ortamı, BUILD veya .bzl dosyasından farklı. Şunları içerir: tüm çekirdek Starlark yerleşik sabit değerler ve işlevler ve aşağıda açıklanan sorguya özgü birkaç sorguya örnek verilebilir, ancak (örneğin) glob, native veya rule olarak ayarlanmıştır ve yükleme ifadelerini desteklemez.

build_options(target)

build_options(target), anahtarları derleme seçeneği tanımlayıcıları olan bir haritayı döndürür (bkz. Yapılandırmalar) olduğunu öğrenmiştiniz. Değerleri yasal Starlark olmayan derleme seçenekleri değerleri bu haritadan çıkarıldı.

Hedef bir giriş dosyasıysa build_options(target), giriş dosyası olarak Yok değerini döndürür hedeflerin boş bir yapılandırması var.

sağlayıcılar(hedef)

providers(target), anahtarları sağlayıcılar (örneğin, "DefaultInfo") ve değerleri Starlark değerleri olan kullanıcılar. Sağlayıcılar değerleri yasal Starlark değerleri olmayanlar bu haritadan çıkarılır.

Örnekler

//foo tarafından üretilen tüm dosyaların temel adlarının boşlukla ayrılmış listesini yazdır:

  bazel cquery //foo --output=starlark \
    --starlark:expr="' '.join([f.basename for f in target.files.to_list()])"

Kural hedefleri tarafından oluşturulan tüm dosyaların yollarının boşlukla ayrılmış listesini yazdır //bar ve alt paketleri:

  bazel cquery 'kind(rule, //bar/...)' --output=starlark \
    --starlark:expr="' '.join([f.path for f in target.files.to_list()])"

//foo tarafından kaydedilen tüm işlemlerin anımsatıcılarının listesini yazdırın.

  bazel cquery //foo --output=starlark \
    --starlark:expr="[a.mnemonic for a in target.actions]"

cc_library //baz tarafından kaydedilen derleme çıkışlarının listesini yazdırın.

  bazel cquery //baz --output=starlark \
    --starlark:expr="[f.path for f in target.output_groups.compilation_outputs.to_list()]"

//foo oluştururken --javacopt komut satırı seçeneğinin değerini yazdırın.

  bazel cquery //foo --output=starlark \
    --starlark:expr="build_options(target)['//command_line_option:javacopt']"

Her hedefin etiketini tam olarak bir çıkışla yazdırın. Bu örnekte, Dosyada tanımlanan Starlark işlevleri.

  $ cat example.cquery

  def has_one_output(target):
    return len(target.files.to_list()) == 1

  def format(target):
    if has_one_output(target):
      return target.label
    else:
      return ""

  $ bazel cquery //baz --output=starlark --starlark:file=example.cquery

Her hedefin etiketini (tam olarak Python 3) yazdırın. Bu örnekte, Dosyada tanımlanan Starlark işlevleri.

  $ cat example.cquery

  def format(target):
    p = providers(target)
    py_info = p.get("PyInfo")
    if py_info and py_info.has_py3_only_sources:
      return target.label
    else:
      return ""

  $ bazel cquery //baz --output=starlark --starlark:file=example.cquery

Kullanıcı tanımlı bir Sağlayıcıdan değer ayıklayın.

  $ cat some_package/my_rule.bzl

  MyRuleInfo = provider(fields={"color": "the name of a color"})

  def _my_rule_impl(ctx):
      ...
      return [MyRuleInfo(color="red")]

  my_rule = rule(
      implementation = _my_rule_impl,
      attrs = {...},
  )

  $ cat example.cquery

  def format(target):
    p = providers(target)
    my_rule_info = p.get("//some_package:my_rule.bzl%MyRuleInfo'")
    if my_rule_info:
      return my_rule_info.color
    return ""

  $ bazel cquery //baz --output=starlark --starlark:file=example.cquery

cquery ve sorgu

cquery ve query birbirini tamamlar ve başarılıdır farklı nişler. Sizin için hangisinin uygun olduğuna karar vermek üzere aşağıdakileri göz önünde bulundurun:

  • cquery, aşağıdakileri yapmak için belirli select() dallarını takip eder: modeli oluşturmayı öğreneceksiniz. query hangisinin hangisi olduğunu bilmiyor derlemenin seçtiği bir daldan fazla olmalıdır. Böylece, tüm dalları dahil ederek yaklaşık maksimum değer elde edersiniz.
  • cquery işlevinin hassasiyeti için daha fazla grafik oluşturmak gerekir query yapıyor. Özellikle, cquery yalnızca query yapılandırılmış hedefleri değerlendirir hedefleri değerlendirir. Bu işlem daha fazla zaman alır ve daha fazla bellek kullanır.
  • cquery tarafından yapılan yorum sorgu dili belirsizliğe yol açıyor gibi özelliklerdir.query Örneğin, "//foo" iki yapılandırmada mevcutsa hangi yapılandırma? cquery "deps(//foo)" kullanmalı mı? config işlevi bu konuda yardımcı olabilir.
  • Daha yeni bir araç olan cquery, belirli kullanımları desteklemiyor durumlarda işe yarar. Ayrıntılar için Bilinen sorunlar başlıklı makaleyi inceleyin.

Bilinen sorunlar

cquery tarafından "oluşturulan" tüm hedefler aynı yapılandırmaya sahip olmalıdır.

Sorgular değerlendirilmeden önce, cquery yalnızca . Kampanyayı "yapılar" varsayılan olarak sorguda görünen tüm etiketler arasından seçilir ifade (bu geçersiz kılınabilir --universe_scope ile). Bu aynı yapılandırmaya sahip olmalıdır.

Bunlar genellikle üst düzey "hedefi" paylaşsa da yapılandırma, kendi yapılandırmalarını yaklaşan kenar geçişleri için gösterilir. cquery bu noktada yetersiz kalıyor.

Geçici çözüm: Mümkünse --universe_scope politikasını daha katı bir değere ayarlayın. kapsam. Örneğin:

# This command attempts to build the transitive closures of both //foo and
# //bar. //bar uses an incoming edge transition to change its --cpu flag.
$ bazel cquery 'somepath(//foo, //bar)'
ERROR: Error doing post analysis query: Top-level targets //foo and //bar
have different configurations (top-level targets with different
configurations is not supported)

# This command only builds the transitive closure of //foo, under which
# //bar should exist in the correct configuration.
$ bazel cquery 'somepath(//foo, //bar)' --universe_scope=//foo

--output=xml için destek sunulmaz.

Deterministik olmayan çıktı.

cquery, derleme grafiğini şuradan otomatik olarak silmez: önceki komutlarda çalışır ve bu nedenle geçmiş sonuçlara ulaşmaya eğilimlidir. daha fazla bilgi edineceksiniz. Örneğin, genrule, şurada bir yönetici geçişi uygular: tools özelliği ile birlikte, diğer bir deyişle, araçlarını exec yapılandırması ile ilgili daha fazla bilgi edinin.

Bu geçişin süregelen etkilerini aşağıda görebilirsiniz.

$ cat > foo/BUILD <<<EOF
genrule(
    name = "my_gen",
    srcs = ["x.in"],
    outs = ["x.cc"],
    cmd = "$(locations :tool) $< >$@",
    tools = [":tool"],
)
cc_library(
    name = "tool",
)
EOF

    $ bazel cquery "//foo:tool"
tool(target_config)

    $ bazel cquery "deps(//foo:my_gen)"
my_gen (target_config)
tool (exec_config)
...

    $ bazel cquery "//foo:tool"
tool(exec_config)

Geçici çözüm: Yapılandırılmış hedeflerin yeniden analiz edilmesini zorunlu kılmak için tüm başlatma seçeneklerini değiştirin. Örneğin, derleme komutunuza --test_arg=<whatever> komutunu ekleyin.

Sorun giderme

Yinelenen hedef kalıpları (/...)

Aşağıdaki durumlarla karşılaşırsanız:

$ bazel cquery --universe_scope=//foo:app "somepath(//foo:app, //foo/...)"
ERROR: Error doing post analysis query: Evaluation failed: Unable to load package '[foo]'
because package is not in scope. Check that all target patterns in query expression are within the
--universe_scope of this query.

bu, yanlış bir şekilde //foo paketinin kapsam dahilinde olmadığını gösterir ancak Bunu --universe_scope=//foo:app içeriyor. Bunun nedeni, cquery Geçici bir çözüm olarak, evrende //foo/... öğesini açıkça ekleyin kapsam:

$ bazel cquery --universe_scope=//foo:app,//foo/... "somepath(//foo:app, //foo/...)"

Bu işe yaramazsa (örneğin, //foo/... ürünündeki bazı hedefler yönlendirilemediği için) seçilen derleme flag'leriyle derleyin) kalıbı açın, şablonu manuel olarak açın ve bileşen paketlerinden bahsetmek istiyorum:

# Replace "//foo/..." with a subshell query call (not cquery!) outputting each package, piped into
# a sed call converting "<pkg>" to "//<pkg>:*", piped into a "+"-delimited line merge.
# Output looks like "//foo:*+//foo/bar:*+//foo/baz".
#
$  bazel cquery --universe_scope=//foo:app "somepath(//foo:app, $(bazel query //foo/...
--output=package | sed -e 's/^/\/\//' -e 's/$/:*/' | paste -sd "+" -))"