Android NDK mendukung penggunaan CMake untuk
mengompilasi kode C dan C++ untuk aplikasi. Halaman ini membahas cara menggunakan
CMake dengan NDK melalui ExternalNativeBuild
Plugin Android Gradle atau saat
memanggil CMake secara langsung.
File toolchain CMake
NDK mendukung CMake melalui file toolchain. File Toolchain adalah file CMake yang menyesuaikan perilaku toolchain untuk kompilasi silang. File toolchain yang digunakan untuk NDK terletak dalam NDK di <NDK>/build/cmake/android.toolchain.cmake
.
Parameter build seperti ABI, minSdkVersion
, dsb. diberikan pada command
line saat memanggil cmake
. Untuk daftar argumen yang didukung, lihat
bagian Argumen toolchain.
File toolchain "baru"
NDK sebelumnya bereksperimen dengan implementasi baru file toolchain yang akan mengurangi perbedaan perilaku antara penggunaan file toolchain NDK dan penggunaan dukungan CMake bawaan. Akhirnya, hal ini memerlukan banyak pekerjaan (yang belum selesai), tetapi sebenarnya tidak meningkatkan perilaku, jadi kami tidak lagi mengejar hal ini.
File toolchain "baru" memiliki regresi perilaku dibandingkan dengan file toolchain "lama". Perilaku default adalah alur kerja yang direkomendasikan. Jika Anda
menggunakan -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF
, sebaiknya hapus flag tersebut
dari build Anda. File toolchain baru tidak pernah mencapai paritas dengan file toolchain lama, sehingga kemungkinan ada regresi perilaku.
Meskipun kami merekomendasikan agar tidak menggunakan file toolchain baru, saat ini tidak ada rencana untuk menghapusnya dari NDK. Tindakan ini akan merusak build yang mengandalkan perbedaan perilaku antara file toolchain baru dan lama, dan sayangnya mengganti nama opsi untuk memperjelas bahwa "lama" sebenarnya direkomendasikan juga akan merusak pengguna opsi tersebut. Jika dengan senang hati Anda menggunakan file toolchain baru, Anda tidak perlu bermigrasi, tetapi perlu diketahui bahwa setiap bug yang dilaporkan terhadap perilaku file toolchain baru mungkin tidak akan diperbaiki, dan sebagai gantinya, Anda harus bermigrasi.
Penggunaan
Gradle
Penggunaan file toolchain CMake dilakukan otomatis saat menggunakan
externalNativeBuild
. Lihat panduan Android Studio tentang Menambahkan kode C dan C++ ke
project untuk informasi selengkapnya.
Command Line
Saat mem-build dengan CMake di luar Gradle, file toolchain tersebut sendiri beserta argumennya harus diteruskan ke CMake. Contoh:
$ cmake \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=$ABI \
-DANDROID_PLATFORM=android-$MINSDKVERSION \
$OTHER_ARGS
Argumen toolchain
Argumen berikut dapat diteruskan ke file toolchain CMake. Jika mem-build dengan Gradle, tambahkan argumen ke android.defaultConfig.externalNativeBuild.cmake.arguments
seperti yang dijelaskan dalam dokumen ExternalNativeBuild. Jika mem-build dari command line, teruskan argumen ke CMake dengan -D
. Misalnya, untuk memaksa armeabi-v7a agar tidak membangun dengan dukungan
Neon, teruskan -DANDROID_ARM_NEON=FALSE
.
ANDROID_ABI
ABI target. Untuk informasi tentang ABI yang didukung, lihat ABI Android.
Gradle
Gradle memberikan argumen ini secara otomatis. Jangan tetapkan argumen ini secara eksplisit dalam file build.gradle
Anda. Untuk mengontrol ABI yang ditargetkan Gradle, gunakan abiFilters
seperti yang dijelaskan dalam ABI Android.
Command Line
CMake melakukan proses build untuk satu target per build. Untuk menargetkan lebih dari satu ABI Android, Anda harus melakukan proses build satu kali per ABI. Sebaiknya gunakan direktori build yang berbeda untuk setiap ABI guna menghindari konflik antar-build.
Nilai | Catatan |
---|---|
armeabi-v7a |
|
armeabi-v7a with NEON |
Sama seperti armeabi-v7a . |
arm64-v8a |
|
x86 |
|
x86_64 |
ANDROID_ARM_MODE
Menentukan apakah akan membuat instruksi arm atau thumb untuk armeabi-v7a. Tidak berpengaruh bagi ABI lainnya. Untuk informasi selengkapnya, lihat dokumentasi ABI Android.
Nilai | Catatan |
---|---|
arm | |
thumb | Perilaku default. |
ANDROID_NATIVE_API_LEVEL
Alias untuk ANDROID_PLATFORM.
ANDROID_PLATFORM
Menetapkan API level minimum yang didukung oleh aplikasi atau library. Nilai ini terkait dengan minSdkVersion
aplikasi.
Gradle
Saat menggunakan Plugin Android Gradle, nilai ini otomatis ditetapkan agar cocok dengan minSdkVersion
aplikasi dan tidak boleh ditetapkan secara manual.
Command Line
Saat memanggil CMake secara langsung, nilai ini ditetapkan secara default ke API level terendah yang didukung oleh NDK yang sedang digunakan. Misalnya, dengan NDK r20, nilai ini ditetapkan secara default ke API level 16.
Beberapa format diterima untuk parameter ini:
android-$API_LEVEL
$API_LEVEL
android-$API_LETTER
Format $API_LETTER
memungkinkan Anda untuk menetapkan android-N
tanpa perlu menentukan nomor yang terkait dengan rilis tersebut. Perlu diketahui bahwa beberapa rilis menerima peningkatan API tanpa peningkatan huruf. API ini dapat ditentukan dengan menambahkan akhiran -MR1
. Misalnya, API level 25 adalah android-N-MR1
.
ANDROID_STL
Menetapkan STL yang akan digunakan untuk aplikasi ini. Untuk informasi selengkapnya, lihat Dukungan
library C++. Secara default, c++_static
akan digunakan.
Nilai | Catatan |
---|---|
c++_shared | Varian library bersama libc ++. |
c++_static | Varian library statis libc ++. |
none | Tidak ada dukungan library standar C++. |
system | STL sistem |
Mengelola flag compiler
Jika Anda perlu meneruskan tanda tertentu ke compiler atau linker untuk build Anda, lihat dokumentasi CMake untuk set_target_compile_options dan kelompok opsi terkait. Bagian "lihat juga" di bagian bawah halaman tersebut memiliki beberapa petunjuk yang berguna.
Secara umum, praktik terbaiknya adalah menerapkan flag compiler sebagai cakupan
terbatas yang tersedia. Flag yang ingin Anda terapkan ke semua target (seperti
-Werror
) tidak praktis untuk diulang per modul, tetapi tetap jarang
diterapkan secara global (CMAKE_CXX_FLAGS
), karena hal tersebut dapat memiliki efek yang tidak diinginkan pada
dependensi pihak ketiga dalam project Anda. Untuk kasus semacam ini, flag dapat
diterapkan pada cakupan direktori (add_compile_options
).
Untuk subset flag compiler yang sempit, flag tersebut juga dapat ditetapkan dalam file build.gradle
Anda menggunakan cppFlags
atau properti serupa. Anda tidak boleh melakukannya. Tanda
yang diteruskan ke CMake dari Gradle akan memiliki perilaku prioritas yang mengejutkan, dalam beberapa
kasus, mengganti flag yang diteruskan secara implisit oleh implementasi yang
diperlukan untuk membangun kode Android. Selalu lebih suka menangani perilaku CMake
secara langsung di CMake. Jika Anda perlu mengontrol flag compiler per buildType
AGP,
lihat Menggunakan jenis build AGP di CMake.
Menggunakan jenis build AGP di CMake
Jika Anda perlu menyesuaikan perilaku CMake ke buildType
Gradle kustom, gunakan
jenis build tersebut untuk meneruskan flag CMake tambahan (bukan flag compiler) yang dapat dibaca
skrip build CMake Anda. Misalnya, jika Anda memiliki varian build "gratis" dan "premium"
yang dikontrol oleh build.gradle.kts dan Anda perlu meneruskan
data tersebut ke CMake:
android {
buildTypes {
free {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=OFF")
}
}
}
premium {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=ON")
}
}
}
}
}
Kemudian, di CMakeLists.txt:
if (DPRODUCT_VARIANT_PREMIUM)
# Do stuff for the premium build.
else()
# Do stuff for the free build.
endif()
Anda dapat menentukan nama variabel, tetapi pastikan untuk menghindari apa pun yang memiliki awalan
ANDROID_
, APP_
, atau CMAKE_
untuk menghindari konflik atau kebingungan dengan
flag yang sudah ada.
Lihat Contoh NDK Sanitizers untuk mengetahui contohnya.
Memahami perintah build CMake
Saat men-debug masalah build CMake, sebaiknya ketahui argumen build spesifik yang digunakan Gradle saat mengompilasi silang untuk Android.
Plugin Android Gradle menyimpan argumen build yang digunakannya untuk menjalankan
build CMake untuk setiap pasangan ABI dan pasangan
jenis build ke build_command.txt
. File-file ini ditemukan dalam direktori
berikut:
<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/
Cuplikan berikut menunjukkan contoh argumen CMake untuk mem-build
rilis contoh hello-jni
yang dapat di-debug dan menargetkan
arsitektur armeabi-v7a
.
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
Menggunakan library bawaan
Jika library bawaan yang perlu Anda impor didistribusikan sebagai AAR, ikuti dokumen dependensi Studio untuk mengimpor dan menggunakannya. Jika tidak menggunakan AGP, Anda dapat mengikuti https://google.github.io/prefab/example-workflow.html, tetapi kemungkinan akan lebih mudah untuk bermigrasi ke AGP.
Untuk library yang tidak didistribusikan sebagai AAR, lihat petunjuk tentang cara menggunakan library
bawaan dengan CMake, lihat dokumentasi add_library
terkait target
IMPORTED
dalam Panduan CMake.
Membuat kode pihak ketiga
Ada beberapa cara untuk membuat kode pihak ketiga sebagai bagian dari project CMake Anda, dan opsi mana yang berfungsi paling baik bergantung pada situasi Anda. Opsi terbaik sering kali adalah tidak melakukan ini sama sekali. Sebagai gantinya, build AAR untuk library dan gunakan di aplikasi Anda. Anda tidak perlu memublikasikan AAR tersebut. AAR dapat bersifat internal untuk project Gradle Anda.
Jika tidak dapat dilakukan:
- Lakukan vendoring (misalnya, salin) sumber pihak ketiga ke dalam repositori Anda dan gunakan add_subdirectory untuk mem-build. Ini hanya berfungsi jika library lain juga di-build dengan CMake.
- Tentukan ExternalProject.
- Build library secara terpisah dari project Anda dan ikuti Menggunakan library bawaan untuk mengimpornya sebagai bawaan.
Dukungan YASM di CMake
NDK menyediakan dukungan CMake untuk mem-build kode penggabungan yang ditulis dalam YASM agar dapat dijalankan pada arsitektur x86 dan x86-64. YASM adalah assembler open source untuk arsitektur x86 dan x86-64, yang didasarkan pada assembler NASM.
Untuk mem-build kode penggabungan dengan CMake, buat perubahan berikut dalam CMakeLists.txt
project:
- Panggil
enable_language
dengan nilai yang ditetapkan keASM_NASM
. - Bergantung pada apakah Anda mem-build library bersama atau biner yang dapat
dieksekusi, panggil
add_library
atauadd_executable
. Dalam argumen, teruskan daftar file sumber yang terdiri dari file.asm
untuk program penggabungan di YASM dan file.c
untuk fungsi atau library C terkait.
Cuplikan berikut menunjukkan cara mengonfigurasi CMakeLists.txt
untuk
mem-build program YASM sebagai library bersama.
cmake_minimum_required(VERSION 3.6.0)
enable_language(ASM_NASM)
add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)
Untuk mengetahui contoh tentang cara mem-build program YASM sebagai file yang dapat dieksekusi, lihat pengujian yasm di repositori git NDK.
Melaporkan masalah
Jika Anda mengalami masalah terkait NDK atau file toolchain CMake-nya, laporkan melalui issue tracker android-ndk/ndk di GitHub. Untuk masalah Gradle atau Plugin Android Gradle, laporkan bug Studio.