Gant 基本
家のビルドシステムをAntからGantへ移行したので、Gantを紹介します。
バージョンは現時点で最新である1.0.2です。
まずGantスクリプトはGroovyスクリプトですが、Antの代替として利用する為にいくつか追加されているものがあります。
target、そしてAntBuilder、ヘルパーとして利用できるいくつかのオブジェクトの事前定義です。
それでは順を追って説明していきます。
* Gantを実行する
スクリプトをbuild.gantとして保存し、gantで実行します。
* targetを定義する
Gantではtargetは名前と説明を持つクロージャになります。
例えば、
target(doSomething : "Do something") {
}
というように書くことができます。
他のtargetに依存する場合は、
target(prepareSomething : "Prepare something") {
}
target(doSomething : "Do something") {
depends("prepareSomething")
}
デフォルトtargetとしたい場合は、
setDefaultTarget("doSomething")
* Antタスクを利用する
Groovyには元々AntBuilderというヘルパークラスがあり、Antのタスクを簡単に呼び出すことができます。
例えば通常GroovyでAntタスクを呼び出す場合、以下のように書けます。
def ant = new AntBuilder()
ant.echo("we're not in XML anymore.")
これをGantでは、
Ant.echo("we're not in XML anymore.")
とでき、またTargetクロージャ内に限っては
echo("we're not in XML anymore.")
とさらに簡略化して書けます。
後で触れますが、Gantの場合実際にはAntBuilderを拡張したGantBuilderを使用しています。
* 外部定義のtargetを使う
Antのimportに代わるのがincludeTargetsです。リストなので<<演算子で追加するという方法で対象を指定します。
コンパイル済みクラスの場合(GantからはCleanとMavenが提供されています)、
includeTargets << gant.targets.Clean
外部ファイルの場合、
includeTargets << new File("./someTargets.gant")
文字列リテラルの場合、
includeTargets << """
target(doSomething: "...") {
...
}
"""
これらを複数指定する場合、以下のように繰り返して記述しても良いですが・・
includeTargets << t1
includeTargets << t2
:
配列を指定すれば再帰的に要素ごとに分割して読み直してくれるので配列で指定することも可能です。
includeTargets << [t1, t2, ...]
なのでこうしても大丈夫です。
includeTargets << [t1, [t2, ...], ...]
* 外部定義のヘルパークラスを使う
Gantファイル内でサービスとして外部クラスを利用できるようにするのがincludeToolです。
includeTargetsと同じく、クラス名、ファイル、文字列リテラルを<<演算子で渡すことができます。
ドキュメントでは公開されていないのですが、ソースを見る限りGantからはExecute、Ivy、LaTeX、Subdirectoriesの各クラスが提供されているようです。
読み込んだクラスはクラス名を変数として事前定義される為、以下のようにクラス名.メソッド名という形で使用します。なのでstaticメソッドというわけではありません。
includeTool << gant.tools.Execute
target(executeCommand: "") {
Execute.executable("cmd /c ...")
}
* 事前定義はどう実装されているのか
ではこれらの事前定義はどのように行っているのでしょうか。
と、その前にまずGroovyShellを利用したスクリプト評価方法を知る必要があります。
GroovyShellはGroovyスクリプトを評価する為のシェルで、評価時の変数をBindingオブジェクトで渡すことができます。
例を挙げてみます。
def binding = new Binding()
binding.x = 2
binding.y = 3
def groovyShell = new GroovyShell(binding)
def result = groovyShell.evaluate("x + y")
println result
とすると結果として・・・
5
とコンソールに表示されます(当たり前ですが)。ちなみにこれはJavaでGroovyを利用する際にも使えます。
このGroovyShellがGantでも使われています。
Gant実行時に呼び出されるのはgant.Gant.groovyですが、この中で
binding = new Binding ( )
とし、これに
binding.Ant = ant // 生成済みGantBuilderオブジェクト
binding.includeTargets = new IncludeTargets ( binding )
binding.includeTool = new IncludeTool ( binding )
binding.target = target // 生成済みtargetクロージャオブジェクト
として各オブジェクトを追加した後、GroovyShellにこのBindingオブジェクトを渡しbuild.gantの評価を行っています。
但しGantではusecacheオプションというものがあり、キャッシュが使われる場合は、
以下のようにコンパイルされたbuild.gantのクラスからオブジェクトを生成後、Bindingオブジェクトを渡し、処理を実行させています。
def script = classLoader.loadClass ( className ).newInstance ( )
script.binding = binding
script.run ( )
ここで生成されるscriptオブジェクトの型は実際はGroovyObjectクラスであり、このオブジェクトはrun()で実行することができます。
* まとめ
Antと比較しての使い心地は、XMLに比べて書きやすい、Groovyで処理が書けるので無理にAntのタスクで解決しなくても良い
(但しAnt用にgroovyタスクが用意されているので後者は理由としては弱いですが)という点でとりあえず満足しています。
またAntからの移行も楽に行えました。
Gantはまだ新しいプロジェクトということもあってドキュメントがほとんどなく手探り状態ですが、調べつつ公開していく予定です。
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/nagai/gant-57fa672c-a-groovy-based-build-system/tbping
Re:Gant 基本
これが格好悪いです。この手のツールでは、タスク間の依存関係の記述が最も重要です。それが宣言的に書けないのは、makeより退化している気がします。
rakeを見ると(参考: http://www2s.biglobe.ne.jp/~idesaku/sss/tech/rake/)、うまくやっています。
groovyはrubyに似ているようなので、taskA,taskBに依存するtaskXの定義は次のように書けても良いと思います。
> target([taskX:[taskA,taskB]])
Re:Gant 基本
僕としては名前付きパラメタでよかったのではないかと思っています。
target(
name : "taskX",
description : "...",
depends : "taskA, taskB") {
...
}