View on GitHub
mixi-inc/AndroidTraining
Android のビルドについて(Gradle)
この章では Android のビルド、とりわけ、Gradleというビルドシステムを用いたビルドについて解説したいと思いす。

記述内容は Android Studio 2.1.2 , Gradle 2.14 時点のものです。

目次


Gradle とは

Gradle とは、Java(JVM)環境におけるビルドシステムのことで、オープンソースプロジェクトとして無償で公開されています。
特長としては、ビルドの記述を XML のような構造ではなく、Groovy ライクな 独自の DSL を用い、スクリプトとして記述できる点です。
用意されているAPIを利用することで、強力な記述が可能となります。

必要環境

バージョン 1.6 以上の JVM を必要とします。

ビルドの構成要素

ビルドスクリプトを実際に触る前に、簡単にビルドの概念を説明します。

ビルドは1つ以上のプロジェクトで構成され、
そのプロジェクトは1つ以上のタスクで構成されます。
以下の様なケースを想像してもらえるとイメージが湧きやすいかと思います。

『アプリパッケージCを生成するために、A及びBのjarが必要で、
 そのA及びBのjarを作るためのモジュールがあり、
 それらを使って、アプリパッケージCを作るためのビルドを用意する』

A, B , Cそれぞれにモジュールがありそのビルドをビルドスクリプトで記述します。
また、タスクとはこれ以上分割できないような作業の単位を指します。

Gradle に触れてみよう

Hello world! の前に環境構築

練習だけなので、簡単に確認できる環境を用意します。
前章のプロジェクトの作成で、既に Android Studio をインストール済みかと思います。
こちらに、Gradle が同梱されていますので、こちらを利用します。

説明は割愛しますが、別途、Gradle公式サイトよりダウンロードして、実行環境を構築して頂いても問題ありません。

プロジェクト構成

Android Studio でProjectを作ると、以下の様なツリー構造となります。 ビルドスクリプトは build.gradle となります。
2つありますが、build.gradle (Project:MyApplication) の方を使います。

project-tree

改めて、Hello world!

build.gradleを開き、既に記載されているものはそのままにしておき、末尾に以下を追記してください。

task hello {
    doLast {
        println 'Hello world!'
    }
}

実行

編集を終えましたら、Android Studio 同梱の Terminal から以下のコマンドを実行してみてください。
helloというタスクを実行するコマンドとなります。
(Terminal は左下のランチャ or Tools > Open Terminal より起動できます。馴染みのものでも構いません)

# Mac OS X / Linux プラットフォームの場合。Windows の場合は、gradlew.batを使用してください
% ./gradlew -q hello

-q オプションは、Gradle のログメッセージを抑制し、引数で与えたタスクのみ、ログ出力を行います。
 今回は練習なので、解りやすいようにこのオプションを利用しています。
 (他のオプションは http://gradle.monochromeroad.com/docs/userguide/gradle_command_line.html を参照してください)
 
 また、gradlewに実行権限がない場合は、chmod +x gradlewとして、権限を付与して実行してみてください。

Hello world!

と出力されたでしょうか。

project-tree

また、ショートカットを用いて、以下の様に記述することも可能です。

task hello << {
    println 'Hello world!'
}

記法

記法の全てをここでは伝えませんが、基本的なものを紹介します。

基本型

task hoge << {
    String fuga = 'fuga'
    int count = 9
    println 'hoge' + fuga + 'piyo'
	println count.toString()
}
% ./gradlew -q hoge
hogefugapiyo
9

繰り返し

task count << {
    3.times {
        println it
    }
}
% ./gradlew -q count
0
1
2

依存関係の記述

task unlockDoor << {
    println "I unlock the door"
}
task enterMyRoom(dependsOn: unlockDoor) << {
    println "I'm home"
}
task relax(dependsOn: enterMyRoom) << {
    println "Relax..."
}
% ./gradlew -q relax
I unlock the door
I'm home
Relax...

% ./gradlew -q enterMyRoom
I unlock the door
I'm home

依存関係のあるタスクが先に実行されていることがわかるかと思います。

それでは、順番を並び替えた以下を実行してください。

task enterMyRoom(dependsOn: unlockDoor) << {
    println "I'm home"
}
task unlockDoor << {
    println "I unlock the door"
}
% ./gradlew -q enterMyRoom
-> ERROR!

エラーが起こって正常に実行できないようになったかと思います。 これは、未定義な unlockDoor を呼びだそうとする事により、起こるエラーです。

以下の様に、呼び出しを文字列にしてあげるだけで、遅延評価されるようになり、問題は起こらなくなります。

task enterMyRoom(dependsOn: 'unlockDoor') << {
    println "I'm home"
}
task unlockDoor << {
    println "I unlock the door"
}
% ./gradlew -q enterMyRoom
I unlock the door
I'm home

また、task定義とは別に依存関係を記述することも可能です。

task unlockDoor << {
    println "I unlock the door"
}
task enterMyRoom << {
    println "I'm home"
}
task relax << {
    println "Relax..."
}

unlockDoor.dependsOn enterMyRoom
relax.dependsOn unlockDoor, enterMyRoom

taskの前後に処理を差し込む

task sample << {
	println 'hoge'
}
sample.doFirst {
	println 'hello!'
}
sample.doLast {
	println 'fuga'
}
sample << {
	println 'piyo'
}
%  ./gradlew -q sample
hello! 
hoge
fuga
piyo

doFirst, doLast<<) を用いることで、タスクの前後に処理を追加することが可能です。
複数の処理を同じ箇所に追加した場合は、定義された順番に実行されます。
また、定義済み task は、上記の様にドットアクセスでタスクを記述できます。

gradlew

上でgradlew(あるいはgradlew.bat)を用いてサンプルコードを実行していましたが、gradlewとはGradleラッパーといい、Gradleのビルド実行において推奨されている方法です。
gradlewの実体はシェルスクリプトです。
指定のバージョンのGradleをダウンロードし、それを用いてビルドを実行を行います。
なので、gradleではなく、gradlewを使うようにしておけば、環境に依存することがありません。

上記の観点より、gradlewをリポジトリに含めるようにしておいてください。
そうすることで、CIや公開リポジトリなりで配布した際にもバージョン依存で悩む必要がなくなるはずです。

なお、gradlewには実行権限が必要なので、無ければ設定してください。

Android Studio における Gradle

Android Studio のパッケージには Gradle が同梱しておりますので、 インストールしてすぐ利用することが可能です。

ビルドスクリプト

例えば新規にMyApplicationという名前のプロジェクトを作成すると、以下の2つの build.gradle が生成されます。

  • build.gradle (Project: MyApplication) => Project直下の build.gradle
  • build.gradle (Module: app) => app内の build.gradle

それぞれについて簡単に説明したいと思います。

Project直下のbuild.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

buildscript / allprojectsrepositories は、外部からインポートする jar のリポジトリを指定します。
デフォルトで jcenter() が指定されています。
これで事が足りるとは思いますが、明示的に他のリポジトリも参照したい場合は以下のように記載します。

buildscript {
    repositories {
        jcenter()
        maven {
        	url "{TARGET_REPOSITORY_URL}"
        }
    }
    ...

dependenciesは依存関係を記述します。
外部のライブラリを読み込みたい場合はここに記述します。
すると、自動的にプロジェクトのExternal Librariesに読み込まれます。

デフォルトの様にmavenCentral() にあるものであれば、パスのみで記述できます。
また、リポジトリが無い jar を読み込みたい場合は、以下の様にします。
lib 以下の jar ファイルを読み込む設定です。

    dependencies {
        compile fileTree(dir:'libs', include: '*.jar')
    }

app内のbuild.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
}

apply plugin: 'com.android.application'はAndroidのPluginを使う上での宣言です。

androidはビルドの情報を記載します。
defaultConfigはデフォルトの設定を記載し、
buildTypesはビルド毎の設定を記載します。

Android Studio の Project Structure との関係

settings.gradleというファイルを確認します。

include ':app'

と書かれているものがProject Structure > Project Settings > Modulesに表示されます。
上記の例だと、appモジュールの設定が表示されます。

しかしながら、一部表示されないものがあったり、メリットは少ないので、build.gradleを編集することをおすすめします。

More infomation

Gradleの触りの部分を紹介しましたが、より理解を深めたい方は以下サイトを参照ください。