การค้นหาที่กำหนดค่าได้ (cquery)

รายงานปัญหา ดูแหล่งที่มา รุ่น Nightly · 7.4 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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](/versions/6.0.0/reference/be/general#test_suite) เนื่องจากไม่ใช่เป้าหมายที่กำหนดค่าไว้ สำหรับการตั้งค่า โปรดดู [aquery](/versions/6.0.0/query/aquery)

ไวยากรณ์พื้นฐาน

การโทร cquery แบบง่ายๆ จะมีลักษณะดังนี้

bazel cquery "function(//target)"

นิพจน์การค้นหา "function(//target)" ประกอบด้วยข้อมูลต่อไปนี้

  • function(...) คือฟังก์ชันที่จะเรียกใช้ในเป้าหมาย cqueryรองรับฟังก์ชันส่วนใหญ่ของ query รวมถึงฟังก์ชันใหม่อีก 2-3 รายการ
  • //target คือนิพจน์ที่ส่งไปยังฟังก์ชัน ในตัวอย่างนี้ นิพจน์คือเป้าหมายแบบง่าย แต่ภาษาของคำค้นหาก็อนุญาตให้ซ้อนฟังก์ชันต่างๆ ได้เช่นกัน ดูตัวอย่างได้ที่วิธีใช้การค้นหา

cquery ต้องมีเป้าหมายเพื่อเรียกใช้ผ่านเฟสการโหลดและการวิเคราะห์ cquery จะแยกวิเคราะห์เป้าหมายที่แสดงในนิพจน์คำค้นหา เว้นแต่จะระบุไว้เป็นอย่างอื่น ดู --universe_scope สำหรับคำค้นหาทรัพยากร Dependency ของเป้าหมายบิลด์ระดับบนสุด

การกำหนดค่า

บรรทัด:

//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 ยังมีฟังก์ชันใหม่ต่อไปนี้ด้วย

การกำหนดค่า

expr ::= config(expr, word)

ออบเจ็กต์ config จะพยายามค้นหาเป้าหมายที่กําหนดค่าไว้สําหรับป้ายกํากับที่ระบุโดยอาร์กิวเมนต์แรกและการกําหนดค่าที่ระบุโดยอาร์กิวเมนต์ที่ 2

ค่าที่ถูกต้องสำหรับอาร์กิวเมนต์ที่ 2 คือ 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 (รายการที่คั่นด้วยจุลภาค)

บ่อยครั้งที่ทรัพยากร Dependencies ของเป้าหมายที่กําหนดค่าไว้จะผ่านการเปลี่ยนแปลง ซึ่งทําให้การกำหนดค่าของทรัพยากรเหล่านั้นแตกต่างจากทรัพยากร Dependencies แฟล็กนี้ช่วยให้คุณค้นหาเป้าหมายได้ราวกับว่าเป้าหมายนั้นสร้างขึ้นโดยอิงตามหรืออิงตามแบบเปลี่ยนผ่านของเป้าหมายอื่น เช่น

# 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)

หากตั้งค่า Flag นี้ ระบบจะสร้างเนื้อหา หากไม่ได้ตั้งค่าไว้ ระบบจะสร้างเป้าหมายทั้งหมดที่กล่าวถึงในนิพจน์การค้นหาแทน การปิดแบบทางอ้อมของเป้าหมายที่สร้างขึ้นจะใช้เป็นจักรวาลของการค้นหา ไม่ว่าจะเลือกวิธีใด เป้าหมายที่จะสร้างต้องสามารถสร้างได้ที่ระดับบนสุด (กล่าวคือ เข้ากันได้กับตัวเลือกระดับบนสุด) cquery แสดงผลลัพธ์การปิดทางอ้อมของเป้าหมายระดับบนสุดเหล่านี้

แม้ว่าการสร้างเป้าหมายทั้งหมดในนิพจน์การค้นหาที่ระดับบนสุดจะเป็นไปได้ แต่คุณอาจไม่ต้องการทําเช่นนั้น เช่น การตั้งค่า --universe_scope อย่างชัดแจ้งอาจป้องกันการสร้างเป้าหมายหลายครั้งในการกําหนดค่าที่คุณไม่สนใจ นอกจากนี้ ยังช่วยให้ระบุเวอร์ชันการกำหนดค่าของเป้าหมายที่ต้องการ (เนื่องจากยังไม่สามารถระบุด้วยวิธีอื่นได้อย่างสมบูรณ์ในปัจจุบัน) คุณควรตั้งค่าสถานะนี้หากนิพจน์คำค้นหาซับซ้อนกว่า deps(//foo)

--implicit_deps (บูลีน ค่าเริ่มต้นคือ "จริง")

การตั้งค่า Flag นี้เป็นเท็จจะกรองผลลัพธ์ทั้งหมดที่ไม่ได้ตั้งค่าไว้อย่างชัดเจนในไฟล์ BUILD และ Bazel จะตั้งค่าไว้ที่อื่นแทน ซึ่งรวมถึงการกรองเครื่องมือทางเทคนิคที่แก้ไขแล้ว

--tool_deps (บูลีน ค่าเริ่มต้นคือ "จริง")

การตั้งค่า Flag นี้เป็นเท็จจะกรองเป้าหมายที่กําหนดค่าไว้ทั้งหมดออก ซึ่งเส้นทางจากเป้าหมายที่ค้นหาไปยังเป้าหมายดังกล่าวจะข้ามการเปลี่ยนระหว่างการกําหนดค่าเป้าหมายกับการกําหนดค่าที่ไม่ใช่เป้าหมาย หากเป้าหมายที่ค้นหาอยู่ในการกําหนดค่าเป้าหมาย การตั้งค่า --notool_deps จะแสดงเฉพาะเป้าหมายที่อยู่ในการกําหนดค่าเป้าหมายด้วย หากเป้าหมายที่ค้นหาอยู่ในการกําหนดค่าที่ไม่ใช่เป้าหมาย การตั้งค่า --notool_deps จะแสดงเฉพาะเป้าหมายในการกําหนดค่าที่ไม่ใช่เป้าหมายเท่านั้น โดยทั่วไปการตั้งค่านี้จะไม่ส่งผลต่อตัวกรองของเครื่องมือทางเทคนิคที่แก้ไขแล้ว

--include_aspects (บูลีน ค่าเริ่มต้นคือ "จริง")

Aspects สามารถเพิ่ม ทรัพยากร Dependency เพิ่มเติมไปยังบิลด์ได้ โดยค่าเริ่มต้น cquery จะไม่ติดตามแง่มุมเนื่องจากทำให้กราฟที่ค้นหาได้ใหญ่ขึ้น ซึ่งจะใช้หน่วยความจํามากขึ้น แต่การปฏิบัติตามกฎจะให้ผลลัพธ์ ที่แม่นยำยิ่งขึ้น

หากคุณไม่ต้องกังวลเกี่ยวกับผลกระทบของหน่วยความจำจากการค้นหาขนาดใหญ่ ให้เปิดใช้งานธงนี้โดยค่าเริ่มต้นใน bazelrc

หากคุณค้นหาโดยปิดใช้แอตทริบิวต์ คุณอาจพบปัญหาที่เป้าหมาย X ดำเนินการสร้างเป้าหมาย Y ไม่สำเร็จ แต่ cquery somepath(Y, X) และ cquery deps(Y) | grep 'X' แสดงผลลัพธ์ไม่แสดงผล เนื่องจากความเกี่ยวข้องเกิดขึ้นผ่านแอตทริบิวต์

รูปแบบเอาต์พุต

โดยค่าเริ่มต้น cquery จะแสดงผลลัพธ์เป็นรายการคู่ป้ายกำกับและการกำหนดค่าตามลําดับความเกี่ยวข้อง นอกจากนี้ คุณยังมีตัวเลือกอื่นๆ ในการแสดงผลลัพธ์ด้วย

ทรานซิชัน

--transitions=lite
--transitions=full

การเปลี่ยนการกําหนดค่าจะใช้ในการสร้างเป้าหมายที่อยู่ภายใต้เป้าหมายระดับบนสุดในการกําหนดค่าที่แตกต่างจากเป้าหมายระดับบนสุด

เช่น เป้าหมายอาจบังคับให้เปลี่ยนเป็นการกําหนดค่าโฮสต์สําหรับข้อกําหนดทั้งหมดในแอตทริบิวต์ tools ซึ่งเราเรียกว่าการเปลี่ยนแอตทริบิวต์ กฎยังบังคับใช้การเปลี่ยนรูปแบบในการกำหนดค่าของตนเองได้ด้วย ซึ่งเรียกว่าการเปลี่ยนรูปแบบคลาสของกฎ รูปแบบเอาต์พุตนี้จะแสดงข้อมูลเกี่ยวกับทรานซิชัน เช่น ประเภทของทรานซิชันและผลที่มีต่อตัวเลือกการสร้าง

รูปแบบเอาต์พุตนี้ทริกเกอร์โดย Flag --transitions ซึ่งตั้งค่าเป็น NONE โดยค่าเริ่มต้น โดยตั้งค่าเป็นโหมด FULL หรือ LITE ได้ FULL mode จะแสดงผลข้อมูลเกี่ยวกับการเปลี่ยนคลาสกฎและการเปลี่ยนแอตทริบิวต์ รวมถึงความแตกต่างโดยละเอียดของตัวเลือกก่อนและหลังการเปลี่ยน โหมด LITE จะแสดงข้อมูลเดียวกันโดยไม่มีความแตกต่างของตัวเลือก

เอาต์พุตข้อความโปรโตคอล

--output=proto

ตัวเลือกนี้จะทําให้ระบบพิมพ์เป้าหมายที่ได้ในรูปแบบบัฟเฟอร์โปรโตคอลไบนารี ดูคำจำกัดความของบัฟเฟอร์โปรโตคอลได้ที่ src/main/protobuf/analysis.proto

CqueryResult คือข้อความระดับบนสุดที่มีผลลัพธ์ของ cquery โดยจะมีรายการข้อความ ConfiguredTarget รายการและรายการข้อความ Configuration ConfiguredTarget แต่ละรายการมี configuration_id ที่มีค่าเท่ากับค่าของช่อง id จากข้อความ Configuration ที่เกี่ยวข้อง

--[no]proto:include_configurations

โดยค่าเริ่มต้น ผลลัพธ์ cquery จะแสดงข้อมูลการกําหนดค่าเป็นส่วนหนึ่งของเป้าหมายที่กําหนดค่าไว้แต่ละรายการ หากต้องการละเว้นข้อมูลนี้และรับเอาต์พุต proto ที่รูปแบบเหมือนกับเอาต์พุต proto ของคําค้นหา ให้ตั้งค่า Flag นี้เป็น "เท็จ"

ดูเอกสารประกอบเอาต์พุต Proto ของการค้นหาเพื่อดูตัวเลือกเพิ่มเติมเกี่ยวกับเอาต์พุต Pro

เอาต์พุตกราฟ

--output=graph

ตัวเลือกนี้จะสร้างเอาต์พุตเป็นไฟล์ .dot ที่เข้ากันได้กับ Graphviz ดูรายละเอียดได้ในเอกสารประกอบเกี่ยวกับเอาต์พุตกราฟของ query cquery ยังรองรับ --graph:node_limit และ --graph:factored ด้วย

เอาต์พุตไฟล์

--output=files

ตัวเลือกนี้จะพิมพ์รายการไฟล์เอาต์พุตที่สร้างขึ้นโดยแต่ละเป้าหมายที่ตรงกับข้อความค้นหา ซึ่งคล้ายกับรายการที่พิมพ์ไว้ที่ท้ายการเรียกใช้ bazel build เอาต์พุตจะมีเฉพาะไฟล์ที่โฆษณาในกลุ่มเอาต์พุตที่ขอตามที่ระบุโดย Flag --output_groups แต่จะมีไฟล์ต้นฉบับ

การกําหนดรูปแบบเอาต์พุตโดยใช้ Starlark

--output=starlark

รูปแบบเอาต์พุตนี้จะเรียกใช้ฟังก์ชัน Starlark สําหรับเป้าหมายที่กําหนดค่าไว้แต่ละรายการในผลการค้นหา และพิมพ์ค่าที่การเรียกแสดงผล Flag --starlark:file จะระบุตำแหน่งของไฟล์ Starlark ที่กําหนดฟังก์ชันชื่อ format ที่มีพารามิเตอร์เดียว target ระบบจะเรียกใช้ฟังก์ชันนี้สําหรับ Target แต่ละรายการในผลการค้นหา หรือคุณจะระบุเฉพาะเนื้อหาของฟังก์ชันที่ประกาศเป็น def format(target): return expr โดยใช้ Flag --starlark:expr เพื่อความสะดวกก็ได้

ภาษาถิ่นสตาร์ลาร์ก "cquery"

สภาพแวดล้อม Starlark ของ cquery แตกต่างจากไฟล์ BUILD หรือ .bzl ซึ่งประกอบด้วย ค่าคงที่และฟังก์ชันในตัวของ Starlark หลักทั้งหมด รวมถึงฟังก์ชันเฉพาะสำหรับ cquery 2-3 รายการที่อธิบายไว้ด้านล่าง แต่ไม่รวม glob, native หรือ rule และจะไม่รองรับคำสั่งโหลด

build_options(target)

build_options(target) จะแสดงผลแผนที่ซึ่งมีคีย์เป็นตัวระบุตัวเลือกการสร้าง (ดูการกำหนดค่า) และค่าที่เป็นค่า Starlark ระบบจะไม่รวมตัวเลือกการสร้างที่มีค่าที่ไม่ใช่ค่า Starlark ที่ถูกต้องไว้ในแผนที่นี้

หากเป้าหมายเป็นไฟล์อินพุต build_options(target) จะแสดงผลเป็น None เนื่องจากเป้าหมายไฟล์อินพุตมีการกําหนดค่าเป็น Null

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()]"

พิมพ์ค่าของตัวเลือกบรรทัดคำสั่ง --javacopt เมื่อสร้าง //foo

  bazel cquery //foo --output=starlark \
    --starlark:expr="build_options(target)['//command_line_option:javacopt']"

พิมพ์ป้ายกำกับของแต่ละเป้าหมายด้วยเอาต์พุตเพียง 1 รายการ ตัวอย่างนี้ใช้ฟังก์ชัน 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 ตาม Branch ของ select() เพื่อสร้างโมเดลกราฟเดียวกับที่คุณสร้าง query ไม่ทราบว่าบิลด์เลือกสาขาใด จึงประมาณมากเกินไปโดยรวมทุกสาขา
  • ความแม่นยำของ cquery ทำให้ต้องสร้างกราฟมากกว่าที่ query ทำได้ กล่าวโดยละเอียดคือ cquery จะประเมินเป้าหมายที่กำหนดค่า ในขณะที่ query จะประเมินเฉพาะเป้าหมาย ซึ่งจะใช้เวลานานกว่าและใช้หน่วยความจำมากขึ้น
  • การตีความภาษาคําค้นหาของ cquery มีความกำกวมซึ่ง query หลีกเลี่ยง เช่น หาก "//foo" มีอยู่ในการกําหนดค่า 2 รายการ 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=&lt;whatever&gt; ลงในคำสั่งบิลด์

การแก้ปัญหา

รูปแบบเป้าหมายแบบเรียกซ้ำ (/...)

หากคุณพบสิ่งต่อไปนี้

$ 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/... ไม่สามารถสร้างขึ้นด้วย Flag การสร้างที่เลือก) ให้เลิกแพ็กเกจรูปแบบเป็นแพ็กเกจย่อยด้วยตนเองโดยใช้การค้นหาการประมวลผลก่อนดังนี้

# 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 "+" -))"