หน้านี้ครอบคลุมหลักเกณฑ์ด้านสไตล์พื้นฐานสำหรับ Starlark รวมถึงข้อมูลเกี่ยวกับมาโครและกฎ
Starlark เป็น ภาษาที่กำหนดวิธีการสร้างซอฟต์แวร์ขึ้นมา จึงเป็นทั้ง การเขียนโปรแกรมและภาษาการกำหนดค่า
คุณจะใช้ Starlark เพื่อเขียนไฟล์ มาโคร และสร้างกฎของ BUILD
มาโครและ
โดยพื้นฐานแล้วก็คือภาษาเมตา ซึ่งจะกำหนดวิธีเขียนไฟล์ BUILD
BUILD
ไฟล์มีวัตถุประสงค์เพื่อให้เรียบง่ายและซ้ำซ้อน
ซอฟต์แวร์ทั้งหมดจะอ่านบ่อยกว่าเขียน โดยเฉพาะอย่างยิ่งสำหรับ
Starlark วิศวกรอ่านไฟล์ BUILD
เพื่อทำความเข้าใจทรัพยากร Dependency ของ
เป้าหมายและรายละเอียด
ของสิ่งที่สร้างขึ้น ค่าที่อ่านได้นี้มักจะเกิดขึ้น
ในการส่งผ่าน
อยู่ในความเร่งรีบหรือทำงานอื่นๆ ไปพร้อมกัน ด้วยเหตุนี้
ความเรียบง่ายและอ่านง่ายคือ สิ่งที่สำคัญมาก เพื่อให้ผู้ใช้สามารถแยกวิเคราะห์และ
เข้าใจ BUILD
ไฟล์อย่างรวดเร็ว
เมื่อผู้ใช้เปิดไฟล์ BUILD
ผู้ใช้ต้องการทราบรายการเป้าหมายอย่างรวดเร็วใน
ไฟล์ หรือตรวจสอบรายการแหล่งที่มาของไลบรารี C++ นั้น หรือนำ
Dependency จากไบนารีของ Java นั้น ทุกครั้งที่คุณเพิ่มชั้นของนามธรรม
ทำให้ผู้ใช้ทำงานเหล่านี้ได้ยากขึ้น
ไฟล์ BUILD
ยังได้รับการวิเคราะห์และอัปเดตโดยเครื่องมือต่างๆ มากมายด้วย เครื่องมือไม่สามารถ
แก้ไขไฟล์ BUILD
ได้หากใช้ abstraction การใช้BUILD
ไฟล์ที่เรียบง่ายจะช่วยให้คุณได้รับเครื่องมือที่ดีขึ้น เมื่อฐานโค้ดเติบโตขึ้น
กระทำการเปลี่ยนแปลงในไฟล์ BUILD
จำนวนมากมากขึ้นเรื่อยๆ
อัปเดตไลบรารีหรือทำความสะอาด
คำแนะนำทั่วไป
- ใช้ Buildifier เป็นตัวจัดรูปแบบและสคริปต์วิเคราะห์
- ทำตามหลักเกณฑ์การทดสอบ
รูปแบบ
รูปแบบ Python
หากไม่แน่ใจ ให้ทำตามคู่มือสไตล์ PEP 8 หากเป็นไปได้ โดยเฉพาะอย่างยิ่ง ให้ใช้การเยื้อง 4 ช่องแทน 2 ช่องเพื่อให้เป็นไปตามรูปแบบของ Python
เนื่องจากStarlark ไม่ใช่ Python จึงใช้รูปแบบบางอย่างของ Python ไม่ได้ ตัวอย่างเช่น PEP 8 แนะนำให้ใช้ is
ในการเปรียบเทียบกับรายการเดี่ยว ซึ่งไม่ใช่โอเปอเรเตอร์ใน Starlark
สตริงเอกสาร
ไฟล์และฟังก์ชันของเอกสารโดยใช้ docstrings
ใช้ docstring ที่ด้านบนของไฟล์ .bzl
แต่ละไฟล์ และไฟล์ docstring สำหรับข้อมูลสาธารณะแต่ละไฟล์
กฎและลักษณะของเอกสาร
ควรบันทึกกฎและมุมมอง รวมถึงแอตทริบิวต์ของกฎและมุมมองนั้นๆ รวมถึงผู้ให้บริการและช่องของผู้ให้บริการโดยใช้อาร์กิวเมนต์ doc
รูปแบบการตั้งชื่อ
- ตัวแปรและชื่อฟังก์ชันใช้อักษรตัวพิมพ์เล็กที่มีคำคั่นด้วย
ขีดล่าง (
[a-z][a-z0-9_]*
) เช่นcc_library
- ค่าส่วนตัวระดับบนสุดจะเริ่มต้นด้วยขีดล่าง 1 ขีด Bazel บังคับใช้ ไม่สามารถใช้ค่าส่วนตัวจากไฟล์อื่นๆ ได้ ตัวแปรภายในไม่ควรใช้ขีดล่างเป็นคำนำหน้า
ความยาวของบรรทัด
เช่นเดียวกับไฟล์ BUILD
จะไม่มีขีดจำกัดความยาวบรรทัดอย่างเข้มงวดเนื่องจากป้ายกำกับมีความยาวได้
เมื่อเป็นไปได้ พยายามใช้อักขระไม่เกิน 79 ตัวต่อบรรทัด (ตามหลังอักขระ Python
คู่มือ, PEP 8) ไม่ควรบังคับใช้หลักเกณฑ์นี้อย่างเคร่งครัด เนื่องด้วยผู้แก้ไขควรแสดงคอลัมน์มากกว่า 80 คอลัมน์ การเปลี่ยนแปลงอัตโนมัติมักจะทำให้เกิดบรรทัดยาวขึ้น และมนุษย์ไม่ควรเสียเวลาแยกบรรทัดที่สามารถอ่านได้อยู่แล้ว
อาร์กิวเมนต์คีย์เวิร์ด
ในอาร์กิวเมนต์คีย์เวิร์ด ควรเว้นวรรครอบเครื่องหมายเท่ากับดังนี้
def fct(name, srcs):
filtered_srcs = my_filter(source = srcs)
native.cc_library(
name = name,
srcs = filtered_srcs,
testonly = True,
)
ค่าบูลีน
เลือกใช้ค่า True
และ False
(แทน 1
และ 0
) สำหรับค่าบูลีน
(เช่น เมื่อใช้แอตทริบิวต์บูลีนในกฎ)
ใช้การพิมพ์เพื่อแก้ไขข้อบกพร่องเท่านั้น
อย่าใช้ฟังก์ชัน print()
ในโค้ดเวอร์ชันที่ใช้งานจริง มีไว้สำหรับ
การแก้ไขข้อบกพร่อง และจะสแปมผู้ใช้โดยตรงและโดยอ้อมทั้งหมดของไฟล์ .bzl
ข้อยกเว้นเพียงอย่างเดียวคือคุณอาจส่งรหัสที่ใช้ print()
หากปิดใช้งาน
ตามค่าเริ่มต้น และสามารถเปิดใช้งานได้โดยการแก้ไขแหล่งที่มาเท่านั้น ตัวอย่างเช่น หาก
การใช้ print()
ได้รับการปกป้องโดย if DEBUG:
ซึ่ง DEBUG
ถูกฮาร์ดโค้ดไว้
False
คำนึงอยู่เสมอว่าข้อความเหล่านี้มีประโยชน์เพียงพอที่จะอธิบายเหตุผลหรือไม่
ผลกระทบต่อความอ่านง่าย
มาโคร
มาโครคือฟังก์ชันที่สร้างอินสแตนซ์ของกฎอย่างน้อย 1 กฎในระยะการโหลด โดยทั่วไปแล้ว ให้ใช้กฎแทนมาโครทุกครั้งที่ทำได้ บิลด์ กราฟที่ผู้ใช้เห็นไม่เหมือนกับกราฟที่ Bazel ใช้ในระหว่าง สร้าง - มาโครจะขยายก่อนที่ Bazel จะทำการวิเคราะห์กราฟของบิลด์
ด้วยเหตุนี้ เมื่อเกิดข้อผิดพลาด ผู้ใช้จะต้องเข้าใจการใช้งานมาโครเพื่อแก้ปัญหาการสร้าง นอกจากนี้ ผลลัพธ์ bazel
query
ยังตีความได้ยากเนื่องจากเป้าหมายที่แสดงในผลการค้นหามาจากการเปิดใช้งานมาโคร สุดท้ายนี้ แอสเซอต์จะไม่รู้จักมาโคร ดังนั้นเครื่องมือที่ใช้กับแอสเซอต์ (IDE และอื่นๆ) อาจใช้งานไม่ได้
การใช้มาโครอย่างปลอดภัยคือการกําหนดเป้าหมายเพิ่มเติมที่มีไว้เพื่ออ้างอิงโดยตรงใน Bazel CLI หรือในไฟล์ BUILD ในกรณีนี้ มีเพียงผู้ใช้ปลายทางของเป้าหมายเหล่านั้นเท่านั้นที่ต้องทราบเกี่ยวกับมาโคร และปัญหาการสร้างที่เกิดจากมาโครจะปรากฏขึ้นเมื่อใช้มาโคร
สำหรับมาโครที่กำหนดเป้าหมายที่สร้าง (รายละเอียดการใช้งานของมาโคร ซึ่งไม่ควรอ้างอิงใน CLI หรือขึ้นอยู่กับเป้าหมาย ไม่ได้สร้างอินสแตนซ์โดยมาโครนั้น) ให้ทำตามแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้
- มาโครควรใช้อาร์กิวเมนต์
name
และกำหนดเป้าหมายที่มีชื่อนั้น เป้าหมายดังกล่าวจะกลายเป็นเป้าหมายหลักของมาโครนั้น - เป้าหมายที่สร้างขึ้น ซึ่งก็คือเป้าหมายอื่นๆ ทั้งหมดที่กําหนดโดยมาโคร ควรมีลักษณะดังนี้
- มีชื่อนำหน้าด้วย
<name>
หรือ_<name>
ตัวอย่างเช่น การใช้name = '%s_bar' % (name)
- มีการแสดงผลแบบจำกัด (
//visibility:private
) และ - มีแท็ก
manual
เพื่อหลีกเลี่ยงการขยายในเป้าหมายไวลด์การ์ด (:all
,...
,:*
ฯลฯ)
- มีชื่อนำหน้าด้วย
- คุณควรใช้
name
เพื่อดึงชื่อของเป้าหมายที่แมโครกำหนดเท่านั้น และไม่ใช้กับอย่างอื่น เช่น อย่าใช้ชื่อเพื่อดึงมา ไฟล์ทรัพยากร Dependency หรือไฟล์อินพุตที่ไม่ได้สร้างขึ้นโดยมาโครเอง - เป้าหมายทั้งหมดที่สร้างในมาโครควรเชื่อมโยงกับเป้าหมายหลักด้วยวิธีใดวิธีหนึ่ง
- ตั้งชื่อพารามิเตอร์ในมาโครให้สอดคล้องกัน หากมีการส่งผ่านพารามิเตอร์
เป็นค่าแอตทริบิวต์ให้กับเป้าหมายหลัก
ให้คงชื่อเดิมไว้ หากเป็นมาโคร
ทำหน้าที่เหมือนแอตทริบิวต์กฎทั่วไป เช่น
deps
ตั้งชื่อตามที่ใช้กับแอตทริบิวต์ (ดูด้านล่าง) - เมื่อเรียกมาโคร ให้ใช้อาร์กิวเมนต์คีย์เวิร์ดเท่านั้น วิธีนี้สอดคล้องกับกฎและช่วยให้อ่านได้ง่ายขึ้นมาก
วิศวกรมักเขียนมาโครเมื่อ Starlark API ของกฎที่เกี่ยวข้อง ไม่เพียงพอสำหรับกรณีการใช้งานเฉพาะ โดยไม่คำนึงว่ากฎ ภายใน Bazel ในโค้ดแบบเนทีฟ หรือใน Starlark หากพบปัญหานี้ โปรดสอบถามผู้เขียนกฎว่าสามารถขยาย API เพื่อให้บรรลุเป้าหมายของคุณได้หรือไม่
โดยทั่วไปแล้ว ยิ่งมาโครคล้ายกับกฎมากเท่าใด ก็ยิ่งดีเท่านั้น
ดูมาโครเพิ่มเติม
กฎ
- กฎ ลักษณะ และแอตทริบิวต์ควรใช้ชื่อตัวพิมพ์เล็ก ("snake) case")
- ชื่อกฎคือคำนามที่อธิบายถึงประเภทหลักของอาร์ติแฟกต์ที่กฎสร้างขึ้นจากมุมมองของข้อกำหนด (หรือผู้ใช้สำหรับกฎระดับล่าง) ไม่จำเป็นต้องเป็นคำต่อท้ายไฟล์ เช่น กฎที่ผลิตอาร์ติแฟกต์ C++ สำหรับใช้เป็นส่วนขยาย Python อาจเรียกว่า
py_extension
สำหรับภาษาส่วนใหญ่ กฎทั่วไปมีดังนี้*_library
- หน่วยการคอมไพล์หรือ "โมดูล"*_binary
- เป้าหมายที่สร้างหน่วยปฏิบัติการหรือหน่วยการทำให้ใช้งานได้*_test
- เป้าหมายการทดสอบ ซึ่งอาจรวมถึงการทดสอบหลายรายการ คาดว่าจะได้รับทั้งหมด การทดสอบในเป้าหมาย*_test
เป็นรูปแบบต่างๆ ในธีมเดียวกันสำหรับ เช่น การทดสอบไลบรารีเดียว*_import
: เป้าหมายที่รวมอาร์ติแฟกต์ที่คอมไพล์ไว้ล่วงหน้า เช่น.jar
หรือ.dll
ที่ใช้ระหว่างการคอมไพล์
- ใช้ชื่อและประเภทที่สอดคล้องกันสำหรับแอตทริบิวต์ บางส่วนที่ใช้งานได้โดยทั่วไป
ได้แก่
srcs
:label_list
ซึ่งอนุญาตไฟล์: ไฟล์ต้นฉบับ ซึ่งมักจะเขียนโดยมนุษย์deps
:label_list
ปกติแล้วไม่อนุญาตไฟล์: การคอมไพล์ ทรัพยากร Dependencydata
:label_list
, การอนุญาตไฟล์: ไฟล์ข้อมูล เช่น ข้อมูลทดสอบ เป็นต้นruntime_deps
:label_list
: ทรัพยากร Dependency ของรันไทม์ที่ไม่จำเป็น เพื่อทำการคอมไพล์
- สำหรับแอตทริบิวต์ที่มีลักษณะการทำงานที่ไม่ชัดเจน (เช่น เทมเพลตสตริง
โดยใช้การแทนพิเศษ หรือเครื่องมือที่ใช้
) ให้แนบเอกสารประกอบโดยใช้อาร์กิวเมนต์คีย์เวิร์ด
doc
ไปยังฟังก์ชัน การประกาศของแอตทริบิวต์ (attr.label_list()
หรือที่คล้ายกัน) - ฟังก์ชันการใช้งานกฎควรเป็นฟังก์ชันส่วนตัวเกือบทุกครั้ง (ตั้งชื่อโดยนำหน้าด้วยเครื่องหมายขีดล่าง) รูปแบบที่ใช้กันโดยทั่วไปคือ
ฟังก์ชันการใช้งานสำหรับ
myrule
ชื่อ_myrule_impl
- ส่งข้อมูลระหว่างกฎโดยใช้อินเทอร์เฟซ provider ที่กําหนดไว้อย่างดี ประกาศและผู้ให้บริการเอกสาร ด้วย
- ออกแบบกฎโดยคำนึงถึงความยืดหยุ่น โปรดทราบว่ากฎอื่นๆ อาจต้องการโต้ตอบกับกฎของคุณ เข้าถึงผู้ให้บริการ และนําการดำเนินการที่คุณสร้างขึ้นมาใช้ซ้ำ
- ปฏิบัติตามหลักเกณฑ์ด้านประสิทธิภาพในกฎ