หน้านี้จะกล่าวถึงวิธีสร้างโปรแกรมด้วย Bazel, การสร้างไวยากรณ์คำสั่ง และ ของรูปแบบเป้าหมาย
คู่มือเริ่มใช้งานฉบับย่อ
หากต้องการเรียกใช้ Bazel ให้ไปที่ไดเรกทอรีพื้นที่ทำงานพื้นฐาน
หรือไดเรกทอรีย่อยทั้งหมด และประเภท bazel
ดูสร้างหากจำเป็นต้องสร้างพื้นที่ทำงานใหม่
bazel help
[Bazel release bazel version]
Usage: bazel command options ...
คำสั่งที่ใช้ได้
analyze-profile
: วิเคราะห์ข้อมูลโปรไฟล์ของบิลด์aquery
: ดำเนินการค้นหาในกราฟการดำเนินการหลังการวิเคราะห์build
: สร้างเป้าหมายที่ระบุcanonicalize-flags
: กำหนดค่าแฟล็ก Bazel เป็นค่า Canonicalclean
: นำไฟล์เอาต์พุตออกและหยุดเซิร์ฟเวอร์ (ไม่บังคับ)cquery
: ดำเนินการค้นหากราฟทรัพยากร Dependency สำหรับหลังการวิเคราะห์dump
: ถ่ายโอนสถานะภายในของกระบวนการของเซิร์ฟเวอร์ Bazelhelp
: พิมพ์ความช่วยเหลือสำหรับคำสั่งหรือดัชนีinfo
: แสดงข้อมูลรันไทม์เกี่ยวกับเซิร์ฟเวอร์ bazelfetch
: ดึงข้อมูลการอ้างอิงภายนอกทั้งหมดของเป้าหมายmobile-install
: ติดตั้งแอปในอุปกรณ์เคลื่อนที่query
: ดำเนินการค้นหากราฟทรัพยากร Dependencyrun
: เรียกใช้เป้าหมายที่ระบุshutdown
: หยุดเซิร์ฟเวอร์ Bazeltest
: สร้างและเรียกใช้เป้าหมายการทดสอบที่ระบุversion
: พิมพ์ข้อมูลเวอร์ชันสำหรับ Bazel
การขอความช่วยเหลือ
bazel help command
: ความช่วยเหลือและตัวเลือกสำหรับรูปภาพcommand
bazel help
startup_options
: ตัวเลือกสําหรับ JVM ที่โฮสต์ Bazelbazel help
target-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 ที่ประกาศ ซึ่งเป็นไฟล์ที่อยู่ใน BUILD
ของเป้าหมายโดยตรง
และทรัพยากร Dependency แบบสโลแกนในไฟล์ที่มีอยู่ใน BUILD
ไฟล์
ทรัพยากร Dependency ของเป้าหมาย หลังจากระบุ Dependency ทั้งหมดแล้ว Bazel จะวิเคราะห์เพื่อดูความถูกต้องและสร้างการดำเนินการสร้าง สุดท้าย Bazel ปฏิบัติการ
คอมไพเลอร์และเครื่องมืออื่นๆ ของบิลด์
ในขั้นตอนการดำเนินการของบิลด์ Bazel จะพิมพ์ข้อความความคืบหน้า ข้อความความคืบหน้าจะแสดงขั้นตอนการสร้างปัจจุบัน (เช่น คอมไพเลอร์หรือโปรแกรมลิงก์) เมื่อเริ่มสร้าง และจำนวนที่เสร็จสมบูรณ์เทียบกับจำนวนการดำเนินการสร้างทั้งหมด ตามที่ จำนวนการดำเนินการทั้งหมดมักเพิ่มขึ้นเมื่อ 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 เนื่องจากไม่มีการเปลี่ยนแปลงใดๆ จึงไม่มีแพ็กเกจที่จะโหลดซ้ำและไม่มีขั้นตอนการสร้างที่จะดำเนินการ หากมีการเปลี่ยนแปลงใน "foo" หรือข้อกําหนด Bazel จะดําเนินการบางอย่างในบิลด์อีกครั้ง หรือทําบิลด์แบบเพิ่มให้เสร็จสมบูรณ์
การสร้างเป้าหมายหลายรายการ
Bazel มีวิธีระบุเป้าหมายที่จะสร้างได้หลายวิธี รายการเหล่านี้เรียกรวมกันว่ารูปแบบเป้าหมาย ไวยากรณ์นี้จะใช้ในคำสั่งต่างๆ เช่น
build
, test
หรือ query
ส่วนป้ายกำกับจะใช้เพื่อระบุเป้าหมายแต่ละรายการ เช่น สำหรับการประกาศการพึ่งพาในไฟล์ BUILD
รูปแบบเป้าหมายของ Bazel จะระบุเป้าหมายหลายรายการ รูปแบบเป้าหมายเป็นรูปแบบทั่วไปของรูปแบบคำสั่งป้ายกำกับสำหรับชุดเป้าหมายโดยใช้ไวลด์การ์ด ในกรณีที่ง่ายที่สุด ป้ายกำกับที่ถูกต้องจะเป็นรูปแบบเป้าหมายที่ถูกต้องด้วย ซึ่งระบุชุดเป้าหมายเพียงชุดเดียว
รูปแบบเป้าหมายทั้งหมดที่ขึ้นต้นด้วย //
ได้รับการแก้ไขแล้วเมื่อเทียบกับรูปแบบปัจจุบัน
Google Workspace ได้อย่างเต็มประสิทธิภาพ
//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 |
เทียบเท่ากับ
|
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 ภายนอกและ symlink ระหว่าง
งานสร้าง อย่างไรก็ตาม นี่อาจเป็นสิ่งที่ไม่เป็นที่ต้องการ เนื่องจาก
คุณอยากรู้
เมื่อมีการเพิ่มทรัพยากร Dependency ภายนอกใหม่ หรือเมื่อคุณต้องการ
"ดึงข้อมูลล่วงหน้า" ทรัพยากร Dependency (เช่น ก่อนเดินทาง ซึ่งคุณจะออฟไลน์) หากคุณ
ต้องการป้องกันไม่ให้มีการเพิ่มทรัพยากร Dependency ใหม่ระหว่างบิลด์
สามารถระบุแฟล็ก --fetch=false
โปรดทราบว่า Flag นี้มีผลกับกฎของที่เก็บซึ่งไม่ได้ชี้ไปยังไดเรกทอรีในระบบไฟล์ในเครื่องเท่านั้น การเปลี่ยนแปลง เช่น local_repository
new_local_repository
และกฎที่เก็บ Android SDK และ NDK
จะมีผลเสมอโดยไม่คำนึงถึงค่า --fetch
หากคุณไม่อนุญาตให้ดึงข้อมูลระหว่างบิลด์และ Bazel พบภายนอกใหม่ ทรัพยากร Dependency บิลด์ของคุณจะล้มเหลว
คุณสามารถดึงข้อมูล Dependency ด้วยตนเองได้โดยเรียกใช้ bazel fetch
หากไม่อนุญาตให้ดึงข้อมูลระหว่างการสร้าง คุณจะต้องเรียกใช้ bazel fetch
ดังนี้
- ก่อนสร้างเป็นครั้งแรก
- หลังจากเพิ่มทรัพยากร Dependency ภายนอกรายการใหม่แล้ว
เมื่อเรียกใช้แล้ว คุณไม่ควรเรียกใช้อีกครั้งจนกว่าไฟล์ WORKSPACE จะเปลี่ยนแปลง
fetch
ใช้รายการเป้าหมายเพื่อดึงข้อมูลการพึ่งพา สำหรับ
ตัวอย่างเช่น การดำเนินการนี้จะดึงทรัพยากร Dependency ที่จำเป็นในการสร้าง //foo:bar
และ //bar:baz
:
bazel fetch //foo:bar //bar:baz
หากต้องการดึงข้อมูล Dependency ภายนอกทั้งหมดสําหรับพื้นที่ทํางาน ให้เรียกใช้คำสั่งต่อไปนี้
bazel fetch //...
คุณไม่จำเป็นต้องเรียกใช้การดึงข้อมูลแบบ Bazel เลย หากมีเครื่องมือทั้งหมด
โดยใช้ (จากไลบรารีไลบรารีไปจนถึง 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 เหล่านี้นอกสภาพแวดล้อม Airgapp ของคุณ ก่อนอื่นให้ ชำระเงินแผนผังแหล่งที่มาของ 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 นี้ไปยังไดเรกทอรีที่สามารถคัดลอกไปยัง Airgapp ของคุณ
ของคุณ โปรดสังเกต Flag --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
ของโปรเจ็กต์ ได้แก่ กฎบิลด์
ค่าของแอตทริบิวต์และชุดทรัพยากร Dependency แบบสับเปลี่ยนที่สมบูรณ์
ประเภทที่ 2 คือข้อมูลภายนอกหรือข้อมูลสภาพแวดล้อมที่ผู้ใช้หรือเครื่องมือสร้างระบุ ได้แก่ ตัวเลือกสถาปัตยกรรมเป้าหมาย ตัวเลือกการคอมไพล์และการลิงก์ และตัวเลือกการกำหนดค่าเครื่องมืออื่นๆ เราเรียกชุดข้อมูลสภาพแวดล้อมที่สมบูรณ์ว่าการกําหนดค่า
บิลด์หนึ่งๆ อาจมีการกำหนดค่ามากกว่า 1 รายการ ลองใช้การคอมไพล์ข้าม ซึ่งคุณสร้าง//foo:bin
ไฟล์ปฏิบัติการสำหรับสถาปัตยกรรม 64 บิต แต่เวิร์กสเตชันเป็นคอมพิวเตอร์ 32 บิต เห็นได้ชัดว่าบิลด์
กำหนดให้สร้าง //foo:bin
โดยใช้เครื่องมือเชนที่สร้างได้ 64 บิต
ไฟล์ปฏิบัติการ แต่ระบบบิลด์ยังต้องสร้างเครื่องมือต่างๆ ที่ใช้ในระหว่าง
สร้างตนเอง เช่น เครื่องมือที่สร้างขึ้นจากแหล่งที่มา แล้วต่อมา
เช่น การสร้างกฎเกณฑ์ (Genrule) และกฎเหล่านี้ต้องสร้างขึ้นเพื่อให้ทำงานบนเวิร์กสเตชันของคุณได้ ดังนั้น
เราจะระบุการกำหนดค่าได้ 2 แบบ ได้แก่ การกำหนดค่าการดำเนินการ ซึ่งใช้
สำหรับเครื่องมือสร้างที่ทำงานระหว่างบิลด์ และการกำหนดค่าเป้าหมาย
(หรือขอการกำหนดค่า แต่เราใช้คำว่า "การกำหนดค่าเป้าหมาย" บ่อยกว่า
แต่คำนั้นมีหลายความหมายอยู่แล้ว) ซึ่งใช้สำหรับการสร้าง
ไบนารีที่คุณขอในท้ายที่สุด
โดยทั่วไปแล้ว จะมีไลบรารีหลายรายการที่เป็นข้อกําหนดเบื้องต้นของทั้งเป้าหมายการสร้างที่ขอ (//foo:bin
) และเครื่องมือ exec อย่างน้อย 1 รายการ เช่น ไลบรารีพื้นฐานบางรายการ ไลบรารีดังกล่าวต้องสร้างขึ้น 2 ครั้ง โดยครั้งหนึ่งสำหรับผู้บริหาร
และอีกครั้งสำหรับการกำหนดค่าเป้าหมาย 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_*
) - ค่าอื่นๆ ทั้งหมดจะยังเป็นค่าเริ่มต้น
มีเหตุผลหลายประการที่ควรเลือกผู้บริหารที่ไม่ซ้ำกัน จากการกำหนดค่าคำขอ สิ่งสำคัญที่สุด
ประการแรก การใช้ไบนารีที่ผ่านการลบข้อมูลและเพิ่มประสิทธิภาพแล้วจะช่วยประหยัดเวลาในการลิงก์และเรียกใช้เครื่องมือ พื้นที่ดิสก์ที่เครื่องมือใช้ และเวลา I/O ของเครือข่ายในบิลด์แบบกระจาย
ข้อ 2 การแยกการกำหนดค่า exec และคำขอในบิลด์ทั้งหมดออก เพื่อหลีกเลี่ยงการสร้างใหม่ซึ่งมีราคาแพงมาก ซึ่งจะเป็นเพราะการเปลี่ยนแปลงเล็กๆ น้อยๆ ส่งคำขอการกำหนดค่า (เช่น การเปลี่ยนตัวเลือกตัวลิงก์) ตามที่อธิบายไว้ ก่อนหน้านี้
แก้ไขการสร้างใหม่แบบเพิ่มทีละส่วน
เป้าหมายหลักอย่างหนึ่งของโครงการ Bazel คือการดูแลส่วนเพิ่มที่ถูกต้อง สร้างใหม่ เครื่องมือสร้างก่อนหน้านี้ โดยเฉพาะเครื่องมือที่ทำงานตามแบรนด์ สมมติฐานที่ไม่สมเหตุสมผลในการใช้งานบิลด์ที่เพิ่มขึ้น
ประการแรก การประทับเวลาของไฟล์จะเพิ่มขึ้นเรื่อยๆ แม้ว่านี่คือ ตามตัวอย่างที่พบได้ทั่วไป ความคิดนี้ผิดได้ง่ายมาก กำลังซิงค์กับ การแก้ไขไฟล์ก่อนหน้าจะทำให้เวลาในการแก้ไขไฟล์ลดลง ระบบที่อิงตามแบรนด์จะไม่สร้างใหม่
กล่าวโดยทั่วไปคือ แม้เครื่องมือจะตรวจจับการเปลี่ยนแปลงของไฟล์ แต่เครื่องมือจะไม่ตรวจหาการเปลี่ยนแปลง
กับคำสั่งต่างๆ หากคุณแก้ไขตัวเลือกที่ส่งไปยังคอมไพเลอร์ในขั้นตอนการสร้างหนึ่งๆ Make จะไม่เรียกใช้คอมไพเลอร์อีกครั้ง และคุณจะต้องทิ้งเอาต์พุตที่ไม่ถูกต้องของบิลด์ก่อนหน้าด้วยตนเองโดยใช้ make clean
นอกจากนี้ Make ยังไม่เสถียรเมื่อการสิ้นสุดกระบวนการย่อยไม่สำเร็จหลังจากที่กระบวนการย่อยนั้นเริ่มเขียนลงในไฟล์เอาต์พุตแล้ว ขณะที่ การดำเนินการ Make ปัจจุบันจะล้มเหลว และการเรียกใช้ Make ในครั้งต่อๆ ไปจะ ทึกทักเอาว่าไฟล์เอาต์พุตที่ตัดให้สั้นลงนั้นถูกต้อง (เนื่องจากใหม่กว่า อินพุต) และจะไม่สร้างใหม่ ในทํานองเดียวกัน หากกระบวนการสร้างถูกยกเลิก สถานการณ์ที่คล้ายกันก็อาจเกิดขึ้นได้
Bazel หลีกเลี่ยงสมมติฐานเหล่านี้และเรื่องอื่นๆ ด้วย Bazel จะดูแลฐานข้อมูลของงานทั้งหมดที่ทำก่อนหน้านี้ และจะข้ามขั้นตอนการสร้างเฉพาะในกรณีที่พบว่าชุดไฟล์อินพุต (และการประทับเวลา) ของขั้นตอนการสร้างนั้น และคำสั่งคอมไพล์สำหรับขั้นตอนการสร้างนั้นตรงกับรายการในฐานข้อมูลทุกประการ และชุดไฟล์เอาต์พุต (และการประทับเวลา) ของรายการฐานข้อมูลตรงกับการประทับเวลาของไฟล์ในดิสก์ทุกประการ การเปลี่ยนแปลงใดๆ ในไฟล์อินพุตหรือเอาต์พุต หรือกับคำสั่งนั้น จะทำให้เกิดการดำเนินการขั้นตอนบิลด์อีกครั้ง
ประโยชน์สำหรับผู้ใช้ของบิลด์ที่เพิ่มขึ้นที่ถูกต้องคือ การเสียเวลาน้อยลงเนื่องจาก
ความสับสน (นอกจากนี้ ยังใช้เวลาน้อยลงในการรอการสร้างใหม่ที่เกิดจากการใช้ make
clean
ไม่ว่าจะจําเป็นหรือต้องมีการเตรียมการ)
สร้างความสอดคล้องและบิลด์ที่เพิ่มขึ้น
โดยทั่วไปแล้ว เราจะกำหนดสถานะของบิลด์ว่าสอดคล้องกันเมื่อไฟล์เอาต์พุตที่คาดไว้ทั้งหมดมีอยู่ และเนื้อหาของไฟล์ถูกต้องตามที่ระบุไว้ในขั้นตอนหรือกฎที่จำเป็นต่อการสร้าง เมื่อคุณแก้ไขไฟล์ต้นฉบับ ระบบจะถือว่าสถานะการสร้างไม่สอดคล้องกัน และยังคงไม่สอดคล้องกันจนกว่าคุณจะเรียกใช้เครื่องมือสร้างให้เสร็จสมบูรณ์ในครั้งถัดไป เราอธิบายสถานการณ์นี้ว่าไม่เสถียร ข้อมูลไม่สอดคล้องกัน เนื่องจากเกิดขึ้นเพียงชั่วคราว และความสม่ำเสมอจะได้รับการกู้คืนโดย ที่กำลังเรียกใช้เครื่องมือสร้าง
ยังมีความไม่สอดคล้องกันอีกประเภทหนึ่งที่ร้ายแรง นั่นคือเวอร์ชันเสถียร
ความไม่สอดคล้องกัน หากบิลด์มีสภาวะที่ไม่สอดคล้องกันแบบคงที่ ระบบจะทำซ้ำ
การเรียกใช้เครื่องมือสร้างสำเร็จไม่กู้คืนความสอดคล้อง: บิลด์
"ค้าง" และเอาต์พุตยังคงไม่ถูกต้อง สถานะที่คงที่แต่ไม่สอดคล้องกันเป็นตัวแปรหลักที่ทำให้ผู้ใช้ Make (และเครื่องมือสร้างอื่นๆ) พิมพ์ make clean
และพบว่าเครื่องมือสร้างล้มเหลวในลักษณะนี้ (และทำการกู้คืนหลังจากนั้น
จาก URL) อาจใช้เวลานานและน่าหงุดหงิดอย่างมาก
โดยหลักการแล้ว วิธีที่ง่ายที่สุดในการสร้างผลงานที่สม่ำเสมอคือการละทิ้ง เอาต์พุตของบิลด์ก่อนหน้าทั้งหมดและเริ่มอีกครั้ง: ทำให้ทุกบิลด์เป็นบิลด์ที่สะอาด เห็นได้ชัดว่าวิธีการนี้ใช้เวลานานเกินไปที่จะนำมาใช้ได้จริง (ยกเว้นบางที สำหรับวิศวกรที่เปิดตัว) ดังนั้น เครื่องมือบิลด์จะต้องสามารถ สร้างบิลด์เพิ่มขึ้นโดยไม่กระทบต่อความสม่ำเสมอ
การวิเคราะห์ทรัพยากร Dependency ที่เพิ่มขึ้นอย่างถูกต้องนั้นทำได้ยาก และอย่างที่ได้อธิบายไปแล้ว เครื่องมือบิลด์อื่นๆ ทำงานได้ไม่ดี เพื่อหลีกเลี่ยงสถานะที่ไม่สอดคล้องกันและคงที่ในระหว่าง งานสร้างที่เพิ่มขึ้น ในทางตรงกันข้าม Bazel ให้การรับประกันดังต่อไปนี้ หลังจากเรียกใช้เครื่องมือสร้างสำเร็จโดยที่คุณไม่ได้ทำการแก้ไขใดๆ การสร้างจะอยู่ในสถานะที่สอดคล้องกัน (หากคุณแก้ไขไฟล์ต้นฉบับในระหว่าง Bazel ไม่ได้ให้การรับประกันใดๆ เกี่ยวกับความสอดคล้องของผลลัพธ์ของ บิลด์ปัจจุบัน แต่รับประกันได้ว่าผลลัพธ์ของบิลด์ถัดไปจะ เพื่อความสอดคล้อง)
เช่นเดียวกับการรับประกันทั้งหมด ก็มีรายละเอียดปลีกย่อยอยู่บ้าง ซึ่งเราทราบมาว่ามีวิธีบางอย่างที่ทำให้เกิดสถานะไม่สอดคล้องกันซึ่งเสถียรกับ Bazel เราจะไม่รับประกันว่า ตรวจสอบปัญหาดังกล่าวซึ่งเกิดขึ้นจากความพยายามอย่างตั้งใจเพื่อค้นหาข้อบกพร่องใน การวิเคราะห์ทรัพยากร Dependency เพิ่มเติม แต่เราจะตรวจสอบ และพยายามอย่างเต็มที่เพื่อแก้ไข สถานะที่ไม่สอดคล้องกันและคงที่ทั้งหมดซึ่งเกิดขึ้นจากปกติหรือ "สมเหตุผล" การใช้ เครื่องมือสร้างขึ้นมา
หากตรวจพบสถานะที่ไม่สอดคล้องกันและเสถียรของ Bazel โปรดรายงานข้อบกพร่อง
การดำเนินการที่แซนด์บ็อกซ์
Bazel ใช้แซนด์บ็อกซ์เพื่อรับประกันว่าการดำเนินการจะทำงานอย่างถูกต้องและปลอดภัย Bazel เรียกใช้spawns (พูดง่ายๆ คือการดำเนินการ) ในแซนด์บ็อกซ์ที่
ประกอบด้วยชุดไฟล์น้อยที่สุดที่เครื่องมือต้องใช้ในการทำงาน ปัจจุบัน Sandboxing ใช้งานได้ใน Linux 3.12 ขึ้นไปที่เปิดใช้ตัวเลือก CONFIG_USER_NS
และใน macOS 10.11 ขึ้นไป
Bazel จะพิมพ์คำเตือนหากระบบไม่รองรับแซนด์บ็อกซ์ เพื่อแจ้งเตือน
ข้อเท็จจริงที่ว่างานสร้างไม่รับประกันว่าสูญเปล่าไม่ได้และอาจส่งผลกระทบต่อ
ระบบโฮสต์ในรูปแบบที่ไม่รู้จัก หากต้องการปิดคำเตือนนี้ คุณสามารถส่งผ่าน
--ignore_unsupported_sandboxing
แจ้งไปที่ Bazel
ในบางแพลตฟอร์ม เช่น Google Kubernetes
เครื่องมือโหนดคลัสเตอร์หรือ Debian
เนมสเปซของผู้ใช้จะถูกปิดใช้งานโดยค่าเริ่มต้นเนื่องจากความปลอดภัย
ของ Google ตรวจสอบได้โดยดูที่ไฟล์ /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
ในกรณีนี้ ให้ลองปิดใช้งานแซนด์บ็อกซ์สำหรับ Genrule ด้วย
--strategy=Genrule=standalone
และสำหรับกฎอื่นๆ ที่มี
--spawn_strategy=standalone
และโปรดรายงานข้อบกพร่องใน
เครื่องมือติดตามปัญหาและระบุว่าคุณกำลังใช้งาน Linux ใดอยู่เพื่อให้เรา
ตรวจสอบและทำการแก้ไขในรุ่นต่อๆ ไป
ขั้นของบิลด์
ใน Bazel การก่อสร้างจะเกิดขึ้นใน 3 ระยะที่แตกต่างกัน ได้แก่ ในฐานะผู้ใช้ การทำความเข้าใจ ซึ่งจะให้ข้อมูลเชิงลึกเกี่ยวกับตัวเลือกที่ควบคุมบิลด์ (ดูด้านล่าง)
ระยะการโหลด
ขั้นตอนแรกคือการโหลด ซึ่งจะโหลด แยกวิเคราะห์ ประเมิน และแคชไฟล์ BUILD ที่จำเป็นทั้งหมดสำหรับเป้าหมายเริ่มต้นและชุดค่าผสมแบบทรานซิทีฟของข้อกำหนด
สำหรับบิลด์แรกหลังจากเริ่มเซิร์ฟเวอร์ Bazel ระยะการโหลดมักจะใช้เวลาหลายวินาทีเนื่องจากมีการโหลดไฟล์ BUILD จำนวนมากจากระบบไฟล์ ในบิวด์ต่อๆ ไป โดยเฉพาะหากไม่มีการเปลี่ยนแปลงไฟล์ BUILD การโหลดจะเกิดขึ้นอย่างรวดเร็ว
ข้อผิดพลาดที่รายงานในระยะนี้ ได้แก่ ไม่พบแพ็กเกจ ไม่พบเป้าหมาย ข้อผิดพลาดด้านภาษาและไวยากรณ์ในไฟล์ BUILD และข้อผิดพลาดการประเมิน
ช่วงการวิเคราะห์
ขั้นที่ 2 การวิเคราะห์จะเกี่ยวข้องกับการวิเคราะห์เชิงอรรถศาสตร์และการตรวจสอบความถูกต้องของ กฎบิลด์แต่ละรายการ การสร้างกราฟทรัพยากร Dependency ของบิลด์ และ การกำหนดสิ่งที่ต้องทำในแต่ละขั้นตอนของการสร้าง
เช่นเดียวกับการโหลด การวิเคราะห์ยังใช้เวลาหลายวินาทีเมื่อคำนวณอย่างครบถ้วน อย่างไรก็ตาม Bazel จะแคชกราฟทรัพยากร Dependency จากบิลด์หนึ่งไปยังอีกบิลด์หนึ่ง วิเคราะห์ว่าต้องใช้อะไรบ้าง ซึ่งสามารถ ทำให้งานสร้างที่ค่อยๆ เพิ่มขึ้นเป็นไปอย่างรวดเร็ว ในกรณีที่แพ็กเกจไม่มีการเปลี่ยนแปลงนับตั้งแต่บิลด์ก่อนหน้า
ข้อผิดพลาดที่รายงานในระยะนี้ ได้แก่ Dependency ที่ไม่เหมาะสม อินพุตที่ไม่ถูกต้องของกฎ และข้อความแสดงข้อผิดพลาดเฉพาะกฎทั้งหมด
ระยะการโหลดและการวิเคราะห์จะรวดเร็วเนื่องจาก Bazel หลีกเลี่ยง I/O ของไฟล์ที่ไม่จำเป็นในระยะนี้ โดยจะอ่านเฉพาะไฟล์ BUILD เพื่อกำหนดงานที่จะทำ การดำเนินการนี้เป็นไปตามการออกแบบและทำให้ Bazel เป็นรากฐานที่ดีสำหรับเครื่องมือวิเคราะห์ เช่น คำสั่ง query ของ Bazel ซึ่งติดตั้งใช้งานในเฟสการโหลด
ระยะการดำเนินการ
ระยะที่ 3 และเป็นระยะสุดท้ายของการสร้างคือการดำเนินการ ขั้นตอนนี้ช่วยให้มั่นใจได้ว่า เอาต์พุตของแต่ละขั้นตอนในการสร้างสอดคล้องกับอินพุตของขั้นตอนนั้น เรียกใช้อีกครั้ง การรวบรวม/การลิงก์/ฯลฯ เครื่องมือที่จำเป็น ขั้นตอนนี้เป็นขั้นตอนที่ใช้เวลาส่วนใหญ่ในการสร้าง ซึ่งอาจใช้เวลาตั้งแต่ 2-3 วินาทีไปจนถึงกว่า 1 ชั่วโมงสำหรับบิลด์ขนาดใหญ่ ข้อผิดพลาดที่รายงานระหว่างระยะนี้ ได้แก่ ไฟล์ต้นฉบับขาดหายไป ข้อผิดพลาดในเครื่องมือที่ดำเนินการโดยการดำเนินการบางอย่างของบิลด์ หรือการไม่สำเร็จของเครื่องมือในการสร้างชุดเอาต์พุตที่คาดไว้