Gradleハマりメモ 〜環境ごとのファイルコピー篇〜

※Gradle 1.12にて実施

やりたかったのは、プロパティ e で指定された環境用のファイルをコピーすること。

最初は以下のように書いた。

apply plugin: 'base'

task copySettings(type: Copy) {
  doFirst {
    if(!project.hasProperty('e')){
      throw new InvalidUserDataException("Input 'e'!")
    }
  }

  from "settings/$project.e"
  into 'build'
}

プロパティ e を指定しないで実行すると以下のようなエラー。

eiryus-MacBook-Air:gradle eiryu$ gradle co

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/eiryu/git/gradle/build.gradle' line: 10

* What went wrong:
A problem occurred evaluating root project 'gradle'.
> Could not find property 'e' on root project 'gradle'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 5.071 secs

期待としては doFirst でバリデーションエラーになって欲しかったが、ビルドスクリプトを解釈する時点で from の部分の $project.e で落ちている模様。closureに変更 from { "settings/$project.e" } しても結果は同じ。

そもそもcleanタスクの実行時にもプロパティ e が必須になってしまうため、以下のように修正する。

  • e をローカル変数envに持つようにする
apply plugin: 'base'

def env
task copySettings(type: Copy) {
  doFirst {
    if(project.hasProperty('e')){
      env= project.e
    }else{
      throw new InvalidUserDataException("Input 'e'!")
    }
  }

  from "settings/$env"
  into 'build'
}

実行すると、

eiryus-MacBook-Air:gradle eiryu$ gradle co -Pe=dev
:copySettings UP-TO-DATE

BUILD SUCCESSFUL

Total time: 3.295 secs

となった。成功はするものの、UP-TO-DATEのためbuildディレクトリが生成されない。。

ここ*1を参考に、task の設定として、outputs.upToDateWhen { false }を追加してみたけどもダメ。

次はローカル変数 env にデフォルト値 'prod' を設定してみた。

eiryus-MacBook-Air:gradle eiryu$ cat build.gradle
apply plugin: 'base'

def env= 'prod'
task copySettings(type: Copy) {
  doFirst {
    if(project.hasProperty('e')){
      env= project.e
    }else{
      throw new InvalidUserDataException("Input 'e'!")
    }
  }

  from "settings/$env"
  into 'build'
}

今度は UP-TO-DATE にならず build ディレクトリが作成された。しかし、常に env が 'prod' と指定されているものとして動いてしまった。

次はfrom の部分をclosure from { "settings/$env" }にして実行。 ようやく指定したプロパティで動かすことに成功。

closure にしていない GString の展開はビルド起動時に行われているからこんな挙動になっているのだろうか? これからもいろいろハマりそう。。

完成版
apply plugin: 'base'

def env= 'prod'
task copySettings(type: Copy){
  doFirst{
    if(project.hasProperty('e')){
      env= project.e
    }else{
      throw new InvalidUserDataException("Input 'e'!")
    }
  }

  from { "settings/$env" }
  into 'build'
}