การจัดรูปแบบไฟล์ 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()
การเรียกใช้กฎและมาโคร
Buildifier สร้างความแตกต่างระหว่างความคิดเห็นแบบสแตนด์อโลนและความคิดเห็น เชื่อมโยงกับองค์ประกอบหนึ่ง หากความคิดเห็นไม่ได้แนบอยู่กับองค์ประกอบใดองค์ประกอบหนึ่ง ให้ใช้ มีบรรทัดว่างอยู่ด้านหลัง ความแตกต่างนั้นสำคัญมากเมื่อดำเนินการแบบอัตโนมัติ การเปลี่ยนแปลง (เช่น เก็บหรือนำความคิดเห็นออกเมื่อลบกฎ)
# 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
1 รายการ หมายความถึงการใช้ชื่อที่ไม่ใช่ เหมือนกันกับชื่อไฟล์ที่ไม่มีนามสกุล - สำหรับกฎ 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:
- เป้าหมาย
proto_library
รายการควรมีชื่อที่ลงท้ายด้วย_proto
- ภาษาเฉพาะของกฎ
*_proto_library
ควรตรงกับ Proto แต่แทนที่_proto
ด้วยคำต่อท้ายที่เจาะจงภาษา เช่นcc_proto_library
:_cc_proto
java_proto_library
:_java_proto
java_lite_proto_library
:_java_proto_lite
- เป้าหมาย
ระดับการแชร์
ควรกำหนดขอบเขตระดับการมองเห็นให้สั้นที่สุดเท่าที่จะทำได้ ขณะที่ยังอนุญาตให้เข้าถึงได้
ผ่านการทดสอบและการอ้างอิงแบบย้อนกลับ ใช้ __pkg__
และ __subpackages__
เป็น
เหมาะสม
หลีกเลี่ยงการตั้งค่าแพ็กเกจ default_visibility
เป็น //visibility:public
ควรตั้งค่า //visibility:public
แยกกันสำหรับเป้าหมายใน
API สาธารณะของโปรเจ็กต์ ซึ่งอาจเป็นไลบรารีที่ออกแบบมาเพื่อให้มีการอ้างอิง
โดยโปรเจ็กต์หรือไบนารีภายนอกที่โปรเจ็กต์ภายนอกสามารถใช้ได้
สร้างกระบวนการสร้าง
การอ้างอิง
การขึ้นต่อกันควรจำกัดเฉพาะการขึ้นต่อกันโดยตรง (การขึ้นต่อกัน) ที่จำเป็นสำหรับแหล่งที่มาที่ระบุไว้ในกฎ) ไม่ต้องแสดงรายการทรัพยากร Dependency แบบสับเปลี่ยน
ทรัพยากร Dependency ภายในแพ็กเกจควรแสดงขึ้นมาก่อนและมีการอ้างอิงในลักษณะ ที่ใช้งานร่วมกันได้กับ การอ้างอิงเป้าหมายในแพ็กเกจปัจจุบัน ด้านบน (ไม่ใช่ชื่อแพ็กเกจสัมบูรณ์)
หากต้องการแสดงรายการทรัพยากร Dependency โดยตรงเป็นรายการเดียว การใช้ "การตั้งค่าร่วม" ทรัพยากร Dependency ของเป้าหมายหลายรายการให้เป็นตัวแปรจะลดความสามารถในการบำรุงรักษา ทำให้ เครื่องมือจะเปลี่ยนการพึ่งพาเป้าหมายไม่ได้ และอาจทำให้เกิด ทรัพยากร Dependency ที่ไม่ได้ใช้
ลูกโลก
ระบุ "ไม่มีเป้าหมาย" ด้วย []
อย่าใช้ glob ที่ไม่ตรงเลย:
มีแนวโน้มที่จะเกิดข้อผิดพลาดมากกว่าและเห็นได้ชัดน้อยกว่ารายการที่ว่างเปล่า
เกิดซ้ำ
อย่าใช้ glob ที่เกิดซ้ำเพื่อจับคู่ไฟล์ต้นฉบับ (เช่น
glob(["**/*.java"])
)
glob ที่เกิดซ้ำทำให้ไฟล์ BUILD
รายการเข้าใจยากเนื่องจากมีการข้าม
ไดเรกทอรีย่อยที่มี BUILD
ไฟล์
โดยทั่วไป glob ที่เกิดซ้ำจะมีประสิทธิภาพน้อยกว่าการมีไฟล์ BUILD
ต่อ
ที่มีกราฟการขึ้นต่อกันที่กำหนดไว้ระหว่างกัน เนื่องจากจะช่วยให้
การแคชจากระยะไกลและการทำงานพร้อมกัน
คุณควรเขียนไฟล์ BUILD
ในแต่ละไดเรกทอรีและกำหนด
กราฟของทรัพยากร Dependency ทั้งหมด
ไม่เกิดซ้ำ
โดยทั่วไปเรายอมรับ glob ที่ไม่เกิดซ้ำ
การประชุมอื่นๆ
ใช้ตัวพิมพ์ใหญ่และขีดล่างเพื่อประกาศค่าคงที่ (เช่น
GLOBAL_CONSTANT
) ใช้ตัวพิมพ์เล็กและขีดล่างเพื่อประกาศตัวแปร (เช่นmy_variable
)ไม่ควรแยกป้ายกำกับแม้จะยาวเกิน 79 อักขระก็ตาม ป้ายกำกับควรเป็นลิเทอรัลสตริงทุกครั้งที่เป็นไปได้ เหตุผล: ทำให้ ค้นหาและแทนที่ได้ง่ายๆ และยังช่วยให้อ่านง่ายขึ้น
ค่าของแอตทริบิวต์ name ควรเป็นสตริงคงที่ลิเทอรัล (ยกเว้น ในมาโคร) เหตุผล: เครื่องมือภายนอกจะใช้แอตทริบิวต์ชื่อเพื่ออ้างอิง กฎ โดยทีมจะต้องค้นหากฎได้โดยไม่ต้องตีความโค้ด
เมื่อตั้งค่าแอตทริบิวต์ประเภทบูลีน ให้ใช้ค่าบูลีน ไม่ใช่ค่าจำนวนเต็ม ด้วยเหตุผลเดิม กฎจะยังคงแปลงจำนวนเต็มเป็นบูลีนตามที่จำเป็น แต่เราไม่แนะนำให้ทำ เหตุผล:
flaky = 1
อาจอ่านผิดว่าระบุ "ป้องกันเป้าหมายนี้โดยการเรียกใช้อีกครั้ง"flaky = True
พูดอย่างตรงไปตรงมา "การทดสอบนี้ไม่น่าเชื่อถือ"
ความแตกต่างกับคู่มือรูปแบบ Python
แม้ว่าความเข้ากันได้กับ คู่มือแนะนำรูปแบบ Python คือเป้าหมาย ซึ่งมีความแตกต่างเล็กน้อย ได้แก่
ไม่มีการจำกัดความยาวของบรรทัดที่เข้มงวด ความคิดเห็นแบบยาวและสตริงแบบยาวมักแยกจากกัน 79 คอลัมน์ แต่ก็ไม่จำเป็น ไม่ควรบังคับใช้ในโค้ด ตรวจสอบหรือส่งสคริปต์ล่วงหน้า เหตุผล: ป้ายกำกับอาจยาวและยาวกว่านี้ได้ ขีดจำกัด การสร้างหรือแก้ไขไฟล์
BUILD
ถือเป็นเรื่องปกติ ซึ่งมีขีดจำกัดความยาวของบรรทัดได้ไม่ดีนักไม่สนับสนุนการต่อสตริงโดยนัย ใช้โอเปอเรเตอร์
+
เหตุผล: ไฟล์BUILD
รายการประกอบด้วยรายการสตริงหลายรายการ คุณอาจจะลืม คอมมา ซึ่งนำไปสู่ผลลัพธ์ที่แตกต่างกันที่สมบูรณ์ ทำให้มีข้อบกพร่องเป็นจำนวนมาก ในช่วงที่ผ่านมา ดูการสนทนานี้เพิ่มเติมใช้เว้นวรรครอบเครื่องหมาย
=
สำหรับอาร์กิวเมนต์คีย์เวิร์ดในกฎ เหตุผล: อาร์กิวเมนต์ที่มีชื่อมีบ่อยกว่าใน Python มากและมักจะใช้อาร์กิวเมนต์ แยกบรรทัดกัน พื้นที่ทำงานช่วยให้อ่านง่ายขึ้น การประชุมนี้มีขึ้นในช่วง เป็นเวลานาน และไม่คุ้มที่จะแก้ไขไฟล์BUILD
ที่มีอยู่ทั้งหมดโดยค่าเริ่มต้น ให้ใช้เครื่องหมายอัญประกาศคู่สำหรับสตริง เหตุผล: นี่ไม่ใช่ ที่ระบุในคู่มือรูปแบบ Python แล้ว แต่แนะนำให้ใช้ความสอดคล้อง ดังนั้นเรา จึงเลือกใช้เพียงสตริงที่มีเครื่องหมายคำพูดคู่ หลายภาษาใช้เครื่องหมายคำพูดคู่ สำหรับลิเทอรัลสตริง
ใช้บรรทัดว่างบรรทัดเดียวระหว่างคำจำกัดความระดับบนสุด 2 รายการ เหตุผล: เหตุผล ของไฟล์
BUILD
ไม่เหมือนกับไฟล์ Python ทั่วไป แต่มี ข้อความระดับบนสุด การใช้บรรทัดว่างบรรทัดเดียวจะทำให้ไฟล์BUILD
ไฟล์สั้นลง