يتناول هذا البرنامج التعليمي أساسيات إنشاء تطبيقات باستخدام لغة Java. ستتمكّن من إعداد مساحة العمل وإنشاء مشروع Java بسيط
يشرح مفاهيم Bazel الرئيسية، مثل الأهداف وملفات BUILD
.
المدة المقدّرة للاكتمال: 30 دقيقة.
ما ستتعرَّف عليه
في هذا البرنامج التعليمي، ستتعرّف على كيفية:
- إنشاء هدف
- عرض العناصر التابعة للمشروع
- تقسيم المشروع إلى استهدافات وحِزم متعددة
- التحكّم في مستوى العرض المستهدَف في جميع الحِزم
- الأهداف المرجعية من خلال التصنيفات
- نشر هدف
قبل البدء
تثبيت Bazel
للاستعداد للبرنامج التعليمي، عليك أولاً تثبيت Bazel إذا لم يسبق لك تثبيته.
تثبيت JDK
ثبِّت Java JDK (الإصدار المفضّل هو 11، ولكن تتوفّر الإصدارات بين 8 و15).
اضبط متغير بيئة JAVA_HOME للتوجيه إلى JDK.
على نظام التشغيل Linux/macOS:
export JAVA_HOME="$(dirname $(dirname $(realpath $(which javac))))"
في نظام التشغيل Windows:
- افتح Control Panel (لوحة التحكم).
- الانتقال إلى "نظام التشغيل" و"نظام التشغيل" و"الأمان" &
- ضمن قائمة "،المتغيّرات والمستخدِمين" (القائمة في أعلى الصفحة)، انقر على "جديد..."،.
- في الحقل "الاسم &المتغيّر"،&أدخِل
JAVA_HOME
. - انقر على &عرض الدليل، &سجلّ؛؛
- انتقِل إلى دليل JDK (مثل
C:\Program Files\Java\jdk1.8.0_152
). - انقر على "OK"جميع نوافذ الحوار.
الحصول على نموذج المشروع
يمكنك استرداد نموذج المشروع من مستودع Bazel' GitHub:
git clone https://github.com/bazelbuild/examples
يتوفر نموذج المشروع لهذا البرنامج التعليمي في الدليل examples/java-tutorial
، وهو منظم على النحو التالي:
java-tutorial
├── BUILD
├── src
│ └── main
│ └── java
│ └── com
│ └── example
│ ├── cmdline
│ │ ├── BUILD
│ │ └── Runner.java
│ ├── Greeting.java
│ └── ProjectRunner.java
└── WORKSPACE
إنشاء المحتوى باستخدام Bazel
إعداد مساحة العمل
قبل إنشاء مشروع، عليك إعداد مساحة عمل له. مساحة العمل هي دليل يضم ملفات المصدر الخاصة بمشروعك وملفات Bazel's، ويتم إنشاؤها بسهولة. يتضمّن الملف أيضًا ملفات يعتبرها Bazel خاصةً:
يعرّف الملف
WORKSPACE
، الذي يعرّف الدليل ومحتواه كمساحة عمل في Bazel، ويتألف من جذر بنية الدليل.توفّر هذه اللعبة ملفًا واحدًا أو أكثر على
BUILD
لإعلام منشئ المحتوى بكيفية إنشاء أجزاء مختلفة من المشروع. (الدليل ضمن مساحة العمل التي تحتوي على ملفBUILD
هو حزمة. ستتعرّف على مزيد من المعلومات عن الحِزم لاحقًا في هذا البرنامج التعليمي.)
لتخصيص دليل كمساحة عمل من Bazel، يمكنك إنشاء ملف فارغ باسم
WORKSPACE
في هذا الدليل.
عندما ينشئ Bazel المشروع، يجب أن تكون جميع الإدخالات والاعتماديات في مساحة العمل نفسها. وتكون الملفات المتوفرة في مساحات عمل مختلفة مستقلة عن بعضها البعض ما لم تكن مرتبطة، وهذا خارج نطاق هذا البرنامج التعليمي.
فهم ملف BUILD
يتضمّن ملف BUILD
عدّة أنواع مختلفة من التعليمات الخاصة بتطبيق Bazel.
والنوع الأكثر أهمية هو قاعدة الإصدار التي تخبر Bazel بكيفية إنشاء النتائج المطلوبة، مثل البرامج الثنائية أو المكتبات القابلة للتنفيذ. يُطلق على كل مثيل من قاعدة إصدار في ملف BUILD
هدف ويشير إلى مجموعة معيّنة من ملفات المصدر والاعتماديات. ويمكن أن يشير الاستهداف أيضًا إلى استهدافات أخرى.
يُرجى إلقاء نظرة على ملف java-tutorial/BUILD
:
java_binary(
name = "ProjectRunner",
srcs = glob(["src/main/java/com/example/*.java"]),
)
في المثال هنا، ينشئ هدف ProjectRunner
مثيل Bazel's المضمّن
java_binary
. تطلب القاعدة من Bazel إنشاء ملف .jar
ونص برمجي لبرنامج تضمين البرنامج الوكيل (كلا منهما تمت تسميته بعد الهدف).
تشير السمات في الهدف بشكلٍ صريح إلى تبعياتها وخياراتها.
السمة name
إلزامية، ولكن العديد منها اختياري. على سبيل المثال، في
قاعدة القاعدة ProjectRunner
، name
هو اسم الهدف، يحدد srcs
الملفات المصدر التي يستخدمها Bazel لإنشاء الهدف، ويحدد main_class
الفئة التي تحتوي على الطريقة الرئيسية. (ربما لاحظت أن المثال الذي نستخدمه يستخدم glob لتمرير مجموعة من ملفات المصدر إلى Bazel بدلاً من إدراجها واحدًا تلو الآخر).
إنشاء المشروع
لإنشاء نموذج لمشروعك، انتقل إلى دليل java-tutorial
وشغّل ما يلي:
bazel build //:ProjectRunner
في التصنيف المستهدف، يكون الجزء //
هو موقع الملف BUILD
المرتبط بجذر مساحة العمل (في هذه الحالة، الجذر نفسه)، وProjectRunner
هو الاسم المستهدف في الملف BUILD
. (ستتعرف أكثر
على التصنيفات المستهدفة في نهاية هذا البرنامج التعليمي.)
تنتج Bazel نتائج مشابهة لما يلي:
INFO: Found 1 target...
Target //:ProjectRunner up-to-date:
bazel-bin/ProjectRunner.jar
bazel-bin/ProjectRunner
INFO: Elapsed time: 1.021s, Critical Path: 0.83s
تهانينا، لقد أنشأت للتو هدف Bazel الأول تُنشئ أماكن Bazel
النتائج في دليل bazel-bin
في جذر مساحة العمل. تصفَّح
محتوى القناة للحصول على فكرة عن بنية Bazel's للعرض.
يمكنك الآن اختبار برنامجك الثنائي الذي تم إنشاؤه حديثًا:
bazel-bin/ProjectRunner
مراجعة الرسم البياني للاعتمادية
يتطلب Bazel اعتمادية الإصدار صراحةً في ملفات BUILD. يستخدم Bazel هذه العبارات لإنشاء الرسم البياني للاعتمادية على المشروع، والذي يُمكّن إصدارات متزايدة دقيقة.
لوضع تمثيل بصري لاعتماديات المشروع، يمكنك إنشاء تمثيل نصي للرسم البياني للاعتمادية من خلال تشغيل هذا الأمر في جذر مساحة العمل:
bazel query --notool_deps --noimplicit_deps "deps(//:ProjectRunner)" --output graph
يوجّه الأمر السابق "بازل" البحث عن جميع تبعيات الهدف
//:ProjectRunner
(باستثناء المضيف والتبعيات الضمنية) وتنسيق الإخراج
كرسم بياني.
بعد ذلك، الصق النص في GraphViz.
كما ترى، يحتوي المشروع على هدف واحد يعمل على إنشاء ملفَي مصدر بدون تبعيات إضافية:
بعد إعداد مساحة العمل وإنشاء المشروع وفحص مهامها، يمكنك إضافة بعض التعقيد.
تحسين إصدار Bazel
على الرغم من أن الاستهداف الوحيد يكفي للمشاريع الصغيرة، قد تحتاج إلى تقسيم المشاريع الأكبر حجمًا إلى استهدافات وحزم متعددة للسماح بالبناء المتزايد السريع (أي إعادة إنشاء ما تم تغييره فقط) وتسريع الإصدارات من خلال بناء أجزاء متعددة من المشروع في آن واحد.
تحديد أهداف تصميم متعددة
يمكنك تقسيم نموذج المشروع إلى هدفين. استبدِل محتوى ملف java-tutorial/BUILD
بما يلي:
java_binary(
name = "ProjectRunner",
srcs = ["src/main/java/com/example/ProjectRunner.java"],
main_class = "com.example.ProjectRunner",
deps = [":greeter"],
)
java_library(
name = "greeter",
srcs = ["src/main/java/com/example/Greeting.java"],
)
باستخدام هذه الإعدادات، ينشئ Bazel مكتبة greeter
أولاً، ثم
البرنامج الثنائي ProjectRunner
. تخبر السمة deps
في java_binary
Bazel أن مكتبة greeter
مطلوبة لإنشاء برنامج ProjectRunner
ثنائي.
لإنشاء هذا الإصدار الجديد من المشروع، شغِّل الأمر التالي:
bazel build //:ProjectRunner
تنتج Bazel نتائج مشابهة لما يلي:
INFO: Found 1 target...
Target //:ProjectRunner up-to-date:
bazel-bin/ProjectRunner.jar
bazel-bin/ProjectRunner
INFO: Elapsed time: 2.454s, Critical Path: 1.58s
يمكنك الآن اختبار برنامجك الثنائي الذي تم إنشاؤه حديثًا:
bazel-bin/ProjectRunner
إذا عدّلت ProjectRunner.java
الآن وأعدت بناء المشروع، سيعمل Bazel على إعادة تجميع هذا الملف فقط.
بعد الاطّلاع على الرسم البياني للاعتمادية، يمكنك ملاحظة أنّ ProjectRunner
يعتمد على المدخلات نفسها التي كانت عليه من قبل، ولكن تختلف بنية الإصدار:
لقد أنشأت المشروع الآن باستخدام هدفين. ينشئ الهدف ProjectRunner
ملفَين مصدر، ويعتمد على هدف آخر واحد (:greeter
)، ما يؤدي إلى إنشاء
ملف مصدر واحد آخر.
استخدام حِزم متعدّدة
لنقسِّم المشروع الآن إلى عدة حِزم. عند الاطّلاع على دليل src/main/java/com/example/cmdline
، يمكنك العثور على الملف BUILD
أيضًا، بالإضافة إلى بعض الملفات المصدر. وبالتالي، في مساحة العمل، تحتوي مساحة العمل الآن على حزمتَين، //src/main/java/com/example/cmdline
و//
(بما أن هناك ملف BUILD
في جذر مساحة العمل).
يُرجى إلقاء نظرة على ملف src/main/java/com/example/cmdline/BUILD
:
java_binary(
name = "runner",
srcs = ["Runner.java"],
main_class = "com.example.cmdline.Runner",
deps = ["//:greeter"],
)
يعتمد الاستهداف runner
على الهدف greeter
في الحزمة //
(بالتالي
التصنيف المستهدف //:greeter
) - يعرف Bazel ذلك من خلال السمة deps
.
إلقاء نظرة على الرسم البياني للاعتمادية:
ومع نجاح هذا الإصدار، يجب منح الهدف runner
صراحةً في نطاق مستوى الرؤية //src/main/java/com/example/cmdline/BUILD
للاستهداف في //BUILD
باستخدام السمة visibility
. ويرجع ذلك إلى أنّ الأهداف التلقائية
لا تظهر إلا للأهداف الأخرى في ملف BUILD
نفسه. (يستخدم Bazel مستوى الرؤية المستهدف لمنع حدوث مشاكل مثل المكتبات التي تحتوي على تفاصيل التنفيذ (تسرب البيانات إلى واجهات برمجة التطبيقات العامة).
ولإجراء ذلك، أضِف السمة visibility
إلى الفئة المستهدفة greeter
في
java-tutorial/BUILD
كما هو موضّح أدناه:
java_library(
name = "greeter",
srcs = ["src/main/java/com/example/Greeting.java"],
visibility = ["//src/main/java/com/example/cmdline:__pkg__"],
)
يمكنك الآن إنشاء حزمة جديدة من خلال تشغيل الأمر التالي على جذر مساحة العمل:
bazel build //src/main/java/com/example/cmdline:runner
تنتج Bazel نتائج مشابهة لما يلي:
INFO: Found 1 target...
Target //src/main/java/com/example/cmdline:runner up-to-date:
bazel-bin/src/main/java/com/example/cmdline/runner.jar
bazel-bin/src/main/java/com/example/cmdline/runner
INFO: Elapsed time: 1.576s, Critical Path: 0.81s
يمكنك الآن اختبار برنامجك الثنائي الذي تم إنشاؤه حديثًا:
./bazel-bin/src/main/java/com/example/cmdline/runner
لقد عدَّلت الآن المشروع لإنشاء حزمتين، تحتوي كل منهما على هدف واحد، وفهم التبعيات بينهما.
استخدام التصنيفات للإشارة إلى الأهداف
في ملفات BUILD
وفي سطر الأوامر، يستخدم Bazel التصنيفات المستهدَفة للإشارة إلى الأهداف المستهدفة، على سبيل المثال //:ProjectRunner
أو //src/main/java/com/example/cmdline:runner
. وتكون البنية على النحو التالي:
//path/to/package:target-name
إذا كان الهدف هدف قاعدة، يكون path/to/package
هو المسار إلى الدليل الذي يحتوي على الملف BUILD
، وtarget-name
هو ما أسماه الهدف في الملف BUILD
(السمة name
). إذا كان الهدف استهداف ملف، يكون path/to/package
هو مسار جذر الجذر، ويمثل target-name
اسم الملف المستهدف، بما في ذلك المسار الكامل له.
عند الإشارة إلى الأهداف في جذر المستودع، يكون مسار الحزمة فارغًا، ما عليك سوى استخدام //:target-name
. عند الإشارة إلى الأهداف في ملف BUILD
نفسه، يمكنك تخطي معرّف جذر //
لمساحة العمل واستخدام
:target-name
فقط.
على سبيل المثال، بالنسبة إلى الأهداف في ملف java-tutorial/BUILD
، لم تكن مضطرًا إلى تحديد مسار الحزمة، بما أن جذر مساحة العمل هو الحزمة (//
)، وكان التصنيفان المستهدفان هما //:ProjectRunner
و//:greeter
.
ومع ذلك، بالنسبة إلى الأهداف في ملف //src/main/java/com/example/cmdline/BUILD
، كان عليك تحديد مسار الحزمة الكامل من //src/main/java/com/example/cmdline
وكان تصنيفك المستهدف هو //src/main/java/com/example/cmdline:runner
.
إرسال هدف Java للنشر
والآن، يمكننا تجميع هدف Java لنشره من خلال إنشاء برنامج ثنائي يتضمن جميع تبعيات وقت التشغيل. وهذا يتيح لك تشغيل البرنامج الثنائي خارج بيئة التطوير.
كما تتذكر، تُنشئ القاعدة java_binary
نصًّا برمجيًا .jar
والنص البرمجي لبرنامج Shell. يمكنك الاطّلاع على محتوى runner.jar
باستخدام هذا الأمر:
jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar
المحتوى هو:
META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/cmdline/
com/example/cmdline/Runner.class
كما ترى، يحتوي runner.jar
على Runner.class
، ولكن لا يعتمد على تحكمه،
Greeting.class
. يضيف النص البرمجي runner
الذي أنشأه Bazel greeter.jar
إلى مسار الصف، لذلك إذا تركته على هذا النحو، سيتم تشغيله محليًا، ولكن
لن يتم تشغيله بشكل مستقل على جهاز آخر. تسمح لك قاعدة java_binary
بإنشاء برنامج ثنائي مستقل وقابل للنشر. ولإنشائها، أضِف
_deploy.jar
إلى الاسم الهدف:
bazel build //src/main/java/com/example/cmdline:runner_deploy.jar
تنتج Bazel نتائج مشابهة لما يلي:
INFO: Found 1 target...
Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date:
bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar
INFO: Elapsed time: 1.700s, Critical Path: 0.23s
لقد صمَّمت للتو runner_deploy.jar
الذي يمكنك تشغيله بشكل مستقل عن بيئة التطوير نظرًا لاحتوائه على العناصر التابعة وقت التشغيل المطلوبة. يمكنك الاطّلاع على محتوى ملف JAR المستقل هذا باستخدام
الأمر نفسه كما في السابق:
jar tf bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar
يتضمن المحتوى كل الفئات المطلوبة لتشغيلها:
META-INF/
META-INF/MANIFEST.MF
build-data.properties
com/
com/example/
com/example/cmdline/
com/example/cmdline/Runner.class
com/example/Greeting.class
المزيد من القراءة
لمزيد من التفاصيل، يُرجى الاطّلاع على:
rules_jvm_external من أجل القواعد لإدارة تبعيات Maven المباشرة.
العناصر التابعة الخارجية لمعرفة المزيد من المعلومات حول التعامل مع المستودعات المحلية والبعيدة.
تعرّف على القواعد الأخرى لمعرفة المزيد من المعلومات عن Bazel.
يمكنك الاطّلاع على البرنامج التعليمي لإصدار C++ للبدء في إنشاء مشاريع C++ باستخدام Bazel.
يتضمن البرنامج التعليمي لتطبيق Android والبرنامج التعليمي لتطبيق iOS للبدء في إنشاء تطبيقات متوافقة مع الأجهزة الجوّالة لنظامي التشغيل Android وiOS مع Bazel.
نتمنى لك مبنى سعيدًا!