Edited at

Android NDK で ccache を有効にする


はじめに

NDK のビルド時 ccache を導入してビルド時間を短縮しましょう。

ccache は簡単に説明すると、コンパイル時に生成されるオブジェクトをキャッシュ化するソフトウェアです。詳しい説明は本家と wikipedia を参照してください。


設定


ccache のインストール


Ubuntu


% sudo apt-get install ccache


MacOS(homebrew)


% brew install ccache


ccache のキャッシサイズの最大値の指定

サイズは大きいほうが良いのでキャッシュ総容量を 20GB に指定します。

% ccache -M 20G


環境変数設定

お使いのシェルのドットファイル( ~/.bashrc or ~/.zshrc )に環境変数を設定してください。

# ccache

export USE_CCACHE=1
export NDK_CCACHE=/usr/local/bin/ccache # Ubuntu なら /usr/bin/ccache
export CCACHE_CPP2=yes
export
CCACHE_COMPILERCHECK=content

設定を反映します。

% source ~/.bashrc (or ~/.zshrc)


手順

環境変数 USE_CCACHENDK_CCACHE が設定されていると、ndk-build が ccache を利用するようになります。

いつも通り ndk-build コマンドを実行するとキャッシュされます。


% cd /path/to/android_project/jni
% ndk-build


無効化

USE_CCACHENDK_CCACHE を unset すると ccache を無効化出来ます。

% unset USE_CCACHE

% unset NDK_CCACHE
% ndk-build

再度有効化するには source コマンドでドットファイルを再読込するか、USE_CCACHE, NDK_CCACHE 環境変数を再設定してください。


キャッシュのクリア

ビルドが失敗するようになったり、キャッシュのヒット率がわるくなったら ccache のキャッシュをクリアしてください。

ccache -cC


Android NDK CMake での ccache の有効方法

ここ数年でビルドシステムが ant から gradle へ、 IDE が Eclipse から Android Studio へ、そして NDK ビルドも ndk-build から CMake へ移行しました。

CMake ビルドでは NDK_CCACHE の環境変数設定だけでは ccache が有効になりません。

試行錯誤の上、NDK CMake ビルドでの ccache を有効にできたので、設定方法について記載します。

(もっと効率の良い設定方法があればご教示くださいませ :bow: )


CMake

NDK の CMakeList.txt へ ccache の設定を入れ込みます。


CMakeLists.txt


option(ENABLE_CCACHE "Enable ccache?" OFF)

# ccache
if (NOT $ENV{NDK_CCACHE} EQUAL "")
set(CCACHE_EXE $ENV{NDK_CCACHE})
if(ENABLE_CCACHE)
if(CMAKE_C_COMPILER_LAUNCHER)
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_C_COMPILER_LAUNCHER}" "${CCACHE_EXE}")
else()
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXE}")
endif()
if(CMAKE_CXX_COMPILER_LAUNCHER)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_CXX_COMPILER_LAUNCHER}" "${CCACHE_EXE}")
else()
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXE}")
endif()
endif()
endif()


NDK_CCACHE 環境変数の定義があれば CMAKE_C_COMPILER_LAUNCHERCMAKE_CXX_COMPILER_LAUNCHERNDK_CCACHE の値(ccache のフルパス)を設定します。

( ndk-build と ccache の設定を共存するために行っています。ふつーであれば find_program(CCACHE_EXE ccache) で ccache コマンドが存在する場合に設定したほうがより汎用的です)

NDK_CCACHE 環境変数宣言に影響せずに ccache の有効無効を切り替えられるように ENABLE_CCACHE オプションを追加します。


app/build.gradle


app/build.gradle

def ndkCcache = System.getenv("NDK_CCACHE")

if (ndkCcache == null) {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
ndkCcache = properties.getProperty('ccache.path')
environment("NDK_CCACHE", ndkCcache)
}

android {
...
buildTypes {
release {
...
}

debug {
...
externalNativeBuild {
cmake {
arguments '-DENABLE_CCACHE=ON'
}
}
}
}
}


最初の処理は NDK_CCACHE 環境変数が未定義の場合に local.propertiesccache.path の値を取得し、 NDK_CCACHE 環境変数を定義する処理です。(Android Studio で gradle を実行すると ~/.bashrc や ~/.zshrc の環境変数を取得できないようなのでこのような処理を入れています。)

local.properties のサンプルは下記のとおりです。


local.properties

...

ccache.path=/usr/local/bin/ccache

Debug ビルドのときのみ ccache が有効になるように android.buildTypes.debug.externalNativeBuild.cmake.arguments-DENABLE_CCACHE=ON を設定しています。 Release ビルドでも ccache を有効にする場合は android.buildTypes.release.externalNativeBuild.cmake.arguments-DENABLE_CCACHE=ON を設定してくださいね。


build

さて、これで設定が完了しました。早速ビルドし ccache が有効になっているか確認してください。

./gradlew clean assembleDebug

./gradlew clean assembleDebug # キャッシュ有効かの確認
ccache -s

二回目の ./gradlew が速かったり、 ccache -s でキャッシュが hit した統計が取れてれば ccache 有効になっています。

おめでとうございます。 :tada: