Gradleでマルチプロジェクトビルド
Gradle Effective Implementation Guideの第7章を参考に。
ディレクトリ構成は以下。
flower/ tree/ master/ settings.gradle build.gradle
flowerプロジェクトとtreeプロジェクトのビルドを統括するmasterプロジェクトを作る。
マルチプロジェクトの定義
settings.gradleでflowerとtreeとmasterがマルチプロジェクトであることをmasterディレクトリ配下のsettings.gradleに定義。
includeFlat 'tree', 'flower'
もし、masterとtree/flowerが以下のようなディレクトリ構成の場合
master/ flower/ tree/
settings.gradleの中身は以下のようになる。
include 'tree', 'flower'
マルチプロジェクトの処理
依存関係を定義してあげると、ひとつのbuild.gradleファイルにマルチプロジェクトすべての処理を書くことが出来る。
allprojects{ task printInfo << { println "This is ${project.name}" } } subprojects{ printInfo << { println "Can be planted" } }
allprojectsブロックでマルチプロジェクト内のすべてのプロジェクトに対してタスクを定義出来る。
subprojectsブロックでは、マルチプロジェクトにおける自プロジェクト意外のプロジェクトに対してのみタスクを定義出来る。(この場合、flower/treeロジェクト)
もちろん、各プロジェクトにbuild.gradleを置いてあげてもOK。
マルチプロジェクトビルドの実行
上記ファイルを用意した後、masterディクレクトリで以下のprintInfoタスクを実行してみる。
kaakaa_hoe@[master]$ gradle printInfo :printInfo This is master :flower:printInfo This is flower Can be planted :tree:printInfo This is tree Can be planted
すると、masterプロジェクトを筆頭にすべてのプロジェクトのprintInfoタスクを実行する。
タスクが実行される順番は、親プロジェクトとなるmasterが一番最初に実行されて、その後はプロジェクト名のアルファベット順で実行される。
もちろんdependsOnを設定してあげることで実行順を制御することが出来る。
サブプロジェクトのタスクのみを実行したい場合は
kaakaa_hoe@[master]$ gradle :flower:printInfo :flower:printInfo This is flower Can be planted BUILD SUCCESSFUL Total time: 2.533 secs
次にflowerディレクトリでタスクを実行してみる。
kaakaa_hoe@[flower]$ gradle printInfo :flower:printInfo This is flower Can be planted BUILD SUCCESSFUL Total time: 2.508 secs
面白いのはflowerディレクトリ配下にはbuild.gradleファイルが存在しないのに、タスクが実行出来ること。
これはGradleが自動で対象プロジェクトがマルチプロジェクトに含まれているかを確認してくれるため。
なので、各プロジェクトにbuild.graldeを投げなくても、settings.gradleとbuild.gradleを含むディレクトリを各プロジェクトとフラットな場所に投げてあげれば、すべてのプロジェクトでgradleタスクを作成することが出来る。
ちょっとbuild.gradleファイルが長くなりそうだけど。
ビルドの依存関係とか成果物に関しても色々設定できるみたいなので、上手く使えれば便利そうですね。
ただ、flowerディレクトリを削除して、masterディレクトリでprintInfoタスクを実行しても同じ結果が得られる。
ディレクトリ構成
tree/ master/ settings.gradle build.gradle
settings.gradle,build.gradleは上記のまま。
実行
kaakaa_hoe@[master]$ gradle printInfo :printInfo This is master :flower:printInfo This is flower Can be planted :tree:printInfo This is tree Can be planted BUILD SUCCESSFUL Total time: 2.53 secs
マルチプロジェクトで実行しても実際のディレクトリを見に行ってるわけではない?
ちょっと確認。
build.gradleファイルにのallprojectsブロックに以下のタスクを追加。
task hasHoge << { def file = file(new File('hoge.txt')) println "${project.name} has hoge? => ${file.exists()}" }
まずは、flowerプロジェクトがある状態で実行。
flower/ hoge.txt tree/ hoge.txt master/ hoge.txt settings.gradle build.gradle
結果
kaakaa_hoe@[master]$ gradle hasHoge :hasHoge master has hoge? => true :flower:hasHoge flower has hoge? => true :tree:hasHoge tree has hoge? => true BUILD SUCCESSFUL Total time: 3.344 secs
flowerディレクトリを削除して実行。
kaakaa_hoe@[master]$ gradle hasHoge :hasHoge master has hoge? => true :flower:hasHoge flower has hoge? => false :tree:hasHoge tree has hoge? => true BUILD SUCCESSFUL Total time: 2.496 secs
ほぅ。
ちゃんと見に行けてる。
ということは指定されたプロジェクトが存在しない場合でも、そのプロジェクトに対するタスクは定義できるってことか。ちょっと気持ち悪い気がする。