CMake'i Yapılandırma

CMake derleme komut dosyası, CMakeLists.txt olarak adlandırmanız gereken bir düz metin dosyasıdır ve CMake'in C/C++ kitaplıklarınızı oluşturmak için kullandığı komutları içerir. Yerel kaynaklarınızın zaten bir CMake derleme komut dosyası yoksa kendiniz bir tane oluşturmanız ve uygun CMake komutlarını eklemeniz gerekir. CMake'i nasıl yükleyeceğinizi öğrenmek için NDK ve CMake'i yükleme ve yapılandırma bölümüne bakın.

Bu bölümde, CMake'a yerel kitaplığınızı oluştururken hangi kaynakların kullanılacağını bildirmek için derleme komut dosyanıza eklemeniz gereken bazı temel komutlar ele alınmaktadır. Daha fazla bilgi edinmek için CMake komutları ile ilgili resmi dokümanları okuyun.

Yeni bir CMake derleme komut dosyası yapılandırdıktan sonra, Gradle'ı CMake projenizi derleme bağımlılığı olarak içerecek şekilde yapılandırmanız gerekir. Böylece Gradle, yerel kitaplığınızı uygulamanızın APK'sı ile oluşturup paketler.

Not: Projenizde ndk-build kullanılıyorsa CMake derleme komut dosyası oluşturmanız gerekmez. Android.mk dosyanızın yolunu sağlayarak mevcut yerel kitaplık projenizi içerecek şekilde Gradle'ı yapılandırabilirsiniz.

CMake derleme komut dosyası oluşturma

CMake derleme komut dosyanız olarak kullanabileceğiniz bir düz metin dosyası oluşturmak için aşağıdaki adımları uygulayın:

  1. IDE'nin sol tarafından Proje bölmesini açın ve açılır menüden Proje görünümünü seçin.
  2. your-module kök dizinini sağ tıklayın ve Yeni > Dosya'yı seçin.

    Not: Derleme komut dosyasını istediğiniz herhangi bir konumda oluşturabilirsiniz. Ancak, derleme komut dosyasını yapılandırırken yerel kaynak dosyalarınızın ve kitaplıklarınızın yolları, derleme komut dosyasının konumuna göre belirlenir.

  3. Dosya adı olarak "CMakeLists.txt" yazın ve Tamam'ı tıklayın.

Artık CMake komutlarını ekleyerek derleme komut dosyanızı yapılandırabilirsiniz. CMake'e yerel kaynak kodundan yerel kitaplık oluşturma talimatı vermek için derleme komut dosyanıza cmake_minimum_required() ve add_library() komutlarını ekleyin:

# 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 )

İpucu: CMake'e kaynak dosyalardan yerel kitaplık oluşturmasını bildirmeye benzer şekilde, add_executable() komutunu kullanarak CMake'e bu kaynak dosyalardan yürütülebilir bir dosya oluşturmasını söyleyebilirsiniz. Ancak yerel kaynaklarınızdan yürütülebilir dosyalar oluşturmak isteğe bağlıdır. APK'nıza paketlenmek üzere yerel kitaplıklar oluşturmak ise çoğu proje gereksinimlerini karşılar.

add_library() kullanarak CMake derleme komut dosyanıza kaynak dosya veya kitaplık eklediğinizde, projenizi senkronize etmenizin ardından Android Studio, Proje görünümünde ilişkilendirilmiş başlık dosyalarını da gösterir. Ancak CMake'in derleme süresinde başlık dosyalarınızı bulabilmesi için CMake derleme komut dosyanıza include_directories() komutunu eklemeniz ve üst bilgilerinizin yolunu belirtmeniz gerekir:

add_library(...)

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

CMake'in kitaplığınızın dosyasını adlandırmak için kullandığı kural şu şekildedir:

liblibrary-name.so

Örneğin, derleme komut dosyasında paylaşılan kitaplığınızın adını "native-lib" olarak belirtirseniz CMake, libnative-lib.so adlı bir dosya oluşturur. Ancak bu kitaplığı Java veya Kotlin kodunuzda yüklerken CMake derleme komut dosyasında belirttiğiniz adı kullanın:

Kotlin

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

Java

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

Not: CMake derleme komut dosyanızda bir kitaplığı yeniden adlandırıyor veya kaldırırsanız Gradle'ın değişiklikleri uygulamadan ya da kitaplığın eski sürümünü APK'nızdan kaldırmadan önce projenizi temizlemeniz gerekir. Projenizi temizlemek için menü çubuğundan Derleme > Projeyi Temizle'yi seçin.

Android Studio, kaynak dosyaları ve üstbilgileri otomatik olarak Proje bölmesindeki cpp grubuna ekler. Birden fazla add_library() komutu kullanarak, CMake'in diğer kaynak dosyalardan derlemesi için ek kitaplıklar tanımlayabilirsiniz.

NDK API'leri ekle

Android NDK, faydalı bulabileceğiniz bir dizi yerel API ve kitaplık sağlar. Projenizin CMakeLists.txt komut dosyası dosyasına NDK kitaplıklarını ekleyerek bu API'lerden istediğinizi kullanabilirsiniz.

Önceden oluşturulmuş NDK kitaplıkları Android platformunda zaten mevcut olduğundan bunları oluşturmanız veya APK'nızda paketlemeniz gerekmez. NDK kitaplıkları zaten CMake'ın arama yolunun bir parçası olduğundan, yerel NDK kurulumunuzda kitaplığın konumunu belirtmenize bile gerek yoktur. Yalnızca kullanmak istediğiniz kitaplığın adını CMake'e sağlayıp kendi yerel kitaplığınıza bağlamanız gerekir.

NDK kitaplığını bulmak ve yolunu değişken olarak depolamak için CMake derleme komut dosyanıza find_library() komutunu ekleyin. Bu değişkeni, derleme komut dosyasının diğer bölümlerinde NDK kitaplığına başvurmak için kullanırsınız. Aşağıdaki örnek, Android'e özel günlük desteği kitaplığını bulur ve yolunu log-lib içinde depolar:

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 )

Yerel kitaplığınızın log kitaplığındaki işlevleri çağırması için CMake derleme komut dosyanızdaki target_link_libraries() komutunu kullanarak kitaplıkları bağlamanız gerekir:

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, oluşturup yerel kitaplığınıza bağlamanız gereken bazı kitaplıkları da kaynak kodu olarak içerir. CMake derleme komut dosyanızda add_library() komutunu kullanarak kaynak kodu yerel bir kitaplıkta derleyebilirsiniz. Yerel NDK kitaplığınıza yol sağlamak için Android Studio'nun sizin için otomatik olarak tanımladığı ANDROID_NDK yol değişkenini kullanabilirsiniz.

Aşağıdaki komut CMake'e, NativeActivity yaşam döngüsü olaylarını ve dokunma girişlerini statik bir kitaplığa dönüştüren ve bunu native-lib öğesine bağlayan android_native_app_glue.c derlemesini söyler:

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} )

Önceden oluşturulmuş başka kitaplıklar ekleme

Önceden oluşturulmuş bir kitaplık eklemek, CMake'in derlemesi için başka bir yerel kitaplık belirtmeye benzer. Ancak kitaplık zaten oluşturulduğundan CMake'e yalnızca kitaplığı projenize aktarmak istediğinizi bildirmek için IMPORTED işaretini kullanmanız gerekir:

add_library( imported-lib
             SHARED
             IMPORTED )

Daha sonra, aşağıda gösterildiği gibi set_target_properties() komutunu kullanarak kitaplığa giden yolu belirtmeniz gerekir.

Bazı kitaplıklar, belirli CPU mimarileri veya Uygulama İkili Arabirimleri (ABI) için ayrı paketler sağlar ve bunları ayrı dizinler halinde düzenler. Bu yaklaşım, kitaplıkların yalnızca istediğiniz kitaplığın sürümlerini kullanmanıza olanak tanırken belirli CPU mimarilerinden yararlanmasına yardımcı olur. Kitaplığın her sürümü için birden fazla komut yazmak zorunda kalmadan CMake derleme komut dosyanıza bir kitaplığın birden fazla ABI sürümünü eklemek istiyorsanız ANDROID_ABI path değişkenini kullanabilirsiniz. Bu değişken, NDK'nın desteklediği varsayılan ABI'lerin bir listesini veya Gradle'ı kullanmak üzere manuel olarak yapılandırdığınız filtrelenmiş ABI'lerin listesini kullanır. Örneğin:

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'in derleme süresinde başlık dosyalarınızı bulması için include_directories() komutunu kullanmanız ve başlık dosyalarınızın yolunu eklemeniz gerekir:

include_directories( imported-lib/include/ )

Not: Derleme zamanı bağımlılığı olmayan önceden oluşturulmuş bir kitaplığı paketlemek istiyorsanız (örneğin, imported-lib bağımlılığı olan önceden oluşturulmuş bir kitaplık eklerken, kitaplığı bağlamak için aşağıdaki talimatları uygulamanız gerekmez).

Önceden oluşturulmuş kitaplığı kendi yerel kitaplığınıza bağlamak için CMake derleme komut dosyanızdaki target_link_libraries() komutuna ekleyin:

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

Önceden oluşturulmuş kitaplığı APK'nızda paketlemek için .so dosyanızın yolunu eklemek üzere sourceSets bloku ile Gradle'ı manuel olarak yapılandırmanız gerekir. APK'nızı oluşturduktan sonra, APK Analizcisi'ni kullanarak Gradle'ın APK'nıza paketlediği kitaplıkları doğrulayabilirsiniz.

Diğer CMake projelerini dahil et

Birden fazla CMake projesi oluşturmak ve bu projelerin çıkışlarını Android projenize eklemek istiyorsanız üst düzey CMake derleme komut dosyası olarak bir CMakeLists.txt dosyası (Gradle'a bağladığınız dosya) kullanabilir ve ek CMake projelerini bu derleme komut dosyasının bağımlılıkları olarak ekleyebilirsiniz. Aşağıdaki üst düzey CMake derleme komut dosyası, add_subdirectory() komutunu kullanarak derleme bağımlılığı olarak başka bir CMakeLists.txt dosyası belirtir ve ardından önceden oluşturulmuş diğer kitaplıklarda olduğu gibi dosyanın çıkışına bağlantı verir.

# 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 )

Komut satırından CMake'i çağırma

Android Studio dışında Ninja projesi oluşturmak üzere CMake'i çağırmak için aşağıdaki komutu kullanın:

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

Bu komut, Android yürütülebilir kitaplıkları (.so dosyaları) oluşturmak için yürütülebilecek Ninja projesini oluşturur. CMAKE_TOOLCHAIN_FILE, NDK'nın CMake desteğini kullanmak için gereklidir. CMake 3.21 veya sonraki sürümler için CMake'in yerleşik NDK desteği kullanılabilir ancak CMake'ın Android için Çapraz Derleme dokümanlarında açıklandığı gibi farklı bir değişken grubu kullanılmalıdır.