دليل النمط .bzl

تتناول هذه الصفحة إرشادات الأنماط الأساسية لتطبيق Starlark وتشمل أيضًا معلومات عن وحدات الماكرو والقواعد.

Starlark هي لغة تحدّد طريقة تصميم البرامج، وهي بالتالي لغة برمجة ولغة ضبط.

يمكنك استخدام Starlark لكتابة BUILD ملفًا ووحدات ماكرو وإنشاء قواعد. وحدات الماكرو هي لغات وصفية في الأساس، وهي تحدّد طريقة كتابة ملفات BUILD. يجب أن تكون ملفات BUILD بسيطة ومتكررة.

تتم قراءة جميع البرامج بمعدل أكبر من كتابتها. ينطبق هذا الأمر على وجه الخصوص على Starlark حيث يقرأ المهندسون ملفات BUILD لفهم تبعيات أهدافهم وتفاصيل إصداراتهم. وغالبًا ما تتم هذه القراءة في الوقت ذاته أو بشكل سريع أو بالتزامن مع إنجاز بعض المهام الأخرى. وبالتالي، تُعدّ البساطة وسهولة القراءة مهمّتَين جدًا حتى يتمكّن المستخدمون من تحليل ملفات BUILD وفهمها بسرعة.

وعندما يفتح المستخدم ملف BUILD، يريد بسرعة معرفة قائمة الأهداف في الملف، أو مراجعة قائمة مصادر مكتبة C++ هذه، أو إزالة اعتمادية من برنامج Java الثنائي. وفي كل مرة تضيف فيها طبقة نظرية، تجعل من الصعب على المستخدم تنفيذ هذه المهام.

يتم أيضًا تحليل BUILD ملفات وتعديلها من خلال العديد من الأدوات المختلفة. قد لا تتمكّن الأدوات من تعديل ملف BUILD إذا كان يستخدم تجريدات. يسمح لك تبسيط ملفات BUILD بالحصول على أدوات أفضل. مع نمو قاعدة الرموز، يزيد تكرار إجراء التغييرات على العديد من ملفات BUILD من أجل تحديث مكتبة أو إزالة البرامج غير المرغوب فيها.

نصائح عامة

النمط

نمط لغة Python

وفي حال الشكوك، اتّبِع دليل أسلوب PEP 8 متى أمكن. وعلى وجه الخصوص، استخدِم أربع مسافات بدلاً من مسافات بادئة لاتباع اصطلاح Python.

بما أنّ Starlark ليست Python، لا يتم تطبيق بعض جوانب نمط Python. على سبيل المثال، ينصح"PEP 8"بأن تكون المقارنات بين الأغاني الفردية وis مفعّلة، وهي ليست عامل تشغيل في Starlark.

حفظ المستندات

ملفات المستندات والوظائف باستخدام docstrings. استخدِم سلسلة مستندات في أعلى كل ملف .bzl، وسلسلة مرجعية لكل دالة عامة.

جوانب المستندات وجوانبها

يجب توثيق القواعد والجوانب جنبًا إلى جنب مع سماتها، وكذلك مقدّمي الخدمة وحقولها، باستخدام الوسيطة doc.

اصطلاح التسمية

  • تستخدم المتغيرات وأسماء الدوال أحرفًا صغيرة مع الفصل بين الكلمات بشرطة سفلية ([a-z][a-z0-9_]*)، مثل cc_library.
  • وتبدأ القيم الخاصة على المستوى الأعلى بشرطة سفلية واحدة. يفرض تطبيق Bazel أنّه لا يمكن استخدام القيم الخاصة من الملفات الأخرى. يجب ألا تستخدم المتغيرات المحلية بادئة الشرطة السفلية.

طول السطر

كما في ملفات BUILD، ما مِن حد أقصى مفروض على طول السطر، حيث يمكن أن تكون التصنيفات طويلة. حاوِل استخدام 79 حرفًا في كل سطر على الأكثر (مع اتّباع إرشادات نمط Python's، 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. يُرجى مراعاة ما إذا كانت هذه العبارات مفيدة بما يكفي لتبرير تأثيرها على سهولة القراءة.

وحدات ماكرو

وحدة الماكرو هي دالة تعمل على إنشاء قاعدة واحدة أو أكثر أثناء مرحلة التحميل. بشكل عام، استخدِم القواعد كلما أمكن بدلاً من وحدات الماكرو. يختلف رسم الرسم البياني الذي يراه المستخدم عن الرسم البياني الذي يستخدمه Bazel أثناء الإصدار، ويتم توسيع وحدات الماكرو قبل إجراء Bazel لأي تحليل للرسم البياني.

ولهذا السبب، عندما يحدث خطأ، سيحتاج المستخدم إلى فهم تنفيذ وحدة الماكرو، لتحديد مشاكل الإصدار وحلّها. بالإضافة إلى ذلك، قد يصعب تفسير نتائج bazel query لأن الأهداف الواردة في النتائج تأتي من التوسع الكبير. وأخيرًا، لا تتوفّر جوانب لاستخدام وحدات الماكرو، لذلك قد يتعذّر استخدام الأدوات استنادًا إلى الجوانب (IDE وغيرها).

الاستخدام الآمن لوحدات الماكرو هو تحديد أهداف إضافية يُقصد الإشارة إليها مباشرةً في واجهة سطر الأوامر في Bazel أو في ملفات BUILD: في هذه الحالة، يجب فقط معرفة المستخدمين النهائيين لتلك الأهداف، ولن تكون أي مشاكل في الإصدار تُحدثها وحدات الماكرو بعيدة عن استخدامها.

بالنسبة إلى وحدات الماكرو التي تحدّد الاستهدافات التي تم إنشاؤها (تفاصيل تنفيذ وحدة الماكرو التي لا يُفترض أن تتم الإشارة إليها في واجهة سطر الأوامر (CLI) أو تعتمد عليها من خلال الأهداف التي لا يتم إنشاؤها بواسطة ذلك الماكرو)، اتّبِع أفضل الممارسات التالية:

  • يجب أن تأخذ وحدة الماكرو وسيطة name وتحدّد هدفًا بهذا الاسم. ويصبح هذا الهدف هو الهدف الرئيسي لذلك الماكرو.
  • الاستهدافات التي يتم إنشاؤها، أي جميع الأهداف الأخرى التي تحدّدها وحدة ماكرو، يجب أن:
    • يجب أن تكون أسماؤهم مسبوقة بالرمز <name> أو _<name>. على سبيل المثال، باستخدام name = '%s_bar' % (name).
    • لها حق دخول محدود (//visibility:private)
    • استخدام علامة manual لتجنّب توسيع نطاق أحرف البدل (:all و... و:* وما إلى ذلك)
  • يجب استخدام name فقط للحصول على أسماء الأهداف المحدّدة في وحدة الماكرو، وليس لأي شيء آخر. على سبيل المثال، لا تستخدم الاسم لاستخراج ملف الاعتمادية أو ملف الإدخال الذي لا يتم إنشاؤه بواسطة وحدة الماكرو نفسها.
  • يجب إقران جميع الأهداف التي تم إنشاؤها في وحدة الماكرو بطريقة ما بالهدف الرئيسي.
  • حافِظ على اتساق أسماء المعلّمات في وحدة الماكرو. في حال تمرير معلّمة باعتبارها قيمة سمة إلى الهدف الرئيسي، اترك اسمها كما هو. إذا كانت معلّمة ماكرو تخدم الغرض نفسه كسمة قاعدة مشتركة، مثل deps، أدخِل الاسم كما تفعل مع السمة (انظر أدناه).
  • عند استدعاء وحدة ماكرو، استخدِم وسيطات الكلمات الرئيسية فقط. يتوافق ذلك مع القواعد ويزيد من سهولة القراءة.

غالبًا ما يكتب المهندسون وحدات ماكرو عندما تكون واجهة برمجة التطبيقات Starlark API غير كافية لحالة الاستخدام المحدّدة، بغض النظر عمّا إذا كانت القاعدة محددة ضمن Bazel في الرمز الأصلي أو في Starlark. إذا كنت تواجه هذه المشكلة، اسأل مؤلف القاعدة عما إذا كان بإمكانه تمديد واجهة برمجة التطبيقات لتحقيق أهدافك.

وكقاعدة عامة، كلما كانت المزيد من وحدات الماكرو تشبه القواعد، كان ذلك أفضل.

يمكنك أيضًا الاطّلاع على وحدات الماكرو.

القواعد

  • يجب أن تستخدم القواعد والجوانب والسمات الخاصة بها أسماء أحرف صغيرة ("snake case").
  • أسماء القواعد هي الأسماء التي تصف النوع الرئيسي من العناصر التي تنتجها القاعدة، من منظور العناصر التابعة (أو من خلال قواعد الخصائص التفصيلية: المستخدم). هذه ليست بالضرورة لاحقة ملف. على سبيل المثال، قد تُسمى القاعدة التي تنتج عنها عناصر C++ بهدف استخدامها كإضافات Python py_extension. وبالنسبة إلى معظم اللغات، تشمل القواعد النموذجية ما يلي:
    • *_library - وحدة تجميع أو "Unit&quot؛
    • *_binary - هدف يُنتج وحدة تنفيذية أو وحدة نشر.
    • *_test - هدف اختباري. ويمكن أن يشمل ذلك اختبارات متعددة. توقّع أن تكون جميع الاختبارات في الهدف *_test من الصيغ مختلفة للموضوع نفسه، على سبيل المثال، اختبار مكتبة واحدة.
    • *_import: هدف يتضمّن عنصرًا مجمّعًا مسبقًا، مثل .jar أو .dll يُستخدم أثناء التجميع.
  • استخدِم أسماء وأنواعًا متسقة للسمات. وتشمل بعض السمات العامة ما يلي:
    • srcs: label_list، ما يسمح بالملفات: الملفات المصدر، عادةً من تأليف الإنسان.
    • deps: label_list لا يسمح عادةً بالملفات: العناصر التابعة للتجميع.
    • data: label_list، ما يسمح بالملفات: ملفات البيانات، مثل بيانات الاختبار، وما إلى ذلك
    • runtime_deps: label_list: تبعيات وقت التشغيل غير مطلوبة للتجميع.
  • بالنسبة إلى أي سمات تتضمّن سلوكًا غير واضح (على سبيل المثال، نماذج السلاسل التي تحتوي على بدائل خاصة أو أدوات تم استدعاءها وفقًا لمتطلبات معيّنة)، قدِّم مستندات باستخدام وسيطة الكلمة الرئيسية doc إلى بيان السمة (attr.label_list()) أو ما شابه ذلك.
  • يجب أن تكون دوال تنفيذ القاعدة دوال خاصة في معظم الأحيان (تُسمى شرطة سفلية رائدة). من الشائع استخدام دالة تنفيذ myrule لاسم _myrule_impl.
  • يمكنك تمرير المعلومات بين قواعدك باستخدام واجهة provider المحددة بشكل جيد. التعريف وحقول مزوّدي المستندات.
  • صمِّم قاعدتك مع مراعاة قابلية التوسّع. ضع في اعتبارك أن القواعد الأخرى قد تريد التفاعل مع القاعدة، والوصول إلى مقدمي الخدمات، وإعادة استخدام الإجراءات التي أنشأتها.
  • واتّبِع إرشادات الأداء في قواعدك.