読者です 読者をやめる 読者になる 読者になる

やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

Gradle+AndroidプラグインでNDKプロジェクトをビルドする

Android Gradle Android NDK

Androidの新ビルドシステムであるGradle plugin for Androidの導入と、標準でまだNDKに対応していないので、その対応方法をまとめました。

【2014/6/11追記】Gradle plugin for Android 0.7でNDKがサポートされました。こちらの記事を参照してください Gradle+Androidプラグイン(0.7以降)でNDKプロジェクトをビルドする - やらなイカ?

尚、今回は(新ビルドシステムの売りである)Product Flavorには対応していません。ディレクトリ構成変えなければいけないので、改めて。

環境

  • ADT 22.0.0(任意/build.gradle生成に使用)
  • Android SDK Platform-tools 17(17以上必須)
  • Gradle 1.6(これからインストール)
  • Gradle plugin for Android 0.4(Gradleによってインストール)

GVM(Groovy enVironment Manager)のインストール

$ curl -s get.gvmtool.net | bash

.bash_profileにパスが追加されているので、Terminalを開きなおす

Gradle 1.6 をインストール

$ gvm list gradle
$ gvm install gradle 1.6
(snip)
Done installing!
Do you want gradle 1.6 to be set as default? (Y/n): y

ちなみにデフォルトバージョンの切り替えは、

$ gvm default gradle 1.6

でできます。

build.gradleをつくる

ADT 22に、Gradleのビルドファイル生成機能が付いたので利用します。

  1. Eclipseのメニューから [File] - [Export...] を選択
  2. Android → "Generate Gradle build files" を選択して [Next >]
  3. 対象プロジェクトを選択して [Finish]
  4. プロジェクト直下にbuild.gradleができます

このままGradleでビルドしようとすると、

FAILURE: Build failed with an exception.
(snip)
* What went wrong:
A problem occurred evaluating root project 'GradleAndroidNdkExample'.
> SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable.

と言われるので、今回はlocal.propertiesにSDKのパスを設定しました。 local.propertiesは、android update projectコマンドでも生成されるので、既にAntでビルドしているプロジェクトなら不要なはず。

NDKに対応する

共有ライブラリをapkに取り込む

そのままgradle buildを実行しても、NDKのビルドはおろか、libs/下の共有ライブラリもapkにバンドルされませんので、build.gradleに以下を追加します

tasks.withType(com.android.build.gradle.tasks.PackageApplication) {
    pkgTask -> pkgTask.jniDir new File(projectDir, 'libs')
}

これにより、apkにlibs/下の(ndk-build済みの)共有ライブラリが組み込まれるようになります。

ndk-buildも実行させる

プロダクト・フレーバーごとに共有ライブラリもビルドしなければならない場合、コンパイルごとにndk-buildを実行させるため、build.gradleに以下を追加します。

task ndkBuild(type:Exec) {
    commandLine 'ndk-build'
}
tasks.withType(Compile) {
    compileTask -> compileTask.dependsOn ndkBuild
}

ただ、ndk-buildが失敗しても後続タスクは止まらない気がするのでご利用は計画的に。

Gradleでビルドする

$ cd プロジェクトのパス
$ gradle build

Antの場合、apkはbin/に生成されますが、Gradleではbuild/apk/に生成されました。

サブコマンドbuildは、デフォルトでビルドタイプdebugとrelease両方のビルドを行ないます。まだ署名の設定を書いていないので、releaseはunsigned.apkまで生成されています。

Relaseビルドに署名を追加する

build.gradleに署名の定義を追加します*1

【5/23追記】キーストア情報をbuild.gradleではなく外部ファイル(gradle.properties)に記述できました。 Gradle+Androidプラグインで証明書情報をgradle.propertiesに移す - やらなイカ? を参照。

android {} 内に以下を追加します。

signingConfigs {
    myConfig {
        storeFile file("example.keystore")
        storePassword "example"
        keyAlias "example"
        keyPassword "example"
    }
}

buildTypes {
    release {
        signingConfig signingConfigs.myConfig
    }
}

再びビルド。今回はreleaseビルドのみ実行します。

$ gradle assembleRelease

今度はrelease-unaligned.apk(zipAlign前)と、release.apkが生成されました。

サンプルプロジェクト

https://github.com/nowsprinting/GradleAndroidNdkExample に置きました。

尚、

  • JNIラッパーの生成にはSWIG/Javaを使っています。.iファイルもjni/下に置いてあります。
  • keystoreはリポジトリに含めていません

参考資料

*1:build.gradleに直接書かなければいけないのが非常に気持ち悪いですが!