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

7.3 · 7.2 · 7.1 · 7.0 · 6.5

หน้านี้จะพูดถึงวิธีสร้างโปรแกรมด้วย 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: ดึงข้อมูลทรัพยากร 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: แสดงรายการคีย์ที่คำสั่งข้อมูลใช้

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

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

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

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

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

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

//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 if foo/bar is a package
  • //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" (ต้องใช้อาร์กิวเมนต์ -- เพื่อป้องกันไม่ให้ระบบตีความอาร์กิวเมนต์ต่อๆ ไปซึ่งขึ้นต้นด้วย - เป็นตัวเลือกเพิ่มเติม)

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

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

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

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

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

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

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

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

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

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

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

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 และนอกจากนี้ แฮชของไฟล์ก็เท่ากับแฮชที่ระบุในคําขอดาวน์โหลด การดำเนินการนี้จะใช้ได้เมื่อมีการระบุแฮชของไฟล์ในการประกาศ WORKSPACE เท่านั้น

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

ใช้ Bazel ในสภาพแวดล้อมที่ไม่มีอากาศ

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

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

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

หากต้องการสร้างทรัพยากร Dependency เหล่านี้นอกสภาพแวดล้อมที่มีการเชื่อมต่ออากาศ ก่อนอื่นให้ตรวจสอบโครงสร้างแหล่งที่มาของ Bazel ในเวอร์ชันที่ถูกต้องก่อน

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

จากนั้นสร้าง tarball ที่มีข้อกำหนดเบื้องต้นรันไทม์โดยนัยสำหรับ 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 ในสภาพแวดล้อมที่มีการป้องกันอากาศ ให้ส่ง Flag --distdir ที่ชี้ไปยังไดเรกทอรี เพื่อความสะดวก ให้คุณเพิ่มเป็นรายการ .bazelrc ได้ ดังนี้

build --distdir=path/to/directory

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

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

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

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

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

--distinct_host_configuration=false

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

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

--distinct_host_configuration=true (ค่าเริ่มต้น)

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

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

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

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

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

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

แก้ไขการสร้างใหม่ที่เพิ่มขึ้นเรื่อยๆ

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

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

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

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

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

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

สร้างความสอดคล้องและค่อยๆ เพิ่มขึ้น

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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