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

รายงานปัญหา ดูแหล่งที่มา /3} /4} {3/4} {3/4} {3/4} {3/4} /4.

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

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

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

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

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

ไฟล์ BUILD รายการยังได้รับการวิเคราะห์และอัปเดตโดยเครื่องมือต่างๆ อีกด้วย เครื่องมืออาจแก้ไขไฟล์ BUILD ไม่ได้หากเครื่องมือดังกล่าวใช้นามธรรม การทำให้ไฟล์ 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 เพื่อให้บรรลุเป้าหมายของคุณหรือไม่

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

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

กฎ

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