คู่มือสไตล์ .bzl

รายงานปัญหา ดูแหล่งที่มา รุ่น Nightly · 7.4 7.3 · 7.2 · 7.1 · 7.0 · 6.5

หน้านี้ครอบคลุมหลักเกณฑ์ด้านสไตล์พื้นฐานสำหรับ Starlark รวมถึงข้อมูลเกี่ยวกับมาโครและกฎ

Starlark เป็น ภาษาที่กำหนดวิธีการสร้างซอฟต์แวร์ขึ้นมา จึงเป็นทั้ง การเขียนโปรแกรมและภาษาการกำหนดค่า

คุณจะใช้ Starlark เพื่อเขียนไฟล์ มาโคร และสร้างกฎของ BUILD มาโครและ โดยพื้นฐานแล้วก็คือภาษาเมตา ซึ่งจะกำหนดวิธีเขียนไฟล์ BUILD BUILD ไฟล์มีวัตถุประสงค์เพื่อให้เรียบง่ายและซ้ำซ้อน

ซอฟต์แวร์ทั้งหมดจะอ่านบ่อยกว่าเขียน โดยเฉพาะอย่างยิ่งสำหรับ Starlark วิศวกรอ่านไฟล์ BUILD เพื่อทำความเข้าใจทรัพยากร Dependency ของ เป้าหมายและรายละเอียด ของสิ่งที่สร้างขึ้น ค่าที่อ่านได้นี้มักจะเกิดขึ้น ในการส่งผ่าน อยู่ในความเร่งรีบหรือทำงานอื่นๆ ไปพร้อมกัน ด้วยเหตุนี้ ความเรียบง่ายและอ่านง่ายคือ สิ่งที่สำคัญมาก เพื่อให้ผู้ใช้สามารถแยกวิเคราะห์และ เข้าใจ BUILD ไฟล์อย่างรวดเร็ว

เมื่อผู้ใช้เปิดไฟล์ BUILD ผู้ใช้ต้องการทราบรายการเป้าหมายอย่างรวดเร็วใน ไฟล์ หรือตรวจสอบรายการแหล่งที่มาของไลบรารี C++ นั้น หรือนำ Dependency จากไบนารีของ Java นั้น ทุกครั้งที่คุณเพิ่มชั้นของนามธรรม ทำให้ผู้ใช้ทำงานเหล่านี้ได้ยากขึ้น

ไฟล์ BUILD ยังได้รับการวิเคราะห์และอัปเดตโดยเครื่องมือต่างๆ มากมายด้วย เครื่องมือไม่สามารถ แก้ไขไฟล์ BUILD ได้หากใช้ abstraction การใช้BUILD ไฟล์ที่เรียบง่ายจะช่วยให้คุณได้รับเครื่องมือที่ดีขึ้น เมื่อฐานโค้ดเติบโตขึ้น กระทำการเปลี่ยนแปลงในไฟล์ BUILD จำนวนมากมากขึ้นเรื่อยๆ อัปเดตไลบรารีหรือทำความสะอาด

คำแนะนำทั่วไป

รูปแบบ

รูปแบบ 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 ปกติแล้วไม่อนุญาตไฟล์: การคอมไพล์ ทรัพยากร Dependency
    • data: label_list, การอนุญาตไฟล์: ไฟล์ข้อมูล เช่น ข้อมูลทดสอบ เป็นต้น
    • runtime_deps: label_list: ทรัพยากร Dependency ของรันไทม์ที่ไม่จำเป็น เพื่อทำการคอมไพล์
  • สำหรับแอตทริบิวต์ที่มีลักษณะการทำงานที่ไม่ชัดเจน (เช่น เทมเพลตสตริง โดยใช้การแทนพิเศษ หรือเครื่องมือที่ใช้ ) ให้แนบเอกสารประกอบโดยใช้อาร์กิวเมนต์คีย์เวิร์ด doc ไปยังฟังก์ชัน การประกาศของแอตทริบิวต์ (attr.label_list() หรือที่คล้ายกัน)
  • ฟังก์ชันการใช้งานกฎควรเป็นฟังก์ชันส่วนตัวเกือบทุกครั้ง (ตั้งชื่อโดยนำหน้าด้วยเครื่องหมายขีดล่าง) รูปแบบที่ใช้กันโดยทั่วไปคือ ฟังก์ชันการใช้งานสำหรับ myrule ชื่อ _myrule_impl
  • ส่งข้อมูลระหว่างกฎโดยใช้อินเทอร์เฟซ provider ที่กําหนดไว้อย่างดี ประกาศและผู้ให้บริการเอกสาร ด้วย
  • ออกแบบกฎโดยคำนึงถึงความยืดหยุ่น โปรดทราบว่ากฎอื่นๆ อาจต้องการโต้ตอบกับกฎของคุณ เข้าถึงผู้ให้บริการ และนําการดำเนินการที่คุณสร้างขึ้นมาใช้ซ้ำ
  • ปฏิบัติตามหลักเกณฑ์ด้านประสิทธิภาพในกฎ