CMake

※NDKのドキュメントの[CMake](https://developer.android.com/ndk/guides/cmake.html)のページだけなかなか日本語化されないので、個人的メモ代わりに日本語化してみました。

# CMake

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

Android StudioでCMakeを使うのが初めてなら、[プロジェクトへのC/C++コードの追加](https://developer.android.com/studio/projects/add-native-code.html)を読んでプロジェクトにネイティブコードを追加する方法について学んでください。このページでは、CMakeビルドをカスタマイズするためのいくつかの追加の情報を提供します。

## GradleでCMake変数を使う

[ネイティブライブラリへのGradleのリンク](https://developer.android.com/studio/projects/add-native-code.html#link-gradle)をしたら、ネイティブライブラリのビルド方法を変更するNDK固有の変数を設定することができます。モジュールレベルの`build.gradle`からCMakeに引数を渡すためには、次のようにします。:

```groovy
android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake build script.
    externalNativeBuild {
      cmake {
        ...
        // 次のようにして変数を設定します:
        // arguments "-D変数名=値".
        arguments "-DANDROID_ARM_NEON=TRUE",
        // 複数の変数を設定するなら、一緒に渡してください:
        // arguments "-D変数名=値1 値2"
        // 次の行は 'rtti' と 'exceptions' を 'ANDROID_CPP_FEATURES' に渡します。
                  "-DANDROID_CPP_FEATURES=rtti exceptions"
      }
    }
  }
  buildTypes {...}

  // このブロックで Gradle を CMake ビルドスクリプトにリンクします。
  externalNativeBuild {
    cmake {...}
  }
}
```

次のテーブルはNDKとCMakeで設定可能ないくつかの変数を説明します。

変数名 | 引数 | 説明
--- | --- | ---
ANDROID_TOOLCHAIN | * clang (デフォルト)<br>* gcc (非推奨) | CMakeが使用するコンパイラーツールチェインを指定します。
ANDROID_PLATFORM | プラットフォーム名と対応するAndroidシステムイメージの完全なリストは、[Android NDK ネイティブ API](https://developer.android.com/ndk/guides/stable_apis.html)を見てください。 | ターゲットAndroidプラットフォーム名を指定します。例えば、`android-18`はAndroid 4.3 (API level 18)を指定します。<br>このフラグを直接変更する代わりに、`minSdkVersion`プロパティをモジュールレベルの`build.gradle`ファイルの`defaultConfig`もしくは`productFlavors`ブロックに指定するべきです。これはライブラリが十分なバージョンのAndroidが動作している端末にインストールされているアプリだけで使われることを確実にします。CMakeツールチェインは次のロジックでABIの最適なプラットフォームバージョンを選択します:<br><ol><li>もし`minSdkVersion`と同じABIバージョンがあれば、それを使います。</li><li>そうでなければ、`minSdkVersion`より小さいプラットフォームバージョンがある場合、その中で最も高いプラットフォームバージョンを使います。これはプラットフォームバージョンが無いということはその前のバージョンからネイティブプラットフォームAPIに何の変更もないということなので、合理的な選択です。</li><li>そうでなければ、`minSdkVersion`より大きな、次に利用可能なバージョンを使います。</li></ol>
ANDROID_STL | 完全なリストは[ヘルパーランタイム](https://developer.android.com/ndk/guides/cpp-support.html#hr)を見てください。デフォルトでは、`gnustl_static`を使います。 | STLを指定します。
ANDROID_PIE | <ul><li>ON (ANDROID_PLATFORM = android-16以上の場合のデフォルト)</li><li>OFF (ANDROID_PLATFORM = android-15以下の場合のデフォルト)</li></ul> | position-independent executables (PIE)を使うかどうかを指定します。AndroidのダイナミックリンカーはAndroid4.1以上でPIEをサポートします。
ANDROID_CPP_FEATURES | デフォルトでは空ですが、次のようないくつかの引数を渡すことができます:<ul><li>rtti (RTTIを使うかどうか)</li><li>exceptions (C++例外を使うかどうか)</li></ul> | ネイティブライブラリをコンパイルする時に使う必要があるC++機能を指定します。例えばRTTI (RunTime Type Information) や C++ 例外等です。
ANDROID_ALLOW_UNDEFINED_SYMBOLS | <ul><li>TRUE</li><li>FALSE (デフォルト)</li></ul> | CMakeが未定義の参照に遭遇した時に未定義のシンボルエラーを投げるかどうかを指定します。この種類のエラーを無効にするためには、`TRUE`を指定してください。
ANDROID_ARM_MODE | <ul><li>arm</li><li>thumb (デフォルト)</li></ul> | ARMターゲットバイナリを`arm`か`thumb`どちらのモードで生成するかを指定します。thumbモードでは、全ての命令は16ビット幅で、thumb/ディレクトリ以下のSTLライブラリとリンクされます。armを指定するとCMakeはライブラリのオブジェクトファイルを32ビットarmモードで生成します。
ANDROID_ARM_NEON | <ul><li>TRUE</li><li>FALSE (デフォルト)</li></ul> | NEONサポートを使ってネイティブライブラリをビルドするかどうかを指定します。
ANDROID_DISABLE_NO_EXECUTE | <ul><li>TRUE</li><li>FALSE (デフォルト)</li></ul> | [NXビット](https://ja.wikipedia.org/wiki/NXビット)を使うかどうかを指定します。この機能を無効にするには、`TRUE`を指定してください。
ANDROID_DISABLE_RELRO | <ul><li>TRUE</li><li>FALSE (デフォルト)</li></ul> | 読み取り専用の再配置を有効にするかどうかを指定します。ANDROID_DISABLE_FORMAT_STRING_CHECKS | <ul><li>TRUE</li><li>FALSE (デフォルト)</li></ul> | フォーマット文字列保護を有効にするかどうかを指定します。有効になっていると、コンパイラーは非定数のフォーマット文字列がprintfスタイルの関数で使用された時にエラーを投げます。

## CMakeビルドコマンドを理解する

CMakeのビルド問題をデバッグするとき、AndroidのためのクロスコンパイルをするときにAndroid Studioが使っているビルド引数を知ることが役に立ちます。

Android StudioはCMakeビルドを実行するのに使用したビルド引数を`cmake_build_command.txt`ファイルに保存します。アプリがターゲットにするそれぞれのApplication Binary Interface (ABI)と、それぞれのビルドタイプ(release や debug)ごとに、Android Studioは`cmake_build_command.txt`ファイルのコピーを生成します。Android Studioは次のディレクトリにファイルを生成します:

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

Tip: 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ビルド引数を挙げています。これらのビルド引数は開発者が設定するものではありません。代わりにAndroid Plugin for Gradleは、プロジェクトのbuild.gradle設定に基づいてこれらの引数を設定します。

ビルド引数 | 説明
--- | ---
-G <ビルドシステム> | CMakeが生成するビルドファイルの種類。<br><br>ネイティブコードを含むAndroid Studioプロジェクトでは、<ビルドシステム>はAndroid Gradle - Ninjaに設定されます。この設定はCMakeがninjaビルドシステムをC/C++ソースのコンパイルとリンクに使用することを示します。CMakeはコンパイラフラグやターゲット名等のGradleプラグインのためのメタデータを含む`android_gradle_build.json`ファイルも生成します。ninjaビルドシステムはAndroid Studioがサポートする唯一のジェネレーターです。
-DANDROID_ABI <abi> | ターゲットABI。<br><br>NDKは、[ABI管理](https://developer.android.com/ndk/guides/abis.html#sa)で説明されているように、一連のABIをサポートしています。このオプションはndk-buildツールが使用する`APP_ABI`変数と似ています。<br><br>デフォルトでは、GradleはネイティブライブラリをABIごとの個別の.soファイルにビルドして、それら全てをAPKにパッケージします。特定のABI設定のビルドのみを行いたい場合は、[ABIの指定](https://developer.android.com/studio/projects/add-native-code.html#specify-abi)を見てください。<br><br>ターゲットABIが指定されていなければ、CMakeはデフォルトでarmeabi-v7aを使います。<br><br>有効なターゲット名は:<ul><li>armeabi: ARMv5TE based CPU with software floating point operations.</li><li>armeabi-v7a: ARMv7 based devices with hardware FPU instructions (VFPv3_D16).</li><li>armeabi-v7a with NEON: Same as armeabi-v7a, but enables NEON floating point instructions. This is equivalent to setting -DANDROID_ABI=armeabi-v7a and -DANDROID_ARM_NEON=ON.</li><li>arm64-v8a: ARMv8 AArch64 instruction set.</li><li>mips: MIPS32 instruction set (r1).</li><li>mips64 - MIPS64 instruction set (r6).</li><li>x86: IA-32 instruction set.</li><li>x86_64 - Instruction set for the x86-64 architecture.</li></ul>
-DANDROID_NDK <パス> | NDKがインストールされているディレクトリへの絶対パス。
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY <パス> | CMakeがビルドしたライブラリを配置するディレクトリ。
-DCMAKE_BUILD_TYPE <種類> | ndk-buildツールのビルドタイプと似ています。有効な値はReleaseとDebugです。デバッグを簡単にするため、CMakeはリリース・デバッグバージョンをビルドの中で除去しませんが、GradleはAPKにパッケージする時にバイナリを除去します。
-DCMAKE_MAKE_PROGRAM <プログラム名> | ネイティブビルドシステムを起動するツール。Gradleプラグインはこの値をAndroid SDKにバンドルされたCMake ninjaジェネレーターに設定します。
-DCMAKE_TOOLCHAIN_FILE <パス> | CMakeがAndroidへのクロスコンパイルで使用する`android.toolchain.cmake`ファイルへのパス。通常、このファイルは$NDK/build/cmake/ディレクトリにあります。$NDKはNDKがインストールされているディレクトリです。詳細は、[Cross Compiling for Android](https://cmake.org/cmake/help/v3.7/manual/cmake-toolchains.7.html#cross-compiling-for-android)を見てください。
-DANDROID_NATIVE_API_LEVEL <レベル> | CMakeがコンパイルするAndroid APIレベル。
-DANDROID_TOOLCHAIN <種類> | CMakeが使用するコンパイラツールチェイン。デフォルトは`clang`。

(以下はあまり興味なさそうだったので省略しました)