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

วันที่ รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 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 Convention

ตั้งแต่ปี 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")
  • ชื่อกฎคือคำนามที่อธิบายถึงอาร์ติแฟกต์ประเภทหลักๆ ที่ จากมุมมองของทรัพยากร Dependency (หรือสำหรับกฎ Leaf แอตทริบิวต์ ผู้ใช้) ไม่จำเป็นต้องเป็นคำต่อท้ายไฟล์ ตัวอย่างเช่น กฎที่ สร้างอาร์ติแฟกต์ 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 ประกาศและผู้ให้บริการเอกสาร ด้วย
  • ออกแบบกฎโดยคำนึงถึงความสามารถในการขยายการใช้งาน ลองดูว่ากฎอื่นๆ อาจ ต้องการโต้ตอบกับกฎ เข้าถึงผู้ให้บริการ และนำ สิ่งที่คุณสร้างขึ้นมา
  • ปฏิบัติตามหลักเกณฑ์ประสิทธิภาพในกฎของคุณ