No Programming, No Life

新しいNPNLです。http://d.hatena.ne.jp/fumokmm/ から引っ越してきました。

Gradleで--daemonオプションを付けた際にnew Fileするとうまくいかない

はじめに

--daemonオプションは高速起動するためのオプションなんですが、まだexperimental(実験段階)なんで何があっても自己責任でお願いしますということです。

$ gradle -h
(省略)
--daemon   Uses the Gradle daemon to run the build. Starts the daemon if not running [experimental].
(省略)

さて、それはそうと、何の気なしに、gradleを高速起動するため、以下aliasを指定してGradleを利用していました。

$ alias gradle="gradle --daemon"

こうしておくと--daemonを付け忘れることもないし便利だからねってことでやっていたんですが、思わぬところでエラーが発生しました。

エラー発生

それはnew File() した時に、存在しているファイルに対して、No such file or directory が発生するというもの。
ちなみに動作確認は、以下バージョンです。

$ gradle -v

------------------------------------------------------------
Gradle 1.0-milestone-3
------------------------------------------------------------

Gradle build time: Monday, 25 April 2011 5:40:11 PM EST
Groovy: 1.7.10
Ant: Apache Ant(TM) version 1.8.2 compiled on December 20 2010
Ivy: 2.2.0
JVM: 1.6.0_26 (Apple Inc. 20.1-b02-384)
OS: Mac OS X 10.6.8 x86_64

実験

まず以下のファイルを用意。

build.grale
task hello << {
  def f = new File('build.gradle')
  assert f.exists()
}

new File()で自分自身のビルドファイルを指定するサンプルです。当然ファイルは見つかるはずですよね?
これを--daemonなしで実行。*1

$ gradle -q hello
$ 

アサーションエラーもない。特に問題なし。
では、--daemonありで実行してみましょう。

$ gradle --daemon -q hello

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/fumo/work/gradletest/bugtest/build.gradle' line: 3

* What went wrong:
Execution failed for task ':hello'.
Cause: Assertion failed: 

assert f.exists()
       | |
       | false
       build.gradle

Cause: assert f.exists()
       | |
       | false
       build.gradle

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

と、ここでコケます。Gradleは自分自身を見失ってしまうわけです。
バグレポートあがってるかな?と思って探していたら、ここを発見。すると、それはバグじゃないよ、new File()の代わりにProject#fileを使えば大丈夫だよとのコメントを発見。なるほどね、Projectってのはorg.gradle.api.Projectのことで、Gradle DSL上だったらどこでも自由に使えるメソッドが定義されている*2インタフェースです。ということで、コメントを信じて早速やってみる。

build2.gradle
task hello << {
  // cf. http://issues.gradle.org/browse/GRADLE-1249
  def f = file('build2.gradle')
  assert f.exists()
}

こうですか?よし、実行してみよう。

$ gradle --daemon -b build2.gradle -q hello
$

おー動いた。

まとめ

GradleのDSL上からは、org.gradle.api.Projectに定義されてるメソッドを使える限り使ったほうが良い。

更新履歴

  • 2011-07-27 id:nobeansさんのブクマコメントにてのご指摘の通り、"補足"は単なる私のミスでしたので削除しました。

*1:[http://bijo-linux.com/girls/unalias/:title=unalias] gradleしておくのを忘れずに。

*2:という認識であってましたっけ。たぶんあってる。教えて詳しい人。