Android NDK, uygulamanız için C ve C++ kodunu derlemek üzere CMake'i kullanmayı destekler. Bu sayfada, CMake'in Android Gradle eklentisinin ExternalNativeBuild
aracılığıyla NDK ile nasıl kullanılacağı veya CMake'in doğrudan çağrıldığı durumlarda 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>/build/cmake/android.toolchain.cmake
adresindeki NDK'da bulunur.
ABI, minSdkVersion
vb. 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'larda, 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ı denemesi yapılmıştı. Bu, önemli miktarda çalışma gerektirdi (henüz tamamlanmadı) ancak davranışı iyileştirmedi. Bu nedenle, bu konuyu artık takip etmiyoruz.
"Yeni" araç zinciri dosyasının, "eski" araç zinciri dosyasına kıyasla davranış regresyonları vardır. 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 toolchain dosyası, eski toolchain dosyasıyla hiçbir zaman eşleşmedi. Bu nedenle, davranışta gerileme olması muhtemeldir.
Yeni araç zinciri dosyasını kullanmamanızı öneririz ancak şu anda NDK'dan kaldırma planımız yoktur. Bu, yeni ve eski araç zinciri dosyaları arasındaki davranış farklılıklarına dayanan derlemeleri bozar ve ne yazık ki "eski" seçeneğinin gerçekten önerildiğini açıkça belirtmek için seçeneği yeniden adlandırmak bu seçeneğin kullanıcılarını bozar. Yeni araç zinciri dosyasını memnuniyetle kullanıyorsanız taşımanız gerekmez. Ancak yeni araç zinciri dosyası davranışıyla ilgili olarak bildirilen hataların muhtemelen düzeltilmeyeceğini ve bunun yerine taşımanız gerektiğini unutmayın.
Kullanım
Gradle
externalNativeBuild
kullanılırken CMake araç zinciri dosyasının kullanımı otomatiktir. Daha fazla bilgi için Android Studio'nun Projenize C ve C++ kodu ekleme kılavuzunu inceleyin.
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 aktarılmalıdır. Örnek:
$ 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 derliyorsanız android.defaultConfig.externalNativeBuild.cmake.arguments
öğesine bağımsız değişkenler ekleyin (ExternalNativeBuild belgelerinde açıklandığı şekilde). Komut satırından derleme yapıyorsanız -D
ile bağımsız değişkenleri CMake'e iletin. Örneğin, armeabi-v7a'yı Neon desteğiyle derlememeye zorlamak için -DANDROID_ARM_NEON=FALSE
değerini iletin.
ANDROID_ABI
Hedef ABI. Desteklenen ABI'ler hakkında bilgi edinmek için Android ABI'leri konusuna bakın.
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'in 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 istiyorsanız her ABI için bir kez derleme yapmanız gerekir. Derlemeler arasındaki çakışmaları önlemek amacıyla 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 mi yoksa thumb talimatları mı oluşturulacağını belirtir. Diğer ABI'ler üzerinde etkisi yoktur. Daha fazla bilgi için Android ABI'leri belgelerine bakın.
Değer | Notlar |
---|---|
kol | |
başparmak | 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
ö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ılırken 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 ediliyor:
android-$API_LEVEL
$API_LEVEL
android-$API_LETTER
$API_LETTER
biçimi, bu sürümle ilişkili sayıyı belirlemeye gerek kalmadan android-N
öğesini belirtmenize olanak tanır. Bazı sürümlerin, sürüm adı değişmeden API sürümünün yükseltildiğini unutmayın. Bu API'ler, -MR1
soneki eklenerek belirtilebilir. Örneğin, API düzeyi 25 için android-N-MR1
değeri kullanılır.
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++_paylaşılan | libc++'nun paylaşılan kitaplık varyantı. |
c++_statik | libc++'nun statik kitaplık varyantı. |
yok | C++ standart kitaplığı desteği yoktur. |
sistem | Sistem STL'si |
Derleyici işaretlerini yönet
Derleme işleminiz 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 dokümanlarına bakın. Sayfanın alt kısmındaki "Ayrıca bakınız" bölümünde bazı faydalı ipuçları yer alır.
Genel olarak, derleyici işaretlerini mevcut en dar kapsam olarak uygulamak en iyi uygulamadır. Tüm hedeflerinize uygulamak istediğiniz işaretlerin (-Werror
gibi) modül başına tekrarlanması uygun değildir ancak yine de projenizdeki üçüncü taraf bağımlılıkları üzerinde istenmeyen etkileri olabileceğinden, bunlar 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, cppFlags
veya benzer özellikler kullanılarak build.gradle dosyanızda da ayarlanabilir. Bunu yapmamalısınız. Gradle'den CMake'e iletilen işaretlerin öncelik davranışları şaşırtıcıdır. Bazı durumlarda, Android kodu oluşturmak için gereken ve uygulama tarafından dolaylı olarak iletilen işaretleri geçersiz kılar. CMake davranışını her zaman doğrudan CMake'de yönetmeyi tercih edin. AGP buildType
başına derleyici işaretlerini kontrol etmeniz gerekiyorsa CMake'de AGP derleme türleriyle çalışma başlıklı makaleyi inceleyin.
CMake'de AGP derleme türleriyle çalışma
CMake davranışını özel bir Gradle buildType
öğesine 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 "ücretli" 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ışmayı veya karışıklığı önlemek için ANDROID_
, APP_
veya CMAKE_
öneklerinden birini kullanmamaya dikkat edin.
Örnek için Sanitizers NDK örneğine bakın.
CMake derleme komutunu anlama
CMake derleme sorunlarında hata ayıklama yaparken Gradle'ın Android için çapraz derleme yaparken kullandığı belirli derleme bağımsız değişkenlerini bilmeniz 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
içine 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ıklama yapılabilir bir sürümünü oluşturmak için kullanılan CMake bağımsız değişkenleri örneği 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 dokümanlarını inceleyin. AGP kullanmıyorsanız https://google.github.io/prefab/example-workflow.html adresini ziyaret edebilirsiniz ancak AGP'ye geçmek muhtemelen çok daha kolaydır.
AAR olarak dağıtılmayan kitaplıklar için CMake ile önceden oluşturulmuş kitaplıkları kullanma talimatlarına, CMake kılavuzundaki IMPORTED
hedefleriyle ilgili add_library
dokümanlarına bakabilirsiniz.
Üçüncü taraf kodu oluşturma
CMake projenizin bir parçası olarak üçüncü taraf kodu oluşturmanın birkaç yolu vardır. Hangi seçeneğin en uygun olduğu durumunuza bağlıdır. Genellikle en iyi seçenek, bunu hiç yapmamaktır. Bunun yerine, kitaplık için bir AAR oluşturun ve bunu uygulamanızda kullanın. Bu AAR'yı yayınlamanız gerekmez. Gradle projenizde dahili olabilir.
Bu seçenek yoksa:
- Üçüncü taraf kaynağını deponuza sağlayın (ör. kopyalayın) ve derlemek için add_subdirectory işlevini kullanın. Bu yöntem yalnızca diğer kitaplık da CMake ile derlenmişse ç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 adımlarını uygulayın.
CMake'de YASM desteği
NDK, x86 ve x86-64 mimarilerinde çalışacak şekilde YASM'da yazılmış derleme kodu oluşturmak için CMake desteği sağlar. YASM, NASM derleyiciyi temel alan, x86 ve x86-64 mimarileri için açık kaynaklı bir derleyicidir.
CMake ile derleme kodu oluşturmak için projenizin CMakeLists.txt
dosyasında aşağıdaki değişiklikleri yapın:
- Değeri
ASM_NASM
olarak ayarlanmışenable_language
öğesini çağırın. - Paylaşılan kitaplık mı yoksa yürütülebilir ikili program mı oluşturduğunuza bağlı olarak
add_library
veyaadd_executable
yöntemini çağırın. Parametrelere, 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 dosya listesi gönderin.
Aşağıdaki snippet'te, YASM programını paylaşılan kitaplık olarak derlemek için CMakeLists.txt
'ünü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ın nasıl yürütülebilir olarak derleneceğine dair bir örnek için NDK git deposundaki yasm test dosyasına bakın.
Sorunları bildirme
NDK veya CMake araç zinciri dosyasıyla ilgili herhangi bir sorunla karşılaşırsanız GitHub'daki android-ndk/ndk sorun izleyicisi aracılığıyla bunları bildirin. Gradle veya Android Gradle eklentisi sorunları için bunun yerine Studio hatası bildirin.