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

รายงานปัญหา ดูแหล่งข้อมูล ดูแหล่งข้อมูล 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

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

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

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

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

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

รูปแบบ

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

วิศวกรมักเขียนมาโครเมื่อ Starlark API ของกฎที่เกี่ยวข้องไม่เพียงพอสำหรับกรณีการใช้งานที่เฉพาะเจาะจง ไม่ว่าจะมีการกำหนดกฎภายใน Bazel ในโค้ดแบบเนทีฟหรือใน Starlark หากคุณพบปัญหานี้ โปรดสอบถามผู้เขียนกฎว่าสามารถขยาย API เพื่อให้บรรลุเป้าหมายของคุณได้หรือไม่

ตามหลักการทั่วไป ยิ่งมาโครมีลักษณะคล้ายกฎมากเท่าใดก็ยิ่งดีเท่านั้น

ดูมาโครเพิ่มเติม

กฎ

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