Gradle で環境ごとにあれもこれも変更する

前回までは Configslurper を使って 環境毎に構成を変更する方法について書きましたが @literalice さんに

Gradleでプロパティなどの設定情報を外出しして切り替えて使う
で 環境毎に別の Gradle ファイルを取り込んで いろいろと変更する方法を教えてもらったので ちょっと試してみました。

まずは基本から...
別の Gradle ファイルは

apply from: 'gradle/other.gradle'
で取り込むことができます。
ちなみに 読み込む Gradle ファイルは の形式で指定できます。

で実際どんなことに使えるかというと

  • 環境毎に 適用するプラグインを変える
  • 環境毎に タスク定義を変える
  • 環境毎に デフォルトタスクを変える
  • OS 毎に 実行するコマンドを変える
  • 共通処理を使い回す
などが考えられます。

これらを実現するには

// OS 判定
ant.condition(property: "os", value: "windows") { os(family: "windows") }
ant.condition(property: "os", value: "unix"   ) { os(family: "unix")    }

files(
   "gradle/${ant.properties['os']}.gradle",
   "gradle/common.gradle",
   "gradle/${env}.gradle",
   "${System.properties['user.home']}/.gradle/build.gradle"
).each { file ->
   if (file.exists()) apply from: file
}
といった感じで 外部の Gradle ファイルを取り込みます。
上から順にファイルを読み込み、後から読み込まれたファイルの内容が優先されます。
もちろん env は 環境を表す変数です。

環境毎に 適用するプラグインを変える

例えば、開発環境だけ eclipse プラグインを適用したり 自分の環境だけ 別のプラグインを適用したりするのに便利です。

gradle/development.gradle
apply plugin: 'eclipse'
$HOME/.gradle/build.gradle
apply plugin: 'something'

環境毎に タスク定義を変える

開発環境にはリリース用のタスクを、 テスト環境、実機環境にはそれぞれのデプロイ用のタスクをそれぞれ定義するといった感じで使えます。

gradle/development.gradle
task release << {
   println 'Preparing the release...'
}
gradle/test.gradle
task deploy << {
   println 'Deploing on the test environment...'
}
gradle/production.gradle
task deploy << {
   println 'Deploing on the production environment...'
}

環境毎に デフォルトタスクを変える

環境毎にデフォルトで実行するタスクを変えたいということはよくあります。
Ant だと よくターゲットの if/unless でがんばっていましたが Gradle ならこんな感じで設定できます。

gradle/development.gradle
defaultTasks 'clean', 'build', 'eclipse'
gradle/test.gradle
defaultTasks 'clean', 'build', 'deploy'
gradle/production.gradle
defaultTasks 'build', 'deploy'

OS毎に 実行するコマンドを変える

@literalice さんも書かれていますが OS 毎に実行するコマンドを変えるのに便利です。

windows.gradle
task something << {
    exec { commandLine "something.bat" }
}
unix.gradle
task something << {
    exec { commandLine "something.sh" }
}

共通処理を取り込む

共通的なタスクの定義や設定などを外部化して使いまわすと便利です。
外部ファイルは URI でも指定できるので どこかのサーバに置いておいて使いまわすのも良いかもしれません。
もちろん、ネットワークのない場所では使えませんけど...

また、残念ながら メソッドの外部化はできないようです。
しかし Groovy には クロージャがあります。
クロージャをプロパティにセットしておけば ちゃんと外部化できるようです。

gradle/common.gradle
cat = { name ->
   println file(name).text
}

tasks systemProperties << {
    new TreeMap(System.properties).each { k, v ->
        println "${k}, ${v}"
    }
}
この外部ファイルを取り込めば 前回の build タスクは
build << {
   cat "${sourceSets.main.classesDir}/Application.properties"
}
のように書くことができます。少しだけいい感じですね...

もし、興味のある方は

https://github.com/bluepapa32/gradle-environment-sample/tree/20110316
にサンプルがありますので試してみてください。