cquery
, query
varyantıdır ve select()
ile derleme seçeneklerinin derleme grafiğindeki etkilerini doğru şekilde işler.
Bu işlem, Bazel'in bu etkileri entegre eden analiz aşamasının sonuçları üzerinde çalıştırılarak gerçekleştirilir. query
ise seçenekler değerlendirilmeden önce Bazel'in yükleme aşamasının sonuçları üzerinde çalışır.
Ö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ç, hedefin oluşturulduğu yapılandırmanın (9f87702)
benzersiz tanımlayıcısını içerir.
cquery
, yapılandırılmış hedef grafiği üzerinden çalıştığı için derleme işlemleri gibi yapılar hakkında bilgi sahibi değildir ve yapılandırılmış hedefler olmadıkları için test_suite
kurallarına erişemez. İlki için aquery
başlıklı makaleyi 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
,query
'in işlevlerinin çoğunu ve birkaç yeni işlevi destekler.//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 kılavuzu'na bakın.
cquery
, yükleme ve analiz aşamalarından geçmek için bir hedef gerektirir. Aksi belirtilmediği sürece cquery
, sorgu ifadesinde listelenen hedefleri ayrıştırır. Üst düzey derleme hedeflerinin bağımlılıklarını sorgulama hakkında bilgi edinmek için --universe_scope
bölümüne bakın.
Yapılandırmalar
Satır:
//tree:ash (9f87702)
//tree:ash
, 9f87702
kimlikli bir yapılandırmada oluşturulduğu anlamına gelir. Çoğu hedef için bu, yapılandırmayı tanımlayan derleme seçeneği değerlerinin opak karma sürümüdür.
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 olan SHA-256 karmaları olmasıdır. cquery
Git kısa karma değerlerine benzer şekilde, tam bir kimliğin geçerli herhangi bir önekini anlar.
Tam kimlikleri görmek için $ bazel config
komutunu çalıştırın.
Hedef kalıp değerlendirmesi
//foo
, cquery
için query
'den farklı bir anlama sahiptir. Bunun nedeni,
cquery
yapılandırılmış hedefleri değerlendirir ve derleme grafiğinde //foo
'nin birden fazla yapılandırılmış sürümü olabilir.
cquery
için sorgu ifadesindeki bir hedef kalıbı, bu kalıpla eşleşen bir etikete sahip her yapılandırılmış hedef için değerlendirilir. Çıkış deterministiktir ancak cquery
, çekirdek sorgu sıralama sözleşmesinin ötesinde sıralama garantisi vermez.
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 sorgulanacağını tam olarak belirtmek istiyorsanız config
işlevini kullanın.
Hedef kalıpları hakkında daha fazla bilgi için query
'nın hedef kalıbı dokümanlarına bakın.
İşlevler
query
tarafından desteklenen işlevler kümesinden cquery
, allrdeps
, buildfiles
, rbuildfiles
, siblings
, tests
ve visible
dışındaki tüm işlevleri destekler.
cquery
ayrıca aşağıdaki yeni işlevleri de sunar:
yapılandırma
expr ::= config(expr, word)
config
operatörü, ilk bağımsız değişkenle belirtilen etiket ve ikinci bağımsız değişkenle belirtilen yapılandırma için yapılandırılmış hedefi bulmaya çalışır.
İkinci bağımsız değişken için geçerli değerler null
veya özel yapılandırma karmasıdır. Karma değerler, $
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 yapılandırmada bulunamazsa yalnızca bulunanlar döndürülür. Belirtilen yapılandırmada sonuç bulunamazsa sorgu başarısız olur.
Seçenekler
Derleme seçenekleri
cquery
, normal bir Bazel derlemesi üzerinde çalışır ve bu nedenle derleme sırasında kullanılabilen seçenekler kümesini devralır.
cquery seçeneklerini kullanma
--universe_scope
(virgülle ayrılmış liste)
Yapılandırılan hedeflerin bağımlılıkları genellikle geçişler yaşar. Bu durum, yapılandırmalarının bağımlı oldukları hedeflerden farklı olmasına neden olur. Bu işaret, bir hedefi başka bir hedefin bağımlılığı veya geçişli bağımlılığı olarak oluşturulmuş gibi sorgulamanıza olanak tanır. Ö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 configuration içinde yapılandırır. Bu nedenle, aşağıdaki sorgular aşağıdaki çıkışları üretir:
Sorgu | Hedef Oluşturuldu | Çıkış |
---|---|---|
bazel cquery "//x:tool" | //x:tool | //x:tool(targetconfig) |
bazel cquery "//x:tool" --universe_scope="//x:my_gen" | //x:my_gen | //x:tool(execconfig) |
Bu işaret ayarlanırsa içeriği oluşturulur. Ayarlanmazsa sorgu ifadesinde belirtilen tüm hedefler oluşturulur. Yerleşik hedeflerin geçişli kapanımı, sorgunun evreni olarak kullanılır. Her iki durumda da oluşturulacak hedefler üst düzeyde oluşturulabilir olmalıdır (yani üst düzey seçeneklerle uyumlu olmalıdır). cquery
, bu üst düzey hedeflerin geçişli kapanışındaki sonuçları döndürür.
Tüm hedefleri en üst düzeydeki bir sorgu ifadesinde oluşturmak mümkün olsa bile bunu yapmamak faydalı olabilir. Örneğin, --universe_scope
değerini açıkça ayarlamak, önemsemediğiniz yapılandırmalarda hedeflerin birden fazla kez oluşturulmasını önleyebilir. Ayrıca, aradığınız hedef yapılandırma sürümünü belirtmenize de yardımcı olabilir. Sorgu ifadeniz deps(//foo)
değerinden daha karmaşıksa bu işareti ayarlamanız gerekir.
--implicit_deps
(boolean, default=True)
Bu işareti false olarak ayarlamak, BUILD dosyasında açıkça ayarlanmamış ve bunun yerine Bazel tarafından başka bir yerde ayarlanmış tüm sonuçları filtreler. Çözülmüş araç zincirlerini filtreleme de buna dahildir.
--tool_deps
(boolean, default=True)
Bu işareti false olarak ayarlamak, sorgulanan hedeften kendilerine giden yolun hedef yapılandırması ile hedef olmayan yapılandırmalar arasında bir geçişi geçtiği tüm yapılandırılmış hedefleri filtreler. Sorgulanan hedef, hedef yapılandırmasında yer alıyorsa --notool_deps
ayarı yalnızca hedef yapılandırmasında da yer alan hedefleri döndürür. Sorgulanan hedef bir hedef dışı yapılandırmadaysa --notool_deps
ayarı yalnızca hedef dışı yapılandırmalardaki hedefleri döndürür. Bu ayar genellikle çözümlenmiş araç zincirlerinin filtrelenmesini etkilemez.
--include_aspects
(boolean, default=True)
Aspects tarafından eklenen bağımlılıkları dahil edin.
Bu işaret devre dışı bırakılırsa cquery somepath(X, Y)
ve cquery deps(X) | grep 'Y'
, X yalnızca bir yön aracılığıyla Y'ye bağlıysa Y'yi atlar.
Çıkış biçimleri
Varsayılan olarak cquery, sonuçları etiket ve yapılandırma çiftlerinin bağımlılık sırasına göre düzenlenmiş bir listede verir. 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, üst düzey hedeflerin altındaki hedefleri üst düzey hedeflerden farklı yapılandırmalarda oluşturmak için kullanılır.
Örneğin, bir hedef, tools
özelliğindeki tüm bağımlılıklar için yönetici yapılandırmasına geçişi zorunlu kılabilir. Bunlara özellik geçişleri denir. Kurallar, kural sınıfı geçişleri olarak bilinen kendi yapılandırmalarına da geçişler uygulayabilir. Bu çıkış biçimi, bu geçişlerle ilgili bilgileri (ör. türleri ve derleme seçenekleri üzerindeki etkileri) verir.
Bu çıkış biçimi, varsayılan olarak NONE
değerine ayarlanmış olan --transitions
işaretiyle tetiklenir. FULL
veya LITE
moduna ayarlanabilir. FULL
modu, geçiş öncesi ve sonrası seçeneklerin ayrıntılı karşılaştırması da dahil olmak üzere kural sınıfı geçişleri ve özellik geçişleri hakkında bilgi verir. LITE
modu, seçenekler farkı olmadan aynı bilgileri verir.
Protokol mesajı çıkışı
--output=proto
Bu seçenek, sonuçta elde edilen hedeflerin ikili protokol arabellek biçiminde yazdırılmasına neden olur. Protokol arabelleğinin tanımını src/main/protobuf/analysis_v2.proto adresinde bulabilirsiniz.
CqueryResult
, cquery sonuçlarını içeren en üst düzeydeki mesajdır. ConfiguredTarget
mesajlarının ve Configuration
mesajlarının listesini içerir. Her ConfiguredTarget
, değeri ilgili Configuration
mesajındaki id
alanının değerine eşit olan bir configuration_id
içerir.
--[no]proto:include_configurations
Varsayılan olarak, cquery sonuçları yapılandırma bilgilerini her bir yapılandırılmış hedef kapsamında döndürür. Bu bilgileri atlamak ve sorgunun proto çıkışıyla aynı şekilde biçimlendirilmiş bir proto çıkışı almak istiyorsanız bu işareti false olarak ayarlayın.
Daha fazla proto çıkışıyla ilgili seçenek için sorgunun proto çıkış belgelerine bakın.
Grafik çıkışı
--output=graph
Bu seçenek, Graphviz ile uyumlu bir .dot dosyası olarak çıktı oluşturur. Ayrıntılar için query
'nın
grafik çıkışı belgelerine bakın. cquery
, --graph:node_limit
ve --graph:factored
'ı da destekler.
Çıkış dosyaları
--output=files
Bu seçenek, sorguyla eşleşen her hedef tarafından üretilen çıkış dosyalarının listesini, bazel build
çağrısının sonunda yazdırılan listeye benzer şekilde yazdırır. Çıkış, --output_groups
işaretiyle belirlenen, istenen çıkış gruplarında reklamı yapılan dosyaları içerir.
Kaynak dosyalar dahil edilir.
Bu çıkış biçimi tarafından verilen tüm yollar, bazel info execution_root
aracılığıyla elde edilebilen execroot'a göre belirlenir. bazel-out
kolaylık sembolik bağlantısı varsa ana depodaki dosya yolları da çalışma alanı dizinine göre çözümlenir.
Starlark kullanarak çıkış biçimini tanımlama
--output=starlark
Bu çıkış biçimi, sorgu sonucundaki her yapılandırılmış hedef için bir Starlark işlevini çağırır ve çağrı tarafından döndürülen değeri yazdırır. --starlark:file
işareti, tek bir parametre olan target
ile format
adlı bir işlevi tanımlayan Starlark dosyasının konumunu belirtir. Bu işlev, sorgu sonucundaki her Hedef için çağrılır. Alternatif olarak, kolaylık sağlaması açısından def format(target): return expr
olarak tanımlanan bir işlevin yalnızca gövdesini --starlark:expr
işaretini kullanarak belirtebilirsiniz.
"cquery" Starlark lehçesi
cquery Starlark ortamı, BUILD veya .bzl dosyasından farklıdır. Bu, tüm temel Starlark yerleşik sabitlerini ve işlevlerini, ayrıca aşağıda açıklanan birkaç cquery'ye özgü olanı içerir ancak (örneğin) glob
, native
veya rule
'i içermez ve yükleme ifadelerini desteklemez.
build_options(target)
build_options(target)
, anahtarları derleme seçeneği tanımlayıcıları olan (bkz. Yapılandırmalar) ve değerleri Starlark değerleri olan bir harita döndürür. Değerleri yasal Starlark değerleri olmayan derleme seçenekleri bu haritadan çıkarılır.
Hedef bir giriş dosyasıysa build_options(target)
, giriş dosyası hedeflerinin yapılandırması boş olduğundan None değerini döndürür.
providers(target)
providers(target)
, anahtarları sağlayıcıların adları (örneğin, "DefaultInfo"
), değerleri ise Starlark değerleri olan bir harita döndürür.
Değerleri yasal Starlark değerleri olmayan sağlayıcılar bu haritaya dahil edilmez.
Örnekler
//foo
tarafından oluşturulan tüm dosyaların temel adlarının boşlukla ayrılmış bir listesini yazdırın:
bazel cquery //foo --output=starlark \ --starlark:expr="' '.join([f.basename for f in providers(target)['DefaultInfo'].files.to_list()])"
//bar
ve alt paketlerinde kural hedefleri tarafından oluşturulan tüm dosyaların yollarının boşlukla ayrılmış bir listesini yazdırın:
bazel cquery 'kind(rule, //bar/...)' --output=starlark \ --starlark:expr="' '.join([f.path for f in providers(target)['DefaultInfo'].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]"
Bir cc_library
//baz
tarafından kaydedilen derleme çıktıları listesini yazdırma.
bazel cquery //baz --output=starlark \ --starlark:expr="[f.path for f in target.output_groups.compilation_outputs.to_list()]"
--javacopt
oluşturulurken //foo
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, bir dosyada tanımlanan Starlark işlevleri kullanılmaktadır.
$ cat example.cquery def has_one_output(target): return len(providers(target)["DefaultInfo"].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
Kesinlikle Python 3 olan her hedefin etiketini yazdırın. Bu örnekte, bir dosyada tanımlanan Starlark işlevleri kullanılmaktadır.
$ 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 query karşılaştırması
cquery
ve query
birbirini tamamlar ve farklı alanlarda öne çıkar. Hangisinin sizin için doğru olduğuna karar vermek için aşağıdakileri göz önünde bulundurun:
cquery
, oluşturduğunuz grafiği tam olarak modellemek için belirliselect()
dalları izler.query
, derlemenin hangi dalı seçeceğini bilmediği için tüm dalları dahil ederek fazla tahmin yapar.cquery
'nın hassasiyeti,query
'ye kıyasla grafiğin daha fazla bölümünün oluşturulmasını gerektirir. Daha açık belirtmek gerekirsecquery
, yapılandırılmış hedefleri değerlendirirkenquery
yalnızca hedefleri değerlendirir. Bu işlem daha fazla zaman alır ve daha fazla bellek kullanır.cquery
'nın sorgu dilini yorumlaması,query
'ın kaçındığı belirsizliğe yol açıyor. Örneğin,"//foo"
iki yapılandırmada varsacquery "deps(//foo)"
hangisini kullanmalıdır? Bu konudaconfig
işlevinden yararlanabilirsiniz.
Belirlenimci olmayan çıkış
cquery
, önceki komutlardan oluşturma grafiğini otomatik olarak silmez.
Bu nedenle, geçmiş sorgulardan sonuç alma olasılığı yüksektir.
Örneğin, genrule
, tools
özelliğinde bir yürütme geçişi uygular. Yani araçlarını yürütme yapılandırmasında yapılandırır.
Bu geçişin kalıcı etkilerini aşağıda görebilirsiniz.
$ cat > foo/BUILD <<
Bu, değerlendirmeye çalıştığınız şeye bağlı olarak istenen bir davranış olabilir veya olmayabilir.
Bunu devre dışı bırakmak için yeni bir analiz grafiği elde etmek üzere cquery
komutunuzdan önce blaze clean
komutunu çalıştırın.
Sorun giderme
Yinelemeli hedef kalıpları (/...
)
Aşağıdaki sorunlarla 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, //foo
paketinin kapsamda olmadığını yanlış bir şekilde öneriyor ancak --universe_scope=//foo:app
paketi kapsamda. Bu durum, cquery
'daki tasarım sınırlamalarından kaynaklanmaktadır. Geçici çözüm olarak, //foo/...
öğesini evren kapsamına açıkça dahil edin:
$ bazel cquery --universe_scope=//foo:app,//foo/... "somepath(//foo:app, //foo/...)"
Bu işe yaramazsa (örneğin, //foo/...
içindeki bazı hedefler seçilen derleme işaretleriyle derlenemediği için) ön işleme sorgusuyla kalıbı manuel olarak bileşen paketlerine açın:
# 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 "+" -))"