cquery
, query
'in select()
özelliğini doğru şekilde işleyen ve seçeneklerin derleme grafiği üzerindeki etkilerini oluşturan bir varyantıdır.
Bunu, bu efektleri entegre eden Bazel analiz aşamasının sonuçlarını inceleyerek yapar. Buna karşın query
, 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 benzersiz bir tanımlayıcısını (9f87702)
içerir.
cquery
, yapılandırılmış hedef grafiğin üzerinde çalıştığı için hedef yapılandırılmamış olduğundan derleme işlemleri veya test_suite
kurallarına erişim gibi yapılar hakkında bilgi içermez. Kodlayıcılar için bkz. aquery
.
Temel söz dizimi
Basit bir cquery
araması şu şekilde görünür:
bazel cquery "function(//target)"
"function(//target)"
sorgu ifadesi şunlardan oluşur:
function(...)
, hedef üzerinde çalıştırılacak işlevdir.cquery
,query
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ılavuzuna bakın.
cquery
, bir hedefin yükleme ve analiz aşamalarından geçmesini 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
sayfasını inceleyin.
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 bir 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 önekidir. 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 kimliğin geçerli tüm ön eklerini anlar.
Tam kimlikleri görmek için $ bazel config
komutunu çalıştırın.
Hedef kalıbı değerlendirmesi
//foo
, cquery
için query
ile farklı bir anlama sahiptir. Bunun nedeni, cquery
ürününün yapılandırılmış hedefleri değerlendirmesi ve derleme grafiğinde birden fazla yapılandırılmış //foo
sürümünün bulunmasıdır.
cquery
için sorgu ifadesindeki bir hedef kalıbı, bu kalıpla eşleşen bir etikete sahip her yapılandırılmış hedefi değerlendirir. Çıktı belirleyicidir ancak cquery
, temel sorgu sıralama sözleşmesi dışında sipariş garantisi vermez.
Bu yöntem, sorgu ifadeleri için query
ile karşılaştırıldığında daha ayrıntılı 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 tanımlamak istiyorsanız config
işlevini kullanın.
Hedef kalıpları hakkında daha fazla bilgi için query
hedef kalıbı belgelerine bakın.
İşlevler
query
tarafından desteklenen işlev grubundan cquery
, visible
, siblings
, buildfiles
ve tests
hariç tümünü destekler.
cquery
aşağıdaki yeni işlevleri de kullanıma sunuyor:
config
expr ::= config(expr, word)
config
operatörü, ikinci bağımsız değişkenin belirttiği ilk bağımsız değişken ve yapılandırmayla belirtilen etiket 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ı şeklindedir. 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)"
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 böylece derleme sırasında sunulan seçenekleri devralır.
Cquery seçeneklerini kullanma
--universe_scope
(virgülle ayrılmış liste)
Genellikle, yapılandırılmış hedeflerin bağımlılıkları geçişlerden geçer. Bu da, yapılandırmalarının bağımlı oldukları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ızı sağlar. Ö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ında yapılandırır. Böylece aşağıdaki sorgular aşağıdaki sonuçları verir:
Sorgu | Oluşturulan Hedef | Çı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. Ayarlanmadığında sorgu ifadesinde belirtilen tüm hedefler oluşturulur. Oluşturulan hedeflerin geçişli olarak kapanması sorgunun evreni olarak kullanılır. Her iki durumda da, oluşturulacak hedefler üst düzeyde oluşturulabilir (yani üst düzey seçeneklerle uyumlu) olmalıdır. cquery
, bu üst düzey hedeflerin geçişli olarak kapanması ile ilgili sonuçları döndürür.
Bir sorgu ifadesinde en üst düzeyde tüm hedefler oluşturmak mümkün olsa bile, bunu yapmamak faydalı olabilir. Örneğin, --universe_scope
parametresini açık bir şekilde ayarlamak, ilgilenmediğiniz yapılandırmalarda birden fazla kez hedef oluşturulmasını engelleyebilir. Arama, bir hedefin hangi yapılandırma sürümünü aradığınızı belirtmenize de yardımcı olabilir (çünkü şu anda bunu başka bir şekilde tam olarak belirtmek mümkün değildir). Sorgu ifadeniz deps(//foo)
ifadesinden daha karmaşıksa bu işareti ayarlamanız gerekir.
--implicit_deps
(boole, varsayılan=Doğru)
Bu işaretin yanlış değerine ayarlanması, BUILD dosyasında açıkça ayarlanmayan ve bunun yerine Bazel tarafından başka bir yerde ayarlanan tüm sonuçları filtreler. Buna çözümlenmiş araç zinciri filtreleme de dahildir.
--tool_deps
(boole, varsayılan=Doğru)
Bu işaretin yanlış değerine ayarlanması, sorgulanan hedeften onlara giden yolun hedef yapılandırma ile hedeflenmeyen yapılandırmalar arasında bir geçişle geçtiği tüm yapılandırılmış hedefleri filtreler.
Sorgulanan hedef hedef yapılandırmadaysa --notool_deps
ayarı yalnızca aynı zamanda hedef yapılandırmada da bulunan hedefleri döndürür. Sorgulanan hedef, hedef olmayan bir yapılandırmadaysa --notool_deps
ayarlaması yalnızca hedef olmayan yapılandırmalarda da hedefleri döndürür. Bu ayar genellikle çözümlenen araç zincirlerinin filtrelenmesini etkilemez.
--include_aspects
(boole, varsayılan=Doğru)
Yönlerle eklenen bağımlılıkları dahil edin.
Bu işaret devre dışıysa cquery somepath(X, Y)
ve
cquery deps(X) | grep 'Y'
X yalnızca bir özellik yoluyla buna bağlıysa Y'yi atlayın.
Çıkış biçimleri
Varsayılan olarak, cquery çıkışları, bağımlılık sıralı etiket ve yapılandırma çiftleri listesiyle sonuçlanır. Sonuçların gösterilmesi için başka seçenekler de bulunmaktadı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 yönetici yapılandırmasına geçiş uygulayabilir. Bunlara özellik
geçişleri denir. Kurallar, kendi yapılandırmalarına da geçişler uygulayabilir (buna kural sınıfı geçişi olarak bilinir). Bu çıktı biçimi, söz konusu geçişlerin türü ve derleme seçenekleri üzerindeki etkisi gibi geçişlerle ilgili bilgiler sağlar.
Bu çıkış biçimi, varsayılan olarak NONE
değerine ayarlanan --transitions
işareti tarafından tetiklenir. FULL
veya LITE
moduna ayarlanabilir. FULL
modu, kural sınıfı geçişleri ve özellik geçişleri hakkında bilgiler verir. Bu bilgiler arasında, geçişten önceki ve sonraki seçeneklerin ayrıntılı farkları da yer alır. LITE
modu, aynı bilgileri seçenek farkı olmadan verir.
Protokol mesajı çıkışı
--output=proto
Bu seçenek, sonuç olarak 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
, sorgunun sonuçlarını içeren en üst düzey iletidir. ConfiguredTarget
mesaj ve Configuration
mesaj listesi 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, sorgu sonuçları her yapılandırılmış hedefin bir parçası olarak yapılandırma bilgileri 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" (yanlış) değerine ayarlayın.
Proto çıkışıyla ilgili daha fazla seçenek için sorgunun proto çıkışı belgelerine bakın.
Grafik çıktısı
--output=graph
Bu seçenek, çıktıyı Graphviz uyumlu .dot dosyası olarak oluşturur. Ayrıntılar için query
grafik çıkışı dokümanlarına göz atın. cquery
, --graph:node_limit
ve --graph:factored
özelliklerini de destekler.
Dosya çıkışı
--output=files
Bu seçenek, bazel build
çağrısının sonunda yazdırılan listeye benzer şekilde sorguyla eşleşen her hedef tarafından oluşturulan çıkış dosyalarının bir listesini yazdırır. Çıkış, yalnızca --output_groups
işaretiyle belirlenen istenen çıkış gruplarında tanıtılan dosyaları içerir.
Kaynak dosyaları içerir.
Bu çıkış biçimi tarafından yayınlanan tüm yollar, bazel info execution_root
aracılığıyla edinilebilen execroot parametresine görelidir. bazel-out
kolaylık sembolü bağlantısı 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 bir Starlark işlevi çağırır ve çağrının döndürdüğü değeri yazdırır. --starlark:file
işareti, tek bir parametre (target
) ile format
adlı bir işlevi tanımlayan Starlark dosyasının konumunu belirtir. Bu işlev, sorgu sonucundaki her bir Target için çağrılır. Alternatif olarak, kolaylık sağlamak amacıyla --starlark:expr
işaretini kullanarak def format(target): return expr
olarak tanımlanan bir işlevin yalnızca gövdesini de belirtebilirsiniz.
"cquery" Starlark lehçesi
Starlark sorgusu 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 ve cquery'ye özel birkaç tanesini içerir ancak (örneğin) glob
, native
veya rule
içermez ve yük ifadelerini desteklemez.
build_options(target)
build_options(target)
, anahtarları derleme seçeneği tanımlayıcıları (bkz. Yapılandırmalar) ve değerleri kendi 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 giriş dosyası hedefleri boş bir yapılandırmaya sahip olduğundan build_options(target)
, Hiçbiri değerini döndürür.
sağlayıcılar(hedef)
providers(target)
, anahtarları sağlayıcı 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:
bazel cquery //foo --output=starlark \ --starlark:expr="' '.join([f.basename for f in target.files.to_list()])"
//bar
içindeki kural hedefleri ve alt paketleri tarafından oluşturulan tüm dosyaların boşlukla ayrılmış 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 hatırlatıcı listesini yazdır.
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 komut satırı seçeneği --javacopt
değerini yazdırın.
bazel cquery //foo --output=starlark \ --starlark:expr="build_options(target)['//command_line_option:javacopt']"
Tam olarak bir çıkışa sahip her bir hedefin etiketini 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 kesinlikle Python 3 olan 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 sorgu karşılaştırması
cquery
ve query
birbirini tamamlar ve farklı nişlerde üstün gelir. Sizin için hangisinin doğru olduğuna karar vermek ü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 şubeyi seçtiğini bilemez. Bu nedenle, tüm dalları dahil ederek normalden fazla tahminde bulunur.cquery
yönteminin hassasiyeti için,query
ile karşılaştırıldığında daha fazla grafik oluşturmak gerekir. Spesifik olarak,cquery
yapılandırılmış hedefleri,query
ise yalnızca hedefleri değerlendirir. Bu işlem daha fazla zaman alır ve daha fazla bellek kullanır.cquery
'ın sorgu dilini yorumlaması,query
tarafından kaçınılan belirsizliğe yol açar. Örneğin,"//foo"
iki yapılandırmada bulunuyorsacquery "deps(//foo)"
hangisini kullanmalıdır?config
işlevi bu konuda size yardımcı olabilir.cquery
, daha yeni bir araç olduğundan belirli kullanım alanları için destek sunmaz. Ayrıntılar için Bilinen sorunlar bölümüne bakın.
Bilinen sorunlar
cquery
tarafından "oluşturulan" tüm hedefler aynı yapılandırmaya sahip olmalıdır.
Sorguları değerlendirmeden önce cquery
, derleme işlemlerinin yürütüleceği noktadan hemen öncesine kadar bir derlemeyi tetikler. "Oluşturduğu" hedefler, sorgu ifadesinde görünen tüm etiketler arasından varsayılan olarak seçilir (bu, --universe_scope
ile geçersiz kılınabilir). Bunlar aynı yapılandırmaya sahip olmalıdır.
Bunlar genellikle üst düzey "hedef" yapılandırmasını paylaşsa da kurallar, gelen uç geçişleriyle kendi yapılandırmalarını değiştirebilir.
Bu noktada cquery
yetersiz kalır.
Geçici çözüm: Mümkünse --universe_scope
öğesini daha katı 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
desteği yoktur.
Belirsiz olmayan çıkış.
cquery
, derleme grafiğini önceki komutlardan otomatik olarak silmez ve bu nedenle geçmiş sorgulardan sonuç almaya eğilimlidir. Örneğin genrule
, tools
özelliğinde bir yürütme geçişi yapar. Yani araçlarını yürütme yapılandırmasında yapılandırır.
Bu geçişin uzun süren 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şlatma seçeneğini değiştirin.
Örneğin, derleme komutunuza --test_arg=<whatever>
komutunu ekleyin.
Sorun giderme
Yinelemeli hedef kalıpları (/...
)
Karşılaştığınız durum:
$ 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
paketini içermesine rağmen kapsam dışında olduğunu gösterir.--universe_scope=//foo:app
Bunun nedeni, cquery
içindeki tasarım sınırlamalarıdır. Geçici bir çözüm olarak, //foo/...
öğesini evren kapsamına açıkça ekleyin:
$ 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 oluşturamadığından) bir ön işleme sorgusu kullanarak kalıbı kendi bileşenlerine ait paketlere 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 "+" -))"