หน้านี้จะตอบคำถามที่พบบ่อยบางข้อเกี่ยวกับทรัพยากร Dependency ภายนอกใน Bazel
MODULE.bazel
ฉันควรกำหนดเวอร์ชันของโมดูล Bazel อย่างไร
การตั้งค่า version ด้วยคําสั่ง module ในที่เก็บต้นฉบับ
MODULE.bazel อาจมีข้อเสียและผลข้างเคียงที่ไม่พึงประสงค์หลายประการหากไม่
ได้รับการจัดการอย่างรอบคอบ
การทำซ้ำ: การเผยแพร่โมดูลเวอร์ชันใหม่มักเกี่ยวข้องกับการเพิ่มเวอร์ชันใน
MODULE.bazelและการติดแท็กการเผยแพร่ ซึ่งเป็น 2 ขั้นตอนแยกกันที่อาจไม่ซิงค์กัน แม้ว่าการทำงานอัตโนมัติจะช่วยลดความเสี่ยงนี้ได้ แต่การหลีกเลี่ยงความเสี่ยงนี้ไปเลยก็เป็นวิธีที่ง่ายและปลอดภัยกว่าความไม่สอดคล้องกัน: ผู้ใช้ที่ลบล้างโมดูลด้วยคอมมิตที่เฉพาะเจาะจงโดยใช้การลบล้างที่ไม่ใช่รีจิสทรีจะเห็นเวอร์ชันที่ไม่ถูกต้อง เช่น หาก
MODULE.bazelในที่เก็บต้นฉบับตั้งค่าเป็นversion = "0.3.0"แต่มีการคอมมิตเพิ่มเติมตั้งแต่การเผยแพร่นั้น ผู้ใช้ที่ลบล้างด้วยคอมมิตใดคอมมิตหนึ่งจะยังคงเห็น0.3.0ในความเป็นจริง เวอร์ชัน ควรแสดงให้เห็นว่าเวอร์ชันนั้นอยู่ก่อนการเผยแพร่ เช่น0.3.1-rc1ปัญหาการลบล้างที่ไม่ใช่รีจิสทรี: การใช้ค่าตัวยึดตำแหน่งอาจทำให้เกิดปัญหา เมื่อผู้ใช้ลบล้างโมดูลด้วยการลบล้างที่ไม่ใช่รีจิสทรี เช่น
0.0.0จะไม่จัดเรียงเป็นเวอร์ชันสูงสุด ซึ่งโดยปกติแล้วจะเป็นลักษณะการทำงานที่ผู้ใช้ต้องการเมื่อทำการลบล้างที่ไม่ใช่รีจิสทรี
ดังนั้น คุณจึงควรหลีกเลี่ยงการตั้งค่าเวอร์ชันในที่เก็บต้นทาง
MODULE.bazel แต่ให้ตั้งค่าใน MODULE.bazel ที่จัดเก็บไว้ในรีจิสทรี
(เช่น รีจิสทรีกลางของ Bazel) ซึ่งเป็นแหล่งข้อมูลที่แท้จริงสำหรับ
เวอร์ชันของโมดูลในระหว่างการแก้ปัญหาการอ้างอิงภายนอกของ Bazel (ดูรีจิสทรีของ Bazel)
โดยปกติแล้วกระบวนการนี้จะทำงานโดยอัตโนมัติ เช่น ที่เก็บกฎตัวอย่าง rules-template จะใช้ bazel-contrib/publish-to-bcr publish.yaml GitHub Action เพื่อ
เผยแพร่รุ่นไปยัง BCR การดำเนินการนี้จะสร้างแพตช์สำหรับแหล่งที่มา
ที่เก็บถาวร MODULE.bazel พร้อมกับเวอร์ชันที่เผยแพร่ ระบบจะจัดเก็บแพตช์นี้ไว้ในรีจิสทรีและใช้เมื่อดึงข้อมูลโมดูลระหว่างการแก้ปัญหาการอ้างอิงภายนอกของ Bazel
ด้วยวิธีนี้ ระบบจะตั้งค่าเวอร์ชันในรุ่นที่อยู่ในรีจิสทรีเป็นเวอร์ชันที่เผยแพร่แล้วอย่างถูกต้อง
ดังนั้น bazel_dep, single_version_override และ
multiple_version_override จะทำงานตามที่คาดไว้ ในขณะที่หลีกเลี่ยงปัญหาที่อาจเกิดขึ้น
เมื่อทำการลบล้างที่ไม่ใช่รีจิสทรี เนื่องจากเวอร์ชันในแหล่งที่มา
ของที่เก็บถาวรจะเป็นค่าเริ่มต้น ('') ซึ่งระบบจะจัดการอย่างถูกต้องเสมอ (เป็นค่าเวอร์ชันเริ่มต้น) และจะทำงานตามที่คาดไว้เมื่อจัดเรียง (ระบบจะถือว่าสตริงว่างเป็นเวอร์ชันสูงสุด)
ฉันควรเพิ่มระดับความเข้ากันได้เมื่อใด
compatibility_level ของโมดูล Bazel
ควรเพิ่มขึ้นในการคอมมิตเดียวกันที่ทำให้เกิดการเปลี่ยนแปลงที่ไม่เข้ากันแบบย้อนหลัง ("การเปลี่ยนแปลงที่ทำให้เกิดข้อขัดข้อง")
อย่างไรก็ตาม Bazel อาจแสดงข้อผิดพลาดหากตรวจพบว่ามีโมดูลเดียวกันที่มีระดับความเข้ากันได้แตกต่างกันอยู่ในกราฟการอ้างอิงที่แก้ไขแล้ว กรณีนี้อาจเกิดขึ้นเมื่อโมดูล 2 โมดูลขึ้นไปขึ้นอยู่กับโมดูลที่ 3 ซึ่งมีระดับความเข้ากันได้ต่างกัน
ดังนั้น การเพิ่ม compatibility_level บ่อยเกินไปอาจเป็นการรบกวนอย่างมาก
และไม่แนะนำ เพื่อหลีกเลี่ยงสถานการณ์นี้ compatibility_level ควรเพิ่มขึ้นเฉพาะเมื่อการเปลี่ยนแปลงที่ไม่รองรับการทำงานร่วมกันส่งผลต่อกรณีการใช้งานส่วนใหญ่ และไม่สามารถย้ายข้อมูลและ/หรือแก้ไขได้ง่าย
เหตุใด MODULE.bazel จึงไม่รองรับ loads
ในระหว่างการแก้ปัญหาการขึ้นต่อกัน ระบบจะดึงข้อมูลไฟล์ MODULE.bazel ของการขึ้นต่อกันภายนอกทั้งหมดที่อ้างอิงจากรีจิสทรี ในขั้นตอนนี้ ระบบยังไม่ได้ดึงข้อมูลที่เก็บถาวรต้นทางของ
การอ้างอิง ดังนั้นหากไฟล์ MODULE.bazel loads
ไฟล์อื่น Bazel จะไม่มีทางดึงข้อมูลไฟล์นั้นได้จริงโดยไม่ต้อง
ดึงข้อมูลที่เก็บถาวรต้นฉบับทั้งหมด โปรดทราบว่าไฟล์ MODULE.bazel นั้นมีความพิเศษเนื่องจากโฮสต์อยู่ในรีจิสทรีโดยตรง
มี Use Case บางอย่างที่ผู้ใช้ที่ขอ loads ใน MODULE.bazel มักสนใจ และสามารถแก้ไขได้โดยไม่ต้องใช้ loads ดังนี้
- การตรวจสอบว่าเวอร์ชันที่แสดงใน MODULE.bazel สอดคล้องกับข้อมูลเมตาของบิลด์ที่จัดเก็บไว้ที่อื่น เช่น ในไฟล์ .bzl ทำได้โดยใช้วิธี
native.module_versionในไฟล์ .bzl ที่โหลดจากไฟล์ BUILD - การแบ่งไฟล์ MODULE.bazel ขนาดใหญ่ออกเป็นส่วนๆ ที่จัดการได้
โดยเฉพาะอย่างยิ่งสำหรับ Monorepo: โมดูลรูทสามารถใช้
คำสั่ง
includeเพื่อแบ่งไฟล์ MODULE.bazel ออกเป็นหลายส่วน ด้วยเหตุผลเดียวกันนี้ เราจึงไม่อนุญาตให้ใช้loadในไฟล์ MODULE.bazel และไม่สามารถใช้includeในโมดูลที่ไม่ใช่รูท - ผู้ใช้ระบบ 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 นี้ก็คือ Bazel จะเรียกใช้ส่วนขยายของโมดูลแบบเลื่อนเวลา กล่าวคือ ส่วนขยายโมดูลจะทำงานก็ต่อเมื่อมีการสังเกตผลลัพธ์ของส่วนขยายนั้น
เท่านั้น เนื่องจาก "เอาต์พุต" ของส่วนขยายโมดูลคือคำจำกัดความของที่เก็บข้อมูล จึงหมายความว่าเราจะเรียกใช้ส่วนขยายโมดูลก็ต่อเมื่อมีการขอที่เก็บข้อมูลที่ส่วนขยายนั้นกำหนด (เช่น หากมีการสร้างเป้าหมาย @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 คืออะไร
ป้ายกำกับที่มีชื่อรีโปที่ชัดเจน (@ นำหน้า 1 รายการ) อาจอ้างอิงถึงสิ่งต่างๆ
ตามบริบทที่ป้ายกำกับนั้นได้รับการแก้ไข เมื่อเห็นป้ายกำกับ
@bar//:bazและสงสัยว่าป้ายกำกับนั้นชี้ไปที่ใด คุณต้องค้นหา
ที่เก็บบริบทก่อน เช่น หากป้ายกำกับอยู่ในไฟล์ BUILD ที่อยู่ในที่เก็บ @@foo แสดงว่าที่เก็บบริบทคือ @@foo
จากนั้นคุณสามารถใช้ตาราง"ระดับการมองเห็นของที่เก็บ" ในคู่มือการย้ายข้อมูลเพื่อดูว่าชื่อที่ปรากฏนั้นเชื่อมโยงกับที่เก็บใดได้จริง ทั้งนี้ขึ้นอยู่กับว่าที่เก็บบริบทคืออะไร
- หากที่เก็บบริบทเป็นที่เก็บหลัก (
@@) ให้ทำดังนี้- หาก
barเป็นชื่อ repo ที่ชัดเจนซึ่งนำมาใช้โดยไฟล์ 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ในโมดูลรูท หรืออินสแตนซ์use_repo_ruleในโมดูลรูท
- โปรดทราบว่ารวมถึงที่เก็บข้อมูลใดๆ ที่แนะนำในส่วนขยายโมดูลที่คล้ายกับ
- หากกำหนดที่เก็บบริบทไว้ใน WORKSPACE ให้ทำดังนี้
- ก่อนอื่น ให้ตรวจสอบว่าคำจำกัดความของที่เก็บบริบทมีแอตทริบิวต์ magical
repo_mappingหรือไม่ หากเป็นเช่นนั้น ให้ดำเนินการกับการแมปก่อน (ดังนั้นสำหรับ repo ที่กำหนดด้วยrepo_mapping = {"@bar": "@baz"}เราจะดู ที่@bazด้านล่าง) - หาก
barเป็นชื่อ repo ที่ชัดเจนซึ่งมาจากไฟล์ MODULE.bazel ของโมดูลรูท@barจะเปลี่ยนเป็นสิ่งที่ไฟล์ MODULE.bazel นั้นอ้าง (ซึ่งเหมือนกับข้อ 1 ในกรณีของที่เก็บหลัก) - มิเช่นนั้น
@barจะเปลี่ยนเป็น@@barซึ่งส่วนใหญ่จะชี้ไปยังรีโปbarที่กำหนดไว้ใน WORKSPACE หากไม่ได้กำหนดรีโปดังกล่าว Bazel จะแสดงข้อผิดพลาด
- ก่อนอื่น ให้ตรวจสอบว่าคำจำกัดความของที่เก็บบริบทมีแอตทริบิวต์ magical
หากต้องการดูเวอร์ชันที่กระชับกว่านี้ ให้ทำดังนี้
- ที่เก็บ Bzlmod-world (ไม่รวมที่เก็บหลัก) จะเห็นเฉพาะที่เก็บ Bzlmod-world
- ที่เก็บ WORKSPACE-world (รวมถึงที่เก็บหลัก) จะดูว่ารูท โมดูลใน Bzlmod world กำหนดอะไรไว้ก่อน จากนั้นจึงกลับไปดูที่เก็บ WORKSPACE-world
โปรดทราบว่าป้ายกำกับในบรรทัดคำสั่ง Bazel (รวมถึงแฟล็ก Starlark, ค่าแฟล็กประเภทป้ายกำกับ และรูปแบบเป้าหมายการสร้าง/ทดสอบ) จะถือว่ามีที่เก็บหลักเป็นที่เก็บบริบท
อื่นๆ
ฉันจะเตรียมและเรียกใช้การสร้างแบบออฟไลน์ได้อย่างไร
ใช้คำสั่ง bazel fetch เพื่อดึงข้อมูลล่วงหน้าของที่เก็บ คุณสามารถใช้แฟล็ก --repo
(เช่น bazel fetch --repo @foo) เพื่อดึงเฉพาะรีโป @foo (ที่แก้ไขใน
บริบทของรีโปหลัก โปรดดูคำถาม
ด้านบน) หรือใช้รูปแบบเป้าหมาย (เช่น bazel fetch @foo//:bar) เพื่อดึงข้อมูลการอ้างอิงแบบทรานซิทีฟทั้งหมดของ
@foo//:bar (ซึ่งเทียบเท่ากับ bazel build --nobuild @foo//:bar)
หากต้องการตรวจสอบว่าไม่มีการดึงข้อมูลเกิดขึ้นระหว่างการบิลด์ ให้ใช้ --nofetch กล่าวอย่างเจาะจงคือ
การดำเนินการนี้จะทำให้ความพยายามในการเรียกใช้กฎที่เก็บที่ไม่ใช่ในเครื่องล้มเหลว
หากต้องการดึงข้อมูลที่เก็บ และแก้ไขเพื่อทดสอบในเครื่อง ให้พิจารณาใช้คำสั่ง bazel vendor
ฉันจะใช้พร็อกซี HTTP ได้อย่างไร
Bazel จะใช้ตัวแปรสภาพแวดล้อม http_proxy และ HTTPS_PROXY ที่โปรแกรมอื่นๆ ยอมรับโดยทั่วไป เช่น curl
ฉันจะทำให้ Bazel ชอบ IPv6 ในการตั้งค่า IPv4/IPv6 แบบ Dual Stack ได้อย่างไร
ในเครื่องที่ใช้ IPv6 เท่านั้น Bazel จะดาวน์โหลดทรัพยากร Dependency ได้โดยไม่ต้องเปลี่ยนแปลงใดๆ อย่างไรก็ตาม
ในเครื่องที่ใช้ IPv4/IPv6 แบบ Dual-stack Bazel จะใช้รูปแบบเดียวกันกับ Java
โดยจะเลือกใช้ IPv4 หากเปิดใช้ ในบางสถานการณ์ เช่น เมื่อเครือข่าย IPv4
ไม่สามารถแก้ไข/เข้าถึงที่อยู่ภายนอกได้ อาจทำให้เกิดNetwork
unreachableข้อยกเว้นและสร้างไม่สำเร็จ ในกรณีเหล่านี้ คุณสามารถลบล้างลักษณะการทำงานของ Bazel เพื่อให้ใช้ IPv6 ก่อนได้โดยใช้พร็อพเพอร์ตี้java.net.preferIPv6Addresses=true system
ดังนี้
ใช้
--host_jvm_args=-Djava.net.preferIPv6Addresses=trueตัวเลือก startup เช่น เพิ่มบรรทัดต่อไปนี้ในไฟล์.bazelrcstartup --host_jvm_args=-Djava.net.preferIPv6Addresses=trueเมื่อเรียกใช้เป้าหมายการสร้าง Java ที่ต้องเชื่อมต่ออินเทอร์เน็ต (เช่น สำหรับการทดสอบการผสานรวม) ให้ใช้
--jvmopt=-Djava.net.preferIPv6Addresses=truetool flag เช่น ใส่ในไฟล์.bazelrcbuild --jvmopt=-Djava.net.preferIPv6Addressesหากคุณใช้
rules_jvm_externalสำหรับ การแก้ปัญหาเวอร์ชันของทรัพยากร Dependency ให้เพิ่ม-Djava.net.preferIPv6Addresses=trueลงในตัวแปรสภาพแวดล้อมCOURSIER_OPTSเพื่อระบุตัวเลือก JVM สำหรับ Coursier ด้วย
เรียกใช้กฎของที่เก็บจากระยะไกลด้วยการดำเนินการจากระยะไกลได้ไหม
ไม่ หรืออย่างน้อยก็ยังไม่ ผู้ใช้ที่ใช้บริการการดำเนินการจากระยะไกลเพื่อเพิ่มความเร็ว
ในการสร้างอาจสังเกตเห็นว่ากฎของที่เก็บยังคงทำงานในเครื่อง เช่น ระบบจะดาวน์โหลด
http_archive ลงในเครื่องก่อน (ใช้แคชการดาวน์โหลดในเครื่องหากมี) จากนั้นจะแตกไฟล์ แล้วอัปโหลดไฟล์ต้นฉบับแต่ละไฟล์ไปยังบริการการดำเนินการระยะไกลเป็นไฟล์อินพุต คุณอาจสงสัยว่า
ทำไมบริการการดำเนินการจากระยะไกลไม่ดาวน์โหลดและแตกไฟล์ที่เก็บถาวรนั้น
เพื่อหลีกเลี่ยงการส่งคำขอที่ไม่จำเป็น
เหตุผลส่วนหนึ่งคือ กฎของ repo (และส่วนขยายโมดูล) คล้ายกับ "สคริปต์" ที่ Bazel เรียกใช้เอง ตัวดำเนินการระยะไกลไม่จำเป็นต้อง ติดตั้ง Bazel ด้วยซ้ำ
อีกเหตุผลหนึ่งคือ Bazel มักต้องการไฟล์ BUILD ในไฟล์เก็บถาวรที่ดาวน์โหลดและ แตกไฟล์แล้วเพื่อทำการโหลดและวิเคราะห์ ซึ่งจะดำเนินการในเครื่อง
เรามีแนวคิดเบื้องต้นในการแก้ปัญหานี้ด้วยการปรับกฎของที่เก็บเป็น
กฎการสร้าง ซึ่งจะช่วยให้เรียกใช้กฎเหล่านั้นจากระยะไกลได้โดยอัตโนมัติ แต่ในทางกลับกัน
ก็ทำให้เกิดข้อกังวลใหม่ๆ เกี่ยวกับสถาปัตยกรรม (เช่น คำสั่ง query อาจต้องเรียกใช้การดำเนินการ ซึ่งจะทำให้การออกแบบซับซ้อนขึ้น)
ดูการสนทนาก่อนหน้านี้เพิ่มเติมเกี่ยวกับหัวข้อนี้ได้ที่วิธีสนับสนุนที่เก็บที่ต้องใช้ Bazel เพื่อดึงข้อมูล