Gradle でアプリケーションを zip 化する

Gradle を使って Vert.x 組み込み実行による単純な Web アプリケーションを zip 化してみました。

サンプルソースは http://github.com/fits/try_samples/tree/master/blog/20131020/

zip 化のタスク定義

とりあえず、Gradle のビルド定義 build.gradle へ下記のように設定すれば zip 化を実現できます。

  • (1) type: Zip、dependsOn: jar を指定したタスクを定義
  • (2) artifacts.archives へ (1) のタスクを設定

(1) で dependsOn: jar のように依存関係を設定しておかないと、ソースのコンパイル (compileJava タスクなど) 前に zip 化のタスクが実行されてしまうので注意が必要です。

なお、(2) の設定によって assemble や build タスク等の実行時に zip 化のタスクを実行するようになります。 (dependsOn: jar によって jar タスクの後に実施されます)

サンプル

それでは、下記のような構成のサンプルプロジェクトを使って zip 化を試してみます。

サンプルプロジェクトの構成
bin
  |_ sampleapp.bat
  |_ ・・・
conf
  |_ dev
      |_ app.properties
  |_ prod
      |_ app.properties
src
  |_ main
      |_ ・・・
web
  |_ ・・・

build.gradle

作成する zip ファイルは下記のような構成にします。

  • (a) bin 内のファイルを zip のルートへ配置
  • (b) conf/xxx 内のファイルを zip の conf へ配置 (xxx は env プロパティの値)
  • (c) アプリケーションの JAR と依存ライブラリを zip の lib へ配置
  • (d) web ディレクトリを zip の web へ配置
zip ファイルの構成
conf
  |_ app.properties
lib
  |_ gradle_zip_sample.jar (アプリケーションの JAR)
  |_ groovy-all-2.1.8.jar
  |_ ・・・
web
  |_ ・・・

sampleapp.bat
・・・

Gradle のビルド定義ファイル build.gradle は以下のようになります。

ビルド定義 build.gradle
apply plugin: 'groovy'
// プロジェクトプロパティを使った環境指定
def env = hasProperty('env')? env: 'dev'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.1.8'
    compile 'io.vertx:vertx-core:2.0.2-final'
    compile 'io.vertx:lang-groovy:2.0.0-final'
}

defaultTasks 'clean', 'build'

// (1) zip 化タスクの定義
task zipApp(type: Zip, dependsOn: jar) {
    // zip ファイル名の変更
    archiveName = "${baseName}_${env}.${extension}"

    // (a) bin 内のファイルを zip のルートへ配置
    from 'bin'

    // (b) conf/xxx 内のディレクトリ・ファイルを zip の conf へ配置(xxx は env の値)
    into('conf') {
        from "conf/$env"
    }

    // (c)
    into('lib') {
        // アプリケーションの JAR
        from jar.archivePath
        // 各種依存ライブラリ
        from configurations.runtime
    }

    // (d)
    into('web') {
        from 'web'
    }
}

// (2)
artifacts {
    archives zipApp
}

Zip のような CopySpec インターフェースの実装クラスでは、from() でコピー元のディレクトリやファイルを指定し、into() でコピー先 (zip ファイル内) のパスを指定します。

なお、一部のディレクトリやファイルのみ特定のパスへコピーするには、下記のように第2引数へクロージャを渡す into(destPath, configureClosure) メソッドを使います。

into('<コピー先>') {
    from '<コピー元>'
    ・・・
}

ここで、from に runtimeClasspath を指定すると、依存ライブラリと共に JAR ファイル化されていないアプリケーションのクラス・リソースファイルがそのまま含まれてしまう点に注意が必要です。

  • runtimeClasspath アプリケーションのクラス・リソースファイル + 依存ライブラリ
runtimeClasspath の内容
・・・/build/classes/main
・・・/build/resources/main
・・・/.gradle/caches/・・・/groovy-all-2.1.8.jar
・・・

依存ライブラリとアプリケーションの JAR ファイル (今回のサンプルでは gradle_zip_sample.jar) を zip へ格納するには runtimeClasspath の代わりに以下を使います。

  • jar.archivePath アプリケーションの JAR ファイル
  • configurations.runtime 依存ライブラリ
configurations.runtime の内容
・・・/.gradle/caches/・・・/groovy-all-2.1.8.jar
・・・

zip 化の実行

gradle コマンドで build タスクを実行すれば build/distributions ディレクトリへ zip ファイルが生成されます。

> gradle build

なお、今回のサンプルでは gradle build もしくは gradle build -Penv=dev で conf/dev/app.properties を conf/app.properties へ配置した gradle_zip_sample_dev.zip ファイルが、gradle build -Penv=prod で conf/prod/app.properties を使った gradle_zip_sample_prod.zip ファイルが作られます。