قالب بندی فایل 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();' > $@",
)
نام گذاری هدف
نام هدف باید توصیفی باشد. اگر هدف حاوی یک فایل منبع باشد، هدف معمولاً باید نامی برگرفته از آن منبع داشته باشد (به عنوان مثال، یک 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
این به معنای استفاده از نامی است که با نام فایل بدون پسوند یکسان نیست. - برای قوانین
*_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
-
- اهداف
دید
دید باید تا حد امکان دقیق باشد، در حالی که همچنان امکان دسترسی با آزمایش و وابستگی معکوس وجود دارد. در صورت لزوم از __pkg__
و __subpackages__
استفاده کنید.
از تنظیم بسته default_visibility
به //visibility:public
اجتناب کنید. //visibility:public
باید به صورت جداگانه فقط برای اهداف در API عمومی پروژه تنظیم شود. اینها میتوانند کتابخانههایی باشند که به گونهای طراحی شدهاند که توسط پروژههای خارجی وابسته باشند یا باینریهایی که میتوانند توسط فرآیند ساخت یک پروژه خارجی مورد استفاده قرار گیرند.
وابستگی ها
وابستگی ها باید به وابستگی های مستقیم (وابستگی های مورد نیاز منابع ذکر شده در قانون) محدود شوند. وابستگی های گذرا را فهرست نکنید.
وابستگی های بسته-محلی باید ابتدا فهرست شوند و به شیوه ای سازگار با مراجع به اهداف در بخش بسته فعلی بالا (نه با نام بسته مطلق آنها) ارجاع داده شوند.
ترجیح دهید وابستگی ها را مستقیماً به عنوان یک لیست واحد فهرست کنید. قرار دادن وابستگی های "مشترک" چندین هدف در یک متغیر، قابلیت نگهداری را کاهش می دهد، ابزارها را نمی توانند وابستگی های یک هدف را تغییر دهند و می تواند منجر به وابستگی های استفاده نشده شود.
گلوب
"بدون هدف" را با []
نشان دهید. از گلوبی استفاده نکنید که با هیچ چیز مطابقت ندارد: این فهرست نسبت به یک لیست خالی بیشتر مستعد خطا و آشکارتر است.
بازگشتی
از glob های بازگشتی برای مطابقت با فایل های منبع استفاده نکنید (به عنوان مثال، glob(["**/*.java"])
).
glob های بازگشتی استدلال فایل های BUILD
را دشوار می کنند زیرا از زیر شاخه های حاوی فایل های BUILD
می کنند.
گلوبهای بازگشتی معمولاً کارایی کمتری نسبت به داشتن یک فایل BUILD
در هر دایرکتوری با نمودار وابستگی تعریفشده بین آنها دارند، زیرا این امکان ذخیرهسازی از راه دور و موازیسازی بهتر را فراهم میکند.
نوشتن یک فایل BUILD
در هر دایرکتوری و تعریف یک نمودار وابستگی بین آنها تمرین خوبی است.
غیر بازگشتی
گلوب های غیر بازگشتی به طور کلی قابل قبول هستند.
سایر کنوانسیون ها
از حروف بزرگ و زیرخط برای اعلام ثابت ها (مانند
GLOBAL_CONSTANT
)، از حروف کوچک و زیرخط برای اعلام متغیرها (مانندmy_variable
) استفاده کنید.برچسب ها هرگز نباید تقسیم شوند، حتی اگر بیشتر از 79 کاراکتر باشند. تا حد امکان برچسب ها باید به صورت رشته ای باشند. دلیل : یافتن و جایگزینی را آسان می کند. همچنین خوانایی را بهبود می بخشد.
مقدار مشخصه name باید یک رشته ثابت تحت اللفظی باشد (به جز در ماکروها). منطق : ابزارهای خارجی از ویژگی name برای ارجاع یک قانون استفاده می کنند. آنها باید قوانینی را بدون نیاز به تفسیر کد پیدا کنند.
هنگام تنظیم ویژگی های نوع بولی، از مقادیر بولی استفاده کنید، نه از مقادیر صحیح. به دلایل قدیمی، قوانین همچنان در صورت نیاز اعداد صحیح را به بولی تبدیل میکنند، اما این کار منع میشود. منطق :
flaky = 1
را میتوان به اشتباه به این صورت خوانده شود که میگوید: «این هدف را با یک بار اجرای مجدد آن حذف کنید».flaky = True
بدون ابهام می گوید "این تست پوسته پوسته است".
تفاوت با راهنمای سبک پایتون
اگرچه سازگاری با راهنمای سبک پایتون یک هدف است، اما چند تفاوت وجود دارد:
بدون محدودیت طول خط. نظرات طولانی و رشته های طولانی اغلب به 79 ستون تقسیم می شوند، اما لازم نیست. نباید در بازبینی کدها یا اسکریپتها از قبل ارسال شود. دلیل : برچسب ها می توانند طولانی باشند و از این حد تجاوز کنند. معمول است که فایلهای
BUILD
توسط ابزار تولید یا ویرایش شوند، که با محدودیت طول خط به خوبی پیش نمیرود.الحاق رشته ضمنی پشتیبانی نمی شود. از عملگر
+
استفاده کنید. دلیل : فایل هایBUILD
حاوی لیست های رشته ای زیادی هستند. به راحتی می توان کاما را فراموش کرد که منجر به یک نتیجه کاملاً متفاوت می شود. این باعث ایجاد باگ های زیادی در گذشته شده است. این بحث را هم ببینید.از فاصله های اطراف علامت
=
برای آرگومان های کلمات کلیدی در قوانین استفاده کنید. دلیل: آرگومان های نامگذاری شده بسیار بیشتر از پایتون هستند و همیشه در یک خط جداگانه قرار دارند. فضاها خوانایی را بهبود می بخشند. این کنوانسیون مدت زیادی است که وجود داشته است و ارزش تغییر همه فایل هایBUILD
موجود را ندارد.بهطور پیشفرض، از علامتهای نقل قول دوتایی برای رشتهها استفاده کنید. دلیل : این در راهنمای سبک پایتون مشخص نشده است، اما سازگاری را توصیه می کند. بنابراین ما تصمیم گرفتیم که فقط از رشته های دو نقل قول استفاده کنیم. بسیاری از زبان ها از دو نقل قول برای حرف های رشته ای استفاده می کنند.
از یک خط خالی بین دو تعریف سطح بالا استفاده کنید. دلیل : ساختار یک فایل
BUILD
مانند یک فایل معمولی پایتون نیست. فقط بیانیه های سطح بالا دارد. استفاده از یک خط خالی باعث کوتاهتر شدن فایلهایBUILD
میشود.