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

รายงานปัญหา ดูแหล่งที่มา Nightly · 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 จะดาวน์โหลดและ Symlink การอ้างอิงภายนอกในระหว่าง การสร้าง อย่างไรก็ตาม คุณอาจไม่ต้องการให้เป็นเช่นนี้ ไม่ว่าจะเป็นเพราะคุณต้องการทราบ เมื่อมีการเพิ่มการอ้างอิงภายนอกใหม่ หรือเพราะคุณต้องการ "โหลดล่วงหน้า" การอ้างอิง (เช่น ก่อนขึ้นเครื่องบินที่คุณจะออฟไลน์) หากต้องการป้องกันไม่ให้มีการเพิ่มการอ้างอิงใหม่ระหว่างการสร้าง คุณสามารถระบุแฟล็ก --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 //...

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

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 ให้มีขนาดเล็ก การขึ้นต่อกันโดยนัยเหล่านี้ มี 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ใช้เครื่องมือที่สามารถสร้างไฟล์ที่เรียกใช้งานได้แบบ 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 ของเครือข่ายในการบิลด์แบบกระจาย

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

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

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