CLOVER🍀

That was when it all began.

Gradleことはじめ

ちょっと更新間隔が空いてしまいましたね。いろいろと予定があったり、暑さに負けたり(笑)していたのが主な原因ですが…。

あと、NettyがそろそろVersion 4を出しそうな雰囲気なのですが、Alpha1からまだしばらくかかりそうなので、方向を変えてGradleを触ってみることにしました。

GradleもVersion 1が(執筆時点では、1.1まで進んでましたが…)リリースされて、なぜかScalaのサポートまで標準で取り込まれているみたいなので、触ってみようかなぁと前々から思っていましたので。

じゃ、やってみましょう。なお、このエントリで扱うGradleのバージョンはGradle 1.1になります。

Gradleとは?

Groovy界隈で、有名なビルドツールです。プロジェクト管理ツール的な感じでもあるので、JavaでのMaven、Scalaでいうsbtに相当します。最近では、OSSのプロダクトもGradleに移行していっているみたいですね。

Mavenとは違い、XMLではなくGroovy DSLで設定ファイル(ビルドスクリプト)を記述します。

Gradle公式サイト
http://www.gradle.org/

ドキュメント[ユーザガイド]
http://www.gradle.org/docs/current/userguide/userguide.html
日本語訳
http://gradle.monochromeroad.com/docs/index.html

インストール

では、ユーザガイドを参照しながら、インストール。
http://www.gradle.org/docs/current/userguide/installation.html

バイナリを公式サイトから落としてきます。
http://www.gradle.org/downloads

今回は、「gradle-1.1-bin.zip」でとりあえずやってみます。

適当な場所にダウンロードして、unzipで展開。

$ unzip gradle-1.1-bin.zip

インストール先は、個人的な趣味で「/usr/local/gradle」にしてます。

$ sudo ln -s gradle-1.1 current

$ pwd
/usr/local/gradle
$ ll
合計 12
drwxr-xr-x  3 root root 4096 Aug  5 20:06 ./
drwxr-xr-x 21 root root 4096 Aug  5 20:06 ../
lrwxrwxrwx  1 root root   10 Aug  5 20:06 current -> gradle-1.1/
drwxr-xr-x  6 root root 4096 Aug  5 20:06 gradle-1.1/

.bashrcなどに環境変数「GRADLE_HOME」を設定し、さらにPATHを通します。

export GRADLE_HOME=/usr/local/gradle/current
PATH=${GRADLE_HOME}/bin:${PATH}

.bashrcを評価して…

$ . .bashrc

インストール確認。

$ gradle -v

------------------------------------------------------------
Gradle 1.1
------------------------------------------------------------

Gradle build time: 2012年7月31日 13時24分32秒 UTC
Groovy: 1.8.6
Ant: Apache Ant(TM) version 1.8.4 compiled on May 22 2012
Ivy: 2.2.0
JVM: 1.7.0_05 (Oracle Corporation 23.1-b03)
OS: Linux 3.2.0-27-generic amd64

この手のツールによくありがちなプロキシ設定ですが、環境変数「JAVA_OPTS」または「GRADLE_OPTS」に-Dシステムプロパティでhttp.proxyHostやhttp.proxyPortを指定すればよさそう。ま、Gradleの場合は「GRADLE_OPTS」を使用する方が無難でしょうね。

また、gradle.propertiesというファイルでシステムプロパティに対して設定する、でもOKなようです。
http://www.gradle.org/docs/current/userguide/build_environment.html#sec:accessing_the_web_via_a_proxy

// HTTPプロキシ
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=userid
systemProp.http.proxyPassword=password
systemProp.http.nonProxyHosts=*.nonproxyrepos.com|localhost

// HTTPSプロキシ
systemProp.https.proxyHost=www.somehost.org
systemProp.https.proxyPort=8080
systemProp.https.proxyUser=userid
systemProp.https.proxyPassword=password
systemProp.https.nonProxyHosts=*.nonproxyrepos.com|localhost

この後、build.gradleなどの「.gradle」拡張子のファイルをGroovy DSLとして使うことがわかっているので、.emacsのGroovy関連の設定を以下の様に変更。

(autoload 'groovy-mode "groovy-mode" "Groovy editing mode." t)
(add-to-list 'auto-mode-alist '("\.groovy$" . groovy-mode))
(add-to-list 'auto-mode-alist '("\.gradle$" . groovy-mode))
(add-to-list 'interpreter-mode-alist '("groovy" . groovy-mode))

Javaで「Hello World」

ユーザガイドでは最初はタスクの定義方法とか使い方が書いていますが、まあビルドツールとして使うことがメインになると思うので、すっ飛ばして簡単なJavaプロジェクトの作成へ。

まずは、プロジェクト用のディレクトリを用意。

$ mkdir hello-gradle
$ cd hello-gradle/

build.gradleを作成。

apply plugin: 'java'

これだけ。

GradleはJavaソースコードが「src/main/java」に配置されていることを期待しているそうなので(Mavenと一緒ですね)、先にディレクトリを作成しておきます。

$ mkdir -p src/main/java

テストコードが必要な場合は、「src/test/java」を作成します。

その他、Java関連のディレクトリ構成についてはこちらを参照してください。
http://www.gradle.org/docs/current/userguide/java_plugin.html#N11D8E

では、「Hello World」から始めてみましょう!。
src/main/java/HelloGradle.java

public class HelloGradle {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

「gradle build」でビルドしてみます。

$ gradle build
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test
:check
:build

BUILD SUCCESSFUL

Total time: 28.037 secs

初回はかなり重い…ですが、なんか一緒に使っていたFirefoxが暴走していたっぽく、必要以上に時間がかかっていたっぽいです…。それでも、次回のビルドは5〜6秒かかりましたが。

ビルドで生成されるファイルは、「build」ディレクトリ配下に置かれます。

$ ll build
合計 32
drwxrwxr-x 8 xxxxx xxxxx 4096 Aug  5 20:49 ./
drwxrwxr-x 5 xxxxx xxxxx 4096 Aug  5 20:49 ../
drwxrwxr-x 3 xxxxx xxxxx 4096 Aug  5 20:49 classes/
drwxrwxr-x 2 xxxxx xxxxx 4096 Aug  5 20:49 dependency-cache/
drwxrwxr-x 2 xxxxx xxxxx 4096 Aug  5 20:49 libs/
drwxrwxr-x 3 xxxxx xxxxx 4096 Aug  5 20:49 reports/
drwxrwxr-x 2 xxxxx xxxxx 4096 Aug  5 20:49 test-results/
drwxrwxr-x 3 xxxxx xxxxx 4096 Aug  5 20:49 tmp/

Mavenでは、「target」ディレクトリでしたね。

前回のビルド結果を破棄するには、「gradle clean」で。

$ gradle clean
:clean

BUILD SUCCESSFUL

Total time: 4.665 secs

現在実行可能なタスクは、「gradle tasks」で確認可能です。

$ gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build tasks
-----------
assemble - Assembles all Jar, War, Zip, and Tar archives.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles the main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles the test classes.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
dependencies - Displays the dependencies of root project 'hello-gradle'.
help - Displays a help message
projects - Displays the sub-projects of root project 'hello-gradle'.
properties - Displays the properties of root project 'hello-gradle'.
tasks - Displays the tasks runnable from root project 'hello-gradle' (some of the displayed tasks may belong to subprojects).

Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.

Rules
-----
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.
Pattern: clean<TaskName>: Cleans the output files of a task.

To see all tasks and more detail, run with --all.

BUILD SUCCESSFUL

Total time: 5.481 secs

これを出すのに、5秒かかっているんですが…。

さて、Mainクラスを実行させるタスクがありません。この辺り、Mavenと一緒でプラグインがないとできないのかなぁ…。

やっぱり?
http://www.gradle.org/docs/current/userguide/application_plugin.html

というわけで、build.gradleを修正。

apply plugin: 'java'
apply plugin: 'application'

mainClassName = "HelloGradle"
$ gradle run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
Hello World

BUILD SUCCESSFUL

Total time: 8.746 secs

動きましたー。なお、sbtのようにMainクラスを勝手に探してくれないかなぁと思ってmainClassNameを端折ってみましたけど、普通にエラーになりました。ユーザガイドにも、Mainクラスを設定しろって書いてますからね…。

なんとなく、このスタイルだとsbtの方が軽いなぁと思うのは、何か勘違いしているでしょうか…?

とりあえず、「Hello World」まで!