หน้านี้จะตอบคําถามที่พบบ่อยบางข้อเกี่ยวกับทรัพยากรภายนอกใน Bazel
MODULE.bazel
เหตุใด MODULE.bazel จึงไม่รองรับ load
ในระหว่างการแก้ไขข้อกำหนด จะมีการดึงข้อมูลไฟล์ MODULE.bazel ของข้อกำหนดภายนอกทั้งหมดที่อ้างอิงจากรีจิสทรี ในขั้นตอนนี้ ระบบยังไม่ได้ดึงข้อมูลไฟล์เก็บถาวรต้นทางของข้อกําหนดเบื้องต้น ดังนั้นหากไฟล์ MODULE.bazel load
เป็นไฟล์อื่น Bazel จะดึงข้อมูลไฟล์นั้นไม่ได้หากไม่ดึงข้อมูลไฟล์เก็บถาวรต้นทางทั้งหมด โปรดทราบว่าไฟล์ MODULE.bazel นั้นมีความพิเศษเนื่องจากโฮสต์อยู่ในรีจิสทรีโดยตรง
โดยทั่วไปแล้ว ผู้ใช้ที่ขอ load
ใน MODULE.bazel จะสนใจ Use Case ต่อไปนี้ ซึ่งสามารถแก้ปัญหาได้โดยไม่ต้องใช้ load
- ตรวจสอบว่าเวอร์ชันที่แสดงใน MODULE.bazel สอดคล้องกับข้อมูลเมตาของบิลด์ที่จัดเก็บไว้ที่อื่น เช่น ในไฟล์ .bzl ซึ่งทำได้โดยใช้เมธอด
native.module_version
ในไฟล์ .bzl ที่โหลดจากไฟล์ BUILD - การแยกไฟล์ MODULE.bazel ขนาดใหญ่มากออกเป็นส่วนๆ ที่จัดการได้ โดยเฉพาะอย่างยิ่งสำหรับโมโนรีโป: โมดูลรูทสามารถใช้คำสั่ง
include
เพื่อแยกไฟล์ MODULE.bazel ออกเป็นหลายส่วนinclude
ใช้ในโมดูลที่ไม่ใช่รูทไม่ได้ด้วยเหตุผลเดียวกันกับที่เราไม่อนุญาตให้ใช้load
ในไฟล์ MODULE.bazel - ผู้ใช้ระบบ WORKSPACE เดิมอาจจำได้ว่าต้องประกาศรีโป จากนั้น
load
จากรีโปนั้นทันทีเพื่อดำเนินการตามตรรกะที่ซับซ้อน ส่วนขยายโมดูลเข้ามาแทนที่ความสามารถนี้
ฉันจะระบุช่วง SemVer สำหรับ bazel_dep
ได้ไหม
ไม่ได้ เครื่องมือจัดการแพ็กเกจอื่นๆ บางรายการ เช่น npm และ Cargo รองรับช่วงเวอร์ชัน (โดยนัยหรือโดยชัดแจ้ง) และมักต้องใช้โปรแกรมแก้ปัญหาข้อจำกัด (ทำให้ผู้ใช้คาดเดาเอาต์พุตได้ยากขึ้น) และทำให้ไม่สามารถแก้ไขเวอร์ชันซ้ำได้หากไม่มีไฟล์ล็อก
แต่ Bazel ใช้การเลือกเวอร์ชันขั้นต่ำแทน เช่นเดียวกับ Go ซึ่งทำให้คาดการณ์เอาต์พุตได้ง่ายและรับประกันความสามารถในการทำซ้ำ ซึ่งเป็นข้อเสียที่สอดคล้องกับเป้าหมายการออกแบบของ Bazel
นอกจากนี้ เวอร์ชันโมดูล Bazel ยังเป็นเซตที่ใหญ่กว่าของ SemVer ดังนั้นสิ่งที่สมเหตุสมผลในสภาพแวดล้อม SemVer ที่เข้มงวดอาจใช้กับเวอร์ชันโมดูล Bazel ไม่ได้เสมอไป
ฉันจะรับ bazel_dep
เวอร์ชันล่าสุดโดยอัตโนมัติได้ไหม
บางครั้งผู้ใช้บางรายจะขอความสามารถในการระบุ bazel_dep(name = "foo",
version = "latest")
เพื่อรับเวอร์ชันล่าสุดของ Dep โดยอัตโนมัติ ซึ่งคล้ายกับคำถามเกี่ยวกับช่วง SemVer และคำตอบก็คือ "ไม่ได้"
โซลูชันที่แนะนําคือให้การทำงานอัตโนมัติจัดการเรื่องนี้ ตัวอย่างเช่น Renovate รองรับโมดูล Bazel
บางครั้งผู้ใช้ที่ถามคำถามนี้ต้องการวิธีทําซ้ำอย่างรวดเร็วระหว่างการพัฒนาในเครื่อง ซึ่งทำได้โดยใช้
local_path_override
เหตุใดจึงมีuse_repo
ทั้งหมดนี้
การใช้ส่วนขยายโมดูลในไฟล์ MODULE.bazel บางครั้งมาพร้อมกับคำสั่ง use_repo
ขนาดใหญ่ ตัวอย่างเช่น การใช้งานทั่วไปของส่วนขยาย go_deps
จาก gazelle
อาจมีลักษณะดังนี้
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(
go_deps,
"com_github_gogo_protobuf",
"com_github_golang_mock",
"com_github_golang_protobuf",
"org_golang_x_net",
... # potentially dozens of lines...
)
คำสั่ง use_repo
แบบยาวอาจดูซ้ำซ้อน เนื่องจากข้อมูลดังกล่าวอยู่ในไฟล์ go.mod
ที่อ้างอิงอยู่แล้ว
สาเหตุที่ Bazel ต้องใช้คำสั่ง use_repo
นี้เนื่องจากจะเรียกใช้ส่วนขยายของข้อบังคับแบบเลื่อนเวลา กล่าวคือ ระบบจะเรียกใช้ส่วนขยายโมดูลก็ต่อเมื่อมีการตรวจพบผลลัพธ์ของส่วนขยายเท่านั้น เนื่องจาก "เอาต์พุต" ของส่วนขยายโมดูลคือคําจํากัดความของที่เก็บ หมายความว่าเราจะเรียกใช้ส่วนขยายโมดูลก็ต่อเมื่อมีคําขอที่เก็บที่ส่วนขยายนั้นกําหนด (เช่น หากมีการบิลด์ @org_golang_x_net//:foo
เป้าหมายในตัวอย่างข้างต้น) อย่างไรก็ตาม เราจะไม่ทราบว่าส่วนขยายโมดูลจะกำหนดที่เก็บใดจนกว่าจะหลังจากเรียกใช้ คำสั่ง use_repo
จะใช้ในกรณีนี้ โดยผู้ใช้สามารถบอก Bazel ว่าต้องการให้สร้างส่วนขยายจากรีโพสิทอรี่ใด จากนั้น Bazel จะเรียกใช้ส่วนขยายก็ต่อเมื่อมีการใช้รีโพสิทอรี่ที่เฉพาะเจาะจงเหล่านี้เท่านั้น
ส่วนขยายโมดูลสามารถแสดงผลออบเจ็กต์ extension_metadata
จากฟังก์ชันการใช้งานเพื่อช่วยดูแลรักษาคำสั่ง use_repo
นี้ ผู้ใช้สามารถเรียกใช้คำสั่ง bazel mod tidy
เพื่ออัปเดตคำสั่ง use_repo
สำหรับส่วนขยายโมดูลเหล่านี้
การย้ายข้อมูล Bzlmod
ระบบจะประเมิน MODULE.bazel หรือ WORKSPACE ก่อน
เมื่อตั้งค่าทั้ง --enable_bzlmod
และ --enable_workspace
แล้ว คุณอาจสงสัยว่าระบบใดจะได้รับการปรึกษาก่อน คำตอบสั้นๆ คือ ระบบจะประเมิน MODULE.bazel (Bzlmod) ก่อน
คำตอบแบบละเอียดคือ "รายการใดจะประเมินก่อน" ไม่ใช่คำถามที่ถูกต้อง แต่คำถามที่ถูกต้องคือ ในบริบทของรีโปที่มีชื่อตามหลักเกณฑ์ @@foo
ชื่อรีโปที่ปรากฏ @bar
จะเปลี่ยนเป็นอะไร หรือจะถามเป็นการแมปรีโปของ @@base
ก็ได้
ป้ายกำกับที่มีชื่อรีโปที่ชัดเจน (@
นำหน้าเพียงตัวเดียว) อาจหมายถึงสิ่งต่างๆ ที่แตกต่างกันไปตามบริบทที่แก้ไข เมื่อเห็นป้ายกำกับ @bar//:baz
และสงสัยว่าป้ายกำกับนั้นชี้ไปยังอะไร คุณจะต้องค้นหารีโปบริบทก่อน เช่น หากป้ายกำกับอยู่ในไฟล์ BUILD ซึ่งอยู่ในรีโป @@foo
รีโปบริบทก็คือ @@foo
จากนั้นใช้ตาราง"repository visibility" ในคู่มือการย้ายข้อมูลเพื่อดูว่าชื่อที่ปรากฏจะนำไปยังที่เก็บข้อมูลใด ทั้งนี้ขึ้นอยู่กับที่เก็บข้อมูลตามบริบท
- หากที่เก็บรีพอสิทเป็นรีพอสิทหลัก (
@@
) ให้ทำดังนี้- หาก
bar
เป็นชื่อรีโปที่ชัดเจนซึ่งแสดงโดยไฟล์ MODULE.bazel ของโมดูลรูท (ผ่านไฟล์bazel_dep
,use_repo
,module
หรือuse_repo_rule
)@bar
จะเปลี่ยนเป็นค่าที่ไฟล์ MODULE.bazel อ้างอิง - หรือหาก
bar
เป็นรีโปที่กําหนดไว้ใน WORKSPACE (ซึ่งหมายความว่าชื่อที่เป็นทางการคือ@@bar
)@bar
จะเปลี่ยนเป็น@@bar
- มิเช่นนั้น
@bar
จะเปลี่ยนเป็นรูปแบบอย่าง@@[unknown repo 'bar' requested from @@]
ซึ่งท้ายที่สุดแล้วจะทำให้มีข้อผิดพลาด
- หาก
- หากที่เก็บข้อมูลบริบทเป็นที่เก็บข้อมูล Bzlmod-world (กล่าวคือ สอดคล้องกับโมดูล Bazel ที่ไม่ใช่รูท หรือสร้างขึ้นโดยส่วนขยายโมดูล) ที่เก็บข้อมูลดังกล่าวจะเห็นเฉพาะที่เก็บข้อมูล Bzlmod-world อื่นๆ เท่านั้น และจะไม่พบที่เก็บข้อมูล WORKSPACE-world
- โปรดทราบว่าการดำเนินการนี้รวมถึงรีพอสิที่เปิดตัวในส่วนขยายโมดูล
non_module_deps
-like ในโมดูลรูท หรือการสร้างอินสแตนซ์use_repo_rule
ในโมดูลรูท
- โปรดทราบว่าการดำเนินการนี้รวมถึงรีพอสิที่เปิดตัวในส่วนขยายโมดูล
- หากกำหนดที่เก็บรีพอสิทของบริบทใน WORKSPACE ให้ทำดังนี้
- ก่อนอื่น ให้ตรวจสอบว่าคําจํากัดความของที่เก็บรีพอซีตมีแอตทริบิวต์
repo_mapping
หรือไม่ หากใช่ ให้ดูการแมปก่อน (สําหรับที่เก็บข้อมูลที่กําหนดด้วยrepo_mapping = {"@bar": "@baz"}
เราจะดูที่@baz
ด้านล่าง) - หาก
bar
เป็นชื่อรีโปที่ชัดเจนซึ่งแสดงโดยไฟล์ MODULE.bazel ของโมดูลรูท@bar
จะแสดงผลเป็นค่าที่ไฟล์ MODULE.bazel อ้างอิง (การดำเนินการนี้เหมือนกับรายการที่ 1 ในกรณีของรีโปหลัก) - มิเช่นนั้น
@bar
จะเปลี่ยนเป็น@@bar
ซึ่งส่วนใหญ่จะชี้ไปยังรีโพสิทอรี่bar
ที่กําหนดไว้ใน WORKSPACE หากไม่ได้กําหนดรีโพสิทอรี่ดังกล่าว Bazel จะแสดงข้อผิดพลาด
- ก่อนอื่น ให้ตรวจสอบว่าคําจํากัดความของที่เก็บรีพอซีตมีแอตทริบิวต์
สำหรับเวอร์ชันที่กระชับยิ่งขึ้น
- รีโพสิทอรี่ Bzlmod-world (ยกเว้นรีโพสิทอรี่หลัก) จะมองเห็นเฉพาะรีโพสิทอรี่ Bzlmod-world
- รีโพซิทอรี WORKSPACE-world (รวมถึงรีโพซิทอรีหลัก) จะดูว่าโมดูลรูทในโลก Bzlmod กำหนดอะไรไว้ก่อน จากนั้นจึงเปลี่ยนไปดูรีโพซิทอรี WORKSPACE-world
โปรดทราบว่าระบบจะถือว่าป้ายกำกับในบรรทัดคำสั่งของ Bazel (รวมถึง Flag ของ Starlark, ค่า Flag ที่เป็นประเภทป้ายกำกับ และรูปแบบเป้าหมายการสร้าง/ทดสอบ) มีที่เก็บข้อมูลหลักเป็นที่เก็บข้อมูลบริบท
อื่นๆ
ฉันจะเตรียมและเรียกใช้บิลด์แบบออฟไลน์ได้อย่างไร
ใช้คำสั่ง bazel fetch
เพื่อโหลดรีโปล่วงหน้า คุณสามารถใช้ Flag --repo
(เช่น bazel fetch --repo @foo
) เพื่อดึงข้อมูลเฉพาะที่เก็บ @foo
(แก้ไขในบริบทของที่เก็บหลัก ดูคำถามด้านบน) หรือใช้รูปแบบเป้าหมาย (เช่น bazel fetch @foo//:bar
) เพื่อดึงข้อมูล Dependency แบบทรานซิทีฟทั้งหมดของ @foo//:bar
(เทียบเท่ากับ bazel build --nobuild @foo//:bar
)
หากต้องการให้ไม่มีการดึงข้อมูลระหว่างการสร้าง ให้ใช้ --nofetch
กล่าวอย่างเจาะจงคือ การดำเนินการใดๆ ก็ตามเพื่อเรียกใช้กฎที่เก็บข้อมูลภายนอกจะไม่สำเร็จ
หากต้องการดึงข้อมูลรีโพสและแก้ไขเพื่อทดสอบในเครื่อง ให้ลองใช้คำสั่ง bazel vendor
ฉันจะใช้พร็อกซี HTTP ได้อย่างไร
Bazel จะใช้ตัวแปรสภาพแวดล้อม http_proxy
และ HTTPS_PROXY
ที่โปรแกรมอื่นๆ ยอมรับโดยทั่วไป เช่น curl
How do I make Bazel prefer IPv6 in dual-stack IPv4/IPv6 setups?
ในเครื่องที่ใช้ IPv6 เท่านั้น Bazel จะดาวน์โหลดทรัพยากรที่เกี่ยวข้องได้โดยไม่ต้องเปลี่ยนแปลง อย่างไรก็ตาม ในเครื่องแบบ Dual Stack IPv4/IPv6 Bazel จะเป็นไปตามรูปแบบเดียวกับ Java โดยจะใช้ IPv4 เป็นหลักหากเปิดใช้ ในบางกรณี เช่น เมื่อเครือข่าย IPv4 ไม่สามารถแก้ไข/เข้าถึงที่อยู่ภายนอกได้ อาจทำให้เกิดข้อยกเว้น Network
unreachable
และการสร้างไม่สำเร็จ ในกรณีเหล่านี้ คุณสามารถลบล้างลักษณะการทํางานของ Bazel เพื่อใช้ IPv6 เป็นหลักได้โดยใช้java.net.preferIPv6Addresses=true
พร็อพเพอร์ตี้ของระบบ
ดังนี้
ใช้
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
startup option เช่น เพิ่มบรรทัดต่อไปนี้ในไฟล์.bazelrc
startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
เมื่อเรียกใช้เป้าหมายการสร้าง Java ที่ต้องเชื่อมต่ออินเทอร์เน็ต (เช่น สําหรับการทดสอบการผสานรวม) ให้ใช้
--jvmopt=-Djava.net.preferIPv6Addresses=true
flag ของเครื่องมือ เช่น ใส่ข้อมูลต่อไปนี้ใน.bazelrc
ไฟล์build --jvmopt=-Djava.net.preferIPv6Addresses
หากคุณใช้
rules_jvm_external
ในการแก้ไขเวอร์ชันของข้อกำหนด ให้เพิ่ม-Djava.net.preferIPv6Addresses=true
ลงในตัวแปรสภาพแวดล้อมCOURSIER_OPTS
เพื่อระบุตัวเลือก JVM สำหรับ Coursier ด้วย
กฎของ repo ทำงานจากระยะไกลด้วยการดำเนินการจากระยะไกลได้ไหม
ไม่ หรืออย่างน้อยก็ยังไม่มี ผู้ใช้ที่ใช้บริการการเรียกใช้จากระยะไกลเพื่อเร่งความเร็วการสร้างอาจเห็นว่ากฎของรีโปยังคงทำงานในเครื่อง ตัวอย่างเช่น ระบบจะดาวน์โหลดhttp_archive
ลงในเครื่อง (โดยใช้แคชการดาวน์โหลดในเครื่อง หากมี) จากนั้นจะแตกไฟล์ จากนั้นจะอัปโหลดไฟล์ต้นทางแต่ละไฟล์ไปยังบริการการเรียกใช้ระยะไกลเป็นไฟล์อินพุต คุณอาจสงสัยว่าเหตุใดบริการการเรียกใช้จากระยะไกลจึงไม่ดาวน์โหลดและแตกไฟล์เก็บถาวรนั้นเลยเพื่อประหยัดเวลาในการส่งข้อมูลไปมา
สาเหตุส่วนหนึ่งคือกฎของ repo (และส่วนขยายโมดูล) คล้ายกับ "สคริปต์" ที่ Bazel เรียกใช้เอง ผู้ดำเนินการระยะไกลไม่จำเป็นต้องติดตั้ง Bazel ไว้ด้วย
อีกเหตุผลหนึ่งคือ Bazel มักต้องใช้ไฟล์ BUILD ในไฟล์เก็บถาวรที่ดาวน์โหลดและแตกไฟล์เพื่อทำการโหลดและการวิเคราะห์ ซึ่งดำเนินการในเครื่อง
เรามีแนวคิดเบื้องต้นในการแก้ปัญหานี้ด้วยการจินตนาการกฎของ repo ใหม่เป็นกฎการสร้าง ซึ่งจะทำให้สามารถเรียกใช้จากระยะไกลได้ แต่ในทางกลับกันก็อาจทำให้เกิดข้อกังวลด้านสถาปัตยกรรมใหม่ (เช่น คำสั่ง query
อาจต้องเรียกใช้การดำเนินการ ซึ่งทำให้การออกแบบมีความซับซ้อน)
ดูการสนทนาก่อนหน้านี้เพิ่มเติมเกี่ยวกับหัวข้อนี้ได้ที่วิธีรองรับที่เก็บซึ่งต้องใช้ Bazel ในการดึงข้อมูล