Gradle芸人業を毎日やってるけど、まだまだ全然Gradleのことわかってないなと思う日々なので、ここは基本に帰って、1つずつドキュメントのメソッド、プロパティをためしていくことにします。
第一回はproject.gradle
編
gradle
プロパティ
初回からマニアックなテーマです。
普通にビルドスクリプトを書く分にはほとんど使うことのないプロパティです。
ただし、これを抑えることで、タスク実行のライフサイクルなどの理解がはかどります。
Gradleのライフサイクル
『Gradle徹底入門』からの引用ですが、Gradleのタスク実行には、次の3つのフェーズがあります。
- 初期化フェーズ
- 設定フェーズ
- 実行フェーズ
初期化フェーズ
ここでは設定の読み込み、プロジェクト構造の解釈を行います。
設定フェーズ
ここではタスクの依存関係の解析、タスクの実行内容の解析などを行います。
実行フェーズ
ここではタスクを実際に実行していきます。
hooks
project.gradle
プロパティのDSLはこちらにあります。
Gradle - Gradle DSL Version 2.6
これを読み解いていくと、各フェーズのHookを次のメソッドで付与することができます。
初期化フェーズ
フェーズ開始前
settingsEvaludated
- 引数 -
Settings
-document - 設定をロードして、ビルドの準備のための準備ができた状態
- 記述可能なビルドファイル -
settings.gradle
- 引数 -
フェーズ終了
projectLoaded
- 引数 -
gradle
- 設定からプロジェクトが構築された状態であり、まだプロジェクトの評価は完了していない
- 記述可能なビルドファイル -
settings.gradle
- 引数 -
設定フェーズ
フェーズ開始前
beforeProject
- 引数 -
project
- プロジェクトの評価開始前
- 記述可能なビルドファイル -
settings.gradle
,build.gradle
(build.gradle
に記述した場合は、ルートプロジェクトに対しては呼び出されない)
- 引数 -
フェーズ終了後
afterProject
- 引数1 -
project
- 引数2 -
failure
- もし評価が失敗した場合 - プロジェクトの評価が完了した後
- 記述可能なビルドファイル -
settings.gradle
,build.gradle
- 引数1 -
なお、beforeProject
とafterProject
はrootProject
-> subProject
の順番で行われる
実行フェーズ
フェーズ開始前
projectsEvaluated
- 引数 -
gradle
- すべてのプロジェクトオブジェクトの評価が完了し、プロジェクトが全て設定された状態で、タスクグラフが利用可能な状態
- 記述可能なビルドファイル -
settings.gradle
,build.gradle
- 引数 -
フェーズ終了後
buildFinished
- 引数1 -
BuildResult
- document - すべてのタスクの実行が終了した場合
- 記述可能なビルドファイル -
settings.gradle
,build.gradle
- 引数1 -
サンプル
ディレクトリー構造
とりあえず、次のようなディレクトリー構造を作ります。
project-root +- src | +- main | | +- java | +- test | +- java +- build.gradle +- gradle.properties +- settings.gradle +- sub | +- src | +- main | | +- java | +- test | +- java +- dub +- src +- main | +- java +- test +- java
スクリプト
settings.gradle
は次のような感じにします。
// 初期化フェーズ終了後 gradle.projectsLoaded {grdl -> def prj = grdl.rootProject logger.lifecycle "====projects loaded(${prj.name})====" logger.lifecycle " after projects created from settings" logger.lifecycle " evaluated[${prj.state.executed}]" } // 初期化フェーズ開始前 gradle.settingsEvaluated {sts -> def prj = sts.rootProject logger.lifecycle "====settings evaluated(${prj.name})====" logger.lifecycle " settingsDir[${sts.settingsDir}]" logger.lifecycle " applied plugins[${sts.plugins.size()}]" logger.lifecycle " **tasks**" logger.lifecycle sts.startParameter.taskNames.join(' -> ') logger.lifecycle " **task-requests**" logger.lifecycle sts.startParameter.taskRequests.collect{"<${it.args.join('|')}>"}.join('-') } // プロジェクト評価前(設定フェーズ前) gradle.beforeProject {prj -> logger.lifecycle "====before project(${prj.name})====" logger.lifecycle " before project evaluation" logger.lifecycle " evaluated[${prj.state.executed}]" } include 'sub', 'dub' rootProject.name = 'project-root'
build.gradle
には通常のビルドスクリプトに加え、次のスクリプトを追加します。
// プロジェクト評価後(設定フェーズ後) gradle.afterProject {prj, fail -> logger.lifecycle "====after project(${prj.name})====" logger.lifecycle " after project evaluation" logger.lifecycle " evaluated[${prj.state.executed}]" } // 実行フェーズ終了後 gradle.buildFinished {result -> def failed = result.failure != null logger.lifecycle "====build finished====" if (failed) { logger.lifecycle " **FAILED**" logger.lifecycle "failure[${result.failure}]" } else { logger.lifecycle " **SUCCEEDED**" logger.lifecycle "failure[none]" } } // 実行フェーズ開始前 gradle.projectsEvaluated {grdl -> def prj = grdl.rootProject logger.lifecycle "====projects evaluated(${prj.name})====" logger.lifecycle " after all project's evaluation" logger.lifecycle " task graph is available" logger.lifecycle " evaluated[${prj.state.executed}]" } // 単なるプリントするだけのタスクを3つ (1..3).each {num -> task "hello${num}" { doLast { println "hello ${num}" } } }
実行
hello1
〜hello3
タスクを実行してみます。
$ gradle hello1 hello2 hello3 ====settings evaluated(project-root)==== settingsDir[/Users/my/projects/project-root] applied plugins[0] **tasks** hello1 -> hello2 -> hello3 **task-requests** <hello1|hello2|hello3> ====projects loaded(project-root)==== after projects created from settings evaluated[false] ====before project(project-root)==== before project evaluation evaluated[false] ====after project(project-root)==== after project evaluation evaluated[true] ====before project(dub)==== before project evaluation evaluated[false] ====after project(dub)==== after project evaluation evaluated[true] ====before project(sub)==== before project evaluation evaluated[false] ====after project(sub)==== after project evaluation evaluated[true] ====projects evaluated(project-root)==== after all project's evaluation task graph is available evaluated[true] :hello1 hello 1 :hello2 hello 2 :hello3 hello 3 BUILD SUCCESSFUL Total time: 1.254 secs ====build finished==== **SUCCEEDED** failure[none]
hooksで紹介した通りの順番で実行されているのがわかるかと思います。
またプロジェクトのstate
(評価された状態)が、beforeProject
ではfalse
からafterProject
でtrue
に変わっているのもわかるかと思います。
さて、今回フェーズについて紹介しました。その2ではタスクグラフと、それを使ってどういうことができるのかを紹介したいと思います。