cquery
, query
varyantının select()
ve derleme seçeneklerinin derleme grafiğindeki etkilerini doğru şekilde işleyen bir varyantıdır.
Bunun için Bazel'in bu efektleri entegre eden analiz aşamasının sonuçlarını gözden geçirir. Buna karşılık query
, seçenekler değerlendirilmeden önce Bazel'ın yükleme aşamasının sonuçları üzerinden ilerler.
Ö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 benzersiz bir tanımlayıcısını (9f87702)
içerir.
cquery
, yapılandırılan hedef grafiğinde çalıştığından derleme işlemleri gibi yapıların ayrıntılarını görmez ve yapılandırılan hedefler olmadığı için test_suite
kurallarına erişemez. İlki için aquery
bölümüne bakın.
Temel söz dizimi
Basit bir cquery
çağrısı şu şekilde görünür:
bazel cquery "function(//target)"
"function(//target)"
sorgu ifadesi aşağıdakilerden oluşur:
function(...)
, hedefte çalıştırılacak işlevdir.cquery
,query
işlevlerinin çoğunu ve birkaç yeni işlevi destekler.//target
, işleve beslenen 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ılavuzuna bakın.
cquery
, yükleme ve analiz aşamalarını tamamlamak için bir hedef gerektirir. Aksi belirtilmedikçe cquery
, sorgu ifadesinde listelenen hedefleri ayrıştırır. Üst düzey derleme hedeflerinin bağımlılıklarını sorgulamak için --universe_scope
bölümüne bakın.
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 hedef için bu, yapılandırmayı tanımlayan derleme seçeneği değerlerinin opak karması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 karmalarına benzer şekilde, tam bir kimliğin geçerli tüm ön eklerini anlar.
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. Bunun nedeni, cquery
özelliğinin yapılandırılmış hedefleri değerlendirmesi ve derleme grafiğinde //foo
öğesinin birden fazla yapılandırılmış sürümüne sahip olabilmesidir.
cquery
için sorgu ifadesindeki bir hedef kalıbı, bu kalıpla eşleşen bir etikete sahip her yapılandırılmış hedefe göre değerlendirilir. Çıkış belirleyicidir ancak cquery
, temel sorgu sipariş sözleşmesi dışında hiçbir sipariş garantisi vermez.
Bu, sorgu ifadeleri için query
ile kıyaslandığında daha hassas sonuçlar verir.
Örneğin, aşağıdaki arama terimi birden fazla sonuç verebilir:
# 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.
Hedef kalıplar hakkında daha fazla bilgi için query
'nin hedef kalıp dokümanlarına bakın.
İşlevler
query
tarafından desteklenen işlev grubundan 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 kullanıma sunar:
yapılandırma
expr ::= config(expr, word)
config
operatörü, ilk bağımsız değişken tarafından belirtilen etiket ve ikinci bağımsız değişken tarafından 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. Karmalar, $
bazel config
veya önceki 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)"
Belirtilen yapılandırmada ilk bağımsız değişkenin tüm sonuçları bulunamazsa yalnızca bulunabilenler 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ılmış hedeflerin bağımlılıkları genellikle geçişlerden geçer. Bu da yapılandırmalarının bağımlılarından 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ı yürütme yapılandırmasında yapılandırır. Böylece aşağıdaki sorgular aşağıdaki çıkışları verir:
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. Oluşturulan hedeflerin geçişli olarak kapatılması, sorgunun evreni olarak kullanılır. Her iki durumda da, oluşturulacak hedefler en üst düzeyde derlenebilir (yani üst düzey seçeneklerle uyumlu) olmalıdır. cquery
, bu üst düzey hedeflerin geçişli kapatılmasıyla ilgili sonuçları döndürür.
Bir sorgu ifadesindeki tüm hedefleri üst düzeyde oluşturmak mümkün olsa bile bunu yapmamak yararlı olabilir. Örneğin, --universe_scope
değerini açıkça ayarlamak, önemsemediğiniz yapılandırmalarda hedeflerin birden çok kez oluşturulmasını önleyebilir. Ayrıca, bir hedefin hangi yapılandırma sürümünü aradığınızı belirtmenize de yardımcı olabilir (şu anda bunu başka bir şekilde tam olarak belirtmek mümkün olmadığından). Sorgu ifadeniz deps(//foo)
'ten daha karmaşıksa bu işareti ayarlamanız gerekir.
--implicit_deps
(boolean, varsayılan=True)
Bu işareti false (yanlış) olarak ayarlamak, BUILD dosyasında açıkça ayarlanıp Bazel tarafından başka bir yere ayarlanmayan tüm sonuçları filtreler. Buna çözümlenmiş araç zincirlerinin filtrelenmesi de dahildir.
--tool_deps
(boole, varsayılan=Doğru)
Bu işaret yanlış olarak ayarlanırsa sorgulanan hedeften kendilerine giden yolun, hedef yapılandırması ile hedef olmayan yapılandırmalar arasındaki geçişten geçtiği tüm yapılandırılmış hedefler filtrelenir.
Sorgulanan hedef hedef yapılandırmadaysa --notool_deps
politikasının ayarlanması, yalnızca hedef yapılandırmada bulunan hedefleri döndürür. Sorgulanan hedef, hedef olmayan bir yapılandırmadaysa --notool_deps
ayarı yalnızca hedef olmayan yapılandırmalardaki hedefleri döndürür. Bu ayar, genellikle çözülmüş araç zincirlerinin filtrelenmesini etkilemez.
--include_aspects
(boole, varsayılan=Doğru)
Aspects tarafından eklenen bağımlılıkları dahil edin.
Bu işaret devre dışı bırakılırsa
X yalnızca bir yönden bağımlıysa cquery somepath(X, Y)
ve cquery deps(X) | grep 'Y'
Y değerini atlar.
Çı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, üst düzey hedeflerden farklı yapılandırmalarda üst düzey hedeflerin altında hedefler oluşturmak için kullanılır.
Örneğin, bir hedef, tools
özelliğindeki tüm bağımlılıklarda exec 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) gösterir.
Bu çıkış biçimi, varsayılan olarak NONE
olarak ayarlanan --transitions
işaretçisi tarafından tetiklenir. FULL
veya LITE
moduna ayarlanabilir. FULL
modu, geçiş öncesi ve sonrası seçeneklerin ayrıntılı bir karşılaştırmasını da içeren kural sınıfı geçişleri ve özellik geçişleri hakkında bilgi verir. LITE
modu, farklı seçenekler olmadan aynı bilgileri verir.
Protokol mesajı çıkışı
--output=proto
Bu seçenek, elde edilen hedeflerin ikili protokol arabelleği biçiminde yazdırılmasına neden olur. Protokol arabelleğinin tanımını src/main/protobuf/analysis_v2.proto adresinde bulabilirsiniz.
CqueryResult
, cquery'nin sonuçlarını içeren üst düzey iletidir. ConfiguredTarget
mesaj ve Configuration
mesajdan oluşan bir liste 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ırılmış her hedefin bir parçası olarak yapılandırma bilgilerini döndürür. Bu bilgileri çıkarmak ve tam olarak sorgunun proto çıkışı gibi biçimlendirilmiş bir proto çıkışı almak istiyorsanız bu işareti false olarak ayarlayın.
Proto çıkışıyla ilgili daha fazla seçenek için sorgunun proto çıkışı belgelerine bakın.
Grafik çıkışı
--output=graph
Bu seçenek, çıkışı Graphviz uyumlu bir .dot dosyası olarak oluşturur. Ayrıntılar için query
'ın grafik çıkış dokümanlarına bakın. cquery
, --graph:node_limit
ve --graph:factored
özelliklerini de destekler.
Dosya çıkışı
--output=files
Bu seçenek, sorguyla eşleşen her hedef tarafından oluşturulan çıkış dosyalarının listesini (bazel build
çağrısının sonunda yazdırılan listeye benzer) yazdırır. Çıkış, yalnızca --output_groups
işaretiyle belirlenen istenen çıkış gruplarında tanıtılan dosyaları içerir.
Kaynak dosyalar bu kapsama girer.
Bu çıkış biçimi tarafından yayınlanan tüm yollar, bazel info execution_root
aracılığıyla elde edilebilen execroot'a görelidir. bazel-out
kolaylık sembolü varsa ana depodaki dosyaların 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 Starlark işlevini çağırır ve çağrı tarafından döndürülen değeri yazdırır. --starlark:file
işaretçisi, format
adlı bir işlevi tek bir parametreyle (target
) tanımlayan bir Starlark dosyasının konumunu belirtir. Bu işlev, sorgu sonucundaki her bir Hedef için çağrılır. Alternatif olarak, kolaylık sağlamak için --starlark:expr
işaretini kullanarak def format(target): return expr
olarak tanımlanan bir işlevin yalnızca gövdesini belirtebilirsiniz.
"cquery" Starlark lehçesi
cquery Starlark ortamı, BUILD veya .bzl dosyasından farklıdır. Tüm temel Starlark yerleşik sabitlerini ve işlevlerini, ayrıca aşağıda açıklanan birkaç cquery'ye özgü sabitleri içerir ancak glob
, native
veya rule
'yi içermez ve load ifadelerini desteklemez.
build_options(hedef)
build_options(target)
, anahtarları derleme seçeneği tanımlayıcıları (bkz. Yapılandırmalar) olan ve değerleri Starlark değerleri olan bir haritayı döndürür. Değerleri yasal Starlark değerleri olmayan derleme seçenekleri
bu haritadan çıkarılır.
Hedef bir giriş dosyasıysa giriş dosyası hedefleri null yapılandırmaya sahip olduğundan build_options(target)
None değerini döndürür.
providers(hedef)
providers(target)
, anahtarları sağlayıcıların adları (örneğin, "DefaultInfo"
) ve değerleri Starlark değerleri olan bir eşleme döndürür. Değerleri yasal Starlark değerleri olmayan sağlayıcılar bu haritadan çıkarılır.
Ö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 target.files.to_list()])"
//bar
ve alt paketlerinde rule 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 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 çıktılarının listesini yazdırma
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, bir dosyada tanımlanan Starlark işlevleri kullanılmaktadır.
$ 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 yazdırın. Bu etiketler yalnızca Python 3'tür. 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 sorgu
cquery
ve query
birbirini tamamlayarak farklı
nişlerde başarılı oluyor. Sizin için en uygun seçeneği belirlemek üzere aşağıdakileri göz önünde bulundurun:
cquery
, oluşturduğunuz grafiği tam olarak modellemek için belirliselect()
dallarını izler.query
, derlemenin hangi dalı seçtiğini bilmediği için tüm dalları dahil ederek fazla tahminde bulunur.cquery
işlevinin hassasiyeti,query
ile kıyaslandığında daha fazla grafik oluşturmayı 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
tarafından sorgu dili yorumlanması,query
tarafından kaçınılan belirsizliklere yol açmaktadır. Örneğin,"//foo"
iki yapılandırmada mevcutsacquery "deps(//foo)"
hangi yapılandırmayı kullanmalıdır?config
işlevi bu konuda yardımcı olabilir.- Daha yeni bir araç olan
cquery
, belirli kullanım alanları için desteğe sahip değildir. Ayrıntılar için Bilinen sorunlar bölümüne bakın.
Bilinen sorunlar
cquery
"derlediği" tüm hedefler aynı yapılandırmaya sahip olmalıdır.
cquery
, sorguları değerlendirmeden önce, derleme işlemlerinin yürütüleceği noktadan hemen önceki bir derlemeyi tetikler. "Oluşturduğu" hedefler, varsayılan olarak sorgu ifadesinde görünen tüm etiketler arasından seçilir (bu işlem --universe_scope
ile geçersiz kılınabilir). Bunların aynı yapılandırmaya sahip olması gerekir.
Bunlar genellikle üst düzey "hedef" yapılandırmasını paylaşsa da kurallar, gelen kenar geçişleriyle kendi yapılandırmalarını değiştirebilir.
cquery
bu noktada yetersiz kalır.
Geçici çözüm: Mümkünse --universe_scope
öğesini daha sıkı bir kapsama ayarlayın. Ö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 yok.
Deterministik olmayan çıkış.
cquery
, önceki komutlardaki derleme grafiğini otomatik olarak silmez ve bu nedenle geçmiş sorgulardaki sonuçları alma eğilimindedir. Örneğin, genquery
, tools
özelliğinde bir yürütme geçişi gerçekleştirir. 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 <<<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 herhangi bir başlangıç seçeneğini değiştirin.
Örneğin, derleme komutunuza --test_arg=<whatever>
komutunu ekleyin.
Sorun giderme
Yinelenen hedef kalıpları (/...
)
Aşağıdakilerle 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, --universe_scope=//foo:app
paketi //foo
paketini içermesine rağmen //foo
paketinin kapsamda olmadığını yanlış bir şekilde belirtir. Bunun nedeni, cquery
içindeki tasarım sınırlamalarıdır. Geçici bir çözüm olarak, evren kapsamına //foo/...
öğesini açıkça ekleyin:
$ bazel cquery --universe_scope=//foo:app,//foo/... "somepath(//foo:app, //foo/...)"
Bu yöntem işe yaramazsa (örneğin, //foo/...
içindeki bazı hedefler seçilen derleme işaretleriyle derlenemezse) önceden işleme sorgusu kullanarak kalıbı bileşen paketlerine manuel olarak 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 "+" -))"