إذا كنت لا تستخدم CMake أو ndk-build ولكنك تريد الدمج الكامل بين أداة إنشاء C/C++ في مكوّن إضافي لـ Android Gradle (AGP) وAndroid Studio، يمكنك إنشاء نظام إنشاء مخصّص لـ C/C++ من خلال إنشاء نص برمجي لنظام التشغيل Shell يكتب معلومات الإنشاء بتنسيق ملف إنشاء Ninja.
تمت إضافة دعم تجريبي لأنظمة إنشاء C/C++ المخصّصة إلى "استوديو Android" وAGP. تتوفّر هذه الميزة بدءًا من الإصدار Android Studio Dolphin | 2021.3.1 Canary 4.
نظرة عامة
من الأنماط الشائعة لمشاريع C/C++، خاصةً تلك التي تستهدف أنظمة تشغيل متعددة، إنشاء مشاريع لكل نظام تشغيل من هذه الأنظمة من تمثيل أساسي.
ومن الأمثلة البارزة على هذا النمط CMake. يمكن أن تنشئ أداة CMake مشاريع لنظامَي التشغيل Android وiOS والأنظمة الأساسية الأخرى من تمثيل أساسي واحد محفوظ في ملف CMakeLists.txt
.
على الرغم من أنّ AGP متوافق مباشرةً مع CMake، تتوفّر أدوات إنشاء مشاريع أخرى غير متوافقة مباشرةً:
تتيح هذه الأنواع من أدوات إنشاء المشاريع استخدام Ninja كتمثيل لنظام التشغيل الخلفي لإنشاء C/C++ أو يمكن تعديلها لإنشاء Ninja كتمثيل لنظام التشغيل الخلفي.
عند الضبط الصحيح، يتيح مشروع AGP المزوّد بنظام مولد متكامل لمشاريع C/C++ للمستخدمين إجراء ما يلي:
يمكنك إنشاء التطبيق من سطر الأوامر و"استوديو Android".
تعديل المصادر باستخدام ميزة الدعم الكامل لخدمة اللغة (مثل التعريف المرجعي) في Android Studio
استخدِم برامج تصحيح الأخطاء في "استوديو Android" لتصحيح أخطاء العمليات الأصلية والمختلطة.
كيفية تعديل عملية الإنشاء لاستخدام نص برمجي مخصّص لإعداد عملية إنشاء C/C++
يشرح هذا القسم خطوات استخدام نص برمجي مخصّص لإعداد عملية إنشاء C/C++ من AGP.
الخطوة 1: تعديل ملف build.gradle
على مستوى الوحدة للإشارة إلى نص برمجي للإعدادات
لتفعيل ميزة Ninja في AGP، عليك ضبط experimentalProperties
في ملف build.gradle
على مستوى الوحدة:
android {
defaultConfig {
externalNativeBuild {
experimentalProperties["ninja.abiFilters"] = [ "x86", "arm64-v8a" ]
experimentalProperties["ninja.path"] = "source-file-list.txt"
experimentalProperties["ninja.configure"] = "configure-ninja"
experimentalProperties["ninja.arguments"] = [
"\${ndk.moduleMakeFile}",
"--variant=\${ndk.variantName}",
"--abi=Android-\${ndk.abi}",
"--configuration-dir=\${ndk.configurationDir}",
"--ndk-version=\${ndk.moduleNdkVersion}",
"--min-sdk-version=\${ndk.minSdkVersion}"
]
}
}
تفسّر AGP السمات على النحو التالي:
ninja.abiFilters
هي قائمة بواجهات ABI المطلوب إنشاؤها. القيم الصالحة هي:x86
وx86-64
وarmeabi-v7a
وarm64-v8a
.ninja.path
هو مسار إلى ملف مشروع C/C++. يمكن أن يكون تنسيق هذا الملف أي تنسيق تريده. ستؤدي التغييرات في هذا الملف إلى ظهور طلب لمزامنة Gradle في Android Studio.ninja.configure
هو مسار إلى ملف نصي سيتم تنفيذه بواسطة Gradle عند الحاجة إلى ضبط مشروع C/C++. يتم ضبط المشروع في عملية التصميم الأولى، أو أثناء مزامنة Gradle في Android Studio، أو عند تغيير إحدى مدخلات نص الإعداد.ninja.arguments
هي قائمة بالوسيطات التي سيتم تمريرها إلى البرنامج النصي الذي يحدّده ninja.configure. يمكن أن تشير العناصر في هذه القائمة إلى مجموعة من وحدات الماكرو التي تعتمد قيمها على سياق الضبط الحالي في AGP:${ndk.moduleMakeFile}
هو المسار الكامل لملفninja.configure
. في المثال، سيكونC:\path\to\configure-ninja.bat
.${ndk.variantName}
هو اسم الصيغة الحالية لملف AGP الذي يتم إنشاؤه. على سبيل المثال، تصحيح الأخطاء أو الإصدار.${ndk.abi}
هو اسم ABI الحالي لـ AGP الذي يتم إنشاؤه. على سبيل المثال،x86
أوarm64-v8a
.
${ndk.buildRoot}
هو اسم مجلد أنشأه AGP يكتب النص البرمجي مخرجاته فيه. سيتم شرح تفاصيل ذلك في الخطوة 2: إنشاء نص الإعداد.${ndk.ndkVersion}
هو إصدار NDK الذي سيتم استخدامه. وتكون هذه القيمة عادةً هي القيمة التي يتم تمريرها إلى android.ndkVersion في ملفbuild.gradle
أو قيمة تلقائية في حال عدم توفّر أي قيمة.${ndk.minPlatform}
هو الحد الأدنى لنظام التشغيل Android المستهدف الذي تطلبه أداة AGP.
ninja.targets
هي قائمة بأهداف Ninja المحدّدة التي يجب إنشاؤها.
الخطوة 2: إنشاء نص الإعداد
الحد الأدنى من مسؤولية النص البرمجي لإعداد الإصدار (configure-ninja.bat
في المثال السابق) هو إنشاء ملف build.ninja
الذي سيُنشئ عند إنشائه باستخدام Ninja جميع النتائج الأصلية للمشروع ويربطها. وتكون هذه الملفات عادةً من النوع .o
(كائن) و.a
(أرشيف) و.so
(كائن مشترَك).
يمكن للنص البرمجي لإعداد الملفات كتابة ملف build.ninja
في مكانَين مختلفَين حسب احتياجاتك.
إذا كان من المقبول أن يختار AGP موقعًا جغرافيًا، يكتب النص البرمجي لإعداد
build.ninja
في الموقع الجغرافي الذي تم ضبطه في الماكرو${ndk.buildRoot}
.إذا كان النص البرمجي للضبط بحاجة إلى اختيار موقع ملف
build.ninja
، سيكتب أيضًا ملفًا باسمbuild.ninja.txt
في الموقع الذي تم ضبطه في الماكرو${ndk.buildRoot}
. يحتوي هذا الملف على المسار الكامل لملفbuild.ninja
الذي كتبه النص البرمجي لإعداد الإصدار.
بنية ملف build.ninja
بشكل عام، ستعمل معظم البنى التي تمثّل بدقة إصدار C/C++ لنظام التشغيل Android. في ما يلي العناصر الرئيسية التي يحتاج إليها كلّ من AGP و"استوديو Android":
قائمة ملفات C/C++ المصدر مع العلامات التي يحتاجها Clang لتجميعها
قائمة مكتبات الإخراج وتكون هذه الملفات عادةً من النوع
.so
(عنصر مشترَك)، ولكن يمكن أن تكون أيضًا من النوع.a
(أرشيف) أو ملفًا قابلاً للتنفيذ (بدون امتداد).
إذا كنت بحاجة إلى أمثلة عن كيفية إنشاء ملف build.ninja
، يمكنك الاطّلاع على ناتج CMake عند استخدام أداة إنشاء build.ninja
.
في ما يلي مثال على نموذج build.ninja
بسيط.
rule COMPILE
command = /path/to/ndk/clang -c $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
أفضل الممارسات
بالإضافة إلى المتطلبات (قائمة الملفات المصدر ومكتبات الإخراج)، إليك بعض أفضل الممارسات المقترَحة.
الإفصاح عن نتائج مُسمّاة باستخدام قواعد phony
ننصحك باستخدام قواعد phony
في بنية build.ninja
كلما أمكن ذلك لمنح أسماء قابلة للقراءة من قِبل البشر لمخرجات الإنشاء. على سبيل المثال، إذا كان لديك إخراج باسم c:/path/to/lib.so
، يمكنك منحه اسمًا يسهل على المستخدمين قراءته على النحو التالي.
build curl: phony /path/to/lib.so
وتتمثل فائدة إجراء ذلك في أنّه يمكنك بعد ذلك تحديد هذا الاسم كهدف إنشاء في ملف build.gradle
. على سبيل المثال:
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
تحديد استهداف "الكل"
عند تحديد استهداف all
، ستكون هذه هي المجموعة التلقائية من المكتبات التي أنشأتها أداة AGP عندما لا يتم تحديد أي استهدافات بشكل صريح في ملف build.gradle
.
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build foo.o : COMPILE foo.cpp
build bar.o : COMPILE bar.cpp
build libfoo.so : LINK foo.o
build libbar.so : LINK bar.o
build all: phony libfoo.so libbar.so
تحديد طريقة إنشاء بديلة (اختياري)
وإحدى حالات الاستخدام الأكثر تقدمًا هي لف نظام إنشاء حالي غير مستند إلى Ninja. في هذه الحالة، لا يزال عليك تمثيل جميع المصادر باستخدام علاماتها مع مكتبات الإخراج حتى يتمكّن Android Studio من تقديم ميزات خدمة اللغة المناسبة، مثل الإكمال التلقائي والانتقال إلى التعريف. ومع ذلك، تريد أن يستند AGP إلى نظام الإنشاء الأساسي أثناء عملية الإنشاء الفعلية.
ولإجراء ذلك، يمكنك استخدام ناتج إنشاء Ninja مع إضافة محددة .passthrough
.
على سبيل المثال، لنفترض أنّك تريد إنهاء عملية MSBuild. سيُنشئ النص البرمجي للإعداد build.ninja
كالمعتاد، ولكنه سيضيف أيضًا هدفًا للمرور يحدّد كيفية استدعاء AGP لـ MSBuild.
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
rule MBSUILD_CURL
command = /path/to/msbuild {flags to build curl with MSBuild}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
build curl : phony lib.so
build curl.passthrough : MBSUILD_CURL
تقديم التعليقات
هذه الميزة تجريبية، لذا نُقدّر بشدة أي ملاحظات وآراء بشأنها. يمكنك تقديم الملاحظات من خلال القنوات التالية:
للحصول على ملاحظات عامة، أضِف تعليقًا إلى هذا الخطأ.
للإبلاغ عن خطأ، افتح Android Studio وانقر على المساعدة > إرسال ملاحظات. احرص على الإشارة إلى "أنظمة إنشاء C/C++ المخصّصة" للمساعدة في توجيه الخطأ.
للإبلاغ عن خطأ إذا لم يكن لديك "استوديو Android" مثبّتًا، يمكنك إرسال تقرير الخطأ باستخدام هذا النموذج.