cquery
, query
का एक वैरिएंट है. यह select()
को सही तरीके से हैंडल करता है. साथ ही, बिल्ड ग्राफ़ पर बिल्ड विकल्पों के इफ़ेक्ट दिखाता है.
यह Bazel के विश्लेषण के चरण के नतीजों को प्रोसेस करके ऐसा करता है. इस चरण में, इन प्रभावों को इंटिग्रेट किया जाता है. 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
के नियमों का ऐक्सेस भी नहीं होता, क्योंकि ये कॉन्फ़िगर किए गए टारगेट नहीं होते. पहले वाले के लिए, 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
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 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)
अगर आपको यह तय करना है कि किस इंस्टेंस से क्वेरी करनी है, तो config
फ़ंक्शन का इस्तेमाल करें.
टारगेट पैटर्न के बारे में ज़्यादा जानने के लिए, query
के टारगेट पैटर्न के बारे में जानकारी देने वाला दस्तावेज़ देखें.
फ़ंक्शन
query
के फ़ंक्शन के सेट में से, cquery
इन फ़ंक्शन के साथ काम करता है: allrdeps
, buildfiles
, rbuildfiles
, siblings
, tests
, और visible
.
cquery
में ये नए फ़ंक्शन भी जोड़े गए हैं:
config
expr ::= config(expr, word)
config
ऑपरेटर, पहले आर्ग्युमेंट से दिखाए गए लेबल और दूसरे आर्ग्युमेंट से बताए गए कॉन्फ़िगरेशन के लिए, कॉन्फ़िगर किया गया टारगेट ढूंढने की कोशिश करता है.
दूसरे तर्क के लिए मान्य वैल्यू, null
या कस्टम कॉन्फ़िगरेशन हैश होती है. हैश को $
bazel config
या पिछले cquery
के आउटपुट से वापस पाया जा सकता है.
उदाहरण:
$ bazel cquery "config(//bar, 3732cc8)" --universe_scope=//foo
$ bazel cquery "deps(//foo)" //bar (exec) //baz (exec) $ 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_binary( name = "tool", srcs = ["tool.cpp"], )
Genrules, अपने टूल को exec कॉन्फ़िगरेशन में कॉन्फ़िगर करते हैं, ताकि यहाँ दी गई क्वेरी के लिए यह आउटपुट मिले:
क्वेरी | टारगेट बनाया गया | आउटपुट |
---|---|---|
bazel cquery "//x:tool" | //x:tool | //x:tool(targetconfig) |
bazel cquery "//x:tool" --universe_scope="//x:my_gen" | //x:my_gen | //x:tool(execconfig) |
अगर यह फ़्लैग सेट किया जाता है, तो इसके कॉन्टेंट बनाए जाते हैं. अगर इसे सेट नहीं किया जाता है, तो क्वेरी एक्सप्रेशन में बताए गए सभी टारगेट बनाए जाते हैं. बिल्ट टारगेट के ट्रांज़िटिव क्लोज़र का इस्तेमाल, क्वेरी के यूनिवर्स के तौर पर किया जाता है. दोनों ही मामलों में, बनाए जाने वाले टारगेट को टॉप लेवल पर बनाया जाना चाहिए. इसका मतलब है कि वे टॉप लेवल के विकल्पों के साथ काम करने चाहिए. cquery
, इन टॉप-लेवल टारगेट के ट्रांज़िटिव क्लोज़र में नतीजे दिखाता है.
भले ही, टॉप लेवल पर क्वेरी एक्सप्रेशन में सभी टारगेट बनाए जा सकते हों, लेकिन ऐसा न करना फ़ायदेमंद हो सकता है. उदाहरण के लिए, --universe_scope
को साफ़ तौर पर सेट करने से, उन कॉन्फ़िगरेशन में टारगेट को कई बार बनाने से रोका जा सकता है जिनके बारे में आपको कोई जानकारी नहीं है. इससे यह भी तय किया जा सकता है कि आपको टारगेट के कॉन्फ़िगरेशन का कौनसा वर्शन चाहिए. फ़िलहाल, इसे पूरी तरह से किसी और तरीके से तय नहीं किया जा सकता. अगर आपकी क्वेरी का एक्सप्रेशन deps(//foo)
से ज़्यादा जटिल है, तो आपको यह फ़्लैग सेट करना चाहिए.
--implicit_deps
(boolean, default=True)
इस फ़्लैग को false पर सेट करने से, उन सभी नतीजों को फ़िल्टर कर दिया जाता है जिन्हें BUILD फ़ाइल में साफ़ तौर पर सेट नहीं किया गया है. इसके बजाय, Bazel उन्हें कहीं और सेट करता है. इसमें, हल हो चुकी टूलचेन को फ़िल्टर करना शामिल है.
--tool_deps
(boolean, default=True)
इस फ़्लैग को false पर सेट करने से, कॉन्फ़िगर किए गए उन सभी टारगेट को फ़िल्टर कर दिया जाता है जिनके लिए क्वेरी किए गए टारगेट से उन तक का पाथ, टारगेट कॉन्फ़िगरेशन और नॉन-टारगेट कॉन्फ़िगरेशन के बीच ट्रांज़िशन को पार करता है.
अगर क्वेरी किया गया टारगेट, टारगेट कॉन्फ़िगरेशन में है, तो --notool_deps
को सेट करने पर, सिर्फ़ वे टारगेट दिखेंगे जो टारगेट कॉन्फ़िगरेशन में भी हैं. अगर क्वेरी किया गया टारगेट, नॉन-टारगेट कॉन्फ़िगरेशन में है, तो --notool_deps
को सेट करने पर, सिर्फ़ ऐसे टारगेट दिखेंगे जो नॉन-टारगेट कॉन्फ़िगरेशन में हैं. आम तौर पर, इस सेटिंग से हल की गई टूलचेन को फ़िल्टर करने पर कोई असर नहीं पड़ता.
--include_aspects
(boolean, default=True)
aspects से जोड़ी गई डिपेंडेंसी शामिल करें.
अगर इस फ़्लैग को बंद कर दिया जाता है, तो cquery somepath(X, Y)
और cquery deps(X) | grep 'Y'
, Y को तब नहीं दिखाते हैं, जब X सिर्फ़ एक पहलू के ज़रिए इस पर निर्भर होता है.
आउटपुट फ़ॉर्मैट
डिफ़ॉल्ट रूप से, cquery, लेबल और कॉन्फ़िगरेशन पेयर की सूची में, डिपेंडेंसी के क्रम में नतीजे दिखाता है. नतीजों को दिखाने के लिए, अन्य विकल्प भी उपलब्ध हैं.
ट्रांज़िशन
--transitions=lite --transitions=full
कॉन्फ़िगरेशन ट्रांज़िशन का इस्तेमाल, टॉप लेवल के टारगेट के नीचे टारगेट बनाने के लिए किया जाता है. ये टारगेट, टॉप लेवल के टारगेट से अलग कॉन्फ़िगरेशन में होते हैं.
उदाहरण के लिए, कोई टारगेट अपने tools
एट्रिब्यूट में मौजूद सभी डिपेंडेंसी पर, एक्ज़ेक कॉन्फ़िगरेशन में ट्रांज़िशन लागू कर सकता है. इन्हें एट्रिब्यूट ट्रांज़िशन कहा जाता है. नियम, अपने कॉन्फ़िगरेशन पर भी ट्रांज़िशन लागू कर सकते हैं. इन्हें नियम क्लास ट्रांज़िशन कहा जाता है. इस आउटपुट फ़ॉर्मैट में, इन ट्रांज़िशन के बारे में जानकारी मिलती है. जैसे, वे किस तरह के हैं और उनका बिल्ड विकल्पों पर क्या असर पड़ता है.
यह आउटपुट फ़ॉर्मैट, --transitions
फ़्लैग से ट्रिगर होता है. यह फ़्लैग डिफ़ॉल्ट रूप से NONE
पर सेट होता है. इसे FULL
या LITE
मोड पर सेट किया जा सकता है. FULL
मोड, नियम क्लास ट्रांज़िशन और एट्रिब्यूट ट्रांज़िशन के बारे में जानकारी देता है. इसमें ट्रांज़िशन से पहले और बाद के विकल्पों के बीच का अंतर भी शामिल होता है. LITE
मोड, विकल्पों में अंतर के बिना एक जैसी जानकारी दिखाता है.
प्रोटोकॉल मैसेज आउटपुट
--output=proto
इस विकल्प की वजह से, टारगेट को बाइनरी प्रोटोकॉल बफ़र फ़ॉर्म में प्रिंट किया जाता है. प्रोटोकॉल बफ़र की परिभाषा src/main/protobuf/analysis_v2.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
फ़्लैग से तय होता है.
इसमें सोर्स फ़ाइलें शामिल होती हैं.
इस आउटपुट फ़ॉर्मैट से जनरेट होने वाले सभी पाथ, execroot के हिसाब से होते हैं. इसे bazel info execution_root
के ज़रिए हासिल किया जा सकता है. अगर bazel-out
सुविधा वाला सिमलंक मौजूद है, तो मुख्य रिपॉज़िटरी में मौजूद फ़ाइलों के पाथ भी वर्कस्पेस डायरेक्ट्री के हिसाब से तय किए जाते हैं.
Starlark का इस्तेमाल करके, आउटपुट फ़ॉर्मैट तय करना
--output=starlark
इस आउटपुट फ़ॉर्मैट में, क्वेरी के नतीजे में कॉन्फ़िगर किए गए हर टारगेट के लिए Starlark फ़ंक्शन को कॉल किया जाता है. साथ ही, कॉल से मिली वैल्यू को प्रिंट किया जाता है. --starlark:file
फ़्लैग, Starlark फ़ाइल की जगह की जानकारी देता है. यह फ़ाइल, format
नाम के फ़ंक्शन को एक पैरामीटर target
के साथ तय करती है. इस फ़ंक्शन को क्वेरी के नतीजे में मौजूद हर 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)
कोई वैल्यू नहीं दिखाता है, क्योंकि इनपुट फ़ाइल टारगेट का कॉन्फ़िगरेशन शून्य होता है.
providers(target)
providers(target)
एक ऐसा मैप दिखाता है जिसकी कुंजियां, providers के नाम होती हैं. उदाहरण के लिए, "DefaultInfo"
और जिनकी वैल्यू, उनकी Starlark वैल्यू होती हैं. जिन प्रोवाइडर की वैल्यू, Starlark की मान्य वैल्यू नहीं हैं उन्हें इस मैप से हटा दिया जाता है.
उदाहरण
//foo
से बनाई गई सभी फ़ाइलों के बेस नेम की सूची को स्पेस से अलग करके प्रिंट करें:
bazel cquery //foo --output=starlark \ --starlark:expr="' '.join([f.basename for f in target.files.to_list()])"
//bar
और इसके सबपैकेज में, rule टारगेट से बनाई गई सभी फ़ाइलों के पाथ की सूची को प्रिंट करें. इस सूची में, हर पाथ के बीच में खाली जगह होनी चाहिए:
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 बनाम query
cquery
और query
एक-दूसरे के पूरक हैं और अलग-अलग निश में बेहतर परफ़ॉर्म करते हैं. यह तय करने के लिए कि आपके लिए कौनसा विकल्प सही है, यहां दी गई जानकारी देखें:
cquery
,select()
की चुनिंदा शाखाओं को फ़ॉलो करता है, ताकि आपके बनाए गए ग्राफ़ का सटीक मॉडल तैयार किया जा सके.query
को यह नहीं पता कि बिल्ड कौनसी ब्रांच चुनता है. इसलिए, यह सभी ब्रांच को शामिल करके अनुमान लगाता है.cquery
को ज़्यादा सटीक बनाने के लिए,query
की तुलना में ज़्यादा ग्राफ़ बनाने की ज़रूरत होती है. खास तौर पर,cquery
, कॉन्फ़िगर किए गए टारगेट का आकलन करता है, जबकिquery
सिर्फ़ टारगेट का आकलन करता है. इसमें ज़्यादा समय लगता है और ज़्यादा मेमोरी का इस्तेमाल होता है.cquery
ने क्वेरी की भाषा को इस तरह से इंटरप्रेट किया है कि इससे अस्पष्टता पैदा होती है. हालांकि,query
ऐसा नहीं करता. उदाहरण के लिए, अगर"//foo"
दो कॉन्फ़िगरेशन में मौजूद है, तोcquery "deps(//foo)"
को किस कॉन्फ़िगरेशन का इस्तेमाल करना चाहिए? इसके लिए,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
एट्रिब्यूट पर exec ट्रांज़िशन लागू करता है. इसका मतलब है कि यह अपने टूल को exec कॉन्फ़िगरेशन में कॉन्फ़िगर करता है.
नीचे दी गई इमेज में, ट्रांज़िशन के बाद के असर को दिखाया गया है.
$ 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)
हल करने का तरीका: स्टार्टअप के किसी भी विकल्प को बदलकर, कॉन्फ़िगर किए गए लक्ष्यों का फिर से विश्लेषण किया जा सकता है.
उदाहरण के लिए, अपनी बिल्ड कमांड में --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 "+" -))"