CMake

Android NDK では CMake を使用してアプリの C コードと C++ コードをコンパイルできます。このページでは NDK で CMake を使用する方法として、Android Gradle プラグインの ExternalNativeBuild を介す場合と、CMake を直接呼び出す場合を説明します。

CMake ツールチェーン ファイル

NDK は CMake をツールチェーン ファイルを使ってサポートします。ツールチェーン ファイルはクロスコンパイルでのツールチェーンの動作をカスタマイズする CMake ファイルです。NDK で使用されるツールチェーン ファイルは NDK 内の <NDK>/build/cmake/android.toolchain.cmake にあります。

ABI、minSdkVersion などのビルド パラメータは、cmake を呼び出すときにコマンドラインで指定します。サポートされる引数のリストについては、ツールチェーンの引数のセクションをご覧ください。

使用方法

Gradle

externalNativeBuild を使用したとき、CMake ツールチェーン ファイルが自動的に使用されます。詳細については、Android Studio のプロジェクトへの C / C++ コードの追加に関するガイドをご覧ください。

コマンドライン

CMake を使って Gradle の外部でビルドする場合、ツールチェーン ファイルそのものとその引数を CMake に渡す必要があります。次に例を示します。

$ cmake \
        -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
        -DANDROID_ABI=$ABI \
        -DANDROID_NATIVE_API_LEVEL=$MINSDKVERSION \
        $OTHER_ARGS
    

ツールチェーンの引数

以下の引数を、CMake ツールチェーン ファイルに渡すことができます。Gradle を使用してビルドする場合は、ExternalNativeBuild ドキュメントに記載のように、引数を android.defaultConfig.externalNativeBuild.cmake.arguments に指定します。コマンドラインからビルドする場合は、-D を指定して CMake に引数を渡します。たとえば、常に Neon のサポートを加えてビルドするように armeabi-v7a に指示するには、-DANDROID_ARM_NEON=TRUE を渡します。

ANDROID_ABI

ターゲットとする ABI です。サポートされている ABI については、Android ABI に関するガイドをご覧ください。

Gradle

Gradle はこの引数を自動的に提供します。この引数を build.gradle ファイル内で明示的に設定しないでください。ABI Gradle が何をターゲットにするかを管理するには、Android ABI に関するガイドに記載のように、abiFilters を使用します。

コマンドライン

CMake はビルドごとに 1 つのターゲットに対してビルドします。複数の Android ABI をターゲットにするには、ABI ごとにビルドする必要があります。ビルド間の競合を回避するには、ABI ごとに異なるビルド ディレクトリを使用することをおすすめします。

armeabi-v7a
armeabi-v7a with NEON -DANDROID_ABI=armeabi-v7a -DANDROID_ARM_NEON=ON と同じ。
arm64-v8a
x86
x86_64

ANDROID_ARM_MODE

armeabi-v7a の ARM 命令と Thumb 命令のどちらを生成するかを指定します。他の ABI には影響しません。詳細については、Android ABI に関するドキュメントをご覧ください。

arm
thumb デフォルト動作。

ANDROID_ARM_NEON

armeabi-v7a の NEON を有効または無効にします。他の ABI には影響しません。API レベル(minSdkVersion または ANDROID_PLATFORM)23 以降のデフォルトは true です。それ以外のデフォルトは false です。詳細については、NEON に関するドキュメントをご覧ください。

TRUE API レベル 23 以降でのデフォルト。
FALSE API レベル 22 以前でのデフォルト。

ANDROID_LD

使用するリンカーを選択します。lld は現在 NDK での試験運用版で、この引数で有効にできます。

lld lld を有効にする。
default 指定した ABI のデフォルトのリンカーを使用する。

ANDROID_NATIVE_API_LEVEL

ANDROID_PLATFORM のエイリアスです。

ANDROID_PLATFORM

アプリまたはライブラリでサポートされる最小の API レベルを指定します。この値はアプリの minSdkVersion に対応します。

Gradle

Android Gradle プラグインを使用する場合、この値はアプリの minSdkVersion に一致するように自動的に設定されるので、手動では設定しないでください。

コマンドライン

CMake を直接呼び出す場合、この値のデフォルトは、使用中の NDK でサポートされる最小の API レベルです。たとえば、NDK r20 の場合、この値はデフォルトで API レベル 16 になります。

このパラメータに指定できる形式は複数あります。

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

$API_LETTER 形式を使用すると、android-N を指定できるので、そのリリースに関連付けられた番号を特定する必要はありません。API 番号が増えても文字が変わらなかったリリースもあるのでご注意ください。その場合の API は、-MR1 サフィックスを追加して指定できます。たとえば、API レベル 25 は android-N-MR1 です。

ANDROID_STL

このアプリに使用する STL を指定します。詳細については、C++ ライブラリ サポートをご覧ください。デフォルトでは c++_static が使用されます。

c++_shared libc++ の共有ライブラリ バリアント。
c++_static libc++ の静的ライブラリ バリアント。
none C++ 標準ライブラリのサポートなし。
system system STL

CMake ビルドコマンドについて

CMake のビルドに関する問題をデバッグする際に、Gradle がクロスコンパイル時に Android 用に使用する各ビルド引数について知っておくと役に立ちます。

Android Gradle プラグインは、ABI とビルドタイプのペアごとに、CMake ビルドの実行に使用するビルド引数を cmake_build_command.txt に保存します。これらのファイルは、次のディレクトリにあります。

<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/
    

次のスニペットは、armeabi-v7a アーキテクチャをターゲットとする hello-jni のサンプルのデバッグ可能なリリースをビルドする CMake 引数の例を示します。

Executable : ${HOME}/Android/Sdk/cmake/3.6.3155560/bin/cmake
    arguments :
    -H${HOME}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/src/main/cpp
    -B${HOME}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/.cxx/cmake/arm7Debug/armeabi-v7a
    -GAndroid Gradle - Ninja
    -DANDROID_ABI=armeabi-v7a
    -DANDROID_NDK=${HOME}/Android/Sdk/ndk-bundle
    -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/build/intermediates/cmake/arm7/debug/obj/armeabi-v7a
    -DCMAKE_BUILD_TYPE=Debug
    -DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.6.3155560/bin/ninja
    -DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake
    -DANDROID_NATIVE_API_LEVEL=23
    -DANDROID_TOOLCHAIN=clang
    jvmArgs :
    

ビルド済みライブラリの使用

CMake でビルド済みライブラリを使用する手順については、CMake マニュアルIMPORTED ターゲットに関する add_library のドキュメントをご覧ください。

CMake での YASM サポート

NDK では、YASM で記述され、x86 と x86-64 アーキテクチャで実行されるアセンブリ コードをビルドする CMake サポートが提供されます。YASM は、NASM アセンブラをベースとする x86 と x86-64 アーキテクチャ用のオープンソース アセンブラです。

CMake でアセンブリ コードをビルドするには、プロジェクトの CMakeLists.txt を次のように変更します。

  1. ASM_NASM に設定する値を指定して enable_language を呼び出します。
  2. 共有ライブラリをビルドするのか、実行可能なバイナリをビルドするのかに応じて、add_library または add_executable{.external} を呼び出します。YASM のアセンブリ プログラムの .asm ファイルと、関連する C ライブラリまたは関数の .c ファイルから構成されるソースファイルのリストを引数に渡します。

次のスニペットは、YASM プログラムを共有ライブラリとしてビルドする CMakeLists.txt の設定方法の例を示します。

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 プログラムを実行可能ファイルとしてビルドする方法の例は、NDK git リポジトリの yasm test をご覧ください。

問題の報告

NDK または CMake のツールチェーン ファイルで問題が発生した場合は、GitHub の android-ndk/ndk 公開バグトラッカーで報告してください。