يتيح Android NDK استخدام CMake ل compiling رمز C وC++ لتطبيقك. تتناول هذه الصفحة كيفية استخدام
CMake مع حزمة NDK من خلال ExternalNativeBuild
في "مكوّن إضافي لنظام Android Gradle" أو عند
استدعاء CMake مباشرةً.
ملف سلسلة أدوات CMake
يتوافق NDK مع CMake من خلال ملف سلسلة الأدوات. ملفات سلسلة الأدوات هي ملفات CMake
التي تخصّص سلوك سلسلة الأدوات للترجمة على أنظمة تشغيل متعددة. يمكن العثور على ملف toolchain
المستخدَم مع حزمة NDK في حزمة NDK على العنوان
<NDK>/build/cmake/android.toolchain.cmake
.
يتم تقديم مَعلمات الإنشاء، مثل ABI وminSdkVersion
وما إلى ذلك، على سطر
الأوامر عند استدعاء cmake
. للحصول على قائمة بالوسيطات المتوافقة، يُرجى الاطّلاع على القسم
وسيطات مجموعة الأدوات.
ملف سلسلة الأدوات "الجديدة"
جرَّب فريق NDK سابقًا عملية تنفيذ جديدة لملف سلسلة الأدوات من شأنها تقليل الاختلافات السلوكية بين استخدام ملف سلسلة الأدوات الخاص بها واستخدام أداة دعم CMake المضمَّنة. وقد تطلّب ذلك قدرًا كبيرًا من العمل (الذي لم يكتمل بعد)، ولكنه لم يؤدّ إلى تحسين الأداء، لذلك لن نواصل هذا المسار.
يتضمّن ملف سلسلة الأدوات "الجديدة" تراجعًا في السلوك مقارنةً بملف سلسلة الأدوات "القديم". السلوك التلقائي هو سير العمل المقترَح. إذا كنت تستخدم -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF
، ننصحك بإزالة هذا الإعداد
من الإصدار. لم يصل ملف سلسلة الأدوات الجديد إلى التكافؤ مع ملف
سلسلة الأدوات القديم، لذا من المحتمل أن يكون هناك تراجع في الأداء.
على الرغم من أنّنا لا ننصح باستخدام ملف سلسلة الأدوات الجديد، لا تتوفّر في الوقت الحالي خطط لإزالته من حزمة NDK. سيؤدي ذلك إلى إيقاف عمليات الإنشاء التي تعتمد على اختلافات السلوك بين ملفات سلسلة الأدوات الجديدة والقديمة، وبالتأكيد، سيؤدي إعادة تسمية الخيار لتوضيح أنّه يُنصح باستخدام الخيار "قديم" إلى إيقاف المستخدمين الذين يستخدمون هذا الخيار. إذا كنت تستخدم بنجاح ملف سلسلة الأدوات الجديد، لن تحتاج إلى نقل البيانات، ولكن يُرجى العِلم أنّه من المحتمل ألا يتم إصلاح أي أخطاء تم الإبلاغ عنها بشأن سلوك ملف سلسلة الأدوات الجديد، وبدلاً من ذلك، عليك نقل البيانات.
الاستخدام
Gradle
يكون استخدام ملف سلسلة أدوات CMake تلقائيًا عند استخدام
externalNativeBuild
. اطّلِع على دليل إضافة رمز C وC++ إلى
مشروعك في Android Studio للحصول على مزيد من المعلومات.
سطر الأوامر
عند إنشاء المشروع باستخدام CMake خارج Gradle، يجب تمرير ملف سلسلة الأدوات نفسه ووسائط الربط إلى CMake. مثلاً:
$ cmake \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=$ABI \
-DANDROID_PLATFORM=android-$MINSDKVERSION \
$OTHER_ARGS
وسيطات سلسلة الأدوات
يمكن تمرير الوسيطات التالية إلى ملف سلسلة أدوات CMake. في حال إنشاء التطبيقات
باستخدام Gradle، أضِف الوسيطات إلى
android.defaultConfig.externalNativeBuild.cmake.arguments
كما هو موضّح في مستندات ExternalNativeBuild. في حال إنشاء المشروع من سطر الأوامر، يجب تمرير الوسائط إلى
CMake باستخدام -D
. على سبيل المثال، لفرض عدم إنشاء armeabi-v7a مع ميزة دعم -DANDROID_ARM_NEON=FALSE
، يمكنك ضبط القيمة -DANDROID_ARM_NEON=FALSE
.
ANDROID_ABI
واجهة ABI المستهدَفة للحصول على معلومات عن واجهات التطبيق الثنائية (ABI) المتوافقة، يُرجى الاطّلاع على واجهات التطبيق الثنائية (ABI) في Android.
Gradle
يوفر Gradle هذه الوسيطة تلقائيًا. لا تضبط هذه القيمة
بشكل صريح في ملف build.gradle
. للتحكّم في واجهات ABI التي يستهدفها Gradle،
استخدِم abiFilters
كما هو موضّح في واجهات ABI لنظام التشغيل Android.
سطر الأوامر
تُنشئ أداة CMake ملفًا واحدًا لكل عملية إنشاء. لاستهداف أكثر من واجهة تطبيق ثنائية (ABI) في Android، عليك إنشاء مرة واحدة لكل واجهة تطبيق ثنائية (ABI). يُنصح باستخدام ملف تعريف ملف مختلف للتجميع لكل ABI لتجنُّب حدوث تعارضات بين عمليات التجميع.
القيمة | ملاحظات |
---|---|
armeabi-v7a |
|
armeabi-v7a with NEON |
الأسعار نفسها في فندق armeabi-v7a . |
arm64-v8a |
|
x86 |
|
x86_64 |
ANDROID_ARM_MODE
تحدِّد هذه السياسة ما إذا كان سيتم إنشاء تعليمات الذراع أو الإبهام لـ armeabi-v7a. لا يؤثر ذلك في واجهات ABI الأخرى. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات واجهات التطبيق الثنائية (ABI) في Android.
القيمة | ملاحظات |
---|---|
ذراع | |
إبهام | السلوك التلقائي |
ANDROID_NATIVE_API_LEVEL
الاسم المعرِّف ANDROID_PLATFORM.
ANDROID_PLATFORM
تحدّد هذه السياسة الحد الأدنى لمستوى واجهة برمجة التطبيقات الذي يتيحه التطبيق أو المكتبة. تتطابق هذه القيمة
مع minSdkVersion
للتطبيق.
Gradle
عند استخدام "مكوّن Android Gradle الإضافي"، يتم ضبط هذه القيمة تلقائيًا لتتطابق مع minSdkVersion
للتطبيق، ويجب عدم ضبطها يدويًا.
سطر الأوامر
عند استدعاء CMake مباشرةً، يتم ضبط هذه القيمة تلقائيًا على أدنى مستوى لواجهة برمجة التطبيقات متوافق مع حزمة NDK المستخدَمة. على سبيل المثال، باستخدام الإصدار r20 من NDK، يتم ضبط هذه القيمة تلقائيًا على المستوى 16 لواجهة برمجة التطبيقات.
يتم قبول تنسيقات متعددة لهذه المعلمة:
android-$API_LEVEL
$API_LEVEL
android-$API_LETTER
يتيح لك تنسيق $API_LETTER
تحديد android-N
بدون الحاجة إلى تحديد الرقم المرتبط بهذا الإصدار. يُرجى العِلم أنّ بعض الإصدارات تلقت زيادة في واجهة برمجة التطبيقات
بدون زيادة عدد الأحرف. يمكن تحديد واجهات برمجة التطبيقات هذه
بإضافة اللاحقة -MR1
. على سبيل المثال، المستوى 25 من واجهة برمجة التطبيقات هو android-N-MR1
.
ANDROID_STL
تحدِّد هذه السياسة نوع STL الذي يجب استخدامه لهذا التطبيق. لمزيد من المعلومات، يُرجى الاطّلاع على توافق مكتبة C++. سيتم استخدام c++_static
تلقائيًا.
القيمة | ملاحظات |
---|---|
c++_shared | نسخة المكتبة المشتركة من libc++ |
c++_static | نسخة المكتبة الثابتة من libc++ |
لا شيء | لا تتوفّر مكتبة C++ العادية. |
النظامية | ملف STL للنظام |
إدارة علامات المُجمِّع
إذا كنت بحاجة إلى تمرير علامات معيّنة إلى المُجمِّع أو المُجمِّع التلقائي لعملية الإنشاء، يُرجى الرجوع إلى مستندات CMake حول set_target_compile_options والمجموعة المرتبطة من الخيارات. يتضمّن قسم "انظر أيضًا" في أسفل هذه الصفحة بعض القرائن المفيدة.
بشكل عام، أفضل ممارسة هي تطبيق علامات المُجمِّع على أنّها أضيق
نطاق متاح. إنّ تكرار العلامات التي تريد تطبيقها على جميع استهدافاتك (مثل
-Werror
) لكل وحدة ليس عمليًا، ولكن نادرًا ما يجب
تطبيقها بشكل عام (CMAKE_CXX_FLAGS
)، لأنّ ذلك قد يكون له تأثيرات غير مرغوب فيها على
التبعيات التابعة لجهات خارجية في مشروعك. وفي هذه الحالات، يمكن تطبيق العلامات
على نطاق الدليل (add_compile_options
).
بالنسبة إلى مجموعة فرعية ضيّقة من علامات المُجمِّع، يمكن أيضًا ضبطها في ملف build.gradle
باستخدام cppFlags
أو سمات مشابهة. يجب عدم تنفيذ هذا الإجراء. إنّ العلامات التي يتم تمريرها إلى CMake من Gradle ستؤدي إلى سلوكيات مفاجئة للأولوية، وفي بعض الحالات، ستلغي العلامات التي تم تمريرها بشكل ضمني من خلال التنفيذ والتي تكون مطلوبة لإنشاء رمز Android. يفضلون دائمًا التعامل مع سلوك CMake
مباشرةً في CMake. إذا كنت بحاجة إلى التحكّم في علامات المُجمِّع لكل ملف AGP buildType
،
اطّلِع على العمل مع أنواع إنشاء AGP في CMake.
العمل مع أنواع إنشاء AGP في CMake
إذا كنت بحاجة إلى تصميم سلوك CMake يتناسب مع buildType
Gradle المخصّص، استخدِم نوع الإصدار هذا لتمرير علامة CMake إضافية (وليس علامة برنامج تجميع) يمكن أن تقرأها النصوص البرمجية لإصدار CMake. على سبيل المثال، إذا كان لديك خياران "مجاني" و "مميّز"
لإنشاء التطبيق يتم التحكّم فيهما من خلال build.gradle.kts وكنت بحاجة إلى تمرير
هذه البيانات إلى CMake:
android {
buildTypes {
free {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=OFF")
}
}
}
premium {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=ON")
}
}
}
}
}
بعد ذلك، في ملف CMakeLists.txt:
if (DPRODUCT_VARIANT_PREMIUM)
# Do stuff for the premium build.
else()
# Do stuff for the free build.
endif()
يمكنك اختيار اسم المتغيّر، ولكن احرص على تجنُّب أي اسم يتضمّن البادئة
ANDROID_
أو APP_
أو CMAKE_
لتجنُّب التداخل أو الخلط مع
العلامات الحالية.
يمكنك الاطّلاع على نموذج NDK لأدوات التطهير للحصول على مثال.
فهم أمر إنشاء CMake
عند تصحيح أخطاء مشاكل إنشاء CMake، من المفيد معرفة ملف برمجة تطبيقات المحدد الذي يستخدمه Gradle عند إجراء عملية الترجمة المتعدّدة المنصات لنظام التشغيل Android.
يحفظ "المكوّن الإضافي لنظام Gradle المتوافق مع Android" وسيطات التصميم التي يستخدمها
لتنفيذ إصدار CMake لكل زوج ABI ونوع الإصدار
في build_command.txt
. يمكن العثور على هذه الملفات في الدليل التالي:
<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/
يعرض المقتطف التالي مثالاً على مَعلمات CMake لإنشاء إصدار قابل لتصحيح الأخطاء من نموذج hello-jni
الذي يستهدف بنية armeabi-v7a
.
Executable : ${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/cmake
arguments :
-H${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/src/main/cpp
-DCMAKE_FIND_ROOT_PATH=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/prefab/armeabi-v7a/prefab
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk/22.1.7171670/build/cmake/android.toolchain.cmake
-DANDROID_ABI=armeabi-v7a
-DANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DANDROID_PLATFORM=android-23
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_SYSTEM_VERSION=23
-B${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/armeabi-v7a
-GNinja
jvmArgs :
Build command args: []
Version: 1
استخدام المكتبات المُنشأة مسبقًا
إذا كانت المكتبة المُسبقة الإنشاء التي تحتاج إلى استيرادها موزَّعة كملف AAR، اتّبِع مستندات الاعتماد في Studio لاستيرادها واستخدامها. إذا كنت لا تستخدم AGP، يمكنك اتّباع الخطوات الواردة في الرابط https://google.github.io/prefab/example-workflow.html، ولكن من المرجّح أن يكون نقل البيانات إلى AGP أسهل بكثير.
بالنسبة إلى المكتبات التي لا يتم توزيعها باعتبارها ملفات AAR، يُرجى الاطّلاع على تعليمات استخدام المكتبات التي تم إنشاؤها مسبقًا باستخدام CMake، ويمكنك الاطّلاع على مستندات add_library
بشأن أهداف IMPORTED
في دليل CMake.
إنشاء رمز جهة خارجية
هناك عدد قليل من الطرق لإنشاء رمز تابع لجهة خارجية كجزء من مشروع CMake ، ويعتمد الخيار الأنسب على حالتك. غالبًا ما يكون أفضل الخيار هو عدم إجراء ذلك على الإطلاق. بدلاً من ذلك، يمكنك إنشاء حزمة AAR لل مكتبة واستخدامها في تطبيقك. وليس عليك بالضرورة نشر هذه الميزة. ويمكن أن يكون داخليًا في مشروع Gradle.
إذا لم يكن هذا الخيار متاحًا:
- يضيف المورّد (أي ينسخ) المصدر التابع لجهة خارجية إلى مستودعك ويستخدم add_subdirectory لإنشاءه. لا يعمل هذا الإجراء إلا إذا كانت المكتبة الأخرى مُنشأة أيضًا باستخدام CMake.
- حدِّد ExternalProject.
- أنشئ المكتبة بشكل منفصل عن مشروعك واتّبِع استخدام المكتبات المُعدّة مسبقًا لاستيرادها كمكتبة مُعدّة مسبقًا.
دعم YASM في CMake
يقدّم NDK دعمًا لواجهة برمجة التطبيقات CMake لإنشاء رمز تجميع مكتوب بلغة YASM لتشغيله على البنيتَين x86 وx86-64. YASM هو عبارة عن مجمّع مفتوح المصدر للبُنى الهندسية x86 وx86-64، استنادًا إلى مجمّع NASM.
لإنشاء رمز تجميع باستخدام CMake، عليك إجراء التغييرات التالية فيملف
CMakeLists.txt
الخاص بمشروعك:
- اتصل برقم
enable_language
مع ضبط القيمة علىASM_NASM
. - بناءً على ما إذا كنت تنشئ مكتبة مشتركة أو برنامجًا ثنائيًا قابلاً للتنفيذ، يمكنك طلب
add_library
أوadd_executable
. في المَعلمات، أدخِل قائمة بالملفات المصدر التي تتألف من ملفات.asm
لبرنامج التجميع في YASM وملفات.c
لمكتبات C أو الدوالّ المرتبطة بها.
يوضّح المقتطف التالي كيفية ضبط CMakeLists.txt
لمحاولة
إنشاء برنامج YASM كمكتبة مشترَكة.
cmake_minimum_required(VERSION 3.6.0)
enable_language(ASM_NASM)
add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)
للحصول على مثال على كيفية إنشاء برنامج YASM كملف قابل للتنفيذ، اطّلِع على yasm test في مستودع git الخاص بـ NDK.
الإبلاغ عن المشاكل
إذا واجهت أي مشاكل مع NDK أو ملف سلسلة أدوات CMake الخاص به، يمكنك الإبلاغ عنها من خلال أداة تتبُّع المشاكل android-ndk/ndk على GitHub. بالنسبة إلى مشاكل Gradle أو المكوّن الإضافي لنظام Gradle المتوافق مع Android، يمكنك الإبلاغ عن خطأ في Studio بدلاً من ذلك.