Help us understand the problem. What is going on with this article?

Maven の provided のような依存指定を Gradle でやってみる

More than 3 years have passed since last update.

概要

Maven の provided スコープのような、「コンパイル時には含めるが Jar には入れない」という依存を記述したかったので、どうやるか調べてみました。

目的

あるアプリケーションAに別のアプリケーションBのコードをjarにして同梱する際、BのjarにAでも利用しているライブラリが入っていると、Aをfat jarにした際に重複してしまって無駄が発生するので、B の依存解決で provided スコープでの依存指定ができるようにしたい、という事情がありました。

 ------------A-----------         ------------B-----------
| lib:lib.commons:0.0.1 |         | lib:lib.commons:0.0.1 | <---この lib.commons-0.0.1 を B.jar から除外したい
|          B.jar        |         ------------------------
 ------------------------

作業環境

Java SE 1.8.0_102
OS Windows 10
Gradle 3.0

作業

provided

まず configurations ブロックで provided を宣言しておきます。

configurations
configurations {
    provided
}

依存の記述

続いて、dependencies で provided の依存を記述します。

dependencies
dependencies {
    provided 'com.jfoenix:jfoenix:1.0.0'
    provided 'org.slf4j:slf4j-api:1.7.21'
    provided 'org.slf4j:slf4j-log4j12:1.7.21'
……

compileJava の記述

provided をコンパイルのクラスパスに含めます。

compileJava
compileJava {
    sourceSets.main.compileClasspath += configurations.provided
    sourceSets.test.compileClasspath += configurations.provided
}

テストのクラスパスに追加

忘れるとテスト実行時に大量の java.lang.NoClassDefFoundError が出ます。

test
test {
    classpath += configurations.provided
}

(任意) application プラグインを使っている場合

run にも入れておきます。

run
run {
    classpath += configurations.provided
}

(任意) Eclipse 上で依存解決したい場合

下記を追加してください。

build.gradleに追記
apply plugin: 'eclipse'

……

eclipse {
    classpath {
        plusConfigurations += [ configurations.provided ]
    }
}

参考

jar タスクの修正

compile のものだけ jar に含めるように指定します。

jar
jar {
……
    from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
……

実践

今回は JVM 言語のスクリプトを実行するアプリケーション のコードを使って試してみます。

(共通) jar生成

修正前後で同じコマンドを使います。

jar生成
$ gradle clean jar
Starting a Gradle Daemon, 1 busy Daemon could not be reused, use --status for details
:clean
:compileJava
:processResources
:classes
:jar

BUILD SUCCESSFUL

Total time: 12.758 secs

修正前

jar のサイズは 24.58MB、jar のファイル数は 15,850 でした。

$ ls -l ScriptRunner-0.0.1.jar
-rw-r--r-- 1 John Kay 197121 24580947 Oct 30 15:31 ScriptRunner-0.0.1.jar

$ ls -lh ScriptRunner-0.0.1.jar
-rw-r--r-- 1 John Kay 197121 24M Oct 30 15:31 ScriptRunner-0.0.1.jar

$ jar tf ScriptRunner-0.0.1_.jar | wc -l
15850

修正

jar に含めない依存を compile から provided に変更します。

https://github.com/toastkidjp/ScriptRunner/commit/f3249eab157fc615ec64c25a58be9ce366660520

修正後

$ gradle clean jar で jar を作り直します。

$ ls -l ScriptRunner-0.0.1.jar
-rw-r--r-- 1 John Kay 197121 10647049 Oct 30 15:34 ScriptRunner-0.0.1.jar

$ ls -lh ScriptRunner-0.0.1.jar
-rw-r--r-- 1 John Kay 197121 11M Oct 30 15:34 ScriptRunner-0.0.1.jar

$ jar tf ScriptRunner-0.0.1.jar | wc -l
8018

生成された jar はファイルサイズが 10.647MB、ファイル数が 8,018 でした。確実に小さくなっているのがわかります。


まとめ

プラグイン等は必要なく、 Gradle 標準の仕組みだけで、 Maven の provided スコープのような依存指定ができました。フレームワークの依存が必要なアプリケーション開発(Storm等)で使えると思います。


参考

toastkidjp
Web 系企業の Android アプリ開発者です。
https://github.com/toastkidjp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away