LoginSignup
4
4

More than 5 years have passed since last update.

Circle CIで Android アプリを parallel buildして OOMと戦う

Posted at

CircleCIで Androidアプリも楽ちんにビルドできるのはいいのだけど、調子に乗って Flavorを増やしていったりすると OOMで殺されがちです。ヒープとかを頑張ってチューンするのにつかれた自分は金にモノを言わせて 3つのコンテナを使って並列ビルドするようにしました。

CircleCIではコンテナごとに 4GiBつかえる!

つまりコンテナを増やして仕事を分割すれば OOMを気にすることなく高速にビルドができるのです。実際はすべてのコンテナでしなきゃいけない仕事があったりするので単純にスケールするものでもないのでしょうが、それでも自分の環境では十分効果が上がりました。

やったこと

仕事でやったことなので repositoryを公開はできませんが概略を書きます:

containerごとに buildを分割

testステージ用の buildスクリプトをつくり、そこで $CIRCLE_NODE_INDEXにしたがって処理を振り分けるコードを書きました。以下の様な感じです:

case $CIRCLE_NODE_INDEX in
    0)
        TERM=dumb ./gradlew assembleFoo testFoo{Debug,Release}UnitTest  -PdisablePreDex
        find app/build/test-results/* -type f -name '*.xml' -exec cp {} $CIRCLE_TEST_REPORTS \;
        ;;
    1)
        TERM=dumb ./gradlew assembleBar testBar{Debug,Release}UnitTest -PdisablePreDex
        find app/build/test-results/* -type f -name '*.xml' -exec cp {} $CIRCLE_TEST_REPORTS \;
        ;;
    2)
        # Instrumentation test

        echo no | android create avd --name emu --target android-15 --abi armeabi-v7a
        nohup bash -c "emulator @emu -no-window &"
        nohup bash -c "adb logcat > app/build/outputs/logcat.txt &"

        TERM=dumb ./gradlew connectedFooDebugAndroidTest -PdisablePreDex

        find app/build/outputs/androidTest-results/connected -type f -name '*.xml' -exec cp {} $CIRCLE_TEST_REPORTS \;
        ;;
esac

コンテナ #0と #1は、それぞれの flavorの APKをつくり Unit testを通します。
コンテナ #2では、Foo flavorでだけで instrumentation testを走らせます。
もう一つコンテナを増やして Bar flavorでも instrumentation test走らせられますが、それはケチってます。

あ、あと上の buildでは wait_for_emulator 的な処理を gradleの中でやっています。並列ビルドにしたからといってその待ちが必要なくなるわけではないのでご注意を。

なぜか最新の data binding libraryが入ってなかったので取得

あと、なぜか並列ビルドすると data binding libraryが見つからず buildが failしました。CircleCIのサポートに聞いてみたのですが、まだちゃんと返事をもらってません。並列用だとイメージが違ったりするのでしょうか?

そこで dependenciesステージで強引にもってくる workaroundを入れました:

circle.yml
dependencies:
  override:
    - ./script/load-dependencies.sh
load-dependencies.sh
#!/bin/bash -e

echo install extra-android-m2repository
echo y | android update sdk --no-ui --all --filter 'extra-android-m2repository'

こんな感じで強引に持ってきてますが、1分ぐらい余計に時間がかかります。何もしなくてもいいようにしたいものです。

まとめ

以上のような変更でビルドを走らせることにより out of memoryを回避できています。おまけに、ビルド時間も短くなりました。22分ぐらいが 14分ぐらいに。1/3になってないのは、すべてのコンテナでやる仕事がばかにならないからですね。

しかし、data binding libraryが見つからないとか、Androidで並列ビルドしてる人が少ないせいで地雷を踏んでしまったのでしょうか。みなさんも試してみていっしょに地雷を踏んでもらうことを期待します。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4