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. پنجره Project را از سمت چپ IDE باز کنید و نمای پروژه را از منوی کشویی انتخاب کنید.
  2. روی فهرست اصلی your-module راست کلیک کرده و New > File را انتخاب کنید.

    توجه: می توانید اسکریپت ساخت را در هر مکانی که می خواهید ایجاد کنید. با این حال، هنگام پیکربندی اسکریپت ساخت، مسیرهای فایل‌های منبع بومی و کتابخانه‌های شما نسبت به مکان اسکریپت ساخت هستند.

  3. "CMakeLists.txt" را به عنوان نام فایل وارد کنید و روی OK کلیک کنید.

اکنون می توانید اسکریپت ساخت خود را با افزودن دستورات CMake پیکربندی کنید. برای دستور 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 شما اکثر نیازهای پروژه را برآورده می کند.

وقتی یک فایل منبع یا کتابخانه را با استفاده از add_library() به اسکریپت ساخت CMake اضافه می‌کنید، Android Studio همچنین فایل‌های هدر مرتبط را پس از همگام‌سازی پروژه‌تان در نمای پروژه نشان می‌دهد. با این حال، برای اینکه CMake بتواند فایل‌های هدر شما را در طول زمان کامپایل پیدا کند، باید دستور include_directories() را به اسکریپت ساخت CMake خود اضافه کنید و مسیر هدر خود را مشخص کنید:

add_library(...)

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

قراردادی که CMake برای نامگذاری فایل کتابخانه شما استفاده می کند به شرح زیر است:

lib library-name .so

برای مثال، اگر «native-lib» را به عنوان نام کتابخانه مشترک خود در اسکریپت ساخت مشخص کنید، CMake فایلی با نام libnative-lib.so ایجاد می کند. با این حال، هنگام بارگیری این کتابخانه در کد جاوا یا کاتلین، از نامی که در اسکریپت ساخت CMake مشخص کرده اید استفاده کنید:

کاتلین

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

جاوا

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

توجه: اگر نام کتابخانه ای را در اسکریپت ساخت CMake خود تغییر دهید یا حذف کنید، باید قبل از اینکه Gradle تغییرات را اعمال کند یا نسخه قدیمی کتابخانه را از APK خود حذف کند، پروژه خود را پاک کنید. برای تمیز کردن پروژه خود، Build > Clean Project را از نوار منو انتخاب کنید.

Android Studio به طور خودکار فایل‌های منبع و هدرها را به گروه cpp در پنجره پروژه اضافه می‌کند. با استفاده از دستورات add_library() متعدد، می‌توانید کتابخانه‌های اضافی را برای CMake تعریف کنید تا از فایل‌های منبع دیگر بسازد.

API های NDK را اضافه کنید

Android NDK مجموعه ای از API ها و کتابخانه های بومی را ارائه می دهد که ممکن است برای شما مفید باشد. شما می توانید با گنجاندن کتابخانه های NDK در فایل اسکریپت CMakeLists.txt پروژه خود از هر یک از این API ها استفاده کنید.

کتابخانه های از پیش ساخته شده NDK در حال حاضر در پلتفرم Android وجود دارند، بنابراین نیازی به ساخت آنها یا بسته بندی آنها در APK ندارید. از آنجایی که کتابخانه‌های NDK در حال حاضر بخشی از مسیر جستجوی CMake هستند، حتی نیازی به تعیین مکان کتابخانه در نصب NDK محلی خود ندارید - فقط باید نام کتابخانه‌ای را که می‌خواهید از آن استفاده کنید و پیوند دهید، به CMake ارائه دهید. آن را در برابر کتابخانه بومی خود.

دستور find_library() را به اسکریپت ساخت CMake خود اضافه کنید تا یک کتابخانه NDK را پیدا کنید و مسیر آن را به عنوان یک متغیر ذخیره کنید. شما از این متغیر برای ارجاع به کتابخانه NDK در قسمت های دیگر اسکریپت ساخت استفاده می کنید. نمونه زیر کتابخانه پشتیبانی لاگ مخصوص اندروید را پیدا می کند و مسیر آن را در 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 Studio به طور خودکار برای شما تعریف می کند.

دستور زیر به 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 است. با این حال، از آنجایی که کتابخانه از قبل ساخته شده است، باید از پرچم IMPORTED استفاده کنید تا به CMake بگویید که فقط می خواهید کتابخانه را به پروژه خود وارد کنید:

add_library( imported-lib
             SHARED
             IMPORTED )

سپس باید مسیر کتابخانه را با استفاده از دستور set_target_properties() مطابق شکل زیر مشخص کنید.

برخی از کتابخانه‌ها بسته‌های جداگانه‌ای را برای معماری‌های خاص CPU یا رابط‌های باینری برنامه (ABI) ارائه می‌کنند و آنها را در فهرست‌های جداگانه سازمان‌دهی می‌کنند. این رویکرد به کتابخانه‌ها کمک می‌کند تا از معماری‌های خاص CPU استفاده کنند و در عین حال به شما امکان می‌دهد فقط از نسخه‌های کتابخانه مورد نظر خود استفاده کنید. برای افزودن چندین نسخه ABI از یک کتابخانه به اسکریپت ساخت CMake خود، بدون نیاز به نوشتن چندین دستور برای هر نسخه از کتابخانه، می توانید از متغیر مسیر ANDROID_ABI استفاده کنید. این متغیر از لیستی از ABIهای پیش‌فرض که 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 خود، می‌توانید با استفاده از APK Analyzer بررسی کنید که کدام کتابخانه‌ها بسته‌های Gradle را به 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 را ایجاد می کند که می تواند برای ایجاد کتابخانه های اجرایی اندروید (فایل های .so ) اجرا شود. CMAKE_TOOLCHAIN_FILE برای استفاده از پشتیبانی CMake NDK مورد نیاز است. برای CMake 3.21 یا جدیدتر، می‌توان از پشتیبانی داخلی NDK CMake به جای آن استفاده کرد، اما گروه متفاوتی از متغیرها باید همانطور که در CMake's Cross Compiling برای مستندات Android توضیح داده شده است استفاده شود.