CMake を設定する

CMake ビルド スクリプトは書式なしテキスト ファイルで、名前は CMakeLists.txt にする必要があります。CMake ビルド スクリプトには、CMake が C / C++ ライブラリのビルドに使用するコマンドを含めます。ネイティブ ソースの CMake ビルド スクリプトがない場合は、自身で作成して適切な CMake コマンドを追加する必要があります。CMake をインストールする方法については、NDK と CMake のインストールと設定をご覧ください。

このセクションでは、ネイティブ ライブラリの作成時に使用するソースを CMake に指示するために、ビルド スクリプトに含める必要がある基本的なコマンドについて説明します。詳しくは、CMake コマンドの公式ドキュメントをご覧ください。

新しい CMake ビルド スクリプトを作成した後、Gradle の設定で CMake プロジェクトをビルド依存関係として含め、Gradle がネイティブ ライブラリをビルドしてアプリの APK にパッケージ化できるようにする必要があります。

注: プロジェクトで ndk-build を使用する場合、CMake ビルド スクリプトの作成は不要です。Gradle の設定Android.mk ファイルへのパスを指定するだけで、既存のネイティブ ライブラリ プロジェクトを含めることができます。

CMake ビルド スクリプトを作成する

CMake ビルド スクリプトとして使用できる書式なしテキスト ファイルを作成する手順は次のとおりです。

  1. IDE の左側にある [Project] ペインを開き、プルダウン メニューの [Project] ビューを選択します。
  2. your-module のルート ディレクトリを右クリックし、[New] > [File] を選択します。

    注: ビルド スクリプトは任意の場所に作成できます。 ただし、ビルド スクリプトを設定するときは、ネイティブ ソースファイルとライブラリのパスにはビルド スクリプトの場所に対する相対パスを指定してください。

  3. ファイル名に「CMakeLists.txt」と入力し、[OK] をクリックします。

これで、CMake コマンドを追加してビルド スクリプトを設定できるようになりました。ネイティブ ソースコードからネイティブ ライブラリを作成するように CMake に指示するには、cmake_minimum_required() コマンドと add_library() コマンドをビルド スクリプトに追加します。

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

ヒント: ソースファイルからネイティブ ライブラリを作成する場合と同様に、add_executable() コマンドを使用して、これらのソースファイルからの実行可能ファイルの作成を CMake に指示できます。ただし、ネイティブ ソースからの実行可能ファイルの作成はオプションであり、ネイティブ ライブラリを作成して APK にパッケージ化することでほとんどのプロジェクト要件は満たされます。

add_library() を使用してソースファイルまたはライブラリを CMake ビルド スクリプトに追加すると、プロジェクトを同期した後に Android Studio の [Project] ビューに関連するヘッダー ファイルも表示されます。ただし、コンパイル時に CMake がヘッダー ファイルを特定できるようにするには、include_directories() コマンドを CMake ビルド スクリプトに追加して、ヘッダーへのパスを指定する必要があります。

add_library(...)

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

CMake で使用するライブラリ ファイルの命名規則は次のとおりです。

liblibrary-name.so

たとえば、ビルド スクリプトで共有ライブラリの名前を「native-lib」と指定すると、CMake によって libnative-lib.so というファイルが作成されます。ただし、このライブラリを Java または Kotlin コードで読み込む場合は、CMake ビルド スクリプトで指定した名前を使用します。

Kotlin

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

Java

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

注: CMake ビルド スクリプト内のライブラリの名前変更または削除を行う場合、Gradle で変更が適用されるには、あるいは古いバージョンのライブラリが APK から削除されるには、プロジェクトをクリーンアップする必要があります。これを行うには、メニューバーで [Build] > [Clean Project] を選択します。

Android Studio は、[Project] ペインの cpp グループにソースファイルとヘッダーを自動的に追加します。複数の add_library() コマンドを使用することで、CMake が他のソースファイルからビルドする追加のライブラリを定義できます。

NDK API を追加する

Android NDK は、有用なネイティブ API とライブラリのセットを提供します。これらの API を使用するには、プロジェクトの CMakeLists.txt スクリプト ファイルに NDK ライブラリを含めます。

ビルド済みの NDK ライブラリは Android プラットフォームにすでに存在するため、ビルドや APK へのパッケージ化の必要はありません。NDK ライブラリはすでに CMake の検索パスに含まれているため、ローカルの NDK のインストールでライブラリの場所を指定する必要もありません。必要なのは、使用するライブラリの名前を CMake に指定して、ネイティブ ライブラリとリンクさせることだけです。

NDK ライブラリを特定して変数にそのパスを保存できるように、CMake ビルド スクリプトに find_library() コマンドを追加します。この変数を使用して、ビルド スクリプトの他の部分で NDK ライブラリを参照します。 次のサンプルでは、Android 固有のログサポート ライブラリを特定し、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 )

ネイティブ ライブラリで log ライブラリの関数を呼び出すには、CMake ビルド スクリプトで target_link_libraries() コマンドを使用してライブラリをリンクする必要があります。

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 の一部のライブラリは、ビルドしてネイティブ ライブラリにリンクする必要があるソースコードとして提供されています。CMake ビルド スクリプトで add_library() コマンドを使用することで、ソースコードをネイティブ ライブラリにコンパイルできます。ローカルの NDK ライブラリへのパスを指定するには、ANDROID_NDK パス変数を使用します。これは、Android Studio が自動的に定義します。

次のコマンドは、NativeActivity のライフサイクル イベントとタップ入力を管理する android_native_app_glue.c を静的ライブラリにビルドして、native-lib にリンクするよう CMake に指示します。

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

その他のビルド済みライブラリを追加する

ビルド済みライブラリを追加する方法は、別のネイティブ ライブラリを CMake でビルドするよう指定する場合と同様です。ただし、ライブラリはビルド済みであるため、IMPORTED フラグを使用して、プロジェクトへのインポートのみを実行するよう CMake に指示する必要があります。

add_library( imported-lib
             SHARED
             IMPORTED )

次に、以下のように set_target_properties() コマンドを使用して、ライブラリへのパスを指定する必要があります。

一部のライブラリには、特定の CPU アーキテクチャ向けの個別のパッケージとなるアプリケーション バイナリ インターフェース(ABI)が用意され、別々のディレクトリにまとめられています。このアプローチにより、ライブラリでは特定の CPU アーキテクチャの活用が容易になり、デベロッパーは必要なバージョンのライブラリのみを使用できます。複数の ABI バージョンのライブラリを CMake ビルド スクリプトに追加する場合、ライブラリのバージョンごとに複数のコマンドを記述する必要はありません。ANDROID_ABI パス変数を使用できます。この変数は、NDK がサポートするデフォルトの ABI のリストを使用するか、手動で Gradle を設定してフィルタした ABI のリストを使用します。次に例を示します。

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 )

コンパイル時に CMake でヘッダー ファイルを特定するには、include_directories() コマンドでヘッダー ファイルへのパスを指定する必要があります。

include_directories( imported-lib/include/ )

注: たとえば、imported-lib の依存関係であるビルド済みライブラリを追加するときなど、ビルド時の依存関係ではないビルド済みライブラリをパッケージ化する場合は、次の手順でライブラリをリンクする必要はありません。

独自のネイティブ ライブラリにビルド済みライブラリをリンクするには、CMake ビルド スクリプトの target_link_libraries() コマンドにライブラリを追加します。

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

ビルド済みライブラリを APK にパッケージ化するには、.so ファイルへのパスを含めるように sourceSets ブロックを指定して、手動で Gradle を設定する必要があります。APK をビルドした後、APK Analyzer で、Gradle が APK にパッケージ化するライブラリを確認できます。

他の CMake プロジェクトを含める

複数の CMake プロジェクトをビルドしてその出力を Android プロジェクトに含める場合は、1 つの CMakeLists.txt ファイルを最上位の CMake ビルド スクリプト(Gradle にリンクするビルド スクリプト)として使用し、そのビルド スクリプトの依存関係として他の CMake プロジェクトを追加できます。以下の最上位の CMake ビルド スクリプトでは、add_subdirectory() コマンドを使用して別の CMakeLists.txt ファイルをビルド依存関係として指定し、他のビルド済みライブラリと同様にその出力に対してリンクしています。

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

コマンドラインから CMake を呼び出す

CMake を呼び出して Android Studio の外部で Ninja プロジェクトを生成するには、次のコマンドを使用します。

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

このコマンドによって、Android 実行可能ライブラリ(.so ファイル)を作成するために実行できる Ninja プロジェクトが生成されます。NDK の CMake サポートを使用するには、CMAKE_TOOLCHAIN_FILE が必要です。CMake 3.21 以降の場合は、CMake の組み込みの NDK サポートを代わりに使用できますが、CMake の Android のクロスコンパイルのドキュメントで説明されているように、別の変数グループを使用する必要があります。