คำสั่ง aquery
ช่วยให้คุณค้นหาการดำเนินการในกราฟบิลด์ได้
โดยจะดำเนินการกับกราฟเป้าหมายที่กำหนดค่าไว้หลังการวิเคราะห์ และแสดงข้อมูลเกี่ยวกับการกระทำ อาร์ติแฟกต์ และความสัมพันธ์
aquery
มีประโยชน์เมื่อสนใจพร็อพเพอร์ตี้ของการดำเนินการ/อาร์ติแฟกต์ที่สร้างขึ้นจากกราฟเป้าหมายที่กําหนดค่าไว้ เช่น การทำงานของคำสั่งจริง
รวมถึงอินพุต/เอาต์พุต/การจำ
เครื่องมือยอมรับตัวเลือกบรรทัดคำสั่งหลายรายการ สิ่งที่ควรทราบคือคำสั่ง aquery จะทำงานที่ด้านบนของบิลด์ Bazel ปกติและรับค่าชุดตัวเลือกที่มีให้ระหว่างบิลด์
โดยรองรับฟังก์ชันชุดเดียวกันกับที่มีให้ใน query
ดั้งเดิม แต่รองรับ siblings
, buildfiles
และ tests
ตัวอย่างเอาต์พุต aquery
(ไม่มีรายละเอียดเฉพาะ)
$ bazel aquery 'deps(//some:label)' action 'Writing file some_file_name' Mnemonic: ... Target: ... Configuration: ... ActionKey: ... Inputs: [...] Outputs: [...]
ไวยากรณ์พื้นฐาน
ตัวอย่างทั่วไปของไวยากรณ์ aquery
มีดังนี้
bazel aquery "aquery_function(function(//target))"
นิพจน์ข้อความค้นหา (ในเครื่องหมายคำพูด) ประกอบด้วยข้อมูลต่อไปนี้
aquery_function(...)
: ฟังก์ชันเฉพาะสำหรับaquery
ดูรายละเอียดเพิ่มเติมด้านล่างfunction(...)
: ทำงานมาตรฐาน เช่นเดียวกับquery
ดั้งเดิม//target
คือป้ายกำกับสำหรับเป้าหมายที่สนใจ
# aquery examples: # Get the action graph generated while building //src/target_a $ bazel aquery '//src/target_a' # Get the action graph generated while building all dependencies of //src/target_a $ bazel aquery 'deps(//src/target_a)' # Get the action graph generated while building all dependencies of //src/target_a # whose inputs filenames match the regex ".*cpp". $ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'
การใช้ฟังก์ชันข้อความค้นหา
มีฟังก์ชัน aquery
3 รายการดังนี้
inputs
: กรองการดำเนินการตามอินพุตoutputs
: กรองการดำเนินการตามเอาต์พุตmnemonic
: กรองการทำงานตามการจำ
expr ::= inputs(word, expr)
โอเปอเรเตอร์ inputs
จะแสดงผลการดำเนินการที่สร้างจากอาคาร expr
ซึ่งมีชื่อไฟล์อินพุตตรงกับนิพจน์ทั่วไปที่ word
ระบุไว้
$ bazel aquery 'inputs(".*cpp", deps(//src/target_a))'
ฟังก์ชัน outputs
และ mnemonic
ใช้ไวยากรณ์ที่คล้ายกัน
นอกจากนี้ คุณยังสามารถรวมฟังก์ชันต่างๆ เข้าด้วยกันเพื่อให้ดำเนินการ "และ" ได้ เช่น
$ bazel aquery 'mnemonic("Cpp.*", (inputs(".*cpp", inputs("foo.*", //src/target_a))))'
คำสั่งด้านบนจะค้นหาการดำเนินการทั้งหมดที่เกี่ยวข้องในการสร้าง //src/target_a
ซึ่งความทรงจำตรงกับ "Cpp.*"
และอินพุตตรงกับรูปแบบ ".*cpp"
และ "foo.*"
ตัวอย่างข้อผิดพลาดทางไวยากรณ์
$ bazel aquery 'deps(inputs(".*cpp", //src/target_a))' ERROR: aquery filter functions (inputs, outputs, mnemonic) produce actions, and therefore can't be the input of other function types: deps deps(inputs(".*cpp", //src/target_a))
ตัวเลือก
ตัวเลือกบิลด์
aquery
ทำงานที่ด้านบนของบิลด์ Bazel ปกติ จึงรับชุดตัวเลือกที่พร้อมใช้งานระหว่างบิลด์
ตัวเลือกคำค้นหา
--output=(text|summary|proto|jsonproto|textproto), default=text
รูปแบบเอาต์พุตเริ่มต้น (text
) ที่มนุษย์อ่านได้ ให้ใช้ proto
, textproto
หรือ jsonproto
สำหรับรูปแบบที่เครื่องอ่านได้
ข้อความ Proto คือ analysis.ActionGraphContainer
--include_commandline, default=true
มีเนื้อหาของบรรทัดคำสั่งสำหรับการดำเนินการในเอาต์พุต (อาจมีขนาดใหญ่)
--include_artifacts, default=true
รวมชื่อของอินพุตและเอาต์พุตการดำเนินการในเอาต์พุต (ซึ่งอาจมีขนาดใหญ่)
--include_aspects, default=true
ระบุว่าจะรวมการดำเนินการที่ Aspect สร้างขึ้นไว้ในเอาต์พุตไหม
--include_param_files, default=false
รวมเนื้อหาของไฟล์พารามิเตอร์ที่ใช้ในคำสั่ง (อาจมีขนาดใหญ่)
--include_file_write_contents, default=false
รวมเนื้อหาไฟล์สำหรับการดำเนินการ actions.write()
และเนื้อหาของไฟล์ Manifest สำหรับการดำเนินการ SourceSymlinkManifest
ระบบจะแสดงเนื้อหาของไฟล์ในช่อง file_contents
ด้วย --output=
xxxproto
เมื่อใช้ --output=text
เอาต์พุตจะมี
FileWriteContents: [<base64-encoded file contents>]
บรรทัด
--skyframe_state, default=false
ดัมพ์ Action Graph จาก Skyframe โดยไม่ต้องทำการวิเคราะห์เพิ่มเติม
เครื่องมือและฟีเจอร์อื่นๆ
การค้นหาเกี่ยวกับสถานะของ Skyframe
Skyframe คือโมเดลการประเมินและ การเพิ่มขึ้นของ Bazel Skyframe ในแต่ละอินสแตนซ์ของเซิร์ฟเวอร์ Bazel จะจัดเก็บกราฟทรัพยากร Dependency ที่สร้างขึ้นจากการเรียกใช้ก่อนหน้าของระยะการวิเคราะห์
ในบางกรณี การค้นหากราฟการดำเนินการใน Skyframe นั้นมีประโยชน์ ตัวอย่างกรณีการใช้งานมีดังนี้
- เรียกใช้
bazel build //target_a
- เรียกใช้
bazel build //target_b
- สร้างไฟล์
foo.out
แล้ว
ในฐานะผู้ใช้ Bazel ฉันต้องการทราบว่า foo.out
สร้างขึ้นจากอาคาร //target_a
หรือ //target_b
หรือไม่
คีย์ตัวหนึ่งอาจเรียกใช้ bazel aquery 'outputs("foo.out", //target_a)'
และ bazel aquery 'outputs("foo.out", //target_b)'
เพื่อคำนวณหาการดำเนินการที่มีความรับผิดชอบในการสร้าง foo.out
และกำหนดกลุ่มเป้าหมาย อย่างไรก็ตาม จำนวนเป้าหมายต่างๆ ที่เคยสร้างไว้ก่อนหน้านี้อาจมีมากกว่า 2 รายการ ซึ่งทำให้การเรียกใช้คำสั่ง aquery
หลายรายการเป็นเรื่องยุ่งยาก
โดยคุณจะใช้แฟล็ก --skyframe_state
แทนได้ ดังนี้
# List all actions on Skyframe's action graph $ bazel aquery --output=proto --skyframe_state # or # List all actions on Skyframe's action graph, whose output matches "foo.out" $ bazel aquery --output=proto --skyframe_state 'outputs("foo.out")'
เมื่อใช้โหมด --skyframe_state
aquery
จะนำเนื้อหาของกราฟการดำเนินการที่ Skyframe เก็บไว้ในอินสแตนซ์ของ Bazel (ไม่บังคับ) ทำการกรองและเอาต์พุตเนื้อหาโดยไม่ต้องเรียกใช้ขั้นตอนการวิเคราะห์อีกครั้ง
สิ่งที่ควรพิจารณาเป็นพิเศษ
รูปแบบเอาต์พุต
ขณะนี้ --skyframe_state
ใช้ได้กับ --output=proto
และ --output=textproto
เท่านั้น
การไม่รวมป้ายกำกับเป้าหมายในนิพจน์การค้นหา
ปัจจุบัน --skyframe_state
จะค้นหากราฟการดำเนินการทั้งหมดที่มีอยู่ใน Skyframe ไม่ว่าเป้าหมายจะเป็นใดก็ตาม การมีป้ายกำกับเป้าหมายที่ระบุในการค้นหาพร้อมกับ --skyframe_state
ถือว่าเป็นข้อผิดพลาดทางไวยากรณ์
# WRONG: Target Included $ bazel aquery --output=proto --skyframe_state **//target_a** ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported. # WRONG: Target Included $ bazel aquery --output=proto --skyframe_state 'inputs(".*.java", **//target_a**)' ERROR: Error while parsing '//target_a)': Specifying build target(s) [//target_a] with --skyframe_state is currently not supported. # CORRECT: Without Target $ bazel aquery --output=proto --skyframe_state $ bazel aquery --output=proto --skyframe_state 'inputs(".*.java")'
การเปรียบเทียบเอาต์พุตคำค้นหา
คุณสามารถเปรียบเทียบเอาต์พุตของการเรียกใช้คำค้นหา 2 รายการที่แตกต่างกันได้โดยใช้เครื่องมือ aquery_differ
ตัวอย่างเช่น เมื่อคุณทำการเปลี่ยนแปลงบางอย่างกับคำจำกัดความของกฎและต้องการยืนยันว่าบรรทัดคำสั่งที่เรียกใช้ไม่มีการเปลี่ยนแปลง aquery_differ
เป็นเครื่องมือให้
เครื่องมือมีอยู่ในที่เก็บ bazelbuild/bazel หากต้องการใช้งาน ให้โคลนที่เก็บไปยังเครื่องภายในของคุณ ตัวอย่างการใช้
$ bazel run //tools/aquery_differ -- \ --before=/path/to/before.proto \ --after=/path/to/after.proto \ --input_type=proto \ --attrs=cmdline \ --attrs=inputs
คำสั่งข้างต้นแสดงผลความแตกต่างระหว่างเอาต์พุต aquery before
กับ after
: การดำเนินการใดมีในผลลัพธ์หนึ่ง แต่ไม่ใช่อีกรายการหนึ่ง การดำเนินการใดมีบรรทัดคำสั่ง/อินพุตต่างกันในเอาต์พุต aquery แต่ละรายการ, ...) ผลลัพธ์ของการเรียกใช้คำสั่งข้างต้นมีดังนี้
Aquery output 'after' change contains an action that generates the following outputs that aquery output 'before' change doesn't: ... /list of output files/ ... [cmdline] Difference in the action that generates the following output(s): /path/to/abc.out --- /path/to/before.proto +++ /path/to/after.proto @@ -1,3 +1,3 @@ ... /cmdline diff, in unified diff format/ ...
ตัวเลือกคำสั่ง
--before, --after
: ไฟล์เอาต์พุต aquery ที่จะเปรียบเทียบ
--input_type=(proto|text_proto), default=proto
: รูปแบบของไฟล์อินพุต การสนับสนุนสำหรับเอาต์พุตคำค้นหา proto
และ textproto
--attrs=(cmdline|inputs), default=cmdline
: แอตทริบิวต์ของการทำงาน
ที่จะเปรียบเทียบ
อัตราส่วนภาพ
คุณอาจนำ Aspects มาใช้ควบคู่กันได้ จากนั้น เอาต์พุตคำค้นหาของการดำเนินการที่สร้างโดย Aspect เหล่านี้จะรวม Aspect path ซึ่งเป็นลำดับของ Aspect ที่ใช้กับเป้าหมายที่สร้างการดำเนินการ
ตัวอย่างของ Aspect-on-Aspect
t0 ^ | <- a1 t1 ^ | <- a2 t2
ให้ i เป็นเป้าหมายของกฎ i ซึ่งจะนำ Aspect ai ไปใช้กับทรัพยากร Dependency ของกฎ
สมมติว่า a2 สร้างการกระทํา X เมื่อใช้กับ t0 เป้าหมาย เอาต์พุตข้อความของ bazel aquery --include_aspects 'deps(//t2)'
สำหรับการดำเนินการ X จะมีลักษณะดังนี้
action ... Mnemonic: ... Target: //my_pkg:t0 Configuration: ... AspectDescriptors: [//my_pkg:rule.bzl%**a2**(foo=...) -> //my_pkg:rule.bzl%**a1**(bar=...)] ...
ซึ่งหมายความว่าการดำเนินการ X
สร้างขึ้นโดย Aspect a2
ซึ่งใช้ใน a1(t0)
โดยที่ a1(t0)
เป็นผลลัพธ์ของ Aspect a1
ที่ใช้กับเป้าหมาย t0
AspectDescriptor
แต่ละรายการจะมีรูปแบบต่อไปนี้
AspectClass([param=value,...])
AspectClass
อาจเป็นชื่อของคลาส Aspect (สำหรับ Aspect ดั้งเดิม) หรือ bzl_file%aspect_name
(สำหรับ Starlark Aspects) AspectDescriptor
จัดเรียงตามลำดับโทโพโลยีของกราฟการขึ้นต่อกัน
การลิงก์กับโปรไฟล์ JSON
ขณะที่คำค้นหาจะให้ข้อมูลเกี่ยวกับการดำเนินการที่เรียกใช้ในบิลด์ (สาเหตุที่เรียกใช้ อินพุต/เอาต์พุต) โปรไฟล์ JSON จะบอกเวลาและระยะเวลาในการดำเนินการให้เราทราบ คุณเลือกที่จะรวมชุดข้อมูล 2 ชุดนี้ผ่านตัวส่วนร่วมได้ ซึ่งก็คือผลลัพธ์หลักของการดำเนินการ
หากต้องการรวมเอาต์พุตของการดำเนินการไว้ในโปรไฟล์ JSON ให้สร้างโปรไฟล์ด้วย --experimental_include_primary_output --noexperimental_slim_json_profile
โปรไฟล์แบบสลิมไม่สามารถใช้กับการรวมเอาต์พุตหลัก เอาต์พุตหลักของการดำเนินการจะรวมอยู่โดยค่าเริ่มต้นโดยค่าเริ่มต้น
ขณะนี้เราไม่มีเครื่องมือ Canonical ที่จะรวมแหล่งข้อมูล 2 แหล่งนี้ แต่คุณควรสร้างสคริปต์ของคุณเองด้วยข้อมูลข้างต้นได้
ปัญหาที่ทราบแล้ว
การจัดการการดำเนินการที่แชร์
ในบางครั้ง การทำงานจะแชร์ระหว่างเป้าหมายที่กำหนดค่าแล้ว
ในระยะการดำเนินการ การดำเนินการที่แชร์เหล่านั้นจะถือว่าเป็นการดำเนินการเดียวและเกิดขึ้นเพียงครั้งเดียว
อย่างไรก็ตาม aquery จะทำงานในกราฟการทำงานก่อนการดำเนินการและหลังการวิเคราะห์ ดังนั้นจึงถือว่าการดำเนินการเหล่านี้เป็นการดำเนินการแยกต่างหากที่อาร์ติแฟกต์เอาต์พุตมี execPath
เหมือนกัน ด้วยเหตุนี้ อาร์ติแฟกต์ที่เทียบเท่ากันจึงดูเหมือนซ้ำกัน
คุณดูรายการปัญหาเกี่ยวกับคำค้นหา/ฟีเจอร์ที่วางแผนไว้ได้ใน GitHub
คำถามที่พบบ่อย
ActionKey ยังคงเหมือนเดิม แม้ว่าเนื้อหาของไฟล์อินพุตจะเปลี่ยนไปก็ตาม
ในบริบทของคำค้นหา ActionKey
จะอ้างถึง String
ที่ได้รับจาก ActionAnalysisMetadata#getKey:
Returns a string encoding all of the significant behaviour of this Action that might affect the output. The general contract of `getKey` is this: if the work to be performed by the execution of this action changes, the key must change. ... Examples of changes that should affect the key are: - Changes to the BUILD file that materially affect the rule which gave rise to this Action. - Changes to the command-line options, environment, or other global configuration resources which affect the behaviour of this kind of Action (other than changes to the names of the input/output files, which are handled externally). - An upgrade to the build tools which changes the program logic of this kind of Action (typically this is achieved by incorporating a UUID into the key, which is changed each time the program logic of this action changes). Note the following exception: for actions that discover inputs, the key must change if any input names change or else action validation may falsely validate.
ซึ่งจะยกเว้นการเปลี่ยนแปลงเนื้อหาของไฟล์อินพุต และไม่ต้องสับสนกับ RemoteCacheClient#ActionKey
การอัปเดต
สำหรับปัญหา/คำขอฟีเจอร์ โปรดส่งปัญหาที่นี่