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

รายงานปัญหา ดูแหล่งที่มา Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

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

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

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

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

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

  • analyze-profile: วิเคราะห์ข้อมูลโปรไฟล์การสร้าง
  • aquery: เรียกใช้การค้นหาในกราฟการดำเนินการหลังการวิเคราะห์
  • build: สร้างเป้าหมายที่ระบุ
  • canonicalize-flags: กำหนดแฟล็ก Bazel ให้เป็นรูปแบบมาตรฐาน
  • clean: นำไฟล์เอาต์พุตออกและหยุดเซิร์ฟเวอร์ (ไม่บังคับ)
  • cquery: เรียกใช้การค้นหากราฟการขึ้นต่อกันหลังการวิเคราะห์
  • dump: ทิ้งสถานะภายในของกระบวนการเซิร์ฟเวอร์ Bazel
  • help: พิมพ์ความช่วยเหลือสำหรับคำสั่งหรือดัชนี
  • info: แสดงข้อมูลรันไทม์เกี่ยวกับเซิร์ฟเวอร์ Bazel
  • fetch: ดึงข้อมูลการอ้างอิงภายนอกทั้งหมดของเป้าหมาย
  • 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

สร้างเป้าหมายเดียว

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

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

เมื่อสิ้นสุดการสร้าง 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

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

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

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

ในขณะที่ป้ายกำกับใช้เพื่อระบุเป้าหมายแต่ละรายการ เช่น เพื่อประกาศการขึ้นต่อกันในไฟล์ 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/... เป็นไวลด์การ์ดเหนือ packages ซึ่งระบุแพ็กเกจทั้งหมดแบบเรียกซ้ำ ใต้ไดเรกทอรี 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 จะดาวน์โหลดและลิงก์สัญลักษณ์การอ้างอิงภายนอกระหว่างการบิลด์ อย่างไรก็ตาม คุณอาจไม่ต้องการให้เป็นเช่นนี้ ไม่ว่าจะเป็นเพราะคุณต้องการทราบ เมื่อมีการเพิ่มการอ้างอิงภายนอกใหม่ หรือเพราะคุณต้องการ "โหลดล่วงหน้า" การอ้างอิง (เช่น ก่อนขึ้นเครื่องบินที่คุณจะออฟไลน์) หากต้องการป้องกันไม่ให้มีการเพิ่มการอ้างอิงใหม่ระหว่างการสร้าง คุณสามารถระบุแฟล็ก --fetch=false ได้ โปรดทราบว่าแฟล็กนี้ใช้ได้กับกฎของที่เก็บที่ไม่ได้ชี้ไปยังไดเรกทอรีในระบบไฟล์ในเครื่องเท่านั้น การเปลี่ยนแปลง เช่น local_repository, new_local_repository และกฎของที่เก็บ Android SDK และ NDK จะมีผลเสมอไม่ว่าค่า --fetch จะเป็นอะไรก็ตาม

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

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

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

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

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

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

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

bazel fetch //...

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

bazel fetch

คุณไม่จำเป็นต้องเรียกใช้ bazel fetch เลยหากมีเครื่องมือทั้งหมดที่ใช้ (ตั้งแต่ JAR ของไลบรารีไปจนถึง JDK เอง) อยู่ภายใต้รูทของเวิร์กสเปซ อย่างไรก็ตาม หากคุณใช้สิ่งอื่นนอกเหนือจากไดเรกทอรีพื้นที่ทำงาน 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 และแฮชของไฟล์ เท่ากับแฮชที่ระบุในคำขอดาวน์โหลด ซึ่งจะใช้ได้ก็ต่อเมื่อมีการระบุแฮชของไฟล์ในการประกาศกฎของที่เก็บ

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

การเรียกใช้ Bazel ในสภาพแวดล้อมที่แยกจากเครือข่ายภายนอก

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

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

แคชที่เก็บข้อมูล (ด้วย Bazel 7 ขึ้นไป)

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

หากต้องการดึงข้อมูลการอ้างอิงเหล่านั้นนอกสภาพแวดล้อมที่แยกจากอินเทอร์เน็ต ให้สร้างพื้นที่ทำงานว่างก่อนโดยทำดังนี้

mkdir empty_workspace && cd empty_workspace
touch MODULE.bazel

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

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

หากยังคงใช้ไฟล์ WORKSPACE เดิมอยู่ ให้เรียกข้อมูลทรัพยากร Dependency ของ WORKSPACE ที่มีอยู่แล้วโดยเรียกใช้

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

สุดท้ายนี้ เมื่อใช้ Bazel ในสภาพแวดล้อมที่แยกจากเครือข่ายภายนอก ให้ส่งแฟล็ก --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 เหล่านี้ภายนอกสภาพแวดล้อมที่แยกจากอินเทอร์เน็ต ให้ ตรวจสอบซอร์สทรีของ 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 นี้ไปยังไดเรกทอรีที่คัดลอกไปยังสภาพแวดล้อมที่แยกจากอินเทอร์เน็ตได้ โปรดสังเกต--strip-components เนื่องจาก --distdir อาจ ค่อนข้างละเอียดอ่อนกับระดับการซ้อนไดเรกทอรี

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

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

build --distdir=path/to/directory

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

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

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

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

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

  • ใช้ 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_*)
  • ค่าอื่นๆ ทั้งหมดจะยังคงเป็นค่าเริ่มต้น

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

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

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

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

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

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

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

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

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

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

สร้างความสม่ำเสมอและการเพิ่มขึ้นทีละน้อย

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

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

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

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

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

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

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

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

ระยะการโหลด

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

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

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

ระยะการวิเคราะห์

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

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

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

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

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

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