CMake

Android NDK, uygulamanız için C ve C++ kodunu derlemek üzere CMake kullanımını destekler. Bu sayfada, Android Gradle eklentisinin ExternalNativeBuild aracılığıyla veya CMake'i doğrudan çağırırken CMake'in NDK ile nasıl kullanılacağı açıklanmaktadır.

CMake araç zinciri dosyası

NDK, toolchain dosyası aracılığıyla CMake'i destekler. Araç zinciri dosyaları, çapraz derleme için araç zincirinin davranışını özelleştiren CMake dosyalarıdır. NDK için kullanılan araç zinciri dosyası, NDK'da <NDK>/build/cmake/android.toolchain.cmake konumunda bulunur.

ABI, minSdkVersion vb. gibi derleme parametreleri, cmake çağrılırken komut satırında verilir. Desteklenen bağımsız değişkenlerin listesi için Toolchain bağımsız değişkenleri bölümüne bakın.

"Yeni" araç zinciri dosyası

Daha önceki NDK'larda, NDK'nın araç zinciri dosyasını kullanma ile yerleşik CMake desteğini kullanma arasındaki davranış farklılıklarını azaltacak araç zinciri dosyasının yeni bir uygulaması deneniyordu. Bu durum, önemli miktarda iş gerektirdi (tamamlanmadı) ancak davranışı iyileştirmedi. Bu nedenle, bu yaklaşımı artık kullanmıyoruz.

"Yeni" araç zinciri dosyasında, "eski" araç zinciri dosyasına kıyasla davranış gerilemeleri var. Varsayılan davranış, önerilen iş akışıdır. -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF kullanıyorsanız bu işareti derlemenizden kaldırmanızı öneririz. Yeni araç zinciri dosyası, eski araç zinciri dosyasıyla hiçbir zaman eşitlenmedi. Bu nedenle, davranış gerilemeleri olması muhtemeldir.

Yeni araç zinciri dosyasının kullanılmasını önermemize rağmen, bu dosyanın NDK'dan kaldırılmasıyla ilgili şu anda bir plan bulunmamaktadır. Bu durum, yeni ve eski araç zinciri dosyaları arasındaki davranış farklılıklarına dayanan derlemelerin bozulmasına neden olur. Ayrıca, "eski"nin aslında önerilen seçenek olduğunu netleştirmek için seçeneği yeniden adlandırmak da bu seçeneği kullananların derlemelerini bozar. Yeni araç zinciri dosyasını kullanmaktan memnunsanız taşıma yapmanız gerekmez. Ancak yeni araç zinciri dosyası davranışıyla ilgili olarak bildirilen hataların düzeltilmeyeceğini ve bunun yerine taşıma yapmanız gerektiğini unutmayın.

Kullanım

Gradle

CMake araç zinciri dosyası, externalNativeBuild kullanılırken otomatik olarak kullanılır. Daha fazla bilgi için Android Studio'nun Projenize C ve C++ kodu ekleme kılavuzuna bakın.

Komut Satırı

Gradle dışında CMake ile derleme yaparken araç zinciri dosyasının kendisi ve bağımsız değişkenleri CMake'e iletilmelidir. Örneğin:

$ cmake \
    -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
    -DANDROID_ABI=$ABI \
    -DANDROID_PLATFORM=android-$MINSDKVERSION \
    $OTHER_ARGS

Toolchain bağımsız değişkenleri

CMake araç zinciri dosyasına aşağıdaki bağımsız değişkenler iletilebilir. Gradle ile derleme yapıyorsanız ExternalNativeBuild belgelerinde açıklandığı gibi android.defaultConfig.externalNativeBuild.cmake.arguments'ya bağımsız değişkenler ekleyin. Komut satırından oluşturuyorsanız bağımsız değişkenleri -D ile CMake'e aktarın. Örneğin, armeabi-v7a'nın Neon desteğiyle oluşturulmasını engellemek için -DANDROID_ARM_NEON=FALSE değerini iletin.

ANDROID_ABI

Hedef ABI. Desteklenen ABI'ler hakkında bilgi için Android ABI'leri başlıklı makaleyi inceleyin.

Gradle

Gradle bu bağımsız değişkeni otomatik olarak sağlar. Bu bağımsız değişkeni build.gradle dosyanızda açıkça ayarlamayın. Gradle'ın hangi ABI'leri hedeflediğini kontrol etmek için Android ABI'leri bölümünde açıklandığı gibi abiFilters kullanın.

Komut Satırı

CMake, derleme başına tek bir hedef için derleme yapar. Birden fazla Android ABI'yi hedeflemek için her ABI için bir kez derleme yapmanız gerekir. Derlemeler arasında çakışma olmaması için her ABI için farklı derleme dizinleri kullanılması önerilir.

Değer Notlar
armeabi-v7a
armeabi-v7a with NEON armeabi-v7a ile aynı
arm64-v8a
x86
x86_64

ANDROID_ARM_MODE

armeabi-v7a için kol veya başparmak talimatlarının oluşturulup oluşturulmayacağını belirtir. Diğer ABI'ler için geçerli değildir. Daha fazla bilgi için Android ABI'leri dokümanına bakın.

Değer Notlar
kol
başparmak Varsayılan davranış.

ANDROID_NATIVE_API_LEVEL

ANDROID_PLATFORM için diğer ad.

ANDROID_PLATFORM

Uygulama veya kitaplık tarafından desteklenen minimum API düzeyini belirtir. Bu değer, uygulamanın minSdkVersion özelliğine karşılık gelir.

Gradle

Android Gradle eklentisi kullanılırken bu değer, uygulamanın minSdkVersion ile eşleşecek şekilde otomatik olarak ayarlanır ve manuel olarak ayarlanmamalıdır.

Komut Satırı

CMake doğrudan çağrıldığında bu değer, varsayılan olarak kullanılmakta olan NDK tarafından desteklenen en düşük API düzeyine ayarlanır. Örneğin, NDK r20 ile bu değer varsayılan olarak API düzeyi 16'dır.

Bu parametre için birden fazla biçim kabul edilir:

  • android-$API_LEVEL
  • $API_LEVEL
  • android-$API_LETTER

$API_LETTER biçimi, android-N sürümünü, bu sürümle ilişkili numarayı belirlemenize gerek kalmadan belirtmenize olanak tanır. Bazı yayınların, harf artışı olmadan API artışı aldığını unutmayın. Bu API'ler, -MR1 soneki eklenerek belirtilebilir. Örneğin, API düzeyi 25 android-N-MR1'dir.

ANDROID_STL

Bu uygulama için hangi STL'nin kullanılacağını belirtir. Daha fazla bilgi için C++ kitaplığı desteği başlıklı makaleyi inceleyin. Varsayılan olarak c++_static kullanılır.

Değer Notlar
c++_shared libc++'nın paylaşılan kitaplık varyantı.
c++_static libc++'nın statik kitaplık varyantı.
yok C++ standart kitaplığı desteği yoktur.
sistem Sistem STL'si

Derleyici işaretlerini yönetme

Derleyiciye veya bağlayıcıya derlemeniz için belirli işaretler iletmeniz gerekiyorsa set_target_compile_options ve ilgili seçenek ailesi için CMake belgelerine bakın. Bu sayfanın en altındaki "Ayrıca bakın" bölümünde bazı faydalı ipuçları yer alır.

Genel olarak, derleyici işaretlerini mümkün olan en dar kapsamda uygulamak en iyi uygulamadır. Tüm hedeflerinize uygulamak istediğiniz işaretlerin (ör. -Werror) her modülde tekrarlanması zahmetlidir ancak yine de projenizdeki üçüncü taraf bağımlılıkları üzerinde istenmeyen etkileri olabileceğinden nadiren genel olarak uygulanmalıdır (CMAKE_CXX_FLAGS). Bu tür durumlarda işaretler dizin kapsamında (add_compile_options) uygulanabilir.

Derleyici işaretlerinin dar bir alt kümesi için cppFlags veya benzer özellikler kullanılarak build.gradle dosyanızda da ayarlanabilirler. Bunu yapmamalısınız. Gradle'dan CMake'e iletilen işaretler, bazı durumlarda Android kodu oluşturmak için gereken ve uygulama tarafından örtülü olarak iletilen işaretleri geçersiz kılarak beklenmedik öncelik davranışlarına neden olur. CMake davranışını her zaman doğrudan CMake'te işlemeyi tercih edin. Derleyici işaretlerini AGP başına kontrol etmeniz gerekiyorsa buildType, CMake'te AGP derleme türleriyle çalışma başlıklı makaleyi inceleyin.

CMake'te AGP derleme türleriyle çalışma

CMake davranışını özel bir Gradle buildType'a göre uyarlamanız gerekiyorsa CMake derleme komut dosyalarınızın okuyabileceği ek bir CMake işareti (derleyici işareti değil) iletmek için bu derleme türünü kullanın. Örneğin, build.gradle.kts dosyanız tarafından kontrol edilen "ücretsiz" ve "premium" adlı derleme varyantlarınız varsa ve bu verileri CMake'e aktarmanız gerekiyorsa:

android {
    buildTypes {
        free {
            externalNativeBuild {
                cmake {
                    arguments.add("-DPRODUCT_VARIANT_PREMIUM=OFF")
                }
            }
        }
        premium {
            externalNativeBuild {
                cmake {
                    arguments.add("-DPRODUCT_VARIANT_PREMIUM=ON")
                }
            }
        }
    }
}

Ardından CMakeLists.txt dosyanızda:

if (DPRODUCT_VARIANT_PREMIUM)
  # Do stuff for the premium build.
else()
  # Do stuff for the free build.
endif()

Değişkenin adını siz belirleyebilirsiniz ancak mevcut işaretlerle çakışmayı veya karışıklığı önlemek için ANDROID_, APP_ veya CMAKE_ önekli adlardan kaçının.

Örnek için Sanitizers NDK örneğine bakın.

CMake derleme komutunu anlama

CMake derleme sorunlarını ayıklarken Gradle'ın Android için çapraz derleme yaparken kullandığı belirli derleme bağımsız değişkenlerini bilmek faydalıdır.

Android Gradle eklentisi, her ABI ve derleme türü çifti için CMake derlemesi yürütmek üzere kullandığı derleme bağımsız değişkenlerini build_command.txt konumuna kaydeder. Bu dosyalar aşağıdaki dizinde bulunur:

<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/

Aşağıdaki snippet'te, armeabi-v7a mimarisini hedefleyen hello-jni örneğinin hata ayıklanabilir sürümünü oluşturmak için kullanılan CMake bağımsız değişkenlerine dair bir örnek gösterilmektedir.

                    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

Önceden oluşturulmuş kitaplıkları kullanma

İçe aktarmanız gereken önceden oluşturulmuş kitaplık AAR olarak dağıtılıyorsa bunları içe aktarmak ve kullanmak için Studio'nun bağımlılık belgelerini inceleyin. AGP kullanmıyorsanız https://google.github.io/prefab/example-workflow.html adresindeki adımları uygulayabilirsiniz ancak AGP'ye geçiş yapmanız çok daha kolay olacaktır.

AAR olarak dağıtılmayan kitaplıklar için CMake ile önceden oluşturulmuş kitaplıkları kullanma talimatlarını add_library IMPORTED hedefleriyle ilgili CMake kılavuzunda bulabilirsiniz.

Üçüncü taraf kodu oluşturma

CMake projenizin bir parçası olarak üçüncü taraf kodu oluşturmanın birkaç yolu vardır. En iyi seçenek, durumunuza bağlıdır. En iyi seçenek genellikle bunu hiç yapmamaktır. Bunun yerine, kitaplık için AAR oluşturun ve bunu uygulamanızda kullanın. Bu AAR'yi yayınlamanız mutlaka gerekmez. Gradle projenizin içinde olabilir.

Bu seçenek yoksa:

  • Üçüncü taraf kaynağını (ör. kopyalama) deponuza aktarın ve oluşturmak için add_subdirectory'yi kullanın. Bu özellik yalnızca diğer kitaplık da CMake ile oluşturulmuşsa çalışır.
  • ExternalProject tanımlayın.
  • Kitaplığı projenizden ayrı olarak oluşturun ve önceden oluşturulmuş olarak içe aktarmak için Önceden oluşturulmuş kitaplıkları kullanma bölümündeki adımları uygulayın.

CMake'te YASM desteği

NDK, x86 ve x86-64 mimarilerinde çalışacak şekilde YASM'de yazılmış derleme kodu oluşturmak için CMake desteği sağlar. YASM, NASM derleyicisine dayalı olarak x86 ve x86-64 mimarileri için açık kaynaklı bir derleyicidir.

CMake ile montaj kodu oluşturmak için projenizin CMakeLists.txt bölümünde aşağıdaki değişiklikleri yapın:

  1. Değeri ASM_NASM olarak ayarlanmış enable_language işlevini çağırın.
  2. Paylaşılan bir kitaplık mı yoksa yürütülebilir bir ikili program mı oluşturduğunuza bağlı olarak add_library veya add_executable işlevini çağırın. Bağımsız değişkenlerde, YASM'deki derleme programı için .asm dosyalarından ve ilişkili C kitaplıkları veya işlevleri için .c dosyalarından oluşan bir kaynak dosyalar listesi iletin.

Aşağıdaki snippet'te, paylaşılan kitaplık olarak bir YASM programı oluşturmak için CMakeLists.txt öğenizi nasıl yapılandırabileceğiniz gösterilmektedir.

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 programının yürütülebilir dosya olarak nasıl oluşturulacağına dair bir örnek için NDK git deposundaki yasm test'e bakın.

Sorunları bildirme

NDK veya CMake araç zinciri dosyasıyla ilgili sorunlarla karşılaşırsanız bunları GitHub'daki android-ndk/ndk sorun izleyici aracılığıyla bildirin. Gradle veya Android Gradle eklentisi sorunları için bunun yerine Studio hatası bildirin.