ضبط CMake

النص البرمجي لإنشاء CMake هو ملف نص عادي يجب عليك تسميته وتتضمّن CMakeLists.txt الأوامر التي يستخدمها CMake لإنشاء مكتبات C/C++. إذا لم تكن المصادر المدمجة مع المحتوى تتضمن إصدار CMake فأنت بحاجة إلى إنشاء واحد بنفسك وتضمين نموذج CMake الأوامر. لمعرفة كيفية تثبيت CMake، راجع تثبيت NDK وإعداده وCMake.

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

بعد ضبط نص برمجي جديد لإنشاء CMake، عليك إجراء ما يلي: ضبط إعدادات Gradle لتضمين مشروع CMake كتبعية بناء، بحيث تنشئ Gradle يدمج مكتبتك المدمجة مع المحتوى حزمة APK لتطبيقك.

ملاحظة: إذا كان مشروعك يستخدم ndk-build، لن تحتاج إلى إجراء ذلك. إنشاء نص برمجي لإنشاء CMake. يمكنك ببساطة إعداد Gradle لتضمين مشروع مكتبتك الأصلية الحالي من خلال توفير مسار إلى Android.mk.

إنشاء نص برمجي لإنشاء CMake

لإنشاء ملف نص عادي يمكنك استخدامه كنص برمجي لإنشاء CMake، والمتابعة على النحو التالي:

  1. افتح جزء المشروع من الجانب الأيمن من بيئة التطوير المتكاملة (IDE) واختَر طريقة عرض المشروع من القائمة المنسدلة.
  2. انقر بزر الماوس الأيمن على الدليل الجذري لـ your-module حدد جديد > ملف.

    ملاحظة: يمكنك إنشاء النص البرمجي للإصدار في أي مكان تريده. مع ذلك، عند ضبط النص البرمجي للإصدار، سيتم تحديد المسارات إلى المصدر الأصلي. ترتبط الملفات والمكتبات بموقع النص البرمجي للإصدار.

  3. أدخِل "CMakeLists.txt". كاسم الملف وانقر على موافق.

يمكنك الآن ضبط النص البرمجي للإصدار من خلال إضافة أوامر CMake. للإرشاد يمكنك إنشاء مكتبة أصلية من رمز مصدر أصلي، وإضافة الأمرَين cmake_minimum_required() وadd_library() إلى النص البرمجي للتصميم:

# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.

add_library( # Specifies the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

ملاحظة: بالطريقة نفسها التي يمكنك بها الطلب من CMake إنشاء مكتبة مدمجة من المحتوى المصدر، فيمكنك استخدام add_executable() لتطلب من CMake إنشاء قابل للتنفيذ من ملفات المصدر هذه. ومع ذلك، فإن إنشاء ملفات تنفيذية من يكون المصدر اختياريًا، وإنشاء مكتبات أصلية لتجميعها في تستوفي حزمة APK معظم متطلبات المشروع.

عند إضافة ملف مصدر أو مكتبة إلى النص البرمجي للإصدار في CMake باستخدام add_library()، يعرض "استوديو Android" أيضًا ملفات العناوين المرتبطة. في عرض المشروع بعد مزامنة مشروعك. ومع ذلك، في لكي يحدد CMake ملفات الرأس أثناء وقت التجميع، يجب عليك إضافة الأمر include_directories() إلى CMake إنشاء نص برمجي وتحديد المسار إلى العناوين:

add_library(...)

# Specifies a path to native header files.
include_directories(src/main/cpp/include/)

في ما يلي الاصطلاح الذي يستخدمه CMake لتسمية ملف مكتبتك:

liblibrary-name.so

على سبيل المثال، إذا حددت "Native-lib" كاسم للمكتبة المشتركة في النص البرمجي للإصدار، ينشئ CMake ملفًا باسم libnative-lib.so ومع ذلك، عند تحميل هذه المكتبة في كود Java أو Kotlin، استخدم الاسم الذي حددته في النص البرمجي لإنشاء CMake:

Kotlin

companion object {
    init {
        System.loadLibrary("native-lib");
    }
}

Java

static {
    System.loadLibrary("native-lib");
}

ملاحظة: في حال إعادة تسمية مكتبة أو إزالتها في إصدار CMake تحتاج إلى تنظيف مشروعك قبل أن تقوم Gradle بتطبيق التغييرات أو إزالة الإصدار الأقدم من المكتبة من حزمة APK. لتنظيف اختَر إنشاء > تنظيف المشروع من شريط القوائم.

يضيف "استوديو Android" الملفات المصدر والعناوين تلقائيًا إلى مجموعة cpp في جزء المشروع. باستخدام عدة أوامر add_library()، يمكنك تحديد لإنشاء مكتبات CMake من ملفات مصدر أخرى.

إضافة واجهات برمجة تطبيقات NDK

يوفّر Android NDK مجموعة من واجهات برمجة التطبيقات والمكتبات الأصلية التي قد تجدها مفيدة. يمكنك استخدام أي من واجهات برمجة التطبيقات هذه عن طريق تضمين مكتبات NDK في ملف نص برمجي واحد (CMakeLists.txt).

مكتبات NDK المنشأة مسبقًا متوفرة على نظام Android الأساسي، ولذلك لا يمكنك تحتاج إلى إنشائها أو تجميعها في ملف APK لديك. نظرًا لأن مكتبات NDK تكون بالفعل جزءًا من مسار بحث CMake، فلا تحتاج حتى إلى تحديد موقع المكتبة في تثبيت NDK المحلي - ما عليك سوى قم بتزويد CMake باسم المكتبة التي تريد استخدامها وربطها مقارنةً بمكتبتك الأصلية.

أضِف الأمر find_library() إلى إصدار CMake. لتحديد موقع مكتبة NDK وتخزين مسارها كمتغير. أنت تستخدم هذا المتغير للإشارة إلى مكتبة NDK في أجزاء أخرى من النص البرمجي للإصدار. يحدد النموذج التالي موقع مكتبة دعم السجلات الخاصة بنظام Android وتخزّن مسارها في log-lib:

find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              log-lib

              # Specifies the name of the NDK library that
              # CMake needs to locate.
              log )

لتتمكّن مكتبتك المدمجة مع المحتوى من استدعاء الدوال في log. تحتاج إلى ربط المكتبات باستخدام الأمر target_link_libraries() في النص البرمجي لإنشاء CMake:

find_library(...)

# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the log library to the target library.
                       ${log-lib} )

يتضمن NDK أيضًا بعض المكتبات كشفرة مصدر تحتاج إلى إنشائها وربطه بمكتبتك الأصلية. يمكنك تجميع التعليمات البرمجية المصدر في مكتبة أصلية باستخدام الأمر add_library() في CMake النص البرمجي للإصدار. لتوفير مسار إلى مكتبة NDK المحلية، يمكنك استخدام متغيّر مسار واحد (ANDROID_NDK) تلقائيًا، وهو "استوديو Android" يحددها لك.

يطلب الأمر التالي من CMake إنشاء android_native_app_glue.c، الذي يدير NativeActivity أحداث مراحل النشاط والإدخال باللمس، في مكتبة ثابتة وتربطها native-lib:

add_library( app-glue
             STATIC
             ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )

# You need to link static libraries against your shared native library.
target_link_libraries( native-lib app-glue ${log-lib} )

إضافة مكتبات أخرى مصمّمة مسبقًا

فإضافة مكتبة منشأة مسبقًا تشبه تحديد مكتبة أصلية أخرى CMake to Build. ومع ذلك، نظرًا لأن المكتبة تم إنشاؤها بالفعل، فستحتاج إلى استخدِم العلامة IMPORTED لإعلام CMake بأنك فقط في استيراد المكتبة إلى مشروعك:

add_library( imported-lib
             SHARED
             IMPORTED )

يجب بعد ذلك تحديد المسار إلى المكتبة باستخدام set_target_properties() باسم كما هو موضح أدناه.

توفر بعض المكتبات حزمًا منفصلة لبنى وحدة معالجة مركزية معينة، أو واجهات التطبيق الثنائية (ABI) وتنظيمها في أدلة منفصلة. يساعد هذا النهج المكتبات في اتخاذ بعض بُنى وحدة المعالجة المركزية (CPU) مع السماح لك باستخدام وإصدارات المكتبة التي تريدها. لإضافة إصدارات متعددة من واجهة التطبيق الثنائية (ABI) لمكتبة إلى النص البرمجي لإنشاء CMake، دون الحاجة إلى كتابة أوامر متعددة لكل إصدار من المكتبة، يمكنك استخدام المسار ANDROID_ABI المتغير. يستخدم هذا المتغيّر قائمة بقيم ABIs التلقائية التي تتوافق معها NDK، أو قائمة مفلتَرة. من واجهات التطبيق الثنائية (ABI) التي عليك ضبط Gradle يدويًا لاستخدامها. مثلاً:

add_library(...)
set_target_properties( # Specifies the target library.
                       imported-lib

                       # Specifies the parameter you want to define.
                       PROPERTIES IMPORTED_LOCATION

                       # Provides the path to the library you want to import.
                       imported-lib/src/${ANDROID_ABI}/libimported-lib.so )

لكي يحدد CMake ملفات الرأس أثناء وقت التجميع، تحتاج إلى استخدام الأمر include_directories() وتضمين المسار إلى ملفات العنوان:

include_directories( imported-lib/include/ )

ملاحظة: إذا كنت تريد إضافة مكتبة سابقة الإنشاء غير تبعية وقت الإصدار — على سبيل المثال، عند إضافة مكتبة مصممة مسبقًا تبعية imported-lib، فلن تحتاج إلى تنفيذ باتباع التعليمات لربط المكتبة.

لربط المكتبة المُعَدة مسبقًا بمكتبتك الأصلية، أضِفها إلى target_link_libraries() في النص البرمجي لإنشاء CMake:

target_link_libraries( native-lib imported-lib app-glue ${log-lib} )

لتجميع المكتبة المُعدة مسبقًا في حزمة APK، يجب: اضبط Gradle يدويًا باستخدام كتلة sourceSets على تضمين المسار إلى ملف .so. بعد إنشاء ملف APK، يمكنك التحقق من مكتبات Gradle المستخدمة في APK عن طريق أداة تحليل APK:

تضمين مشاريع CMake الأخرى

إذا كنت ترغب في إنشاء مشروعات CMake متعددة وتضمين مخرجاتها في مشروع Android، يمكنك استخدام ملف CMakeLists.txt واحد إنشاء نص برمجي عالي المستوى في CMake (وهو الذي الرابط إلى Gradle) وإضافة مشاريع CMake إضافية كتبعيات لذلك الإصدار البرنامج النصي. يستخدم النص البرمجي التالي ذو المستوى الأعلى لإصدار CMake add_subdirectory() لتحديد الأمر. ملف CMakeLists.txt آخر كتبعية إصدار ثم ينشئ روابط مقارنةً بمخرجاتها تمامًا كما هو الحال مع أي مكتبة أخرى مصممة مسبقًا.

# Sets lib_src_DIR to the path of the target CMake project.
set( lib_src_DIR ../gmath )

# Sets lib_build_DIR to the path of the desired output directory.
set( lib_build_DIR ../gmath/outputs )
file(MAKE_DIRECTORY ${lib_build_DIR})

# Adds the CMakeLists.txt file located in the specified directory
# as a build dependency.
add_subdirectory( # Specifies the directory of the CMakeLists.txt file.
                  ${lib_src_DIR}

                  # Specifies the directory for the build outputs.
                  ${lib_build_DIR} )

# Adds the output of the additional CMake build as a prebuilt static
# library and names it lib_gmath.
add_library( lib_gmath STATIC IMPORTED )
set_target_properties( lib_gmath PROPERTIES IMPORTED_LOCATION
                       ${lib_build_DIR}/${ANDROID_ABI}/lib_gmath.a )
include_directories( ${lib_src_DIR}/include )

# Links the top-level CMake build output against lib_gmath.
target_link_libraries( native-lib ... lib_gmath )

استدعاء CMake من سطر الأوامر

استخدم الأمر التالي لاستدعاء CMake لإنشاء مشروع Ninja خارج في Android Studio:

cmake
-Hpath/to/cmakelists/folder
-Bpath/to/generated/ninja/project/debug/ABI
-DANDROID_ABI=ABI                               // For example, arm64-v8a
-DANDROID_PLATFORM=platform-version-string      // For example, android-16
-DANDROID_NDK=android-sdk/ndk/ndk-version
-DCMAKE_TOOLCHAIN_FILE=android-sdk/ndk/ndk-version/build/cmake/android.toolchain.cmake
-G Ninja

سينشئ هذا الأمر مشروع Ninja الذي يمكن تنفيذه لإنشاء مكتبات Android التنفيذية (.so ملف) CMAKE_TOOLCHAIN_FILE هو لاستخدام CMake support الخاص بـ NDK. بالنسبة إلى CMake 3.21 أو إصدار أحدث، يتضمن CMake يمكن استخدام دعم NDK بدلاً من ذلك، ولكن يجب استخدام مجموعة مختلفة من المتغيرات كما هو موضّح في مستندات Cross Compiling for Android التابعة لـ CMake.