หน้านี้ครอบคลุมหลักเกณฑ์ด้านสไตล์พื้นฐานสำหรับ Starlark รวมถึงข้อมูลเกี่ยวกับมาโครและกฎ
Starlark เป็นภาษาที่กําหนดวิธีสร้างซอฟต์แวร์ จึงทําหน้าที่เป็นทั้งภาษาการเขียนโปรแกรมและภาษาการกําหนดค่า
คุณจะใช้ Starlark เพื่อเขียนไฟล์ BUILD
, มาโคร และกฎการสร้าง มาโครและกฎเป็นภาษาเมตา ซึ่งกำหนดวิธีเขียนไฟล์ BUILD
ไฟล์ BUILD
มีไว้เพื่อใช้ซ้ำๆ และเรียบง่าย
ซอฟต์แวร์ทั้งหมดจะอ่านบ่อยกว่าเขียน โดยเฉพาะอย่างยิ่งสำหรับ Starlark เนื่องจากวิศวกรจะอ่านไฟล์ BUILD
เพื่อให้เข้าใจการพึ่งพาของเป้าหมายและรายละเอียดของบิลด์ การอ่านนี้มักเกิดขึ้นโดยไม่ได้ตั้งใจ รีบร้อน หรือทําควบคู่ไปกับงานอื่นๆ ดังนั้น ความเรียบง่ายและความสามารถในการอ่านจึงเป็นสิ่งสำคัญอย่างยิ่งเพื่อให้ผู้ใช้สามารถแยกวิเคราะห์และทำความเข้าใจไฟล์ BUILD
ได้อย่างรวดเร็ว
เมื่อผู้ใช้เปิดไฟล์ BUILD
ผู้ใช้ต้องการทราบรายการเป้าหมายในไฟล์อย่างรวดเร็ว หรือตรวจสอบรายการแหล่งที่มาของไลบรารี C++ นั้น หรือนําข้อกําหนดในการพึ่งพาออกจากไบนารี Java นั้น ทุกครั้งที่คุณเพิ่มชั้นการแยกความคิด ผู้ใช้จะทํางานเหล่านี้ได้ยากขึ้น
ไฟล์ BUILD
ยังได้รับการวิเคราะห์และอัปเดตโดยเครื่องมือต่างๆ มากมายด้วย เครื่องมืออาจแก้ไขไฟล์ BUILD
ไม่ได้หากใช้การแยกแยะ การใช้BUILD
ไฟล์ที่เรียบง่ายจะช่วยให้คุณได้รับเครื่องมือที่ดีขึ้น เมื่อฐานโค้ดมีขนาดใหญ่ขึ้น การเปลี่ยนแปลงในไฟล์ BUILD
หลายไฟล์เพื่ออัปเดตไลบรารีหรือล้างข้อมูลจึงเกิดขึ้นบ่อยขึ้น
คำแนะนำทั่วไป
- ใช้ Buildifier เป็นตัวจัดรูปแบบและโปรแกรมตรวจไวยากรณ์
- ทำตามหลักเกณฑ์การทดสอบ
รูปแบบ
รูปแบบ Python
หากไม่แน่ใจ ให้ทำตามคู่มือสไตล์ PEP 8 หากเป็นไปได้ โดยเฉพาะอย่างยิ่ง ให้ใช้การเยื้อง 4 ช่องแทน 2 ช่องเพื่อให้เป็นไปตามรูปแบบของ Python
เนื่องจากStarlark ไม่ใช่ Python จึงใช้รูปแบบบางอย่างของ Python ไม่ได้ ตัวอย่างเช่น PEP 8 แนะนำให้ใช้ is
ในการเปรียบเทียบกับรายการเดี่ยว ซึ่งไม่ใช่โอเปอเรเตอร์ใน Starlark
สตริงเอกสาร
อธิบายไฟล์และฟังก์ชันโดยใช้ docstring
ใช้ 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
เพื่อดึงข้อมูลชื่อของเป้าหมายที่แมโครกำหนดเท่านั้น และไม่ใช้กับอย่างอื่น เช่น อย่าใช้ชื่อเพื่อดึงข้อมูลไฟล์ที่ต้องพึ่งพาหรือไฟล์อินพุตที่ไม่ได้สร้างโดยมาโครเอง - เป้าหมายทั้งหมดที่สร้างในมาโครควรเชื่อมโยงกับเป้าหมายหลักด้วยวิธีใดวิธีหนึ่ง
- ตั้งชื่อพารามิเตอร์ในมาโครให้สอดคล้องกัน หากส่งพารามิเตอร์เป็นค่าแอตทริบิวต์ไปยังเป้าหมายหลัก ให้ใช้ชื่อเดิม หากพารามิเตอร์มาโครมีวัตถุประสงค์เดียวกับแอตทริบิวต์กฎทั่วไป เช่น
deps
ให้ตั้งชื่อตามแอตทริบิวต์ (ดูด้านล่าง) - เมื่อเรียกใช้มาโคร ให้ใช้เฉพาะอาร์กิวเมนต์คีย์เวิร์ด วิธีนี้สอดคล้องกับกฎและช่วยให้อ่านได้ง่ายขึ้นมาก
วิศวกรมักจะเขียนมาโครเมื่อ Starlark API ของกฎที่เกี่ยวข้องไม่เพียงพอสำหรับ Use Case ที่เฉพาะเจาะจง ไม่ว่ากฎจะกำหนดภายใน Bazel ในโค้ดเนทีฟหรือใน Starlark ก็ตาม หากคุณพบปัญหานี้ โปรดสอบถามผู้เขียนกฎว่าสามารถขยาย API เพื่อให้บรรลุเป้าหมายของคุณได้หรือไม่
โดยทั่วไปแล้ว ยิ่งมาโครคล้ายกับกฎมากเท่าใด ก็ยิ่งดีเท่านั้น
ดูมาโครด้วย
กฎ
- กฎ แง่มุม และแอตทริบิวต์ของกฎและแง่มุมควรใช้ชื่อแบบพิมพ์เล็ก ("snake case")
- ชื่อกฎคือคำนามที่อธิบายถึงประเภทหลักของอาร์ติแฟกต์ที่กฎสร้างขึ้นจากมุมมองของข้อกำหนด (หรือผู้ใช้สำหรับกฎระดับล่าง) ซึ่งไม่จำเป็นต้องเป็นคำต่อท้ายไฟล์ เช่น กฎที่ผลิตอาร์ติแฟกต์ C++ สำหรับใช้เป็นส่วนขยาย Python อาจเรียกว่า
py_extension
กฎทั่วไปสำหรับภาษาส่วนใหญ่มีดังนี้*_library
- หน่วยการคอมไพล์หรือ "โมดูล"*_binary
- เป้าหมายที่สร้างไฟล์ปฏิบัติการหรือหน่วยการทำให้ใช้งานได้*_test
- เป้าหมายการทดสอบ ซึ่งอาจรวมถึงการทดสอบหลายรายการ คาดหวังว่าการทดสอบทั้งหมดในเป้าหมาย*_test
จะเป็นรูปแบบต่างๆ ในธีมเดียวกัน เช่น การทดสอบคลังภาพเดียว*_import
: เป้าหมายที่รวมอาร์ติแฟกต์ที่คอมไพล์ไว้ล่วงหน้า เช่น.jar
หรือ.dll
ที่ใช้ระหว่างการคอมไพล์
- ใช้ชื่อและประเภทที่สอดคล้องกันสำหรับแอตทริบิวต์ แอตทริบิวต์ที่ใช้งานได้โดยทั่วไปมีดังนี้
srcs
:label_list
ซึ่งอนุญาตไฟล์: ไฟล์ต้นฉบับ ซึ่งมักจะเขียนโดยมนุษย์deps
:label_list
โดยปกติแล้วไม่อนุญาตให้ใช้ไฟล์: คอมไพล์ ข้อกําหนดdata
:label_list
ซึ่งอนุญาตไฟล์: ไฟล์ข้อมูล เช่น ข้อมูลทดสอบ ฯลฯruntime_deps
:label_list
: ไลบรารีรันไทม์ที่ไม่จําเป็นสําหรับการคอมไพล์
- สำหรับแอตทริบิวต์ที่มีลักษณะการทำงานที่ไม่ชัดเจน (เช่น เทมเพลตสตริงที่มีการแทนที่พิเศษ หรือเครื่องมือที่เรียกใช้โดยมีข้อกำหนดเฉพาะ) ให้ระบุเอกสารประกอบโดยใช้อาร์กิวเมนต์คีย์เวิร์ด
doc
ในการประกาศแอตทริบิวต์ (attr.label_list()
หรือคล้ายกัน) - ฟังก์ชันการใช้งานกฎควรเป็นฟังก์ชันส่วนตัวเกือบทุกครั้ง (ตั้งชื่อโดยนำหน้าด้วยเครื่องหมายขีดล่าง) รูปแบบที่พบบ่อยคือการตั้งชื่อฟังก์ชันการใช้งานของ
myrule
เป็น_myrule_impl
- ส่งข้อมูลระหว่างกฎโดยใช้อินเทอร์เฟซ provider ที่กําหนดไว้อย่างดี ประกาศและจัดทำเอกสารเกี่ยวกับช่องผู้ให้บริการ
- ออกแบบกฎโดยคำนึงถึงความยืดหยุ่น โปรดทราบว่ากฎอื่นๆ อาจต้องการโต้ตอบกับกฎของคุณ เข้าถึงผู้ให้บริการ และนําการดำเนินการที่คุณสร้างขึ้นมาใช้ซ้ำ
- ปฏิบัติตามหลักเกณฑ์ด้านประสิทธิภาพในกฎ