cquery
, query
का एक वैरिएंट है. यह select()
और बिल्ड ग्राफ़ पर बिल्ड विकल्पों के असर को सही तरीके से मैनेज करता है.
ऐसा करने के लिए, Basel के विश्लेषण के चरण के नतीजों को ध्यान में रखा जाता है. इस फ़ेज़ में, इन इफ़ेक्ट को इंटिग्रेट किया जाता है. इसके उलट, query
विकल्पों का आकलन करने से पहले, Bazel के लोडिंग फ़ेज़ के नतीजों पर काम करता है.
उदाहरण के लिए:
$ 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)
हर नतीजे में, उस कॉन्फ़िगरेशन का एक यूनीक आइडेंटिफ़ायर (9f87702)
शामिल होता है जिससे टारगेट बनाया गया है.
cquery
, कॉन्फ़िगर किए गए टारगेट ग्राफ़ पर चलता है. इसमें बिल्ड ऐक्शन या [test_suite](/versions/6.2.0/reference/be/general#test_suite)
नियमों जैसे आर्टफ़ैक्ट की अहम जानकारी नहीं है, क्योंकि ये कॉन्फ़िगर नहीं किए गए टारगेट हैं. पहले के लिए, [aquery](/versions/6.2.0/docs/aquery)
देखें.
बेसिक सिंटैक्स
एक सामान्य cquery
कॉल ऐसा दिखाई देता है:
bazel cquery "function(//target)"
क्वेरी एक्सप्रेशन "function(//target)"
में ये चीज़ें शामिल होती हैं:
function(...)
, टारगेट पर चलने वाला फ़ंक्शन है.cquery
,query
के ज़्यादातर फ़ंक्शन के साथ-साथ कुछ नए फ़ंक्शन के साथ भी काम करता है.//target
फ़ंक्शन को दिया गया एक्सप्रेशन है. इस उदाहरण में, एक्सप्रेशन एक आसान टारगेट है. हालांकि, क्वेरी लैंग्वेज में फ़ंक्शन को नेस्ट करने की सुविधा भी होती है. उदाहरण के लिए, क्वेरी करने का तरीका देखें.
cquery
को लोड करने और विश्लेषण के चरणों में चलने के लिए टारगेट की ज़रूरत होती है. जब तक अलग से न बताया जाए, cquery
, क्वेरी एक्सप्रेशन में दिए गए टारगेट को पार्स करता है. टॉप-लेवल के बिल्ड टारगेट की डिपेंडेंसी के बारे में क्वेरी करने के लिए, --universe_scope
देखें.
कॉन्फ़िगरेशन
लाइन:
//tree:ash (9f87702)
का मतलब है कि //tree:ash
को आईडी 9f87702
वाले कॉन्फ़िगरेशन में बनाया गया था. ज़्यादातर टारगेट के लिए, यह कॉन्फ़िगरेशन को तय करने वाले बिल्ड विकल्प की वैल्यू का ओपेक हैश है.
कॉन्फ़िगरेशन का पूरा कॉन्टेंट देखने के लिए, इसे चलाएं:
$ bazel config 9f87702
होस्ट कॉन्फ़िगरेशन, खास आईडी (HOST)
का इस्तेमाल करता है. जनरेट नहीं की गई सोर्स फ़ाइलें, जैसे कि आम तौर पर srcs
में पाई जाने वाली सोर्स फ़ाइलें, खास आईडी (null)
का इस्तेमाल करती हैं, क्योंकि उन्हें कॉन्फ़िगर करने की ज़रूरत नहीं होती.
9f87702
, पूरे आईडी का प्रीफ़िक्स है. ऐसा इसलिए है, क्योंकि पूरे आईडी, SHA-256 हैश होते हैं. ये लंबे होते हैं और इन्हें समझना मुश्किल होता है. cquery
, पूरे आईडी के किसी भी मान्य प्रीफ़िक्स को समझता है. यह Git शॉर्ट हैश की तरह ही है.
पूरे आईडी देखने के लिए, $ bazel config
चलाएं.
टारगेट पैटर्न का इवैलुएशन
//foo
का cquery
का मतलब query
से अलग होता है. इसकी वजह यह है कि cquery
, कॉन्फ़िगर किए गए टारगेट का आकलन करता है. साथ ही, हो सकता है कि बिल्ड ग्राफ़ में //foo
के कई कॉन्फ़िगर किए गए वर्शन हों.
cquery
के लिए, क्वेरी एक्सप्रेशन में मौजूद टारगेट पैटर्न, कॉन्फ़िगर किए गए हर ऐसे टारगेट की जांच करता है जिसके लेबल का मिलान उस पैटर्न से होता है. आउटपुट डिटरमिनिस्टिक होता है, लेकिन cquery
, क्वेरी के क्रम से जुड़े मुख्य समझौते के अलावा, क्रम से जुड़ी कोई गारंटी नहीं देता.
इससे query
के मुकाबले, क्वेरी एक्सप्रेशन के लिए बेहतर नतीजे मिलते हैं.
उदाहरण के लिए, इनसे कई नतीजे मिल सकते हैं:
# Analyzes //foo in the target configuration, but also analyzes # //genrule_with_foo_as_tool which depends on a host-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 (HOST)
अगर आपको यह तय करना है कि किस इंस्टेंस पर क्वेरी करनी है, तो config
फ़ंक्शन का इस्तेमाल करें.
टारगेट पैटर्न के बारे में ज़्यादा जानकारी के लिए, query
के टारगेट पैटर्न से जुड़े दस्तावेज़ देखें.
फ़ंक्शन
query
के साथ काम करने वाले फ़ंक्शन के सेट में से cquery
, allrdeps
, buildfiles
, rbuildfiles
, siblings
, tests
, और visible
को छोड़कर सभी के साथ काम करता है.
cquery
में ये नए फ़ंक्शन भी पेश किए गए हैं:
config
expr ::= config(expr, word)
config
ऑपरेटर, दूसरे तर्क के बताए गए पहले आर्ग्युमेंट और कॉन्फ़िगरेशन से दिखाए गए लेबल के लिए, कॉन्फ़िगर किए गए टारगेट को ढूंढने की कोशिश करता है.
दूसरे आर्ग्युमेंट के लिए, target
, host
, null
या
कस्टम कॉन्फ़िगरेशन हैश वैल्यू इस्तेमाल की जा सकती हैं. हैश को $
bazel config
या पिछले cquery
के आउटपुट से वापस पाया जा सकता है.
उदाहरण:
$ bazel cquery "config(//bar, host)" --universe_scope=//foo
$ bazel cquery "deps(//foo)" //bar (HOST) //baz (3732cc8) $ bazel cquery "config(//baz, 3732cc8)"
अगर तय किए गए कॉन्फ़िगरेशन में, पहले आर्ग्युमेंट के सभी नतीजे नहीं मिलते हैं, तो सिर्फ़ वे नतीजे दिखाए जाते हैं जो मिल सकते हैं. अगर तय किए गए कॉन्फ़िगरेशन में कोई नतीजा नहीं मिलता है, तो क्वेरी पूरी नहीं होती.
विकल्प
बिल्ड के विकल्प
cquery
, सामान्य Bazel बिल्ड पर चलता है. इसलिए, यह बिल्ड के दौरान उपलब्ध विकल्पों का सेट इनहेरिट करता है.
cquery के विकल्पों का इस्तेमाल करना
--universe_scope
(कॉमा से अलग की गई सूची)
कॉन्फ़िगर किए गए टारगेट की डिपेंडेंसी, अक्सर ट्रांज़िशन से गुज़रती हैं. इस वजह से, उनका कॉन्फ़िगरेशन, डिपेंडेंट से अलग हो जाता है. इस फ़्लैग की मदद से, किसी टारगेट से क्वेरी की जा सकती है, जैसे कि उसे किसी डिपेंडेंसी या किसी दूसरे टारगेट के लिए, ट्रांज़िट पर निर्भरता के तौर पर बनाया गया हो. उदाहरण के लिए:
# x/BUILD genrule( name = "my_gen", srcs = ["x.in"], outs = ["x.cc"], cmd = "$(locations :tool) $< >$@", tools = [":tool"], ) cc_library( name = "tool", )
Genrules, अपने टूल को होस्ट कॉन्फ़िगरेशन में कॉन्फ़िगर करते हैं, ताकि नीचे दी गई क्वेरी से ये आउटपुट मिलें:
क्वेरी | टारगेट बनाया गया | आउटपुट |
---|---|---|
bazel cquery "//x:tool" | //x:tool | //x:tool(targetconfig) |
bazel cquery "//x:tool" --universe_scope="//x:my_gen" | //x:my_gen | //x:tool(hostconfig) |
अगर यह फ़्लैग सेट है, तो इसका कॉन्टेंट बनाया जाता है. अगर यह सेट नहीं है, तो क्वेरी एक्सप्रेशन में बताए गए सभी टारगेट बनाए जाते हैं. बनाए गए टारगेट के ट्रांज़िशन क्लोज़र का इस्तेमाल, क्वेरी के यूनिवर्स के तौर पर किया जाता है. किसी भी स्थिति में, बनाए जाने वाले टारगेट टॉप लेवल पर बनाए जाने लायक होने चाहिए (यानी, टॉप लेवल विकल्पों के साथ काम कर सकते हैं). cquery
इन टॉप-लेवल टारगेट को अस्थायी तौर पर बंद
करने का नतीजा दिखाता है.
भले ही, टॉप लेवल पर क्वेरी एक्सप्रेशन में सभी टारगेट बनाए जा सकते हैं, लेकिन ऐसा न करना फ़ायदेमंद हो सकता है. उदाहरण के लिए, --universe_scope
को साफ़ तौर पर सेट करने से, उन कॉन्फ़िगरेशन में कई बार टारगेट बनाने से रोका जा सकता है जिनमें आपकी दिलचस्पी नहीं है. इससे यह भी पता चल सकता है कि आपको टारगेट के किस कॉन्फ़िगरेशन वर्शन की ज़रूरत है. फ़िलहाल, किसी और तरीके से इसकी पूरी जानकारी नहीं दी जा सकती. अगर आपकी क्वेरी एक्सप्रेशन, deps(//foo)
से ज़्यादा जटिल है, तो आपको यह फ़्लैग सेट करना चाहिए.
--implicit_deps
(बुलियन, डिफ़ॉल्ट=सही)
इस फ़्लैग को 'गलत है' पर सेट करने से, ऐसे सभी नतीजे फ़िल्टर हो जाते हैं जिन्हें बिल्ड फ़ाइल में साफ़ तौर पर सेट नहीं किया गया है. इसके बजाय, बेज़ल ने कहीं और सेट नहीं किया है. इसमें, ठीक किए गए टूलचेन को फ़िल्टर करना भी शामिल है.
--tool_deps
(बूलियन, डिफ़ॉल्ट=सही)
इस फ़्लैग को 'गलत' पर सेट करने से, उन सभी कॉन्फ़िगर किए गए टारगेट को फ़िल्टर कर दिया जाता है जिनके लिए, क्वेरी किए गए टारगेट से उन तक का पाथ, टारगेट कॉन्फ़िगरेशन और नॉन-टारगेट कॉन्फ़िगरेशन के बीच ट्रांज़िशन को पार करता है.
अगर क्वेरी किया गया टारगेट, टारगेट कॉन्फ़िगरेशन में है, तो --notool_deps
सेटिंग सिर्फ़ ऐसे टारगेट दिखाएगी जो टारगेट कॉन्फ़िगरेशन में भी हैं. अगर क्वेरी किया गया टारगेट, नॉन-टारगेट कॉन्फ़िगरेशन में है, तो --notool_deps
सेटिंग सिर्फ़ नॉन-टारगेट कॉन्फ़िगरेशन में भी टारगेट दिखाएगी. आम तौर पर, इस सेटिंग से रिज़ॉल्व किए गए टूलचेन को फ़िल्टर करने पर असर नहीं पड़ता.
--include_aspects
(बुलियन, डिफ़ॉल्ट=सही)
ऐस्पेक्ट, किसी बिल्ड में अन्य डिपेंडेंसी जोड़ सकते हैं. डिफ़ॉल्ट रूप से, cquery
में आसपेक्ट का इस्तेमाल नहीं किया जाता, क्योंकि इससे क्वेरी किए जा सकने वाले ग्राफ़ का साइज़ बड़ा हो जाता है और ज़्यादा मेमोरी का इस्तेमाल होता है. हालांकि, इनका पालन करने से ज़्यादा सटीक नतीजे मिलते हैं.
अगर आपको बड़ी क्वेरी से मेमोरी पर पड़ने वाले असर की चिंता नहीं है, तो अपने bazelrc में डिफ़ॉल्ट रूप से इस फ़्लैग को चालू करें.
अगर आपने एस्पेक्ट बंद करके क्वेरी की है, तो आपको एक समस्या का सामना करना पड़ सकता है. इसमें, टारगेट Y बनाते समय टारगेट X काम नहीं करता, लेकिन cquery somepath(Y, X)
और cquery deps(Y) | grep 'X'
कोई नतीजा नहीं दिखाते. इसकी वजह यह है कि एस्पेक्ट के ज़रिए डिपेंडेंसी होती है.
आउटपुट फ़ॉर्मैट
डिफ़ॉल्ट रूप से, cquery लेबल और कॉन्फ़िगरेशन पेयर की सूची में, नतीजों को डिपेंडेंसी के हिसाब से दिखाता है. नतीजों को दिखाने के लिए, और भी विकल्प हैं.
ट्रांज़िशन
--transitions=lite --transitions=full
कॉन्फ़िगरेशन ट्रांज़िशन का इस्तेमाल, टॉप लेवल टारगेट के मुकाबले अलग-अलग कॉन्फ़िगरेशन में टॉप लेवल टारगेट के नीचे के टारगेट बनाने के लिए किया जाता है.
उदाहरण के लिए, कोई टारगेट अपने tools
एट्रिब्यूट में मौजूद सभी डिपेंडेंसी पर, होस्ट कॉन्फ़िगरेशन में ट्रांज़िशन लागू कर सकता है. इन्हें एट्रिब्यूट ट्रांज़िशन कहा जाता है. नियम, खुद के कॉन्फ़िगरेशन पर भी ट्रांज़िशन लागू कर सकते हैं. इन्हें रूल क्लास ट्रांज़िशन कहा जाता है. यह आउटपुट फ़ॉर्मैट, इन ट्रांज़िशन के बारे में जानकारी दिखाता है. जैसे, वे किस तरह के हैं और बिल्ड के विकल्पों पर उनका क्या असर पड़ता है.
यह आउटपुट फ़ॉर्मैट, --transitions
फ़्लैग से ट्रिगर होता है, जो डिफ़ॉल्ट रूप से NONE
पर सेट होता है. इसे FULL
या LITE
मोड पर सेट किया जा सकता है. FULL
मोड, नियम की क्लास के ट्रांज़िशन और एट्रिब्यूट ट्रांज़िशन के बारे में जानकारी देता है. इसमें ट्रांज़िशन से पहले और बाद के विकल्पों के बीच के अंतर की पूरी जानकारी भी शामिल होती है. LITE
मोड, विकल्पों के अंतर के बिना वही जानकारी दिखाता है.
प्रोटोकॉल मैसेज का आउटपुट
--output=proto
इस विकल्प की वजह से, नतीजे के तौर पर मिले टारगेट, बाइनरी प्रोटोकॉल के बफ़र फ़ॉर्म में प्रिंट हो जाते हैं. प्रोटोकॉल बफ़र की परिभाषा, src/main/protobuf/analysis.proto पर देखी जा सकती है.
CqueryResult
टॉप लेवल का मैसेज होता है, जिसमें cquery के नतीजे होते हैं. इसमें ConfiguredTarget
मैसेज और Configuration
मैसेज की सूची होती है. हर ConfiguredTarget
में एक configuration_id
होता है, जिसकी वैल्यू, उससे जुड़े Configuration
मैसेज के id
फ़ील्ड की वैल्यू के बराबर होती है.
--[no]proto:include_configurations
डिफ़ॉल्ट रूप से, cquery के नतीजे, कॉन्फ़िगर किए गए हर टारगेट के हिस्से के तौर पर कॉन्फ़िगरेशन की जानकारी दिखाते हैं. अगर आपको इस जानकारी को छोड़कर, क्वेरी के प्रोटो आउटपुट की तरह फ़ॉर्मैट किया गया प्रोटो आउटपुट पाना है, तो इस फ़्लैग को 'गलत' पर सेट करें.
प्रोटो आउटपुट से जुड़े ज़्यादा विकल्पों के लिए, क्वेरी के प्रोटो आउटपुट का दस्तावेज़ देखें.
ग्राफ़ का आउटपुट
--output=graph
यह विकल्प, Graphviz के साथ काम करने वाली .dot फ़ाइल के तौर पर आउटपुट जनरेट करता है. ज़्यादा जानकारी के लिए, query
के ग्राफ़ आउटपुट के दस्तावेज़ देखें. cquery
के साथ --graph:node_limit
और
--graph:factored
भी काम करते हैं.
फ़ाइल आउटपुट
--output=files
यह विकल्प, क्वेरी से मैच होने वाले हर टारगेट से जनरेट हुई आउटपुट फ़ाइलों की सूची को प्रिंट करता है. यह सूची, bazel build
को कॉल करने के आखिर में प्रिंट की गई सूची से मिलती-जुलती होती है. आउटपुट में सिर्फ़ वे फ़ाइलें शामिल होती हैं जिनका विज्ञापन, अनुरोध किए गए आउटपुट ग्रुप में किया गया है. यह --output_groups
फ़्लैग से तय होता है.
इसमें सोर्स फ़ाइलें शामिल होती हैं.
Starlark का इस्तेमाल करके आउटपुट फ़ॉर्मैट तय करना
--output=starlark
यह आउटपुट फ़ॉर्मैट, क्वेरी के नतीजे में कॉन्फ़िगर किए गए हर टारगेट के लिए Starlark फ़ंक्शन को कॉल करता है. साथ ही, कॉल से मिली वैल्यू को प्रिंट करता है. --starlark:file
फ़्लैग, Starlark फ़ाइल की जगह की जानकारी देता है. इस फ़ाइल में, format
नाम के फ़ंक्शन के बारे में बताया गया है. इसमें एक पैरामीटर, target
है. क्वेरी के नतीजे में मौजूद हर टारगेट के लिए, इस फ़ंक्शन को कॉल किया जाता है. इसके अलावा, --starlark:expr
फ़्लैग का इस्तेमाल करके, def format(target): return expr
के तौर पर एलान किए गए फ़ंक्शन का सिर्फ़ मुख्य हिस्सा बताया जा सकता है.
'cquery' Starlark बोली
cquery Starlark एनवायरमेंट BUILD या .bzl फ़ाइल से अलग है. इसमें सभी मुख्य Starlark
बिल्ट-इन कॉन्सटेंट और फ़ंक्शन
के साथ-साथ नीचे बताई गई cquery से जुड़ी कुछ खास बातें शामिल हैं. हालांकि, (उदाहरण के लिए) glob
,
native
या rule
शामिल नहीं हैं. साथ ही, यह लोड स्टेटमेंट के साथ काम नहीं करती.
build_options(target)
build_options(target)
ऐसा मैप दिखाता है जिसकी कुंजियां विकल्प के आइडेंटिफ़ायर हैं (कॉन्फ़िगरेशन देखें) और जिनकी वैल्यू Starlark की वैल्यू हैं. उन विकल्पों का निर्माण करें जिनके मान कानूनी स्टारलार्क मान नहीं हैं
इस मैप से हटा दिए गए हैं.
अगर टारगेट कोई इनपुट फ़ाइल है, तो build_options(target)
None दिखाता है. ऐसा इसलिए होता है, क्योंकि इनपुट फ़ाइल के टारगेट का कॉन्फ़िगरेशन शून्य होता है.
providers(target)
providers(target)
एक मैप दिखाता है, जिसकी कुंजियां प्रोवाइडर के नाम (उदाहरण के लिए, "DefaultInfo"
) होती हैं और जिनकी वैल्यू उनकी Starlark वैल्यू होती हैं. जिन प्रोवाइडर की वैल्यू, Starlark की मान्य वैल्यू नहीं हैं उन्हें इस मैप से हटा दिया गया है.
उदाहरण
//foo
से जनरेट की गई सभी फ़ाइलों के बेस नेम की सूची को प्रिंट करें. इसमें नामों के बीच स्पेस दिया गया हो:
bazel cquery //foo --output=starlark \ --starlark:expr="' '.join([f.basename for f in target.files.to_list()])"
//bar
और इसके सबपैकेज में नियम टारगेट के मुताबिक बनाई गई सभी फ़ाइलों के पाथ की सूची, स्पेस से अलग करके बनाई गई हो:
bazel cquery 'kind(rule, //bar/...)' --output=starlark \ --starlark:expr="' '.join([f.path for f in target.files.to_list()])"
//foo
से रजिस्टर की गई सभी कार्रवाइयों के मेनिमोनिक की सूची प्रिंट करें.
bazel cquery //foo --output=starlark \ --starlark:expr="[a.mnemonic for a in target.actions]"
cc_library
//baz
से रजिस्टर किए गए कंपाइलेशन आउटपुट की सूची प्रिंट करें.
bazel cquery //baz --output=starlark \ --starlark:expr="[f.path for f in target.output_groups.compilation_outputs.to_list()]"
//foo
बनाते समय, कमांड लाइन विकल्प --javacopt
की वैल्यू प्रिंट करें.
bazel cquery //foo --output=starlark \ --starlark:expr="build_options(target)['//command_line_option:javacopt']"
हर टारगेट का लेबल सिर्फ़ एक आउटपुट के साथ प्रिंट करें. इस उदाहरण में, किसी फ़ाइल में तय किए गए Starlark फ़ंक्शन का इस्तेमाल किया गया है.
$ 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
हर उस टारगेट का लेबल प्रिंट करें जो सिर्फ़ Python 3 के लिए है. इस उदाहरण में, किसी फ़ाइल में तय किए गए Starlark फ़ंक्शन का इस्तेमाल किया गया है.
$ 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
उपयोगकर्ता की ओर से तय किए गए प्रोवाइडर से वैल्यू निकालें.
$ 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 बनाम क्वेरी
cquery
और query
एक-दूसरे के साथ काम करते हैं और अलग-अलग तरह के विषयों पर बेहतरीन कॉन्टेंट बनाते हैं. अपने लिए सही विकल्प चुनने के लिए, यहां दी गई बातों को ध्यान में रखें:
cquery
, आपके बनाए गए सटीक ग्राफ़ को मॉडल करने के लिए,select()
की खास शाखाओं का पालन करता है.query
को यह नहीं पता कि बिल्ड किस शाखा को चुनता है. इसलिए, सभी शाखाओं को शामिल करके, अनुमान को बढ़ा दिया जाता है.cquery
के सटीक नतीजे पाने के लिए,query
की तुलना में ज़्यादा ग्राफ़ बनाने की ज़रूरत होती है. खास तौर पर,cquery
, कॉन्फ़िगर किए गए टारगेट का आकलन करता है, जबकिquery
सिर्फ़ टारगेट का आकलन करता है. इसमें ज़्यादा समय लगता है और यह ज़्यादा स्टोरेज का इस्तेमाल करता है.cquery
की क्वेरी भाषा के बारे में दी गई जानकारी में अस्पष्टता है, जबकिquery
में ऐसा नहीं है. उदाहरण के लिए, अगर"//foo"
दो कॉन्फ़िगरेशन में मौजूद है, तो"//foo"
को किस कॉन्फ़िगरेशन का इस्तेमाल करना चाहिए?cquery "deps(//foo)"
[config](#config)
फ़ंक्शन से इसमें मदद मिल सकती है.- नए टूल के तौर पर,
cquery
इस्तेमाल के कुछ मामलों में काम नहीं करता है. ज़्यादा जानकारी के लिए, ऐसी समस्याएं जिनके बारे में पहले से जानकारी है देखें.
पहले से मालूम समस्याएं
cquery
"बिल्ड" करने वाले सभी टारगेट का कॉन्फ़िगरेशन एक ही होना चाहिए.
क्वेरी का आकलन करने से पहले, cquery
उस पॉइंट से ठीक पहले बिल्ड अप ट्रिगर करता है जहां बिल्ड ऐक्शन लागू होंगे. यह "बिल्ड" करने वाले टारगेट, डिफ़ॉल्ट रूप से क्वेरी एक्सप्रेशन में दिखने वाले सभी लेबल से चुने जाते हैं. इसे --universe_scope
से बदला जा सकता है. इनका कॉन्फ़िगरेशन एक जैसा होना चाहिए.
आम तौर पर, ये टॉप-लेवल "टारगेट" कॉन्फ़िगरेशन शेयर करते हैं. हालांकि, इनकमिंग एज ट्रांज़िशन की मदद से नियम, अपने कॉन्फ़िगरेशन में बदलाव कर सकते हैं.
cquery
में यह सुविधा नहीं है.
समाधान: अगर मुमकिन हो, तो --universe_scope
को ज़्यादा सख्त स्कोप पर सेट करें. उदाहरण के लिए:
# 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
के लिए कोई सहायता नहीं है.
नॉन-डेटरमिनिस्टिक आउटपुट.
cquery
, पिछले निर्देशों से बिल्ड ग्राफ़ को अपने-आप नहीं मिटाता. इसलिए, यह पिछली क्वेरी के नतीजे दिखा सकता है. उदाहरण के लिए, genquery
अपने tools
एट्रिब्यूट पर होस्ट ट्रांज़िशन लागू करता है. इसका मतलब है कि यह होस्ट कॉन्फ़िगरेशन में अपने टूल कॉन्फ़िगर करता है.
नीचे, उस ट्रांज़िशन के असर देखे जा सकते हैं.
$ 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 (host_config) ... $ bazel cquery "//foo:tool" tool(host_config)
समाधान: कॉन्फ़िगर किए गए टारगेट का फिर से विश्लेषण करने के लिए, किसी भी स्टार्टअप विकल्प को बदलें.
उदाहरण के लिए, अपने बिल्ड कमांड में --test_arg=<whatever>
जोड़ें.
समस्या का हल
बार-बार इस्तेमाल होने वाले टारगेट पैटर्न (/...
)
अगर आपको:
$ 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.
इससे गलत तरीके से यह पता चलता है कि पैकेज //foo
, दायरे में नहीं है. हालांकि, --universe_scope=//foo:app
में यह शामिल है. ऐसा, cquery
में डिज़ाइन से जुड़ी सीमाओं की वजह से होता है. इसे ठीक करने के लिए, यूनिवर्स के दायरे में //foo/...
को साफ़ तौर पर शामिल करें:
$ bazel cquery --universe_scope=//foo:app,//foo/... "somepath(//foo:app, //foo/...)"
अगर ऐसा नहीं होता है (उदाहरण के लिए, //foo/...
में मौजूद कुछ टारगेट, चुने गए बिल्ड फ़्लैग के साथ बिल्ड नहीं हो सकते), तो पैटर्न को मैन्युअल तरीके से, प्री-प्रोसेसिंग क्वेरी की मदद से उसके कॉम्पोनेंट पैकेज में अनपैक करें:
# 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 "+" -))"