Gradle使い方メモ

  • 488
    いいね
  • 0
    コメント

Gradle を実際に触ってみたときのメモ。

基本的な話は vvakame さんの Gradle入門 を読んでいる前提。

環境

OS

Windows 7 64bit

Java

1.7.0_40

Gradle

1.9

インストール

Java

割愛

Gradle

ここ を開いて gradle-1.9-bin.zip をクリックして zip をダウンロード。

zip を解凍したら、 gradle-1.9\bin にパスを通す。

コマンドプロンプトを開いて、 gradle --version を入力。

バージョンの情報が出力されたら OK。

プロキシの設定

HTTPプロキシ
systemProp.http.proxyHost=<プロキシホスト名>
systemProp.http.proxyPort=<プロキシポート番号>
systemProp.http.proxyUser=<認証ユーザ名>
systemProp.http.proxyPassword=<パスワード>
HTTPSプロキシ
systemProp.https.proxyHost=<プロキシホスト名>
systemProp.https.proxyPort=<プロキシポート番号>
systemProp.https.proxyUser=<認証ユーザ名>
systemProp.https.proxyPassword=<パスワード>

上記設定を、以下のいずれかに記述する。

  • プロジェクトのルートに配置した gradle.properties
  • Gradle ホームフォルダ(<ユーザのホームフォルダ>\.gradle)に配置した gradle.properties

簡単な Java プロジェクトを作る

コマンドラインから実行して Hello Gradle!! と出力するだけの簡単なプロジェクトを作る。

build.gradle を作成する

プロジェクトのルートフォルダに、 build.gradle という名前のテキストファイルを作成する。

内容は以下。

build.gradle
apply plugin: 'java'

Java ソースコードを作成する

次に、 Java のソースコードを作成する。 src\main\java がデフォルトのソースフォルダの場所なので、その下に sample\gradle とフォルダを作って、 GradleMain.java を配置する。
GradleMain.java の内容は以下。

GradleMain.java
package sample.gradle;

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

フォルダ構成は以下のようになる。

フォルダ構成
│  build.gradle
└─src
    └─main
        └─java
            └─sample
                └─gradle
                        GradleMain.java

デフォルトのフォルダ構成

src
├─main
│  ├─java          : 製品の Java ソースコード
│  └─resources     : 製品のリソース
└─test
    ├─java          : テスト Java ソースコード
    └─resources     : テストのリソース

基本のフォルダ構成は Maven と同じ感じ。

コンパイルする

コマンドプロンプトを開いて、 build.gradle のあるフォルダまで移動し、以下のコマンドを実行。

Javaソースコードをコンパイルする
>gradle compileJava

すると、以下のように build フォルダの下に class ファイルが生成される。

│  build.gradle
│
├─build
│  └─classes
│      └─main
│          └─sample
│              └─gradle
│                      GradleMain.class
│  
└─src
    └─main
        └─java
            └─sample
                └─gradle
                        GradleMain.java

実行する

コンパイルで生成されたclassファイルを普通に実行する
>java -cp build\classes\main sample.gradle.GradleMain
Hello Gradle!!

生成したファイルを消す

生成したファイルを消す
>gradle clean

build フォルダが削除される。

タスクを複数指定する

タスクを複数指定して実行する
>gradle clean compileJava

clean してから compileJava が実行される。

コンパイルのオプションを色々設定する

javac のオプション

javac コマンドで指定できるオプションは、 gralde では build.gradle で以下のように指定する。

build.gradle
apply plugin: 'java'

compileJava {
    options.encoding = 'Shift_JIS'
}

compileJava の中で options.<オプション名> = <値> とすれば指定できる。上記例は、ソースコードのエンコーディングを指定している。

指定できるオプション名については CompileOptions - Gradle DSL Version 1.11 を参照。

ソース・class ファイルの JDK バージョンを指定する

javac-source, -target に対応するオプションは以下のように指定する。

build.gradle
apply plugin: 'java'

sourceCompatibility = '1.6' // -source
targetCompatibility = '1.6' // -target

Gradle からアプリケーションを実行する

アプリケーションプラグイン を使えば、 java コマンドを叩く代わりに Gradle 経由でアプリケーションを実行できる。

まず、 build.gradle を以下のように記述する。

build.gradle
apply plugin: 'application'

mainClassName = 'sample.gradle.GradleMain'

apply plugin: 'application' でアプリケーションプラグインの使用を宣言し、 mainClassName に Main クラスの FQCN を指定する。
※アプリケーションプラグインを使えば java プラグインも利用できるようになるので、 java プラグインの宣言は不要。

あとは、以下のように run タスクを実行すれば OK。

runタスクでアプリケーションを実行する
>gradle run

run タスクで実行する Main クラスにコマンドライン引数を渡す

コマンドライン引数を渡したい場合、単純に gradle run の後に引数を書き連ねてもうまくいかない。

runタスクの後ろに引数を書いてもダメ
>gradle run hoge fuga

hogefuga は、実行する Main クラスの main メソッドには渡されない。

gradle-user - Command line arguments to application? ←同じ疑問を持った人がいて、どうも書き込みを見る限り普通にコマンドライン引数のノリで引数を渡すことはできず、以下のように build.gradle の記述を工夫する必要があるみたい。

build.gradle
apply plugin: 'application'

mainClassName = 'sample.gradle.GradleMain'

run {
    if (project.hasProperty('args')) {    // "args" というプロパティが渡されていたら
        args project.args.split('\\s+')   // 空白文字で split して、 run タスクの args オプションにセットする
    }
}

実行するときは、以下のようにコマンドライン引数を渡す。

runタスクにコマンドライン引数を渡す
>gradle run -Pargs="hoge fuga piyo"
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
{hoge,fuga,piyo}

起動用スクリプトを自動生成する

同じくアプリケーションプラグインを使えば、作成したプログラムの起動用スクリプト(Windows と Unix 用)を自動生成できる。

起動スクリプトの生成は、 startScripts タスクを使用する。

起動スクリプトを生成する
>gradle startScripts

タスクが完了すると、 build\scripts の下に起動用スクリプトファイルが出力されている。
デフォルトでは、 build.gradle のあるフォルダの名前でスクリプトファイルが出力される。

スクリプトファイルの名前は build.gradle で以下のように指定できる。

build.gradle
apply plugin: 'application'

mainClassName = 'sample.gradle.GradleMain'

startScripts {
    applicationName = 'hoge'
}

applicationName で指定できる。

他に指定できる値については CreateStartScripts - Gradle DSL を参照。

作成したアプリケーションを全部 zip にまとめて出力する

同じくアプリケーションプラグインを使えば、次のファイル類をまとめた zip ファイルを、タスク一発で生成できる。

  • ソースをコンパイルして固めた jar
  • 依存 jar ファイル一式
  • 起動スクリプト

タスクの名前は distZip

全部入りのzipを生成する
>gradle distZip

タスクが完了すると build\distributions に zip ファイルが出力される。
解凍すると、以下のようなフォルダ構成になっている。

├─bin  : 起動スクリプトが配置されている
└─lib  : ソースをコンパイルして固めた jar 及び依存 jar ファイル

こちらも build.gradle で zip ファイルの名前を任意の値に変更できる。

build.gradle
apply plugin: 'application'

mainClassName = 'sample.gradle.GradleMain'

distZip {
    baseName = 'HelloGradle'
}

baseName で指定する。

他に指定できる値については Zip - Gradle DSL Version 1.8 を参照。

Maven より圧倒的に楽だ……。

ちなみに、 tar にしたい場合は distTar というタスクがある。

ソース以外の任意のファイルをアプリケーションに含める

src/main/java および src/main/resources の下にあるファイルは、全て jar に固められてしまう。

そうではなく、 jar の外に出しておいて、かつアプリに含まれるようにしたいファイルが存在する場合は、 src/dist フォルダの下に配置する。

フォルダ構成
project/
  `-src
    |-main/java/
    `-dist/
      |-hoge.txt
      `-fuga/
        `-piyo.txt
> gradle installApp

installApp は ver 3.0 から削除され installDist に置き換わる予定なので注意。

タスク実行後
project/
   `-build/install/
     |-hoge.txt
     |-fuga/
     |  `-piyo.txt
     |-bin/
     `-lib/
  • src/dist の下に配置したファイルやフォルダが、そのままアプリケーションのルートに配置される。

サードパーティのライブラリ(jar)を使用する

Apache Commons Lang を使った例。

ローカルに jar ファイルがある場合

jar ファイルが lib\commons-lang3-3.1.jar にある場合、 build.gradle に以下のように記述する。

build.gradle
apply plugin: 'java'

dependencies {
    compile files('lib/commons-lang3-3.1.jar')
}

dependencies 内の files で jar を指定している。

jar ファイルの指定は、次のようにもできる。

ローカルのjarの指定方法
dependencies {
    // 個別ファイル複数指定
    compile files('lib/hoge.jar', 'lib/fuga.jar')
    // lib フォルダ直下の jar を全て指定
    compile fileTree(dir: 'lib', include: '*.jar')
    // lib フォルダ以下、サブフォルダも含めて全 jar ファイルを指定
    compile fileTree(dir: 'lib', include: '**/*.jar')
}

Maven2 のセントラルリポジトリに存在する jar を指定する場合

Maven2 のセントラルリポジトリに存在する jar を指定する場合は、 build.gradle を以下のように記述する。

build.gradle
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1'
}

groupGroupIdnameArtifactId を指定する。

リポジトリからダウンロードした jar ファイルは、 %ユーザのホームフォルダ%\.gradle\caches 以下に保存される。
ライブラリをキャッシュする場所を変更したい場合は、環境変数 GRADLE_USER_HOME に任意のフォルダのパスを設定すれば良い。

dependencies の部分は、以下のようにも書ける。

dependencies {
    compile 'org.apache.commons:commons-lang3:3.1'
}

セントラルリポジトリ以外の Maven リポジトリを指定する

JSONIC 1.2.0 を Seasar が提供している Maven リポジトリから落としてみる。

build.gradle
apply plugin: 'application'

mainClassName = 'sample.gradle.GradleMain'

repositories {
    maven {
        url "http://maven.seasar.org/maven2"
    }
}

dependencies {
    compile 'net.arnx.jsonic:jsonic:1.2.0'
}

repositories の中の maven の中の url に使用するリポジトリの URL を設定すれば、セントラルリポジトリ以外の Maven リポジトリも使用できるようになる。

GradleMain.java
package sample.gradle;

import java.util.Map;
import java.util.HashMap;

import net.arnx.jsonic.JSON;

public class GradleMain {
    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();

        map.put("hoge", "HOGE");
        map.put("fuga", "FUGA");
        map.put("piyo", "PIYO");

        System.out.println(JSON.encode(map));
    }
}
実行
>gradle clean run
:clean
:compileJava
:processResources UP-TO-DATE
:classes
:run
{"fuga":"FUGA","hoge":"HOGE","piyo":"PIYO"}

BUILD SUCCESSFUL

Javadoc を生成する

Javadocを生成するタスク
>gradle javadoc

build\docs\javadoc の下に Javadoc が生成される。

GradleMain.java
package sample.gradle;

/**
 * メインクラスです。
 */
public class GradleMain {

    /**
     * メインメソッドです。
     * @param args コマンドライン引数
     */
    public static void main(String[] args) {
        System.out.println("Hello Gradle!!");
    }
}

生成された Javadoc

gradleで生成したjavadoc.jpg

JUnit を実行する

JUnit4 + jMockit でテストコードを作成して実行してみる。

src/main/java/sample/gradle/GradleMain.java
package sample.gradle;

public class GradleMain {
    public String method() {
        return "original";
    }
}
src/test/java/sample/gradle/GradleMainTest.java
package sample.gradle;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;

import org.junit.Test;
import mockit.Mocked;
import mockit.Expectations;

public class GradleMainTest {

    @Mocked private GradleMain gradleMain;

    @Test
    public void test() {
        // setup
        new Expectations() {{
            gradleMain.method(); result = "stub";
        }};

        // exercise
        String actual = gradleMain.method();

        // verfiy
        assertThat(actual, is("stub"));
    }
}
build.gradle
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'com.googlecode.jmockit:jmockit:1.4'
    testCompile 'junit:junit:4.11'
    testCompile 'org.hamcrest:hamcrest-library:1.3'
}

JUnit とかはテストでだけ使うので testCompile を指定している。

テストを実行する
>gradle test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test

BUILD SUCCESSFUL

デフォルトは、全ての class ファイルがチェックされて、テストクラスを見つけたら全部実行される。

テスト結果を HTML で確認する

test タスクが完了すると build\reports\tests の下にテスト結果が HTML で出力される。

gradleが生成したテスト結果HTML.jpg

2013/12/22 修正

デフォルトでは HTML は出力されず、 reports.html.enabled = true にする必要があると記述していたが、よく見たらデフォルトは出力されるようになっていたので、特に設定なしで HTML 出力は可能でした。すみません。

War を作成する

WAR プラグイン を使って war ファイルをビルドし、 Tomcat にデプロイしてみる。

サーブレットの実装は以下。

src/main/java/sample/gradle/GradleServlet.java
package sample.gradle;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;

import java.io.IOException;

@WebServlet("/servlet")
public class GradleServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.getWriter().println("Hello Gradle War Plugin!!");
    }
}

デフォルトでは、 src/main/webapp 以下が、ウェブアプリケーションのソースフォルダになるので、その直下に index.html を配置する。
内容は以下。

src/main/webapp/index.html
<html>
  <head>
    <title>index</title>
  </head>
  <body>
    <h1>Index</h1>
    <a href="servlet">GradleServlet</a>
  </body>
</html>

最後に、 build.gradle を以下のように記述する。

build.gradle
apply plugin: 'war'

repositories {
    mavenCentral()
}

dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
}

war {
    archiveName = 'hello.war'
}

先頭で WAR プラグインの利用を宣言。

servlet の実装は実行環境が提供してくれるので、war ファイル内に servlet の jar を含めないように providedCompile を指定している。
providedCompile は WAR プラグインを使用している時にだけ利用可能。

wararchiveName は、生成する war ファイルの名前を指定している。これを指定しない場合は、デフォルトでは build.gradle の存在するフォルダの名前が war ファイルのベースに利用される。

war の生成は、 war タスクで実行できる。

warタスクを実行してwarファイルを生成する
>gradle war

タスクが完了すると、 build\libs の下に war ファイルが生成される。
これを Tomcat に配備してブラウザからアクセスする。

gradleで生成したサーブレットアプリケーション1.jpg

gradleで生成したサーブレットアプリケーション2.jpg

マルチプロジェクトを作成する

基本

フォルダ構成
│  build.gradle
│  settings.gradle
│
├─hoge
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Hoge.java
│
├─fuga
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Fuga.java
│
└─src
    └─main
        └─java
            └─sample
                └─gradle
                        Main.java

ルートフォルダと hoge フォルダ、 fuga フォルダがそれぞれプロジェクトとなっている。

hogefuga がサブプロジェクトフォルダであることを明示するためには、ルートフォルダに settings.gradle を配置し、以下のように記述する。

settings.gradle
include 'hoge', 'fuga'

hogefuga がもっと深い階層に存在する場合は、次のように : (コロン)繋ぎで記述する。

settings.gradle
include 'subprojects:gui:hoge', 'subprojects:web:fuga'

区切り文字が / ではなく : なのには以下の理由がある。

以前Gradleでは、プロジェクトのパスセパレータとして「/」を使用していました。しかし、このセパレータ文字はdirectoryタスク(「ディレクトリの作成 」参照)が導入されたときに廃止されています。directoryタスクのタスク名に、「/」が含まれるためです。

第56章 マルチプロジェクトのビルド - 56.5. プロジェクトとタスクのパス

各プロジェクトの設定は、以下のようにルートフォルダの build.gradle にまとめて書くことができる。

build.gradle
allprojects {
    apply plugin: 'java'
}

allprojects の中には、ルートのプロジェクトも含めた、全プロジェクトに共通の設定を記述することができる。

ルートフォルダでタスクを実行すれば、各プロジェクトごとにタスクがそれぞれ実行される。

ルートフォルダでcompileJavaタスクを実行
>gradle compileJava

>tree
│  build.gradle
│  settings.gradle
│
├─hoge
│  ├─build
│  │  └─classes
│  │      └─main
│  │          └─sample
│  │              └─gradle
│  │                      Hoge.class
│  │  
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Hoge.java
│
├─fuga
│  ├─build
│  │  └─classes
│  │      └─main
│  │          └─sample
│  │              └─gradle
│  │                      Fuga.class
│  │  
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Fuga.java
│
├─build
│  └─classes
│      └─main
│          └─sample
│              └─gradle
│                      Main.class
│
└─src
    └─main
        └─java
            └─sample
                └─gradle
                        Main.java

サブプロジェクトだけにまとめて設定をする

ルートプロジェクト以外の全サブプロジェクトに設定を適用させたい場合は、 subprojects に設定を記述する。

build.gradle
allprojects {
    apply plugin: 'java'
}

subprojects {
    apply plugin: 'war'
}

上記設定で war タスクを実行すると、 hogefuga プロジェクトだけが war にアーカイブされる。

subprojectsにだけWarプラグインを適用させた場合
>gradle war

>tree /f
│  build.gradle
│  settings.gradle
│
├─hoge
│  ├─build
│  │  └─libs
│  │          hoge.war
│  │
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Hoge.java
│
├─fuga
│  ├─build
│  │  └─libs
│  │          fuga.war
│  │
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Fuga.java
│
└─src
   └─main
       └─java
           └─sample
               └─gradle
                       Main.java

サブプロジェクト毎に個別の設定をする

さらにプロジェクト毎に個別の設定をしたい場合は、以下のいずれかの方法が利用できる。

  • project(String) メソッドを使用する
  • サブプロジェクトのフォルダごとに build.gradle を配置する

project(String) メソッドを使用する

build.gradle
allprojects {
    apply plugin: 'application'
    mainClassName = 'sample.gradle.Main'
}

project(':hoge') {
    mainClassName = 'sample.gradle.Hoge'
}

project(':fuga') {
    mainClassName = 'sample.gradle.Fuga'
}

全プロジェクトにアプリケーションプラグインを適用し、 Main クラスとして sample.gradle.Main を設定している。
ただし、 Main クラスについては、 project(String) でプロジェクトごとに Main クラスを再定義している。

runタスクの実行結果
>gradle run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
Main
:fuga:compileJava UP-TO-DATE
:fuga:processResources UP-TO-DATE
:fuga:classes UP-TO-DATE
:fuga:run
Fuga
:hoge:compileJava UP-TO-DATE
:hoge:processResources UP-TO-DATE
:hoge:classes UP-TO-DATE
:hoge:run
Hoge

BUILD SUCCESSFUL

※各クラスは、自分のクラス名を出力する実装になっている(Hoge クラスは Hoge と出力する)。

サブプロジェクトのフォルダごとに build.gradle を配置する

フォルダ構成
│  build.gradle
│  settings.gradle
│
├─hoge
│  │  build.gradle
│  │
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Hoge.java
│
├─fuga
│  │  build.gradle
│  │
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Fuga.java
│
└─src
   └─main
       └─jaga
           └─sample
               └─gradle
                       Main.java

ルートの build.gradle の内容は以下。

ルートのbuild.gradle
allprojects {
    apply plugin: 'application'
    mainClassName = 'sample.gradle.Main'
}

各サブプロジェクトに配置している build.gradle の内容は以下。

hogeプロジェクトのbuild.gradle
mainClassName = 'sample.gradle.Hoge'
fugaプロジェクトのbuild.gradle
mainClassName = 'sample.gradle.Fuga'
runタスクの実行
>gradle run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
Main
:fuga:compileJava UP-TO-DATE
:fuga:processResources UP-TO-DATE
:fuga:classes UP-TO-DATE
:fuga:run
Fuga
:hoge:compileJava UP-TO-DATE
:hoge:processResources UP-TO-DATE
:hoge:classes UP-TO-DATE
:hoge:run
Hoge

BUILD SUCCESSFUL

特定のサブフォルダ以下のサブプロジェクトにだけ設定を適用する

フォルダ構成
├─core
└─web
    ├─hoge
    └─fuga

ルートフォルダに core プロジェクトがあり、 web フォルダの下に hogefuga プロジェクトが存在する。

web フォルダ以下に存在するサブプロジェクトにだけ設定を適用したい場合は、次のように build.gradle を記述する。

build.gradle
subprojects {
    apply plugin: 'java'

    repositories {
        mavenCentral()
    }
}

project(':web') {
    subprojects {
        apply plugin: 'war'

        dependencies {
            providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
        }
    }
}

web フォルダも実は プロジェクトの1つ なので、その中でまた subprojects を使って設定を記述すれば、 web プロジェクトのサブプロジェクト全体に設定を適用させることができる。

特定のプロジェクトだけでタスクを実行する

前述したとおり、ルートフォルダでタスクを実行すると全プロジェクトで指定したタスクが実行される。

特定のプロジェクトでだけタスクを実行したい場合は、以下のようにタスクを指定する。

特定のプロジェクトだけでタスクを実行する
>gradle :hoge:compileJava

:<プロジェクトへのパス>:<実行するタスク> と指定する。

複数指定する場合は以下のようにする。

プロジェクト指定のタスクを複数実行する
>gradle :hoge:clean :hoge:compileJava

プロジェクト間の依存関係を設定する

フォルダ構成
│  build.gradle
│  settings.gradle
│
├─hoge
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Hoge.java
│
├─fuga
│  └─src
│      └─main
│          └─java
│              └─sample
│                  └─gradle
│                          Fuga.java
│
└─piyo
    └─src
        └─main
            └─java
                └─sample
                    └─gradle
                            Piyo.java
Hoge.java
package sample.gradle;

public class Hoge {
    public static void main(String[] args) {
        Fuga.fuga("Hoge");
        Piyo.piyo("Hoge");
    }
}
Fuga.java
package sample.gradle;

public class Fuga {
    public static void fuga(String caller) {
        System.out.println(caller + " calls Fuga#fuga() method.");
        Piyo.piyo("Fuga");
    }
}
Piyo.java
package sample.gradle;

public class Piyo {
    public static void piyo(String caller) {
        System.out.println(caller + " calls Piyo#piyo() method.");
    }
}
settings.gradle
include 'hoge', 'piyo', 'fuga'
  • hoge プロジェクトは、 fugapiyo の2つのプロジェクトに依存している
  • fuga プロジェクトは、 piyo プロジェクトに依存している

上記のようにプロジェクト間に依存関係がある場合は、以下のように build.gradle を記述する。

build.gradle
subprojects {
    apply plugin: 'application'
}

project(':hoge') {
    dependencies {
        compile project(':fuga'), project(':piyo')
    }
    mainClassName = 'sample.gradle.Hoge'
}

project(':fuga') {
    dependencies {
        compile project(':piyo')
    }
}

依存関係は各プロジェクト毎に dependencies 内で定義する。

settings.gradle は、プロジェクトの依存関係に関係なく、好きな順番で記述して問題ない。

Hoge#main(String[])を実行
>gradle :hoge:run
:piyo:compileJava
:piyo:processResources UP-TO-DATE
:piyo:classes
:piyo:jar
:fuga:compileJava
:fuga:processResources UP-TO-DATE
:fuga:classes
:fuga:jar
:hoge:compileJava
:hoge:processResources UP-TO-DATE
:hoge:classes
:hoge:run
Hoge calls Fuga#fuga() method.
Fuga calls Piyo#piyo() method.
Hoge calls Piyo#piyo() method.

BUILD SUCCESSFUL

Eclipse で Gradle を利用する

Eclipse のバージョンは Juno を前提とする。

プラグインのインストール

Groovy-Eclipse for Juno

build.gradle とかの編集は groovy エディタがあった方がいいので、 Groovy-Eclipse for Juno を入れておく。

マーケットプレイスからプラグインをインストールする。

Gradle Integration for Eclipse

マーケットプレイスから、 Gradle Integration for Eclipse をインストールする。

デフォルトだと Spring Dashboard とかをインストールしようとするけど、自分の環境?では必要なファイルが見つからない的なエラーが出てインストールできなかった。
(optional) って書いてるので、 Spring DashboardSpring UAA Integration はチェックを外してインストールした。

インストールが完了したら Eclipse を再起動。

このプラグインには 2013/12/07 現在 Gradle 1.5 がバンドルされているみたいで、デフォルトではその Gradle を使おうとするっぽい。

それは困るので、 Gradle の切り換えを行う。

[ウィンドウ] → [設定] と選択し、 [Gradle] を開く。
次に [Gradle Distribution] で [フォルダー]を選択し、既にインストールしている Gradle 1.9 のフォルダのパスを設定する。

Gradleプラグインの設定.jpg

Gradle プロジェクトを作る

[ファイル] → [新規] → [その他] → [Gradle] → [Gradle Project] を選択。

[プロジェクト名] を入力して、 [Sample project] でプロジェクトのひな形を選択する。
とりあえず、 [Java Quickstart] を選択。

作成されたプロジェクトは以下。

Gradleプラグインで生成されたプロジェクトの様子.jpg

なんか色々生成されてる。

既存の Gradle プロジェクトを Eclipse にインポートする

フォルダ構成
│  build.gradle
│
└─src
    └─main
        └─java
            └─sample
                └─gradle
                        GradleMain.java
build.gradle
apply plugin: 'application'

mainClassName = 'sample.gradle.GradleMain'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.apache.commons:commons-lang3:3.1'
}

上記プロジェクトを Eclipse にインポートする。

Eclipse 上で [ファイル] → [インポート] を選択。
[Gradle] → [Gradle Project] を選択して次へ。

[ルート・フォルダー] に上記プロジェクトのフォルダパスを入力し、 [Build Model] をクリックする。
するとプロジェクトが読み込まれるので、 [完了] をクリックする。

eclipseにインポート.jpg

既存のGradleプロジェクトをインポート.jpg

依存ライブラリは Eclipse の Gradle プラグインが管理してくれているようで、 .classpath ファイルは以下のようになっている。

.classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" path="src/main/java"/>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
    <classpathentry exported="true" kind="con" path="org.springsource.ide.eclipse.gradle.classpathcontainer"/>
    <classpathentry kind="output" path="bin"/>
</classpath>

Gradle の Eclipse プラグインを使って生成した Eclipse プロジェクトだと、 .classpath に jar のフルパスが記述されてて開発者毎の環境に依存しないように工夫をしないといけないけど、この方法だと問題なさそう。

Web アプリケーションのプロジェクトを WTP としてインポートする

こっち参照→「Java - EclipseのGradleプラグイン使ってるときにprovidedCompileで指定しているjarもWEB-INF/libに配備されて困ったときの話 - Qiita [キータ]

Eclipse プロジェクト上での JRE を指定する

特に指定しない場合、ワークスペースのデフォルトの JRE を使うようになる。

任意の JRE を使用したい場合は、以下のように build.gradle を設定する。

build.gradle(一部)
ext.jreName = 'jdk1.7.0_51'

eclipse {
    classpath {
        containers.clear()
        containers.add("org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/${jreName}")
    }
}

jreName は、 Eclipse に登録している「インストール済み JRE」の名前を指定する。

参考

プロジェクトの依存関係を確認する

dependencies タスクで確認する

build.gradle
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile 'commons-dbcp:commons-dbcp:1.4'
    compile 'com.google.inject:guice:3.0'
    testCompile 'junit:junit:4.11'
}

コンパイル時の依存ライブラリに Apache Commons DBCP と Google Guice を、テストコンパイル時の依存ライブラリに JUnit をとりあえず設定している。

この状態で dependencies タスクを実行すると、各タスク毎での依存ライブラリの様子が確認できる。

>gradle dependencies

(中略)

compile - Compile classpath for source set 'main'.
+--- commons-dbcp:commons-dbcp:1.4
|    \--- commons-pool:commons-pool:1.5.4
\--- com.google.inject:guice:3.0
     +--- javax.inject:javax.inject:1
     +--- aopalliance:aopalliance:1.0
     \--- org.sonatype.sisu.inject:cglib:2.2.1-v20090111
          \--- asm:asm:3.1

(中略)

testCompile - Compile classpath for source set 'test'.
+--- commons-dbcp:commons-dbcp:1.4
|    \--- commons-pool:commons-pool:1.5.4
+--- com.google.inject:guice:3.0
|    +--- javax.inject:javax.inject:1
|    +--- aopalliance:aopalliance:1.0
|    \--- org.sonatype.sisu.inject:cglib:2.2.1-v20090111
|         \--- asm:asm:3.1
\--- junit:junit:4.11
     \--- org.hamcrest:hamcrest-core:1.3

(中略)

BUILD SUCCESSFUL

Total time: 9.731 secs

レポートプラグインを使って出力する

build.gradle
apply plugin: 'java'
apply plugin: 'project-report'

repositories {
    mavenCentral()
}

dependencies {
    compile 'commons-dbcp:commons-dbcp:1.4'
    compile 'com.google.inject:guice:3.0'
    testCompile 'junit:junit:4.11'
}

apply plugin: 'project-report' を追加すると、レポートプラグインが使える。

dependencyReport タスク

dependencyReportタスクの実行
>gradle dependencyReport

build\reports\project の下に dependencies.txt というファイルが出力される。
内容は、 dependencies タスクを実行したのと同じ。

htmlDependencyReport タスク

htmlDependencyReportタスクの実行
>gradle htmlDependencyReport

build\reports\project\dependencies の下に色々とファイルが出力されるので、 index.html を開くと HTML 形式のレポートが見れる。

依存関係レポート_index.jpg

依存関係レポート_project.jpg

htmlDependencyReport タスク(マルチプロジェクトの場合)

マルチプロジェクトで何も設定せずに htmlDependencyReport タスクを実行すると、サブプロジェクト毎に HTML レポートが出力されてしまう。
1つの HTML レポートに、すべてのサブプロジェクトの依存関係を出力したい場合は、次のように build,gradle を記述する。

build.gradle
allprojects {
    apply plugin: 'java'
    apply plugin: 'project-report'

    repositories {
        mavenCentral()
    }

    dependencies {
        testCompile 'junit:junit:4.11'
    }
}

project(':hoge') {
    dependencies {
        compile 'commons-dbcp:commons-dbcp:1.4'
    }
}

project(':fuga') {
    dependencies {
        compile 'com.google.inject:guice:3.0'
    }
}

htmlDependencyReport {
    projects = project.allprojects
}

htmlDependencyReportprojects = project.allprojects を指定すれば、以下のようにルートの HTML レポートにすべてのサブプロジェクトのレポートをまとめて出力できる。

依存関係レポート_multi_index.jpg

依存関係レポート_multi_hoge.jpg

ただし、 projects = project.allprojects という指定方法は今後の Gradle のバージョンでは変更になる可能性があるらしい(2013/12/19 現在)。

Note: This class is incubating and may change in a future version of Gradle.

HtmlDependencyReportTask - Gradle DSL Version 1.11-20131203060736+0000

プロパティファイルを使う

build.gradle があるフォルダに gradle.properties という名前でプロパティファイルを配置しておけば、プロパティファイルに宣言したキーの名前で通常の変数と同じように使えるようになる。

gradle.properties
hoge=HOGE
build.gradle
task sample << {
    println "hoge=${hoge}"
}
実行
>gradle :sample
:sample
hoge=HOGE

BUILD SUCCESSFUL

Total time: 2.566 secs

でも、せっかく Groovy が使えるので、後述の ConfigSlurper を使った方がいい気がする。

ConfigSlurper を使う

使い方自体は普通に Groovy で使う のと同じ。

唯一気をつけないと行けないのは、 読み込んだコンフィグ情報をトップレベルの変数で宣言してはいけない 、という点。

config.gradle
hoge {
    name = 'HOGE'
    fuga = [1, 2, 3]

    piyo {
        value = false
    }
}
build.gradle
config = new ConfigSlurper().parse(new File('config.gradle').toURL())

task config << {
    println config
}
実行結果
>gradle config
Creating properties on demand (a.k.a. dynamic properties) has been deprecated and is scheduled to be removed in Gradle 2.0. Please read http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html for information on the replacement for dynamic properties.
Deprecated dynamic property: "config" on "root project 'gradle'", value: "{hoge={name=HOGE, fuga...".
:config
{hoge={name=HOGE, fuga=[1, 2, 3], piyo={value=false}}}

BUILD SUCCESSFUL

Total time: 2.701 secs

タスクは成功するが、ガッツリ警告が表示される。

理由は以下。

Gradle 1.0 milestone 9より、拡張プロパティを追加する際にはextを使用することが強く推奨されるようになっていますが、まだ強制はされません。 そのため存在しないプロパティに値を設定してもGradleの実行は失敗せず、警告が表示されます。

ということで、拡張プロパティをセットするときは ext に追加してあげる。

build.gradle
ext.config = new ConfigSlurper().parse(new File('config.gradle').toURL())

task config << {
    println config
}
実行結果
>gradle config
:config
{hoge={name=HOGE, fuga=[1, 2, 3], piyo={value=false}}}

BUILD SUCCESSFUL

Total time: 2.782 secs

Ant タスクを実行する

build.gradle
task ant << {
    ant.mkdir dir: 'dir'

    ant.echo message: 'ant echo', file: 'ant.txt'

    ant.copy(todir: 'dir') {
        fileset file: 'ant.txt'
    }
}
実行
>dir /b
build.gradle

>gradle :ant
:ant

BUILD SUCCESSFUL

Total time: 2.825 secs

>tree /f
│  ant.txt
│  build.gradle
│
└─dir
        ant.txt
  • ant という名前の変数に ant のタスクと同じ名前のメソッドが定義されているので、それを使う。
  • 属性は <属性名>: <値> という形式でタスクメソッドの引数に渡す。
  • ネストされる要素は、タスクメソッドにクロージャーで渡す。

以下のようにもまとめて書くこともできる。

task ant << {
    ant {
        mkdir dir: 'dir'
        echo message: 'ant echo', file: 'ant.txt'
        copy(todir: 'dir') {
            fileset file: 'ant.txt'
        }
    }
}

Gradle Wrapper を使う

Gradle Wrapper(ラッパー)を有効にすると、ビルドに必要な Gradle をコマンド1つで自動インストールできるようになる。

Gradle のバージョンを、開発者ごとに揃えることができる。

Gradle Wrapper を有効にする

build.gradle
task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}

build.gradle に、上記のようにタスクを追加する。

そして、このタスクを実行する。

> gradle wrapper
:wrapper

BUILD SUCCESSFUL

Total time: 4.854 secs

すると、以下のようにファイルが追加される。

追加されるファイル
|-gradle/
|  `-wrapper/
|     |-gradle-wrapper.jar
|     `-gradle-wrapper.properties 
|-gradlew
`-gradlew.bat

これらのファイルは、全てバージョン管理システムに追加する。

Gradle Wrapper を実行する

各開発者は、プロジェクトをバージョン管理システムからチェックアウトしてきたら、ルートにある gradlew.bat または gradlew を実行する。

すると、 Gradle が自動でインストールされる。

タスクは、 > gradlew <タスク> で実行することができる。

参考