Groovyを野良ビルドしてみよう

はじめに

G* Advent Calendarの4日目を担当させていただきたいと存じますnobeansと申します。どうもどうも。

さて今回のネタとして、

  • 自プロダクトのGroovyServとか
  • 今一押しのビルドツールGradleとか
  • この前のTDDBC横浜で注目を集めたBDDフレームワークのSpockとか

そういうのを紹介しようかなとも一瞬思ったんですが、他の人のブログとかも含めて日本語情報も割と充実している気がするので、今日はちょっと毛色を変えてGroovyそのものを自前でビルドする方法について紹介してみます。

対象者

  • Groovyの処理系に興味がある人
  • Groovyの言語仕様を変更して愉しみたい人
  • バグFIXのパッチを書いて本家のGroovyコミュニティに貢献したい人

多忙な人のための要約

$ git clone git://git.codehaus.org/groovy-git.git && ant install

を実行したらいいよ。

ソースコードを持ってくる

何はともあれ、ソースコードをとってきましょう。

元々GroovyはCodehausのSubversionリポジトリを使ってましたが、ここ最近Gitに移行されました。とはいっても、GithubじゃなくてCodehaus上のGitリポジトリがメインリポジトリです。

$ git clone git://git.codehaus.org/groovy-git.git

としてcloneしましょう。結構時間がかかります。


Githubにもミラーが作られてるので、使い慣れたそっちからとってきてもOKです。自分はGithub派なのでこっちでやってます。
https://github.com/groovy/groovy-core

$ git clone https://github.com/groovy/groovy-core.git

ビルドする

詳細はこちら。
http://groovy.codehaus.org/Building+Groovy+from+Source

Antでビルド

公式ドキュメントに書かれてるのがなぜかAntを使う方法なのですね。意外。

$ ant install

と実行するとビルドが開始されます。
すると、テストが実行されて無事に通るまでかなり時間がかかります。Macbook Core2Duo/2.4GHz Memory 8GBなマシンで、12分弱かかりました。CPU振り切りっぱなしで、ファンがうるさいです。

手っ取り早くテストをスキップして実行ファイルを手に入れたいときは、オプションを指定しましょう。

$ ant install -DskipTests=true

ビルドが完了すると、target/installに実行ファイル一式が生成されます。普通にGroovyのtarballとかzipをダウンロードして展開したディレクトリと同じだと考えればOKです。

試しに実行してみると、

$ target/install/bin/groovy --version
Picked up _JAVA_OPTIONS: -Dfile.encoding=utf-8 -Xms128m -Xmx1024m
Groovy Version: 2.0.0-beta-2-SNAPSHOT JVM: 1.6.0_29

とでました。2.x系ですね。最先端。

Gradleでビルド

GroovyistならやっぱりGradleですよね。Gradle。
一応、既にGradleでもビルドできるようになってるんですけど、まだ正式じゃなってことなんでしょうかねぇ。ということで試してみます。

Gradleって何?インストールとかしてないよ?という人もご安心ください。GradleにはGradle Wrapperという仕組みがあって、Gradleを明示的にインストールしなくても色々自動でやってくれます。プロジェクト直下にあるgradlew (Windowsの場合はgradlew.bat)を実行すると、実行に必要なgradleの実行ファイル一式zipを自動的にダウンロードして、ビルドを開始してくれるのです。

$ ./gradlew assemble

まずzipのダウンロードに結構時間がかかります。あと、依存関係のjarも色々引っ張ってくるのでそれもかなり時間がかかります。トータルで12〜15分くらいはかかります。とはいえ、2度目以降はそれらのダウンロードは不要なので割とサクっと動くはずです。

ビルドが完了すると、target/distributionsの配下にzipファイルが3つできてるはずです。binary, docs, srcの3種類ですね。とりあえずbinary版を展開して実行してみましょう。

$ unzip target/distributions/groovy-binary-2.0.0-beta-2-SNAPSHOT.zip
Archive:  target/distributions/groovy-binary-2.0.0-beta-2-SNAPSHOT.zip
   creating: groovy-2.0.0-beta-2-SNAPSHOT/
..(snip)..
  inflating: groovy-2.0.0-beta-2-SNAPSHOT/bin/groovy.bat
replace groovy-2.0.0-beta-2-SNAPSHOT/bin/groovy.icns? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
  inflating: groovy-2.0.0-beta-2-SNAPSHOT/bin/groovy.icns
..(snip)..
  inflating: groovy-2.0.0-beta-2-SNAPSHOT/CLI-LICENSE.txt
$ groovy-2.0.0-beta-2-SNAPSHOT/bin/groovy --version
Picked up _JAVA_OPTIONS: -Dfile.encoding=utf-8 -Xms128m -Xmx1024m
Groovy Version: ##ImplementationVersion## JVM: 1.6.0_29

なぜかzip中にbin/groovy.icnsのエントリがダブっているとか、GroovyVersionの出力文字列がビルド時に置換できてないとか、やはり標準になってないだけあって、Gradleビルドファイルは調整中のようです...。

まだしばらくは素直に公式ドキュメント通りにAntを使った方が無難そうです。

Groovyを改造してみよう

Groovy JDK、略してGDKって知ってますか?
Javaの標準クラスに、便利だと思うメソッドを片っ端からGroovyメタプログラミング機能(以降、MOP)を利用して突っ込んでみました、というAPI群のことです。

http://groovy.codehaus.org/groovy-jdk/

File#getText()とかDate#format()とかやたら便利なメソッドが一杯追加されてるんですけど、これを実現してるのがGroovyのDefaultGroovyMethodsというクラスです。

例えば、このクラスに

    public static String getText(File file) throws IOException {
        // ...
    }

というメソッドがあるんですが、これがMOPで適用されると、Fileインスタンスに対して引数なしでgetText()メソッドを呼び出したときにこのstaticメソッドの処理が実行されてStringがreturnされる、ことになります。メソッド・戻り値はそのまま同じですが、第1引数がレシーバで、(この例では存在しませんが)第2引数以降がそのレシーバに渡すメソッド引数となるところがポイントです。

というわけで、オレオレ便利メソッドを突っ込んで遊ぶのに、DefaultGroovyMethodsクラスはちょうどいい素材になります。

さて、はじめての改造なので、ここはやはり HelloWorld ですよね。景気よくObjectクラスにhelloWorld()メソッドを仕込んでみましょう。

src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.javaを開いて、

    public static String helloWorld(Object object) {
        return "Hello, World!";
    }

というstaticメソッドをDefaultGroovyMethodsクラスの適当なところに追加してから、無難にAntでビルドし直しましょう。

さて、コマンドラインhelloWorld()を試してみると...

$ target/install/bin/groovy -e "println helloWorld()"
Hello, World!

やりましたね!!

さいごに

使ってるOSSプロダクトのソースコード一式をいつでも参照できるようにローカルディスクに入れておくのは、開発者としての身だしなみだと思いますが、せっかくそこにコードがあるなら単に読むだけではなく、積極的に改造・バグ修正・パッチ作成をして、更にその成果を本家にコントリビュートできると素敵ですね。


というわけで、
Enjoy your Groovy life!

12/5追記

環境変数GROOVY_HOMEですが、最近のGroovyなら実行したgroovyシェルスクリプトから辿って自動解釈してくれるので、設定してなくてもOKです。自分は無設定で生活してます。
既にGROOVY_HOMEを設定してる人は、上記の野良ビルド版を実行するときに、GROOVY_HOMEを解除するかまたは野良ビルド版のディレクトリパスに変更してからお試しください。