สร้างโปรแกรมด้วย Bazel

รายงานปัญหา ดูแหล่งที่มา

หน้านี้จะกล่าวถึงวิธีสร้างโปรแกรมด้วย Bazel, ชุดคำสั่งตามรูปแบบไวยากรณ์ของคำสั่ง และไวยากรณ์ของรูปแบบเป้าหมาย

คู่มือเริ่มใช้งานฉบับย่อ

หากต้องการเรียกใช้ Bazel ให้ไปที่ไดเรกทอรีพื้นที่ทำงานฐานหรือไดเรกทอรีย่อยใดก็ได้ของไดเรกทอรี และพิมพ์ bazel โปรดดูสร้าง หากคุณต้องการสร้างพื้นที่ทำงานใหม่

bazel help
                             [Bazel release bazel version]
Usage: bazel command options ...

คำสั่งที่ใช้ได้

  • analyze-profile: วิเคราะห์ข้อมูลโปรไฟล์บิลด์
  • aquery: ดำเนินการค้นหาในกราฟการดำเนินการหลังการวิเคราะห์
  • build: สร้างเป้าหมายที่ระบุ
  • canonicalize-flags: หน้า Canonical สำหรับ Flag Bazel
  • clean: นําไฟล์เอาต์พุตออกและเลือกหยุดเซิร์ฟเวอร์
  • cquery: ดำเนินการค้นหากราฟทรัพยากร Dependency หลังการวิเคราะห์
  • dump: ถ่ายโอนสถานะภายในของกระบวนการของเซิร์ฟเวอร์ Bazel
  • help: พิมพ์ความช่วยเหลือสำหรับคำสั่งหรือดัชนี
  • info: แสดงข้อมูลรันไทม์เกี่ยวกับเซิร์ฟเวอร์เบเซล
  • fetch: ดึงข้อมูลทรัพยากร Dependency ภายนอกทั้งหมดของเป้าหมาย
  • mobile-install: ติดตั้งแอปในอุปกรณ์เคลื่อนที่
  • query: ดำเนินการค้นหากราฟทรัพยากร Dependency
  • run: เรียกใช้เป้าหมายที่ระบุ
  • shutdown: หยุดเซิร์ฟเวอร์ Bazel
  • test: สร้างและเรียกใช้เป้าหมายการทดสอบที่ระบุ
  • version: พิมพ์ข้อมูลเวอร์ชันสำหรับ Bazel

การขอความช่วยเหลือ

  • bazel help command: ความช่วยเหลือและตัวเลือกสำหรับ command ในการพิมพ์
  • bazel helpstartup_options: ตัวเลือกสำหรับ JVM โฮสติ้ง Bazel
  • bazel helptarget-syntax: อธิบายไวยากรณ์สำหรับการระบุเป้าหมาย
  • bazel help info-keys: แสดงรายการคีย์ที่ใช้โดยคำสั่ง info

เครื่องมือ bazel ทำงานได้หลายอย่างที่เรียกว่าคำสั่ง ส่วนขยายที่ใช้บ่อยที่สุดคือ bazel build และ bazel test คุณสามารถเรียกดูข้อความช่วยเหลือออนไลน์ โดยใช้ bazel help

การสร้างเป้าหมาย 1 รายการ

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

หากต้องการสร้างโปรแกรมด้วย Bazel ให้พิมพ์ bazel build ตามด้วยเป้าหมายที่ต้องการสร้าง

bazel build //foo

หลังจากออกคำสั่งเพื่อสร้าง //foo คุณจะเห็นเอาต์พุตในลักษณะนี้

INFO: Analyzed target //foo:foo (14 packages loaded, 48 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
  bazel-bin/foo/foo
INFO: Elapsed time: 9.905s, Critical Path: 3.25s
INFO: Build completed successfully, 6 total actions

ขั้นแรก Bazel จะโหลดแพ็กเกจทั้งหมดในกราฟทรัพยากร Dependency ของเป้าหมาย ซึ่งรวมถึงทรัพยากร Dependency ที่ประกาศ ไฟล์ที่แสดงในไฟล์ BUILD ของเป้าหมายโดยตรง และทรัพยากร Dependency แบบสกรรม ไฟล์ที่แสดงอยู่ในไฟล์ BUILD ของทรัพยากร Dependency ของเป้าหมาย หลังจากระบุทรัพยากร Dependency ทั้งหมดแล้ว Bazel จะวิเคราะห์ความถูกต้องและสร้างการทำงานของบิลด์ สุดท้าย Bazel เรียกใช้คอมไพเลอร์และเครื่องมืออื่นๆ ของบิลด์

ระหว่างขั้นตอนการดำเนินการของบิลด์ Bazel จะพิมพ์ข้อความความคืบหน้า ข้อความความคืบหน้าจะแสดงขั้นตอนของบิลด์ปัจจุบัน (เช่น คอมไพเลอร์หรือ Linker) เมื่อเริ่มต้น และจำนวนที่เสร็จสมบูรณ์จากจำนวนการดำเนินการทั้งหมดของบิลด์ เมื่อการสร้างเริ่มทำงาน จำนวนการดำเนินการทั้งหมดมักจะเพิ่มขึ้นเมื่อ Bazel ค้นพบกราฟการดำเนินการทั้งหมด แต่ตัวเลขจะคงที่ภายใน 2-3 วินาที

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

หากคุณพิมพ์คำสั่งเดิมอีกครั้ง บิลด์จะเสร็จสิ้นเร็วขึ้นมาก

bazel build //foo
INFO: Analyzed target //foo:foo (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
  bazel-bin/foo/foo
INFO: Elapsed time: 0.144s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action

นี่คือnull build เนื่องจากไม่มีอะไรเปลี่ยนแปลง จึงไม่มีแพ็กเกจให้โหลดซ้ำ และไม่มีขั้นตอนของบิลด์ให้ดำเนินการ หากมีการเปลี่ยนแปลงบางอย่างใน "foo" หรือการอ้างอิง Bazel จะดำเนินการสร้างบางอย่างอีกครั้ง หรือสร้างบิลด์ที่เพิ่มขึ้น

การสร้างเป้าหมายหลายเป้าหมาย

Bazel สามารถระบุเป้าหมายที่จะสร้างได้หลายวิธี โดยรวมแล้วเหล่านี้เรียกว่ารูปแบบเป้าหมาย ไวยากรณ์นี้จะใช้ในคำสั่งอย่างเช่น build, test หรือ query

ขณะที่ป้ายกำกับใช้เพื่อระบุเป้าหมายแต่ละรายการ เช่น สำหรับการประกาศทรัพยากร Dependency ในไฟล์ BUILD แต่รูปแบบเป้าหมายของ Bazel จะระบุเป้าหมายหลายรายการ รูปแบบเป้าหมายเป็นการสรุปไวยากรณ์ป้ายกำกับสำหรับชุดของเป้าหมายโดยใช้ไวลด์การ์ด ในกรณีที่เรียบง่ายที่สุด ป้ายกำกับที่ถูกต้องคือรูปแบบเป้าหมายที่ถูกต้องด้วย ซึ่งระบุชุดของเป้าหมาย 1 อย่างเท่านั้น

รูปแบบเป้าหมายทั้งหมดที่เริ่มต้นด้วย // จะได้รับการแก้ไขโดยสัมพันธ์กับพื้นที่ทำงานปัจจุบัน

//foo/bar:wiz เฉพาะเป้าหมายเดียว //foo/bar:wiz
//foo/bar เทียบเท่ากับ //foo/bar:bar
//foo/bar:all เป้าหมายกฎทั้งหมดในแพ็กเกจ foo/bar
//foo/... เป้าหมายกฎทั้งหมดในทุกแพ็กเกจภายใต้ไดเรกทอรี foo
//foo/...:all เป้าหมายกฎทั้งหมดในทุกแพ็กเกจภายใต้ไดเรกทอรี foo
//foo/...:* เป้าหมายทั้งหมด (กฎและไฟล์) ในแพ็กเกจทั้งหมดภายใต้ไดเรกทอรี foo
//foo/...:all-targets เป้าหมายทั้งหมด (กฎและไฟล์) ในแพ็กเกจทั้งหมดภายใต้ไดเรกทอรี foo
//... กฎทั้งหมดกำหนดเป้าหมายในแพ็กเกจในที่เก็บหลัก ไม่รวมเป้าหมายจากที่เก็บภายนอก
//:all กฎจะกำหนดเป้าหมายทั้งหมดในแพ็กเกจระดับบนสุด หากมีไฟล์ "BUILD" ที่รูทของพื้นที่ทำงาน

รูปแบบเป้าหมายที่ไม่ได้ขึ้นต้นด้วย // จะได้รับการแก้ไขโดยสัมพันธ์กับไดเรกทอรีที่ใช้งานอยู่ปัจจุบัน ตัวอย่างเหล่านี้สมมติว่าเป็นไดเรกทอรีที่ใช้งานได้ของ foo:

:foo เทียบเท่ากับ //foo:foo
bar:wiz เทียบเท่ากับ //foo/bar:wiz
bar/wiz เทียบเท่ากับสิ่งต่อไปนี้
  • //foo/bar/wiz:wiz หาก foo/bar/wiz เป็นแพ็กเกจ
  • //foo/bar:wiz หาก foo/bar เป็นแพ็กเกจ
  • //foo:bar/wiz เมื่อสั่งซื้อนอกเหนือจากมูลค่าที่กำหนด
bar:all เทียบเท่ากับ //foo/bar:all
:all เทียบเท่ากับ //foo:all
...:all เทียบเท่ากับ //foo/...:all
... เทียบเท่ากับ //foo/...:all
bar/...:all เทียบเท่ากับ //foo/bar/...:all

โดยค่าเริ่มต้น ระบบจะติดตามลิงก์สัญลักษณ์ของไดเรกทอรีสำหรับรูปแบบเป้าหมายที่เกิดซ้ำ ยกเว้นที่ชี้ไปยังใต้ฐานเอาต์พุต เช่น ลิงก์สัญลักษณ์อำนวยความสะดวกที่สร้างขึ้นในไดเรกทอรีรากของพื้นที่ทำงาน

นอกจากนี้ Bazel จะไม่ทำตามลิงก์สัญลักษณ์เมื่อประเมินรูปแบบเป้าหมายที่เกิดซ้ำในไดเรกทอรีที่มีไฟล์ชื่อดังนี้ DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN

foo/... คือไวลด์การ์ดเหนือแพ็กเกจ ซึ่งระบุแพ็กเกจทั้งหมดซ้ำใต้ไดเรกทอรี foo (สําหรับรูททั้งหมดของเส้นทางแพ็กเกจ) :all เป็นไวลด์การ์ดที่มากกว่าเป้าหมายซึ่งจับคู่กฎทั้งหมดภายในแพ็กเกจ 2 รายการนี้รวมกันได้เหมือนใน foo/...:all และเมื่อมีการใช้ไวลด์การ์ดทั้ง 2 แบบ ตัวย่อนี้จะย่อเป็น foo/...

นอกจากนี้ :* (หรือ :all-targets) เป็นไวลด์การ์ดที่ตรงกับทุกเป้าหมายในแพ็กเกจที่ตรงกัน รวมถึงไฟล์ที่ปกติแล้วไม่ได้สร้างขึ้นด้วยกฎใดๆ เช่น ไฟล์ _deploy.jar ที่เชื่อมโยงกับกฎ java_binary

ซึ่งหมายความว่า :* หมายถึงชุดย่อยของ :all ในขณะที่อาจสับสนได้ แต่ไวยากรณ์นี้อนุญาตให้ใช้ไวลด์การ์ด :all ที่คุ้นเคยกับบิลด์ทั่วไปซึ่งไม่ต้องการการสร้างเป้าหมายอย่างเช่น _deploy.jar

นอกจากนี้ Bazel ยังอนุญาตให้ใช้เครื่องหมายทับแทนเครื่องหมายทวิภาคที่ไวยากรณ์ป้ายกำกับกำหนด ซึ่งมักจะสะดวกเมื่อใช้การขยายชื่อไฟล์ Bash เช่น foo/bar/wiz เทียบเท่ากับ //foo/bar:wiz (หากมีแพ็กเกจ foo/bar) หรือ //foo:bar/wiz (หากมีแพ็กเกจ foo)

คำสั่ง Bazel จำนวนมากยอมรับรายการรูปแบบเป้าหมายเป็นอาร์กิวเมนต์ และทั้งหมดยึดตามโอเปอเรเตอร์นิเสธคำนำหน้า - ซึ่งสามารถใช้เพื่อลบชุดเป้าหมายออกจากชุดที่ระบุโดยอาร์กิวเมนต์ก่อนหน้า โปรดทราบว่าลำดับเป็นเรื่องสำคัญ ตัวอย่างเช่น

bazel build foo/... bar/...

หมายถึง "สร้างเป้าหมายทั้งหมดที่ต่ำกว่า foo และเป้าหมายทั้งหมดที่อยู่ภายใต้ bar" ในขณะที่

bazel build -- foo/... -foo/bar/...

หมายถึง "สร้างเป้าหมายทั้งหมดที่อยู่ใต้ foo ยกเว้นที่อยู่ด้านล่าง foo/bar" (จำเป็นต้องใช้อาร์กิวเมนต์ -- เพื่อป้องกันไม่ให้อาร์กิวเมนต์ต่อมาที่ขึ้นต้นด้วย - ได้รับการตีความเป็นตัวเลือกเพิ่มเติม)

แต่สิ่งสำคัญที่ควรทราบคือ การลบเป้าหมายด้วยวิธีนี้ไม่ได้รับประกันว่าจะไม่มีการสร้างเป้าหมาย เพราะอาจเป็นทรัพยากร Dependency ของเป้าหมายที่ไม่ได้ถูกหักออก เช่น หากมีเป้าหมาย //foo:all-apis ที่รายการอื่นๆ อาศัย //foo/bar:api ระบบจะสร้างเป้าหมายหลังเป็นส่วนหนึ่งของการสร้าง

เป้าหมายที่มี tags = ["manual"] จะไม่รวมอยู่ในรูปแบบเป้าหมายไวลด์การ์ด (..., :*, :all ฯลฯ) เมื่อระบุไว้ในคำสั่งอย่างเช่น bazel build และ bazel test (แต่จะรวมอยู่ในรูปแบบเป้าหมายไวลด์การ์ดเชิงลบ กล่าวคือจะถูกหักออก) คุณควรระบุเป้าหมายทดสอบดังกล่าวด้วยรูปแบบเป้าหมายที่ชัดเจนในบรรทัดคำสั่งหากต้องการให้ Bazel สร้าง/ทดสอบเป้าหมายดังกล่าว ในทางตรงกันข้าม bazel query จะไม่ทำการกรองใดๆ โดยอัตโนมัติ (ซึ่งจะทำให้วัตถุประสงค์ของ bazel query)

กำลังดึงข้อมูลทรัพยากร Dependency ภายนอก

โดยค่าเริ่มต้น Bazel จะดาวน์โหลดและเชื่อมโยงทรัพยากร Dependency ภายนอกระหว่างการสร้าง แต่วิธีนี้อาจไม่เป็นที่ต้องการ เพราะคุณต้องการทราบเมื่อมีการเพิ่มทรัพยากร Dependency ใหม่ หรือเพราะคุณต้องการ "ดึงข้อมูลทรัพยากร Dependency "ล่วงหน้า" (เช่น ก่อนเที่ยวบินที่คุณจะออฟไลน์) หากต้องการป้องกันไม่ให้มีการเพิ่มทรัพยากร Dependency ใหม่ระหว่างบิลด์ คุณระบุแฟล็ก --fetch=false ได้ โปรดทราบว่าแฟล็กนี้มีผลเฉพาะกับกฎที่เก็บที่ไม่ได้ชี้ไปยังไดเรกทอรีในระบบไฟล์ในเครื่องเท่านั้น เช่น การเปลี่ยนแปลงใน local_repository, new_local_repository และกฎที่เก็บ Android SDK และ NDK จะมีผลเสมอโดยไม่คำนึงถึงค่า --fetch

หากคุณไม่อนุญาตให้ดึงข้อมูลระหว่างบิลด์และ Bazel พบทรัพยากร Dependency ใหม่ภายนอก บิลด์ของคุณจะล้มเหลว

คุณดึงข้อมูลทรัพยากร Dependency ด้วยตนเองได้โดยเรียกใช้ bazel fetch หากไม่อนุญาตระหว่างการดึงข้อมูลบิลด์ คุณจะต้องเรียกใช้ bazel fetch ดังนี้

  • ก่อนที่คุณจะสร้างเป็นครั้งแรก
  • หลังจากเพิ่มทรัพยากร Dependency ภายนอกใหม่แล้ว

เมื่อเรียกใช้แล้ว คุณไม่ควรต้องเรียกใช้อีกครั้งจนกว่าไฟล์ WORKSPACE จะมีการเปลี่ยนแปลง

fetch ใช้รายการเป้าหมายเพื่อดึงข้อมูลทรัพยากร Dependency ตัวอย่างเช่น การดำเนินการนี้จะดึงข้อมูลทรัพยากร Dependency ที่จำเป็นในการสร้าง //foo:bar และ //bar:baz

bazel fetch //foo:bar //bar:baz

หากต้องการดึงทรัพยากร Dependency ภายนอกทั้งหมดสำหรับพื้นที่ทำงาน ให้เรียกใช้คำสั่งต่อไปนี้

bazel fetch //...

หากใช้ Bazel 7 ขึ้นไป หากคุณเปิดใช้ Bzlmod คุณจะดึงข้อมูลทรัพยากร Dependency ภายนอกทั้งหมดได้โดยเรียกใช้

bazel fetch

คุณไม่จำเป็นต้องเรียกใช้การดึงข้อมูลแบบ Bazel เลยหากมีเครื่องมือทั้งหมดที่ใช้อยู่ (ตั้งแต่ Jars ในไลบรารีไปจนถึง JDK เอง) ภายใต้รูทของ Workspace แต่หากคุณกำลังใช้รายการนอกไดเรกทอรีพื้นที่ทำงาน Bazel จะเรียกใช้ bazel fetch โดยอัตโนมัติก่อนที่จะเรียกใช้ bazel build

แคชที่เก็บ

Bazel พยายามหลีกเลี่ยงการดึงข้อมูลไฟล์เดียวกันหลายครั้ง แม้ว่าจะจำเป็นต้องใช้ไฟล์เดียวกันในพื้นที่ทำงานอื่น หรือหากคำจำกัดความของที่เก็บภายนอกมีการเปลี่ยนแปลง แต่ยังคงต้องดาวน์โหลดไฟล์เดียวกัน วิธีการคือ Bazel จะแคชไฟล์ทั้งหมดที่คุณดาวน์โหลดในแคชที่เก็บ ซึ่งโดยค่าเริ่มต้นแล้วจะอยู่ที่ ~/.cache/bazel/_bazel_$USER/cache/repos/v1/ ตำแหน่งเปลี่ยนแปลงได้ด้วยตัวเลือก --repository_cache โดยจะมีการแชร์แคชระหว่างพื้นที่ทำงานทั้งหมดและ Bazel เวอร์ชันที่ติดตั้ง รายการจะนำมาจากแคชถ้า Bazel รู้อย่างมั่นใจว่ามีสำเนาของไฟล์ที่ถูกต้อง กล่าวคือเมื่อคำขอดาวน์โหลดมีผลรวม SHA256 ของไฟล์ที่ระบุ และไฟล์ที่มีแฮชนั้นอยู่ในแคช ดังนั้นการระบุแฮชสำหรับไฟล์ภายนอกแต่ละไฟล์ จึงไม่เพียงแค่เป็นความคิดที่ดีในแง่ของความปลอดภัยเท่านั้น แต่ยังช่วยหลีกเลี่ยงการดาวน์โหลดที่ไม่จำเป็นด้วย

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

[เลิกใช้งานแล้ว] ไดเรกทอรีไฟล์การกระจาย

เลิกใช้งานแล้ว: ขอแนะนำให้ใช้แคชที่เก็บเพื่อสร้างบิลด์แบบออฟไลน์

ไดเรกทอรีการกระจายเป็นกลไก Bazel อีกแบบหนึ่งเพื่อหลีกเลี่ยงการดาวน์โหลดที่ไม่จำเป็น Bazel ค้นหาไดเรกทอรีการเผยแพร่ก่อนแคชที่เก็บ ความแตกต่างหลักๆ คือไดเรกทอรีการกระจายต้องมีการเตรียมการด้วยตนเอง

เมื่อใช้ตัวเลือก --distdir=/path/to-directory คุณจะระบุไดเรกทอรีแบบอ่านอย่างเดียวเพิ่มเติมเพื่อใช้ค้นหาไฟล์แทนการดึงข้อมูลได้ ระบบจะนำไฟล์มาจากไดเรกทอรีดังกล่าวหากชื่อไฟล์เหมือนกับชื่อพื้นฐานของ URL และแฮชของไฟล์เท่ากับชื่อที่ระบุไว้ในคำขอดาวน์โหลด การดำเนินการนี้จะใช้ได้เมื่อมีการระบุแฮชของไฟล์ในการประกาศ WORKSPACE

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

การวิ่ง Bazel ในสภาพแวดล้อมที่ไม่มีการปิดกั้น

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

อย่างไรก็ตาม ทรัพยากร Dependency โดยนัยเหล่านี้อาจก่อให้เกิดปัญหาเมื่อเรียกใช้ Bazel ในสภาพแวดล้อมที่มีการปกปิดไว้ แม้ว่าคุณจะใช้บริการการพึ่งพาภายนอกทั้งหมดก็ตาม ในการแก้ปัญหาดังกล่าว คุณสามารถเตรียมแคชที่เก็บ (ด้วย Bazel 7 หรือใหม่กว่า) หรือไดเรกทอรีการเผยแพร่ (โดยใช้ Bazel ก่อนหน้าเวอร์ชัน 7) ที่มีการขึ้นต่อกันเหล่านี้บนเครื่องที่เข้าถึงเครือข่าย แล้วถ่ายโอนไปยังสภาพแวดล้อมที่มีการออกอากาศด้วยวิธีออฟไลน์

แคชที่เก็บ (พร้อม Bazel 7 ขึ้นไป)

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

หากต้องการดึงข้อมูลทรัพยากร Dependency ดังกล่าวนอกสภาพแวดล้อมที่เติมเต็ม (Airgapped) ให้สร้างพื้นที่ทำงานที่ว่างเปล่าก่อน

mkdir empty_workspace && cd empty_workspace
touch MODULE.bazel
touch WORKSPACE

หากต้องการดึงข้อมูลทรัพยากร Dependency ของ Bzlmod ในตัว ให้เรียกใช้

bazel fetch --repository_cache="path/to/repository/cache"

หากคุณยังต้องใช้ไฟล์ WORKSPACE เดิมเพื่อดึงข้อมูลทรัพยากร Dependency ในตัวของ Workspace ให้เรียกใช้

bazel sync --repository_cache="path/to/repository/cache"

ขั้นตอนสุดท้าย เมื่อคุณใช้ Bazel ในสภาพแวดล้อมที่มี Airgappel ให้ส่งแฟล็ก --repository_cache เดียวกัน เพื่อความสะดวก คุณเพิ่มบัญชีเป็น .bazelrc ได้ ดังนี้

common --repository_cache="path/to/repository/cache"

นอกจากนี้ คุณยังอาจต้องโคลน BCR ในเครื่องและใช้แฟล็ก --registry ชี้สำเนาในเครื่องเพื่อป้องกันไม่ให้ Bazel เข้าถึง BCR ผ่านอินเทอร์เน็ต เพิ่มบรรทัดต่อไปนี้ใน .bazelrc

common --registry="path/to/local/bcr/registry"
ไดเรกทอรีการกระจาย (ที่มี Bazel ก่อนหน้าเวอร์ชัน 7)

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

หากต้องการสร้างทรัพยากร Dependency เหล่านี้นอกสภาพแวดล้อมที่มีการปิดผนึกดังกล่าว ก่อนอื่นให้เช็คเอาต์ต้นไม้แหล่งที่มาของ Bazel ในเวอร์ชันที่ถูกต้อง

git clone https://github.com/bazelbuild/bazel "$BAZEL_DIR"
cd "$BAZEL_DIR"
git checkout "$BAZEL_VERSION"

จากนั้นสร้าง Tarball ที่มีทรัพยากร Dependency ของรันไทม์โดยนัยสำหรับ Bazel เวอร์ชันนั้นๆ

bazel build @additional_distfiles//:archives.tar

ส่งออก tarball นี้ไปยังไดเรกทอรีซึ่งสามารถคัดลอกไปยังสภาพแวดล้อมที่มี Airgapped ของคุณได้ โปรดสังเกตธง --strip-components เนื่องจาก --distdir อาจเหมาะสมมากกับระดับการซ้อนไดเรกทอรี ดังนี้

tar xvf bazel-bin/external/additional_distfiles/archives.tar \
  -C "$NEW_DIRECTORY" --strip-components=3

ขั้นตอนสุดท้าย เมื่อคุณใช้ Bazel ในสภาพแวดล้อมที่มี Airgapped ให้ส่งแฟล็ก --distdir ที่ชี้ไปยังไดเรกทอรี เพื่อความสะดวก คุณเพิ่มบัญชีเป็น .bazelrc ได้ ดังนี้

build --distdir=path/to/directory

สร้างการกำหนดค่าและการคอมไพล์ข้ามระบบ

อินพุตทั้งหมดที่ระบุลักษณะการทำงานและผลลัพธ์ของบิลด์หนึ่งๆ แบ่งออกได้เป็น 2 หมวดหมู่ที่แตกต่างกัน ประเภทแรกคือข้อมูลภายในที่จัดเก็บไว้ในไฟล์ BUILD ของโปรเจ็กต์ ได้แก่ กฎบิลด์ ค่าของแอตทริบิวต์ และชุดทรัพยากร Dependency แบบสลับที่ครบถ้วน ประเภทที่ 2 คือข้อมูลภายนอกหรือสภาพแวดล้อม ซึ่งผู้ใช้หรือเครื่องมือบิลด์เป็นผู้กำหนด ซึ่งก็คือตัวเลือกสถาปัตยกรรมเป้าหมาย ตัวเลือกการรวบรวมและลิงก์ และตัวเลือกการกำหนดค่าเชนเครื่องมืออื่นๆ เราเรียกชุดข้อมูลสภาพแวดล้อมทั้งหมดว่าเป็นการกำหนดค่า

ในแต่ละบิลด์ อาจมีการกำหนดค่ามากกว่า 1 รายการ ลองใช้ครอสคอมไพล์ ซึ่งจะสร้างไฟล์ปฏิบัติการ //foo:bin สำหรับสถาปัตยกรรม 64 บิต แต่เวิร์กสเตชันของคุณเป็นเครื่องแบบ 32 บิต แน่นอนว่าบิลด์จะต้องสร้าง //foo:bin โดยใช้ Toolchain ที่สร้างไฟล์สั่งการแบบ 64 บิตได้ แต่ระบบบิลด์จะต้องสร้างเครื่องมือต่างๆ ที่ใช้ระหว่างตัวบิลด์นั้นด้วย เช่น เครื่องมือที่สร้างจากต้นทางแล้วนำมาใช้ภายหลัง เช่น การสร้างกฎ และจะต้องสร้างเพื่อให้ทำงานบนเวิร์กสเตชันได้ เราจึงระบุการกำหนดค่าได้ 2 แบบ ได้แก่ การกำหนดค่า exec ซึ่งใช้สำหรับการสร้างเครื่องมือที่ทำงานระหว่างบิลด์ และการกำหนดค่าเป้าหมาย (หรือการกำหนดค่าคำขอ แต่เราใช้ "การกำหนดค่าเป้าหมาย" บ่อยกว่าแม้ว่าคำนั้นจะมีหลายความหมายอยู่แล้ว) ซึ่งใช้ในการสร้างไบนารีที่คุณขอในท้ายที่สุด

โดยปกติแล้วจะมีไลบรารีจำนวนมากที่เป็นข้อกำหนดเบื้องต้นของทั้งเป้าหมายบิลด์ที่ขอ (//foo:bin) และเครื่องมือ exec อย่างน้อย 1 รายการ เช่น ไลบรารีพื้นฐานบางรายการ ไลบรารีดังกล่าวต้องสร้างขึ้น 2 ครั้ง ครั้งแรกสำหรับการกำหนดค่า exec และอีกครั้งหนึ่งสำหรับการกำหนดค่าเป้าหมาย Bazel ดูแลดูแลให้มีการสร้างตัวแปรทั้ง 2 ตัวและแยกไฟล์ที่ดึงมาไว้แยกกันเพื่อหลีกเลี่ยงการรบกวน ซึ่งโดยปกติแล้ว เป้าหมายดังกล่าวจะสร้างพร้อมกันได้ เนื่องจากแต่ละไฟล์เป็นอิสระจากกัน หากคุณเห็นข้อความความคืบหน้าที่ระบุว่ามีการสร้างเป้าหมายที่ระบุ 2 ครั้ง ก็น่าจะเป็นคำอธิบาย

การกำหนดค่าการดำเนินการจะได้มาจากการกำหนดค่าเป้าหมายดังนี้

  • ใช้ Crosstool (--crosstool_top) เวอร์ชันเดียวกับที่ระบุไว้ในการกำหนดค่าคำขอ เว้นแต่จะระบุ --host_crosstool_top
  • ใช้ค่า --host_cpu สําหรับ --cpu (ค่าเริ่มต้น: k8)
  • ใช้ค่าของตัวเลือกเหล่านี้เหมือนกับที่ระบุไว้ในการกำหนดค่าคำขอ: --compiler, --use_ijars และถ้าใช้ --host_crosstool_top ระบบจะใช้ค่า --host_cpu เพื่อค้นหา default_toolchain ใน Crosstool (ไม่สนใจ --compiler) สำหรับการกำหนดค่า exec
  • ใช้ค่า --host_javabase สำหรับ --javabase
  • ใช้ค่า --host_java_toolchain สำหรับ --java_toolchain
  • ใช้บิลด์ที่เพิ่มประสิทธิภาพสำหรับโค้ด C++ (-c opt)
  • สร้างข้อมูลการแก้ไขข้อบกพร่อง (--copt=-g0)
  • ตัดข้อมูลการแก้ไขข้อบกพร่องจากไฟล์ปฏิบัติการและไลบรารีที่ใช้ร่วมกัน (--strip=always)
  • วางไฟล์ที่ได้มาทั้งหมดไว้ในตำแหน่งพิเศษ ซึ่งต่างจากไฟล์ที่ได้ใช้โดยการกำหนดค่าคำขอที่เป็นไปได้
  • ระงับการประทับไบนารีที่มีข้อมูลบิลด์ (ดูตัวเลือก --embed_*)
  • ค่าอื่นๆ ทั้งหมดจะยังคงอยู่ในค่าเริ่มต้น

มีเหตุผลหลายประการที่ควรเลือกการกำหนดค่าการดำเนินการที่แตกต่างจากการกำหนดค่าคำขอ สิ่งที่สำคัญที่สุด:

ประการแรก การใช้ไบนารีที่ตัดออกและเพิ่มประสิทธิภาพจะช่วยลดเวลาที่ใช้ในการลิงก์และเรียกใช้เครื่องมือ พื้นที่ในดิสก์ที่เครื่องมือใช้ และเวลา I/O ของเครือข่ายในบิลด์แบบกระจาย

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

แก้ไขการสร้างใหม่ส่วนเพิ่มที่ถูกต้อง

หนึ่งในเป้าหมายหลักของโปรเจ็กต์ Bazel คือเพื่อให้แน่ใจว่าจะมีการสร้างใหม่เพิ่มขึ้นอย่างถูกต้อง เครื่องมือสร้างเวอร์ชันก่อนหน้า โดยเฉพาะเครื่องมือที่อิงจาก Make มักตั้งสมมติฐานหลายอย่างเกี่ยวกับการนำบิลด์แบบเพิ่มไปใช้

ประการแรก การประทับเวลาของไฟล์เพิ่มขึ้นแบบจำเจ ถึงแม้จะเป็นกรณีทั่วไป แต่ก็อาจลบล้างข้อสันนิษฐานนี้ได้ง่ายมาก การซิงค์กับการแก้ไขไฟล์ก่อนหน้านี้ทำให้เวลาในการแก้ไขไฟล์ลดลง ส่วนระบบแบบสร้างจะไม่มีการสร้างใหม่

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

นอกจากนี้ Make ไม่มีประสิทธิภาพต่อการสิ้นสุดกระบวนการย่อยรายการใดรายการหนึ่งที่ไม่สำเร็จ หลังจากที่กระบวนการย่อยนั้นเริ่มเขียนไปยังไฟล์เอาต์พุตแล้ว แม้ว่าการดำเนินการปัจจุบันของ Make จะไม่สำเร็จ แต่การเรียกใช้ Make ในครั้งต่อๆ ไปจะสันนิษฐานได้ว่าไฟล์เอาต์พุตที่ตัดแล้วถูกต้อง (เนื่องจากเป็นไฟล์ที่ใหม่กว่าอินพุต) และจะไม่มีการสร้างใหม่ ในทำนองเดียวกัน หากกระบวนการ "สร้าง" ถูกหยุดการทำงาน ก็อาจเกิดเหตุการณ์ที่คล้ายคลึงกันขึ้นได้

บุณยวีร์หลีกเลี่ยงข้อสันนิษฐานเหล่านี้ รวมถึงข้ออื่นๆ ด้วย Bazel เก็บรักษาฐานข้อมูลของงานทั้งหมดที่เคยทำก่อนหน้านี้ และจะยกเว้นขั้นตอนการสร้างเฉพาะเมื่อพบว่าชุดไฟล์อินพุต (และการประทับเวลา) ไปยังขั้นตอนของบิลด์นั้น และคำสั่งการคอมไพล์สำหรับขั้นตอนของบิลด์นั้นตรงกันทุกประการกับขั้นตอนหนึ่งในฐานข้อมูล และชุดไฟล์เอาต์พุต (และการประทับเวลาของไฟล์) ของรายการในฐานข้อมูลตรงกับการประทับเวลาของไฟล์ในดิสก์ทุกประการ การเปลี่ยนแปลงใดๆ กับไฟล์อินพุตหรือไฟล์เอาต์พุตหรือตัวคำสั่งเองจะทำให้มีการดำเนินการขั้นตอนบิลด์อีกครั้ง

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

สร้างความสอดคล้องและบิลด์ที่เพิ่มขึ้น

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

มีความไม่สอดคล้องกันอีกประเภทหนึ่งคือ ความไม่สอดคล้องกันคงที่ หากบิลด์มีสถานะที่ไม่สอดคล้องกันอย่างคงที่ การเรียกใช้เครื่องมือสร้างที่สําเร็จซ้ำๆ จะไม่คืนค่าความสอดคล้อง: บิลด์ "ค้าง" และเอาต์พุตยังคงไม่ถูกต้อง สถานะ "ไม่คงที่" เสถียรเป็นเหตุผลหลักที่ผู้ใช้ "Make (และเครื่องมือบิลด์อื่นๆ)" ประเภท make clean การค้นพบว่าเครื่องมือสร้างล้มเหลวด้วยวิธีนี้ (จากนั้นกู้คืนจากเครื่องมือนี้) อาจเป็นกระบวนการที่ใช้เวลานานและน่าหงุดหงิดมาก

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

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

ดังเช่นการรับประกันทั้งหมด ต้องมีรายละเอียดบางอย่าง นั่นเป็นที่ทราบกันดีว่าเราจะแก้ไขสถานะและไม่สอดคล้องกันของ Bazel ได้อย่างไม่คงที่ เราจะไม่รับประกันว่าจะสามารถตรวจสอบปัญหาดังกล่าวที่เกิดจากการพยายามค้นหาข้อบกพร่องโดยไตร่ตรองอย่างรอบคอบในการวิเคราะห์ทรัพยากร Dependency ที่เพิ่มขึ้น แต่เราจะตรวจสอบและแก้ปัญหาอย่างดีที่สุดเพื่อแก้ไขสถานะที่ไม่สอดคล้องกันอย่างมีเสถียรภาพทั้งหมดซึ่งเกิดจากการใช้งานเครื่องมือสร้างตามปกติหรือ "สมเหตุสมผล"

หากคุณตรวจพบสถานะที่ไม่สอดคล้องกันอย่างคงที่กับ Bazel โปรดรายงานข้อบกพร่อง

การดำเนินการแซนด์บ็อกซ์

Bazel ใช้แซนด์บ็อกซ์เพื่อรับประกันว่าการดำเนินการต่างๆ จะเป็นไปอย่างถูกต้องและเหมาะสม Bazel เรียกใช้ฉาก (การกระทำแบบคร่าวๆ) ในแซนด์บ็อกซ์ที่มีชุดไฟล์จำนวนน้อยที่สุดที่เครื่องมือต้องใช้ในการทำงาน ปัจจุบันแซนด์บ็อกซ์ใช้งานได้ใน Linux 3.12 ขึ้นไปที่เปิดใช้ตัวเลือก CONFIG_USER_NS และใน macOS 10.11 หรือใหม่กว่าด้วย

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

ในบางแพลตฟอร์ม เช่น โหนดคลัสเตอร์ Google Kubernetes Engine หรือ Debian ระบบจะปิดใช้งานเนมสเปซของผู้ใช้โดยค่าเริ่มต้นเนื่องจากข้อกังวลด้านความปลอดภัย ซึ่งตรวจสอบได้โดยดูที่ไฟล์ /proc/sys/kernel/unprivileged_userns_clone หากมีไฟล์อยู่และมี 0 เนมสเปซของผู้ใช้จะสามารถเปิดใช้งานด้วย sudo sysctl kernel.unprivileged_userns_clone=1 ได้

ในบางกรณี แซนด์บ็อกซ์ Bazel จะดำเนินการกฎไม่ได้เนื่องจากการตั้งค่าระบบ อาการโดยทั่วไปคือข้อผิดพลาดที่แสดงข้อความที่คล้ายคลึงกับ namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory ในกรณีดังกล่าว ให้ลองปิดใช้งานแซนด์บ็อกซ์สำหรับ genrules ที่มี --strategy=Genrule=standalone และสำหรับกฎอื่นๆ ที่มี --spawn_strategy=standalone นอกจากนี้ โปรดรายงานข้อบกพร่องในเครื่องมือติดตามปัญหาของเรา และระบุการกระจายของ Linux ที่คุณใช้เพื่อให้เราตรวจสอบและทำการแก้ไขในรุ่นต่อๆ ไปได้

ขั้นตอนต่างๆ ของบิลด์

ใน Bazel บิลด์จะเกิดขึ้นใน 3 ขั้นตอนที่ต่างกัน ในฐานะผู้ใช้ การทำความเข้าใจความแตกต่างระหว่าง เวอร์ชันทั้งสองจะทำให้ข้อมูลเชิงลึกเกี่ยวกับตัวเลือกที่ควบคุมบิลด์ (ดูด้านล่าง)

ระยะการโหลด

อย่างแรกคือ loading ระหว่างที่มีการโหลด แยกวิเคราะห์ ประเมิน และแคชไฟล์ BUILD ที่จำเป็นทั้งหมดสำหรับเป้าหมายเริ่มต้น และการปิดทรัพยากร Dependency แบบชั่วคราว

สำหรับบิลด์แรกหลังจากเซิร์ฟเวอร์ Bazel เริ่มทำงาน โดยทั่วไปขั้นตอนการโหลดจะใช้เวลาหลายวินาทีเมื่อมีการโหลดไฟล์ BUILD จำนวนมากจากระบบไฟล์ ในบิวด์ต่อๆ ไป โดยเฉพาะอย่างยิ่งหากไม่มีไฟล์ BUILD เปลี่ยนแปลง การโหลดจะเกิดขึ้นอย่างรวดเร็วมาก

ข้อผิดพลาดที่รายงานในระยะนี้ ได้แก่ ไม่พบแพ็กเกจ, ไม่พบเป้าหมาย, ข้อผิดพลาดด้านคำศัพท์และไวยากรณ์ในไฟล์ BUILD และข้อผิดพลาดในการประเมิน

ขั้นการวิเคราะห์

ขั้นที่ 2 ของการวิเคราะห์จะเกี่ยวกับการวิเคราะห์เชิงความหมายและการตรวจสอบความถูกต้องของกฎบิลด์แต่ละแบบ การสร้างกราฟการอ้างอิงบิลด์ และการกำหนดว่าต้องทำงานใดในแต่ละขั้นตอนของบิลด์

เช่นเดียวกับการโหลด การวิเคราะห์ใช้เวลาหลายวินาทีเมื่อคำนวณทั้งหมด อย่างไรก็ตาม Bazel จะแคชกราฟทรัพยากร Dependency จากบิลด์หนึ่งไปยังบิลด์ถัดไป แล้ววิเคราะห์เฉพาะสิ่งที่มี ซึ่งช่วยให้สร้างบิลด์แบบเพิ่มความเร็วได้มากในกรณีที่แพ็กเกจไม่มีการเปลี่ยนแปลงตั้งแต่บิลด์ก่อนหน้า

ข้อผิดพลาดที่รายงานในขั้นตอนนี้ ได้แก่ การอ้างอิงที่ไม่เหมาะสม อินพุตที่ไม่ถูกต้องไปยังกฎ และข้อความแสดงข้อผิดพลาดเฉพาะกฎทั้งหมด

ขั้นตอนการโหลดและการวิเคราะห์เป็นไปอย่างรวดเร็วเนื่องจาก Bazel หลีกเลี่ยง I/O ไฟล์ที่ไม่จำเป็นในขั้นนี้ โดยจะอ่านเฉพาะไฟล์ BUILD เท่านั้นเพื่อตัดสินว่าจะต้องทำให้เสร็จไหม ซึ่งเป็นการออกแบบที่ทำให้ Bazel เป็นรากฐานที่ดีสำหรับเครื่องมือวิเคราะห์ เช่น คำสั่งคำค้นหาของ Bazel ซึ่งจะนำไปใช้ในขั้นตอนการโหลด

ระยะดำเนินการ

ขั้นที่ 3 ซึ่งเป็นขั้นสุดท้ายของบิลด์คือการดำเนินการ ระยะนี้ช่วยดูแลให้เอาต์พุตของแต่ละขั้นตอนในบิลด์สอดคล้องกับอินพุต การเรียกใช้การคอมไพล์/ลิงก์/เครื่องมืออื่นๆ อีกครั้งตามความจำเป็น ขั้นตอนนี้คือที่ที่บิลด์ใช้เวลาส่วนใหญ่ ตั้งแต่ไม่กี่วินาทีไปจนถึงเกิน 1 ชั่วโมงสำหรับงานสร้างขนาดใหญ่ ข้อผิดพลาดที่รายงานในระยะนี้ ได้แก่ ไฟล์ต้นฉบับขาดหายไป ข้อผิดพลาดในเครื่องมือที่ดำเนินการโดยการดำเนินการบิลด์บางอย่าง หรือเครื่องมือสร้างชุดเอาต์พุตที่คาดไว้ไม่ได้