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 doğrudan CMake'i çağırarak NDK ile CMake'in nasıl kullanılacağı açıklanmaktadır.

CMake araç zinciri dosyası

NDK, CMake'i bir araç zinciri dosyası aracılığıyla 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 gibi derleme parametreleri, cmake çağrılırken komut satırında verilir. Desteklenen bağımsız değişkenlerin listesi için Araç zinciri bağımsız değişkenleri bölümüne bakın.

"Yeni" araç zinciri dosyası

Önceki NDK'lar, NDK'nın araç zinciri dosyasını kullanma ile yerleşik CMake desteğini kullanma arasındaki davranış farklılıklarını azaltacak yeni bir araç zinciri dosyası uygulaması denedi. Bu, önemli miktarda çalışma gerektirdi (tamamlanmadı) ancak davranışı iyileştirmedi. Bu nedenle artık bu konuyu takip etmiyoruz.

"Yeni" araç zinciri dosyası, "eski" araç zinciri dosyasına kıyasla davranış gerilemelerine sahiptir. 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şdeğerliğe ulaşmadığından davranış gerilemeleri olabilir.

Yeni araç zinciri dosyasını kullanmanızı önermesek de şu anda bu dosyayı NDK'dan kaldırmayı planlamıyoruz. Bunu yapmak, yeni ve eski araç zinciri dosyaları arasındaki davranış farklılıklarına dayanan derlemeleri bozar. Maalesef seçeneği, "eski" seçeneğinin aslında önerildiğini netleştirecek şekilde yeniden adlandırmak da bu seçeneği kullanan kullanıcıları etkiler. Yeni araç zinciri dosyasını kullanmaktan memnunsanız taşıma işlemi yapmanız gerekmez. Ancak yeni araç zinciri dosyası davranışıyla ilgili bildirilen hataların muhtemelen düzeltilmeyeceğini ve bunun yerine taşıma işlemi yapmanız gerekeceğini unutmayın.

Kullanım

Gradle

externalNativeBuild kullanılırken CMake araç zinciri dosyası 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

Araç zinciri bağımsız değişkenleri

Aşağıdaki bağımsız değişkenler CMake araç zinciri dosyasına iletilebilir. Gradle ile derleme yapıyorsanız ExternalNativeBuild belgelerinde açıklandığı şekilde android.defaultConfig.externalNativeBuild.cmake.arguments öğesine bağımsız değişkenler ekleyin. Komut satırından derleme yapıyorsanız bağımsız değişkenleri -D ile CMake'e iletin. Örneğin, armeabi-v7a'yı Neon desteği olmadan derlemeye zorlamak 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 hedefleyeceğini kontrol etmek için Android ABI'leri bölümünde açıklandığı şekilde abiFilters kullanın.

Komut Satırı

CMake, derleme başına tek bir hedef için derleme yapar. Birden fazla Android ABI'yı hedeflemek için her ABI için bir kez derleme yapmanız gerekir. Derlemeler arasında çakışmaları önlemek için her ABI için farklı derleme dizinleri kullanmanız ö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 arm veya thumb talimatlarının oluşturulup oluşturulmayacağını belirtir. Diğer ABI'ler üzerinde etkisi yoktur. Daha fazla bilgi için Android ABI'leri belgelerini inceleyin.

Değer Notlar
kol
beğenme Varsayılan davranış.

ANDROID_NATIVE_API_LEVEL

ANDROID_PLATFORM için takma ad.

ANDROID_PLATFORM

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

Gradle

Android Gradle Eklentisi kullanılırken bu değer, uygulamanın minSdkVersion değeriyle 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ılan 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'ya ayarlanır.

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

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

$API_LETTER biçimi, ilgili sürümle ilişkili numarayı belirlemenize gerek kalmadan android-N değerini belirtmenize olanak tanır. Bazı sürümlerde API artışı yapılmış ancak harf artışı yapılmamıştır. Bu API'ler, -MR1 son eki 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 bölümüne bakın. Varsayılan olarak c++_static kullanılır.

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

Derleyici işaretlerini yönetme

Derlemeniz için derleyiciye veya bağlayıcıya belirli işaretler iletmeniz gerekiyorsa set_target_compile_options ve ilgili seçenek ailesi için CMake belgelerine bakın. Bu sayfanın alt kısmındaki "Ayrıca bakınız" bölümünde bazı faydalı ipuçları var.

Genel olarak en iyi uygulama, derleyici işaretlerini mevcut en dar kapsamda uygulamaktır. Tüm hedeflerinize uygulamak istediğiniz işaretleri (ör. -Werror) her modül için tekrarlamak zahmetlidir. Ancak projenizdeki üçüncü taraf bağımlılıkları üzerinde istenmeyen etkilere yol açabileceğinden bu işaretler nadiren genel olarak (CMAKE_CXX_FLAGS) uygulanmalıdır. Bu gibi durumlarda işaretler dizin kapsamında (add_compile_options) uygulanabilir.

Derleyici işaretlerinin dar bir alt kümesi için bunlar, cppFlags veya benzer özellikler kullanılarak build.gradle dosyanızda da ayarlanabilir. Bunu yapmamalısınız. Gradle'dan CMake'e iletilen işaretler, şaşırtıcı öncelik davranışlarına sahip olur. Bazı durumlarda, Android kodunu derlemek için gereken ve uygulama tarafından dolaylı olarak iletilen işaretleri geçersiz kılar. CMake davranışını her zaman doğrudan CMake'te işlemeyi tercih edin. Derleyici işaretlerini AGP'ye göre 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 için 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 tarafından kontrol edilen "ücretsiz" ve "premium" derleme varyantlarınız varsa ve bu verileri CMake'e iletmeniz 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 belirlersiniz ancak mevcut işaretlerle çakışma veya karışıklık olmaması için ANDROID_, APP_ veya CMAKE_ ön ekine sahip herhangi bir şey kullanmadığınızdan emin olun.

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

CMake derleme komutunu anlama

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

Android Gradle eklentisi, her ABI ve derleme türü çifti için CMake derlemesi yürütmek amacıyla kullandığı derleme bağımsız değişkenlerini build_command.txt dizinine 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 bir 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 derlenmiş kitaplık, AAR olarak dağıtılıyorsa bunları içe aktarmak ve kullanmak için Studio'nun bağımlılık dokümanlarını inceleyin. AGP kullanmıyorsanız https://google.github.io/prefab/example-workflow.html adresindeki talimatları uygulayabilirsiniz ancak AGP'ye geçiş yapmak muhtemelen çok daha kolay olacaktır.

AAR olarak dağıtılmayan kitaplıklar için önceden oluşturulmuş kitaplıkları CMake ile kullanma talimatlarını CMake kılavuzundaki IMPORTED hedefleriyle ilgili add_library belgelerinde 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 bir AAR oluşturun ve uygulamanızda bunu kullanın. Bu AAR'yi yayınlamanız gerekmez. Gradle projenizin dahili bir parçası olabilir.

Bu mümkün değilse:

  • Üçüncü taraf kaynağı deponuza kopyalayın ve derlemek için add_subdirectory komutunu kullanın. Bu, yalnızca diğer kitaplık da CMake ile oluşturulmuşsa çalışır.
  • ExternalProject tanımlayın.
  • Kitaplığı projenizden ayrı olarak derleyin ve önceden derlenmiş olarak içe aktarmak için Önceden derlenmiş kitaplıkları kullanma bölümündeki adımları uygulayın.

CMake'te YASM desteği

NDK, x86 ve x86-64 mimarilerinde çalışmak üzere YASM ile yazılmış assembly kodunu derlemek için CMake desteği sağlar. YASM, NASM çeviriciyi temel alan, x86 ve x86-64 mimarileri için açık kaynaklı bir çeviricidir.

CMake ile assembly kodu derlemek için projenizin CMakeLists.txt dosyasında aşağıdaki değişiklikleri yapın:

  1. enable_language yöntemini ASM_NASM değeriyle ç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 assembly programı için .asm dosyalarından ve ilişkili C kitaplıkları veya işlevleri için .c dosyalarından oluşan kaynak dosyaların listesini iletin.

Aşağıdaki snippet'te, bir YASM programını paylaşılan kitaplık olarak derlemek için CMakeLists.txt dosyanızı 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ı yürütülebilir dosya olarak derleme örneği için NDK git deposundaki yasm test bölümüne bakın.

Sorunları bildirme

NDK veya CMake araç zinciri dosyasıyla ilgili sorun yaşarsanız bunları GitHub'daki android-ndk/ndk Issue Tracker aracılığıyla bildirin. Gradle veya Android Gradle eklentisi sorunları için Studio hatası bildirin.