การจัดรูปแบบไฟล์ BUILD
เป็นไปตามแนวทางเดียวกับ Go ซึ่งเครื่องมือมาตรฐานจะจัดการกับปัญหาเกี่ยวกับการจัดรูปแบบส่วนใหญ่
Buildifier เป็นเครื่องมือที่แยกวิเคราะห์และปล่อยซอร์สโค้ดในรูปแบบมาตรฐาน ดังนั้นไฟล์ BUILD
ทุกไฟล์จะได้รับการจัดรูปแบบด้วยวิธีเดียวกัน ซึ่งทําให้การจัดรูปแบบไม่ใช่ปัญหาในระหว่างการตรวจสอบโค้ด นอกจากนี้ยังช่วยให้เครื่องมือทําความเข้าใจ แก้ไข และสร้างไฟล์ BUILD
ได้ง่ายขึ้น
การจัดรูปแบบไฟล์ BUILD
ต้องตรงกับเอาต์พุตของ buildifier
ตัวอย่างการจัดรูปแบบ
# Test code implementing the Foo controller.
package(default_testonly = True)
py_test(
name = "foo_test",
srcs = glob(["*.py"]),
data = [
"//data/production/foo:startfoo",
"//foo",
"//third_party/java/jdk:jdk-k8",
],
flaky = True,
deps = [
":check_bar_lib",
":foo_data_check",
":pick_foo_port",
"//pyglib",
"//testing/pybase",
],
)
โครงสร้างไฟล์
คําแนะนํา: ใช้ลําดับต่อไปนี้ (มีองค์ประกอบทั้งหมดที่ไม่บังคับ)
คําอธิบายแพ็กเกจ (ความคิดเห็น)
ใบแจ้งยอด
load()
ทั้งหมดฟังก์ชัน
package()
การเรียกใช้กฎและมาโคร
ตัวสร้างความแตกต่างระหว่างความคิดเห็นแบบสแตนด์อโลนกับความคิดเห็นที่แนบอยู่กับองค์ประกอบ หากไม่ได้แนบความคิดเห็นไว้ในองค์ประกอบเฉพาะ ให้ใช้บรรทัดว่างหลังจากความคิดเห็นนั้น ความแตกต่างนี้สําคัญเมื่อทําการเปลี่ยนแปลงอัตโนมัติ (เช่น เก็บหรือนําความคิดเห็นออกเมื่อลบกฎ)
# Standalone comment (such as to make a section in a file)
# Comment for the cc_library below
cc_library(name = "cc")
การอ้างอิงไปยังเป้าหมายในแพ็กเกจปัจจุบัน
ไฟล์ควรอ้างอิงด้วยเส้นทางที่สัมพันธ์กับไดเรกทอรีของแพ็กเกจ
(โดยไม่ใช้การอ้างอิงเลย เช่น ..
) ไฟล์ที่สร้างควรมี ":
" นําหน้า เพื่อบ่งชี้ว่าไม่ใช่แหล่งที่มา ไฟล์ต้นฉบับไม่ควรขึ้นต้นด้วย :
กฎควรขึ้นต้นด้วย :
เช่น สมมติว่า x.cc
เป็นไฟล์ต้นฉบับ
cc_library(
name = "lib",
srcs = ["x.cc"],
hdrs = [":gen_header"],
)
genrule(
name = "gen_header",
srcs = [],
outs = ["x.h"],
cmd = "echo 'int x();' > $@",
)
การตั้งชื่อเป้าหมาย
ชื่อเป้าหมายควรสื่อความหมาย หากเป้าหมายมีไฟล์ต้นฉบับ 1 ไฟล์ โดยทั่วไปเป้าหมายควรมีชื่อที่มาจากแหล่งที่มานั้น (เช่น cc_library
สําหรับ chat.cc
อาจมีชื่อเป็น chat
หรือ java_library
สําหรับ DirectMessage.java
อาจมีชื่อว่า direct_message
)
เป้าหมายที่มีชื่อเดียวกันของแพ็กเกจ (เป้าหมายที่มีชื่อเดียวกับไดเรกทอรีที่มี) ควรให้ฟังก์ชันการทํางานที่อธิบายโดยชื่อไดเรกทอรี หากไม่มีเป้าหมายดังกล่าว อย่าสร้างเป้าหมายที่มีชื่อเดียวกัน
ต้องการใช้ชื่อย่อเมื่อกล่าวถึงเป้าหมายที่ไม่ระบุชื่อ (//x
แทนที่จะเป็น //x:x
) หากคุณอยู่ในแพ็กเกจเดียวกัน ให้ใช้การอ้างอิงในพื้นที่ (:x
แทน //x
)
หลีกเลี่ยงการใช้ชื่อเป้าหมายที่ "จองแล้ว" ซึ่งมีความหมายพิเศษ ซึ่งรวมถึง all
, __pkg__
และ __subpackages__
ชื่อเหล่านี้มีความหมายพิเศษและอาจทําให้เกิดความสับสนและลักษณะการทํางานที่ไม่คาดคิดเมื่อนํามาใช้
ในกรณีที่ไม่มีรูปแบบการประชุมที่ใกล้เคียงกัน คําแนะนําบางส่วนที่ Google ใช้กันอย่างแพร่หลายมีดังนี้
- โดยทั่วไป ให้ใช้ "snake_case"
- สําหรับ
java_library
ที่มีsrc
จะหมายถึงการใช้ชื่อที่ไม่เหมือนกับชื่อไฟล์ที่ไม่มีนามสกุล - สําหรับกฎ Java
*_binary
และ*_test
ให้ใช้ "Upper CamelCase" ซึ่งจะทําให้ชื่อเป้าหมายตรงกับหนึ่งในsrc
ได้ สําหรับjava_test
อาจทําให้แอตทริบิวต์test_class
อนุมานจากชื่อเป้าหมายได้
- สําหรับ
- หากมีตัวแปรหลายรายการของเป้าหมายหนึ่งๆ ให้เพิ่มคําต่อท้ายที่ให้คําอธิบาย (เช่น
:foo_dev
,:foo_prod
หรือ:bar_x86
,:bar_x64
) - กําหนดเป้าหมาย
_test
ด้วย_test
,_unittest
,Test
หรือTests
- หลีกเลี่ยงคําต่อท้ายที่ไม่มีความหมาย เช่น
_lib
หรือ_library
(เว้นแต่จะต้องหลีกเลี่ยงความขัดแย้งระหว่างเป้าหมาย_library
กับ_binary
ที่เกี่ยวข้อง) - สําหรับเป้าหมายที่เกี่ยวข้องกับต้นแบบ ให้ทําดังนี้
- เป้าหมาย
proto_library
รายการควรมีชื่อที่ลงท้ายด้วย_proto
- กฎ
*_proto_library
ภาษาที่เจาะจงควรตรงกับโปรโตพื้นฐาน แต่แทนที่_proto
ด้วยคําต่อท้ายภาษาที่เจาะจง เช่นcc_proto_library
:_cc_proto
java_proto_library
:_java_proto
java_lite_proto_library
:_java_proto_lite
- เป้าหมาย
ระดับการแชร์
ควรกําหนดขอบเขตระดับการเข้าถึงให้มากที่สุดเท่าที่จะเป็นไปได้ ขณะที่ยังอนุญาตการเข้าถึงด้วยการทดสอบและทรัพยากร Dependency แบบย้อนกลับ ใช้ __pkg__
และ __subpackages__
ตามความเหมาะสม
หลีกเลี่ยงการตั้งค่าแพ็กเกจ default_visibility
เป็น //visibility:public
ควรตั้งค่า //visibility:public
แต่ละรายการสําหรับเป้าหมายใน API สาธารณะของโปรเจ็กต์เท่านั้น ซึ่งอาจเป็นไลบรารีที่ออกแบบมาเพื่อใช้โปรเจ็กต์ภายนอกหรือไบนารีที่กระบวนการสร้างของโปรเจ็กต์ภายนอกใช้ได้
การอ้างอิง
ทรัพยากร Dependency ต้องจํากัดตามทรัพยากร Dependency โดยตรง (ทรัพยากร Dependency ที่จําเป็นโดยแหล่งที่มาที่ระบุไว้ในกฎ) ไม่ต้องระบุทรัพยากร Dependency ชั่วคราว
ควรแสดงทรัพยากร Dependency ในแพ็กเกจก่อน และอ้างอิงด้วยวิธีที่ใช้ได้กับส่วนการอ้างอิงถึงเป้าหมายในแพ็กเกจปัจจุบันด้านบน (ไม่ใช่ชื่อแพ็กเกจสัมบูรณ์)
ระบุรายการทรัพยากร Dependency โดยตรงเป็นรายการเดียว การทําให้ทรัพยากร Dependency "ทั่วไป" ของตัวแปรหลายรายการกลายเป็นตัวแปรจะช่วยลดการดูแลรักษา และทําให้เครื่องมือไม่สามารถเปลี่ยนแปลงทรัพยากร Dependency ของเป้าหมายได้ และอาจทําให้ทรัพยากร Dependency ที่ไม่ได้ใช้อยู่ในนั้น
แสงสะท้อน
ระบุว่า "ไม่มีเป้าหมาย" ด้วย []
อย่าใช้ Glob ที่ตรงกับของแถม
ข้อผิดพลาดมักเกิดข้อผิดพลาดและเห็นได้ชัดน้อยกว่ารายการที่ว่างเปล่า
เกิดซ้ํา
อย่าใช้ Glop ที่เกิดซ้ําเพื่อจับคู่กับไฟล์แหล่งที่มา (เช่น glob(["**/*.java"])
)
การเกิด GLOB ซ้ําทําให้ไฟล์ BUILD
ไม่ทราบสาเหตุเนื่องจากข้ามไดเรกทอรีย่อยที่มี BUILD
ไฟล์
โดยทั่วไปแล้ว GLOB ที่เกิดซ้ําจะมีประสิทธิภาพน้อยกว่าการมีไฟล์ BUILD
ต่อไดเรกทอรีที่มีการกําหนดทรัพยากร Dependency ไว้ เนื่องจากทําให้การแคชและการโหลดพร้อมกันทําได้ดีขึ้น
แนวทางปฏิบัติที่ดีคือการเขียนไฟล์ BUILD
ในแต่ละไดเรกทอรีและกําหนดกราฟ Dependency ระหว่างไฟล์เหล่านั้น
ไม่เกิดซ้ํา
โดยทั่วไปจะใช้ GLOB ที่ไม่เกิดซ้ําได้
การประชุมอื่นๆ
ใช้ตัวพิมพ์ใหญ่และขีดล่างเพื่อประกาศค่าคงที่ (เช่น
GLOBAL_CONSTANT
) ใช้ตัวพิมพ์เล็กและขีดล่างเพื่อประกาศตัวแปร (เช่นmy_variable
)คุณไม่ควรแยกป้ายกํากับออก แม้ว่าป้ายกํากับจะยาวกว่า 79 อักขระก็ตาม ป้ายกํากับควรเป็นสัญพจน์ของสตริงทุกครั้งที่ทําได้ ความสําคัญและเหตุผล: ช่วยให้คุณค้นหาและแทนที่ได้อย่างง่ายดาย และยังช่วยปรับปรุงให้อ่านง่ายขึ้น
ค่าของแอตทริบิวต์ชื่อควรเป็นสตริงค่าคงที่ตามจริง (ยกเว้นมาโคร) ความสําคัญ: เครื่องมือภายนอกใช้แอตทริบิวต์ชื่อเพื่ออ้างถึงกฎ พวกเขาจําเป็นต้องค้นหากฎโดยไม่ต้องตีความโค้ด
เมื่อตั้งค่าแอตทริบิวต์ประเภทบูลีน ให้ใช้ค่าบูลีน ไม่ใช่ค่าจํานวนเต็ม สําหรับเหตุผลเดิม กฎยังคงแปลงจํานวนเต็มเป็นบูลีนตามที่จําเป็น แต่เราไม่แนะนําให้ทําเช่นนั้น ความสําคัญ:
flaky = 1
อาจทําให้เข้าใจผิดว่า "ทําให้เป้าหมายนี้ลดลงโดยการเรียกใช้อีกครั้งครั้งเดียว"flaky = True
บอกว่า "การทดสอบนี้ไม่น่าเชื่อถือ"
ความแตกต่างกับคําแนะนําเกี่ยวกับสไตล์ Python
แม้ว่าความเข้ากันได้กับคําแนะนําเกี่ยวกับสไตล์ Python จะเป็นเป้าหมาย แต่ก็มีความแตกต่างบางประการดังนี้
ไม่จํากัดความยาวของบรรทัด ความคิดเห็นแบบยาวและสตริงแบบยาวมักจะแบ่งออกเป็น 79 คอลัมน์ แต่ไม่จําเป็น ไม่ควรบังคับใช้ในการตรวจสอบโค้ดหรือส่งสคริปต์ล่วงหน้า เหตุผล: ป้ายกํากับอาจยาวและเกินขีดจํากัดนี้ เป็นเรื่องปกติที่ไฟล์
BUILD
จะถูกสร้างหรือแก้ไขโดยเครื่องมือ ซึ่งมีประสิทธิภาพไม่ดีหากมีขีดจํากัดความยาวบรรทัดระบบไม่รองรับการเชื่อมโยงสตริงแบบโดยนัย ใช้โอเปอเรเตอร์
+
ความสําคัญและที่มาของปัญหา:BUILD
ไฟล์มีรายการสตริงจํานวนมาก ลืมเครื่องหมายจุลภาคได้ง่ายๆ ซึ่งนําไปสู่ผลลัพธ์ที่ต่างกันโดยสิ้นเชิง สิ่งนี้เคยสร้างข้อบกพร่องจํานวนมาก ดูการสนทนานี้ด้วยใช้การเว้นวรรครอบๆ เครื่องหมาย
=
เพื่อดูอาร์กิวเมนต์ของคีย์เวิร์ดในกฎ เหตุผล: อาร์กิวเมนต์ที่มีชื่อใช้บ่อยกว่าใน Python มากและอยู่ในบรรทัดแยกต่างหากเสมอ พื้นที่ทํางานจะช่วยให้อ่านง่ายขึ้น การประชุมนี้ดําเนินมาเป็นเวลานานแล้ว จึงไม่ควรแก้ไขไฟล์BUILD
ที่มีอยู่ทั้งหมดโดยค่าเริ่มต้น ให้ใช้เครื่องหมายคําพูดคู่สําหรับสตริง ความสําคัญ: ส่วนนี้ไม่ได้ระบุในคู่มือสไตล์ Python แต่แนะนําให้ใช้ความสอดคล้อง เราจึงตัดสินใจใช้เฉพาะสตริงที่ใส่เครื่องหมายคําพูดคู่เท่านั้น หลายภาษาใช้เครื่องหมายคําพูดคู่ สําหรับสัญพจน์ของสตริง
ใช้บรรทัดว่างบรรทัดเดียวระหว่างคําจํากัดความระดับบนสุด 2 รายการ เหตุผล: โครงสร้างของไฟล์
BUILD
ไม่เหมือนไฟล์ Python ทั่วไป มีเฉพาะข้อความระดับบนสุดเท่านั้น การใช้บรรทัดว่างบรรทัดเดียวจะทําให้ไฟล์BUILD
รายการสั้นลง