matsukaz's blog

Agile, node.js, ruby, AWS, cocos2d-xなどなどいろいろやってます

cocos2d-x(Android NDK)ビルドを高速化する方法とオススメ設定

こんにちは!対戦型脳トレアプリ BrainWars のエンジニア、matsukazです!
一緒にcocos2d-xとかrailsとかAWSとかスタンディングしてくれる仲間を絶賛募集中!!と、ちょっとPRしてみる。


BrainWarsはcocos2d-xで開発してるんですが、ccache を導入することでAndroid NDKビルドにかかる時間を劇的に改善できました。
今までビルドに30分近くかかってたのが3分程度まで短縮!すばらしー!ヽ(=´▽`=)ノ

動作確認したNDKのバージョンは、この記事を書いてる時点で最新のr10dです。
cocos2d-xの話で書いてますが、cocos2d-xに限らず高速化できるかと。

というわけでccacheの説明と導入方法、注意点などご紹介します。

ccacheってなに?

C、C++Objective-CObjective-C++に対応したコンパイラーキャッシュです。
前回コンパイルした結果をキャッシュしておいて、次にコンパイルする際にファイルに変更がなければキャッシュを利用するというもの。
なので高速化できるのは2回目のコンパイルからです。

ccache is a compiler cache. It speeds up recompilation by caching previous compilations and detecting when the same compilation is being done again. Supported languages are C, C++, Objective-C and Objective-C++.

ccache — Overview

インストール方法

3.2系以降を使った方が良いです。
それ以前だと一部オプションが存在しなかったりします。

Homebrewでインストール(簡単でオススメ)
brew install --HEAD ccache

automakeがないと言われた場合は以下でインストールします。

brew install automake
ソースからインストール

Homebrewのスクリプト で指定しているファイルを利用します。

curl -L https://www.samba.org/ftp/ccache/ccache-3.2.1.tar.bz2 | tar zx
cd ccache-3.2.1

./configure
make
make install

# /usr/bin/にないとndk-buildが動かない
sudo ln -s /usr/local/bin/ccache /usr/bin/ccache
ソースからインストール(GitHub

GitHub上の jrosdahl/ccache · GitHub からv3.2以降のバージョンをインストールしようとすると、
#45963 (ccache-devel: Update to ccache 3.2) – MacPorts の問題に引っかかってmakeが途中でコケます。
developmentモードでビルドしようとして、-Werror指定があるためにwarningがerrorとして処理されてしまうようです。

どうしてもGitHub上のソースからインストールしたい場合は、以下の手順でdevelopmentモードを無効にしてからインストールします。

git clone https://github.com/jrosdahl/ccache.git
cd ccache

touch dev_mode_disabled
autoheader
autoconf

./configure
make
make install

# /usr/bin/にないとndk-buildが動かない
sudo ln -s /usr/local/bin/ccache /usr/bin/ccache
パッケージインストール

パッケージインストールを利用した場合、ccacheのバージョンが古い可能性があります。
Amazon Linux 2014.09だとyumで入れた場合はEL6のリポジトリが使われていて、ccacheは3.1.6という古いバージョンでした。ご注意を。

キャッシュの有効化

以下の設定をするだけで、Android NDKビルド時にキャッシュが有効化されます。

export NDK_CCACHE=/usr/local/bin/ccache

.bash_profileとか/etc/profile.dとかに設定すると良いかと。
(cocos2d-xの
How to use CCache to speed up cocos2d-x android compilation | Cocos2d-x というページでは、USE_CCACHEの設定とかdefault-build-commands.mkファイルの編集とか書いてあるけど、最新バージョンのccacheとNDKであれば不要です)

動作確認

$ ccache -s

cache directory                     /Users/matsukaz/.ccache
primary config                      /Users/matsukaz/.ccache/ccache.conf
secondary config      (readonly)    /usr/local/Cellar/ccache/HEAD/etc/ccache.conf
cache hit (direct)                     0
cache hit (preprocessed)               0
cache miss                             0
files in cache                         0
cache size                           0.0 kB
max cache size                       5.0 GB

この状態でcocos2d-xのプロジェクトをビルドすると、

$ ccache -s

cache directory                     /Users/matsukaz/.ccache
primary config                      /Users/matsukaz/.ccache/ccache.conf
secondary config      (readonly)    /usr/local/Cellar/ccache/HEAD/etc/ccache.conf
cache hit (direct)                     0
cache hit (preprocessed)               0
cache miss                           633
files in cache                      2066
cache size                         345.1 MB
max cache size                       3.0 GB

files in cacheの項目が0から633になりました。ファイルがキャッシュされています。
コンパイル後のファイルを削除してから再びビルドすると、

$ ccache -s

cache directory                     /Users/matsukaz/.ccache
primary config                      /Users/matsukaz/.ccache/ccache.conf
secondary config      (readonly)    /usr/local/Cellar/ccache/HEAD/etc/ccache.conf
cache hit (direct)                   633
cache hit (preprocessed)               0
cache miss                           633
files in cache                      2066
cache size                         345.1 MB
max cache size                       3.0 GB

cache hitの項目が0から633に!全てのファイルがキャッシュヒットしたようです。
ビルド時間も30分弱から2分程度まで高速化しました(C++コンパイルはほんの数秒で、ほとんどはjavaコンパイルやjarの作成時間)。すばらしー!ヽ(=´▽`=)ノ

おすすめの設定

-pオプションで現在の設定を確認できます。

$ ccache -p
(default) base_dir =
(default) cache_dir = /Users/matsukaz/.ccache
(default) cache_dir_levels = 2
(default) compiler =
(default) compiler_check = mtime
(default) compression = false
(default) compression_level = 6
(default) cpp_extension =
(default) direct_mode = true
(default) disable = false
(default) extra_files_to_hash =
(default) hard_link = false
(default) hash_dir = false
(default) log_file =
(default) max_files = 0
(default) max_size = 5.0G
(default) path =
(default) prefix_command =
(default) read_only = false
(default) read_only_direct = false
(default) recache = false
(default) run_second_cpp = false
(default) sloppiness =
(default) stats = true
(default) temporary_dir =
(default) umask =
(default) unify = false

設定値は以下の順に読み込まれます。

  • 環境変数
  • $HOME/.ccache/ccache.conf
  • <sysconfdir>/ccache.conf (/etc/ccache.conf や /usr/local/etc/ccache.conf)

上記で設定していない項目は、全てデフォルト値が利用されます。
なお設定ファイルは直接編集しても良いですし、ccache -oで指定することもできます。
ここではccache -oを利用した手順で説明します。

compiler_check (CCACHE_COMPILERCHECK)

ファイルの更新チェック方法を指定します。

デフォルト値はmtimeで、ファイルの更新日時で判断しています。
そのため、gitなどでブランチを切り替えたりするとファイルの更新日時が変わってしまい、キャッシュがうまく効かないことがあります。

おすすめの設定値はcontentです。
ファイルの内容を元に更新チェックが行われますので、gitのブランチ切り替え時なども正しくキャッシュが効くようになります。

# 環境変数で指定する場合
export CCACHE_COMPILERCHECK=content

# 設定ファイルで指定する場合
ccache -o compiler_check=content

max_size (CCACHE_MAXSIZE)

キャッシュの保持上限サイズです。デフォルトは5GBのようです(環境によって違うかも)。
ビルド環境に合わせて随時調整してください(ローカル環境では3GB、ビルドサーバは10GBにするとか)。

# 環境変数で指定する場合
export CCACHE_MAXSIZE=3G

# 設定ファイルで指定する場合
ccache -o max_size=3G

base_dir (CCACHE_BASEDIR)

ccacheは絶対パスでキャッシュ対象を制御しています。
そのため、同じ内容でもディレクトリが異なるとキャッシュがうまく効かないケースがあります。

例えば

/usr/src
├── app
│   └── コンパイル対象
└── app2
    └── appと同じ内容

上記のようにappとapp2で同じ内容を含んでいる場合でも、絶対パスが異なるためccacheのキャッシュは共有されません。
base_dirは相対パスでキャッシュ対象を制御可能にする設定で、こうしたケースで有効です。

cd /usr/src/app
export CCACHE_BASEDIR=/usr/src/app

# appをビルド
...

cd /usr/src/app2
export CCACHE_BASEDIR=/usr/src/app2

# app2をビルド
...

こんな感じでbase_dirを指定してからビルドすると、指定したディレクトリからみた相対パスでキャッシュ対象を制御してくれるため、appとapp2でキャッシュが共有されるようになります。
ビルドするたびに設定するのは面倒なので、あらかじめビルドスクリプトを用意したりすると良いかと。

まとめ

ccacheをインストールして有効化するだけでビルドが高速化するので、とってもオススメです!
ぜひ使ってみてくださいー。

Objective-Cでもいけるらしいんですが、いまんとこまだやってないです。
やり方分かる方いたら教えて下さいませm(_ _)m

(cocos2d-xの
How to use CCache to speed up cocos2d-x android compilation | Cocos2d-x でやり方書いてあるんですが、逆に遅くなったかもって言ってるので正しくできてなさそうw)


2015/02/04 18:50追記

Eclipseでビルドする場合はユーザの環境変数が利用されないようなので、以下の設定をする必要がありました。

f:id:matsukaz:20150204210121p:plain

CCACHE_BASEDIR=${build_project} 
NDK_CCACHE=/usr/local/bin/ccache 
NDK_ROOT=NDKインストール先

2015/02/05 11:50追記

EclipseでCCACHE_BASEDIRを設定してもうまくbase_dirが効いてないようです・・・なぜ。
また何かわかったら追記します。

2015/02/22 01:15追記

EclipseのCCACHE_BASEDIRは一応効いてました!
ただ${build_project} みたいな指定だとダメだったので、絶対パスでプロジェクトのディレクトリを指定するのが良いかと思います。

CCACHE_BASEDIR=プロジェクトのディレクトリ
NDK_CCACHE=/usr/local/bin/ccache 
NDK_ROOT=NDKインストール先

という感じで。





3億円 (1/6スケール ジョークトイ)

3億円 (1/6スケール ジョークトイ)