CMake

Android Studio 2.2 以降では、NDK と CMake を使用して C および C++ コードをネイティブ ライブラリにコンパイルできます。Android Studio では、IDE の統合ビルドシステムである Gradle を使用して、このライブラリを APK にパッケージ化します。

CMake を Android Studio で初めて使用する場合は、プロジェクトへの C / C++ コードの追加に進み、ネイティブ ソースのプロジェクトへの追加、CMake ビルド スクリプトの作成、Gradle 依存関係としての CMake プロジェクトの追加の基本を学習します。このページでは、CMake ビルドのカスタマイズに使用できる追加情報を提供します。

Gradle での CMake 変数の使用

Gradle を CMake プロジェクトにリンクすると、CMake がネイティブ ライブラリをビルドする方法を変更する、特定の NDK 固有の変数を構成できます。引数をモジュールレベルの build.gradle ファイルから CMake に渡すには、次の DSL を使用します。

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake build script.
    externalNativeBuild {
      cmake {
        ...
        // Use the following syntax when passing arguments to variables:
        // arguments "-DVAR_NAME=ARGUMENT".
        arguments "-DANDROID_ARM_NEON=TRUE",
        // If you're passing multiple arguments to a variable, pass them together:
        // arguments "-DVAR_NAME=ARG_1 ARG_2"
        // The following line passes 'rtti' and 'exceptions' to 'ANDROID_CPP_FEATURES'.
                  "-DANDROID_CPP_FEATURES=rtti exceptions"
      }
    }
  }
  buildTypes {...}

  // Use this block to link Gradle to your CMake build script.
  externalNativeBuild {
    cmake {...}
  }
}

以下の表は、NDK で CMake を使用する場合に構成できる変数の一部を示しています。

変数名 引数 説明
ANDROID_PLATFORM

プラットフォーム名と対応する Android システム イメージの完全な一覧は、Android NDK ネイティブ API をご覧ください。

ターゲットの Android プラットフォームの名前を指定します。たとえば、android-18 は Android 4.3(API レベル 18)を指定します。

このフラグを直接変更するのではなく、モジュールレベルの build.gradle ファイルdefaultConfig ブロックまたは productFlavors ブロックで minSdkVersion プロパティを設定します。これにより、ライブラリが Android の適切なバージョンを実行している端末にインストールされたアプリでのみ実行されます。次に、CMake のツールチェーンが、次のロジックを使用して、ビルドする ABI に最適なプラットフォーム バージョンを選択します。

  1. minSdkVersion と同じ ABI のプラットフォーム バージョンがある場合、CMake はそのバージョンを使用します。
  2. そうではなく、ABI 用の minSdkVersion より低いプラットフォーム バージョンがある場合、CMake はそれらのプラットフォーム バージョンのうち最も高いものを使用します。通常、プラットフォーム バージョンがない場合、以前の利用可能バージョン以降、ネイティブ プラットフォーム API に変更がないことを意味するため、これが妥当な選択になります。
  3. そうでない場合、CMake では minSdkVersion より高い、次に利用可能なプラットフォーム バージョンを使用します。
ANDROID_STL

完全なオプション リストについては、ヘルパー ランタイムをご覧ください。

デフォルトでは、CMake は c++_static を使用します。

CMake が使用する STL を指定します。

ANDROID_PIE
  • ONANDROID_PLATFORM = android-16 以上の場合のデフォルト)
  • OFFANDROID_PLATFORM = android-15 以下の場合のデフォルト)

位置独立実行ファイル(PIE)を使用するかどうかを指定します。Android のダイナミック リンカーは Android 4.1(API レベル 16)以上で PIE をサポートします。

ANDROID_CPP_FEATURES

この変数はデフォルトでは空です。ただし、次に示すとおり、渡すことのできる引数がいくつかあります。

  • rtti(コードが RTTI を使用することを示します)
  • exceptions(コードが C++ の例外を使用することを示します)

ネイティブ ライブラリをコンパイルする場合に CMake が使用する必要がある、RTTI (RunTime Type Information)や C++ 例外など、特定の C++ 機能を指定します。

ANDROID_ALLOW_UNDEFINED_SYMBOLS
  • TRUE
  • FALSE(デフォルト)

ネイティブ ライブラリのビルド中に CMake で未定義の参照が発生した場合に undefined symbol エラーをスローするかどうかを指定します。このようなタイプのエラーを無効にするには、この変数を TRUE に設定します。

ANDROID_ARM_MODE
  • arm
  • thumb(デフォルト)

ARM ターゲット バイナリを arm モードか thumb モードのどちらで生成するかを指定します。thumb モードでは、それぞれの指示は 16 ビット幅で thumb/ ディレクトリの STL ライブラリにリンクされています。arm の受け渡しによって、ライブラリのオブジェクト ファイルを 32 ビットの ARM モードで生成するよう CMake に指示します。

ANDROID_ARM_NEON
  • TRUE
  • FALSE

CMake で NEON を有効にしてネイティブ ライブラリをビルドするかどうかを指定します。デフォルト値は API レベルが 23 以降であれば true、それ以外の場合は false です。

ANDROID_DISABLE_FORMAT_STRING_CHECKS
  • TRUE
  • FALSE(デフォルト)

フォーマット文字列を保護してソースコードをコンパイルするかどうかを指定します。有効にすると、printf スタイルの関数で非定数フォーマット文字列が使用されている場合にコンパイラからエラーがスローされます。

CMake ビルドコマンドとは

CMake ビルドの問題をデバッグする場合は、Android 用にクロスコンパイルするときに Android Studio が使用する特定のビルド引数を理解しておくと便利です。

Android Studio は、CMake ビルドの実行に使用するビルド引数を cmake_build_command.txt ファイルに保存します。アプリがターゲットとする各アプリケーション バイナリ インターフェース(ABI)、およびその ABI のそれぞれのビルドタイプ(つまり、リリースデバッグ)について、Android Studio はその特定の構成用に cmake_build_command.txt ファイルのコピーを生成します。その後、Android Studio が生成されたファイルを次のディレクトリに保存します。

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

ヒント:Android Studio では、検索キーボード ショートカット(shift+shift)を使用したり、入力フィールドに cmake_build_command.txt と入力したりして、これらのファイルを簡単に表示できます。

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

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

ビルド引数

次の表では、Android の主な CMake ビルド引数を取り上げています。これらのビルド引数はデベロッパーが設定するものではありません。代わりに、Gradle 用の Android プラグイン がプロジェクト内で build.gradle 構成に基づいてこれらの引数を設定します。

ビルド引数 説明
-G <build-system>

CMake が生成するビルド ファイルの種類。

ネイティブ コードを使用する Android Studio のプロジェクトについては、<build-system>Android Gradle - Ninja に設定されます。この設定は、CMake が ninja ビルドシステムを使用して、アプリ向けに C/C++ ソースをコンパイルし、リンクすることを示します。CMake はコンパイラ フラグやターゲット名など、CMake ビルドに関する Gradle プラグインのメタデータを含む android_gradle_build.json ファイルも生成します。

この設定は、CMake が ninja ビルドシステムとともに Gradle を使用して、アプリ向けに C/C++ ソースをコンパイルし、リンクすることを示します。ninja ビルドシステムは Studio がサポートする唯一のジェネレータです。

-DANDROID_ABI <abi>

ターゲット ABI。

NDK は ABI 管理に示すように、一連の ABI をサポートしています。このオプションは ndk-build ツールで使用される APP_ABI 変数に類似しています。

デフォルトで、Gradle は ABI および NDK のサポートのためにネイティブ ライブラリを個別の .so ファイルにビルドし、これらのファイルをすべて APK にパッケージ化します。Gradle で特定の ABI 構成に対してのみビルドを行う必要がある場合は、プロジェクトへの C / C++ コードの追加の手順をご覧ください。

ターゲット ABI が指定されていない場合、CMake はデフォルトで armeabi-v7a を使用します。

有効なターゲット名は次のとおりです。

  • armeabi:ソフトウェア浮動小数点演算での ARMv5TE ベースの CPU。
  • armeabi-v7a:ハードウェア FPU 手順による ARMv7 ベースの端末(VFPv3_D16)。
  • armeabi-v7a with NEON:NEON 浮動小数点命令が有効であること以外は armeabi-v7a と同じです。これは -DANDROID_ABI=armeabi-v7a-DANDROID_ARM_NEON=ON の設定に相当します。
  • arm64-v8a:ARMv8 AArch64 命令セット。
  • x86:IA-32 命令セット。
  • x86_64 - x86-64 アーキテクチャの命令セット。
-DANDROID_NDK <path> ホスト上の NDK インストールのルート ディレクトリへの絶対パス。
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY <path> CMake がビルド時に LIBRARY ターゲット ファイルを配置するホストの場所。
-DCMAKE_BUILD_TYPE <type> ndk-build ツールのビルドタイプと似ています。有効な値は ReleaseDebug です。デバッグを簡単に行うため、CMake ではビルドの一部としてリリースやデバッグ バージョンをストライピングしません。ただし、Gradle がバイナリを APIK にパッケージ化する場合はこれをストライピングします。
-DCMAKE_MAKE_PROGRAM <program-name> ネイティブのビルドシステムをリリースするツール。Gradle プラグインはこの値を、Android SDK にバンドルされている CMake ninja ジェネレータに設定します。
-DCMAKE_TOOLCHAIN_FILE <path> CMake が Android 向けのクロスコンパイルで使用する android.toolchain.cmake ファイルへのパス。通常、このファイルは $NDK/build/cmake/ ディレクトリにあり、ここでは $NDK はホスト上の NDK インストール ディレクトリです。ツールチェーン ファイルの詳細については、Android 向けのクロス コンパイルをご覧ください。
-DANDROID_NATIVE_API_LEVEL <level> CMake がコンパイルする Android API レベル。
-DANDROID_TOOLCHAIN <type> CMake が使用するコンパイラのツールチェーン。デフォルト値は clang です。

CMake での YASM サポート

NDK は YASM で記述されたアセンブリ コードをビルドし、x86 と x86-64 アーキテクチャで実行するための CMake サポートを提供します。YASM は x86 と x86-64 アーキテクチャに対応するオープンソースのアセンブラであり、NASM アセンブラに基づいています。

これは、アセンブリ コードから C ライブラリまたは関数にアクセスするためにアセンブリ言語プログラムまたはルーチンを C コードとリンクする場合に便利です。また、コンパイル済み C コードに短いアセンブリ ルーチンを含めることで、アセンブリ コードによるマシン パフォーマンスの向上を利用できます。

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

  1. 値を ASM_NASM に設定して、enable_language を呼び出します。
  2. 共有ライブラリと実行可能バイナリのどちらをビルドするかに応じて、add_library または add_executable を呼び出します。引数では、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 コードをご覧ください。

問題の報告

CMake のオープンソース バージョン以外の理由で問題が発生した場合は、GitHub の android-ndk/ndk Issue Tracker から報告してください。