Mengonfigurasi CMake

Skrip build CMake adalah file teks biasa yang harus diberi nama CMakeLists.txt dan berisi perintah yang digunakan CMake untuk mem-build library C/C++. Jika sumber native belum memiliki skrip build CMake, Anda harus membuatnya sendiri dan menyertakan perintah CMake yang sesuai. Untuk mempelajari cara menginstal CMake, lihat Menginstal serta mengonfigurasi NDK dan CMake.

Bagian ini membahas tentang beberapa perintah dasar yang harus disertakan dalam skrip build agar dapat memberi tahu CMake, sumber yang digunakan saat membuat library native. Untuk mempelajari lebih lanjut, baca dokumentasi resmi tentang perintah CMake.

Setelah mengonfigurasi skrip build CMake baru, Anda harus mengonfigurasi Gradle untuk menyertakan project CMake sebagai dependensi build, agar Gradle dapat mem-build dan memaketkan library native dengan APK aplikasi.

Catatan: Jika project menggunakan ndk-build, Anda tidak perlu membuat skrip build CMake. Cukup konfigurasikan Gradle untuk menyertakan project library native yang ada dengan menyediakan jalur ke file Android.mk.

Membuat skrip build CMake

Untuk membuat file teks biasa yang dapat digunakan sebagai skrip build CMake, lakukan langkah-langkah berikut:

  1. Buka panel Project dari sisi kiri IDE, lalu pilih tampilan Project dari menu drop-down.
  2. Klik kanan direktori utama your-module, lalu pilih New > File.

    Catatan: Anda dapat membuat skrip build di lokasi mana pun yang diinginkan. Namun, saat mengonfigurasi skrip build, lokasi file dan library sumber native bersifat relatif terhadap lokasi skrip build.

  3. Masukkan "CMakeLists.txt" sebagai nama file, lalu klik OK.

Kini Anda dapat mengonfigurasi skrip build dengan menambahkan perintah CMake. Untuk memerintahkan CMake membuat library native dari kode sumber native, tambahkan perintah cmake_minimum_required() dan add_library() ke skrip build:

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

Tips: Mirip dengan cara memerintahkan CMake untuk membuat library native dari file sumber, Anda dapat menggunakan perintah add_executable() untuk memerintahkan CMake membuat file yang dapat dieksekusi dari file sumber tersebut. Namun, mem-build file yang dapat dieksekusi dari sumber native bersifat opsional, dan mem-build library native untuk dipaketkan dalam APK akan memenuhi sebagian besar persyaratan project.

Bila menambahkan file sumber atau library ke skrip build CMake menggunakan add_library(), Android Studio juga akan menampilkan file header terkait dalam tampilan Project setelah Anda menyinkronkan project. Namun, agar CMake dapat menemukan file header selama waktu kompilasi, Anda harus menambahkan perintah include_directories() ke skrip build CMake dan menetapkan jalur ke header:

add_library(...)

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

Konvensi yang digunakan CMake untuk menamai file library adalah sebagai berikut:

liblibrary-name.so

Misalnya, jika Anda menetapkan "native-lib" sebagai nama library bersama dalam skrip build, CMake akan membuat file bernama libnative-lib.so. Namun, saat memuat library ini dalam kode Java atau Kotlin, gunakan nama yang ditetapkan dalam skrip build CMake:

Kotlin

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

Java

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

Catatan: Jika mengganti nama atau menghapus library dalam skrip build CMake, Anda harus membersihkan project sebelum Gradle menerapkan perubahan atau menghapus versi library yang lebih lama dari APK. Untuk membersihkan project, pilih Build > Clean Project dari panel menu.

Android Studio secara otomatis menambahkan file sumber dan header ke grup cpp dalam panel Project. Dengan beberapa perintah add_library(), Anda dapat menentukan library tambahan agar CMake mem-build dari file sumber lain.

Menambahkan API NDK

Android NDK menyediakan kumpulan library dan API native yang mungkin berguna. Anda dapat menggunakan salah satu API ini dengan menyertakan library NDK dalam file skrip CMakeLists.txt project.

Library NDK bawaan sudah ada di platform Android, sehingga Anda tidak perlu mem-build atau memaketkannya ke dalam APK. Karena library NDK sudah menjadi bagian dari jalur penelusuran CMake, Anda bahkan tidak perlu menetapkan lokasi library dalam penginstalan NDK lokal. Anda hanya perlu memberi CMake nama library yang ingin digunakan dan menautkannya terhadap library native Anda sendiri.

Tambahkan perintah find_library() ke skrip build CMake untuk menemukan library NDK dan menyimpan jalurnya sebagai variabel. Gunakan variabel ini untuk merujuk ke library NDK di bagian lain dalam skrip build. Contoh berikut menemukan Support Library log khusus Android dan menyimpan jalurnya di log-lib:

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 )

Agar library native dapat memanggil fungsi dalam library log, Anda harus menautkan library menggunakan perintah target_link_libraries() dalam skrip build CMake:

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 juga mencakup beberapa library sebagai kode sumber yang perlu di-build dan ditautkan ke library native. Anda dapat mengompilasi kode sumber menjadi library native menggunakan perintah add_library() dalam skrip build CMake. Untuk menyediakan jalur ke library NDK lokal, Anda dapat menggunakan variabel jalur ANDROID_NDK, yang otomatis ditentukan oleh Android Studio untuk Anda.

Perintah berikut meminta CMake untuk mem-build android_native_app_glue.c, yang mengelola input sentuh dan peristiwa siklus proses NativeActivity, menjadi library statis dan menautkannya ke native-lib:

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

Menambahkan library bawaan lainnya

Cara menambahkan library bawaan mirip dengan cara menetapkan library native lainnya yang perlu di-build CMake. Namun, karena library sudah di-build, Anda harus menggunakan tanda IMPORTED untuk memberi tahu CMake bahwa Anda hanya ingin mengimpor library ke project:

add_library( imported-lib
             SHARED
             IMPORTED )

Selanjutnya Anda harus menetapkan jalur ke library menggunakan perintah set_target_properties() sebagaimana ditunjukkan di bawah ini.

Beberapa library menyediakan paket terpisah untuk arsitektur CPU tertentu, atau ABI (Antarmuka Biner Aplikasi), lalu mengelolanya menjadi direktori terpisah. Pendekatan ini membantu library memanfaatkan arsitektur CPU tertentu sekaligus memungkinkan Anda hanya menggunakan versi library yang diinginkan. Guna menambahkan beberapa versi ABI library ke skrip build CMake tanpa harus menulis beberapa perintah untuk setiap versi library, Anda dapat menggunakan variabel jalur ANDROID_ABI. Variabel ini menggunakan daftar ABI default yang didukung NDK, atau daftar ABI terfilter yang dikonfigurasi secara manual untuk digunakan Gradle. Contoh:

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 )

Agar CMake dapat menemukan file header selama waktu kompilasi, Anda harus menggunakan perintah include_directories() dan menyertakan jalur ke file header:

include_directories( imported-lib/include/ )

Catatan: Jika Anda ingin memaketkan library bawaan yang bukan dependensi waktu build, misalnya saat menambahkan library bawaan yang merupakan dependensi imported-lib, Anda tidak perlu melakukan petunjuk berikut untuk menautkan library.

Untuk menautkan library bawaan ke library native, tambahkan library tersebut ke perintah target_link_libraries() dalam skrip build CMake:

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

Guna memaketkan library bawaan ke dalam APK, Anda harus mengonfigurasi Gradle secara manual dengan blok sourceSets untuk menyertakan jalur ke file .so. Setelah mem-build APK, Anda dapat memverifikasi library yang dipaketkan Gradle ke dalam APK menggunakan APK Analyzer.

Menyertakan project CMake lainnya

Jika ingin mem-build beberapa project CMake dan menyertakan output-nya dalam project Android, Anda dapat menggunakan satu file CMakeLists.txt sebagai skrip build CMake level teratas (yaitu yang ditautkan ke Gradle) dan menambahkan project CMake tambahan sebagai dependensi skrip build tersebut. Skrip build CMake level teratas berikut menggunakan perintah add_subdirectory() untuk menetapkan file CMakeLists.txt lain sebagai dependensi build, lalu menautkan pada output-nya seperti halnya library bawaan lain.

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

Memanggil CMake dari command line

Gunakan perintah berikut untuk memanggil CMake guna membuat project Ninja di luar Android Studio:

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

Perintah ini akan menghasilkan project Ninja yang dapat dieksekusi untuk membuat library Android yang dapat dieksekusi (file .so). CMAKE_TOOLCHAIN_FILE diperlukan untuk menggunakan dukungan CMake NDK. Untuk CMake 3.21 atau yang lebih baru, dukungan NDK bawaan CMake dapat digunakan, tetapi grup variabel lain harus digunakan seperti yang dijelaskan dalam dokumentasi Mengompilasi Silang untuk Android dari CMake.