คู่มือแนะนำรูปแบบการสร้าง

วันที่ รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

การจัดรูปแบบไฟล์ 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 ไฟล์สั้นลง