Gradleでoptionalなdependencyを定義する

最近はMavenではなくGradleもよく触るようになったpom職人です。

さて、Mavenのpom.xmlではdependencyにoptionalという設定ができます。例えば、Aというライブラリがlogback-classicに依存していたとします。BというWebアプリケーションがAに依存していたばあい、Bも必然的にlogback-classicに依存することになります。 pom.xmlではoptionalをtrueにすることで、Bがlogback-classicに依存することを回避することができます。

<dependency></dependency>
    <groupid></groupid>ch.qos.logback
    <artifactid></artifactid>logback-classic
    <version></version>1.0.13
    <optional></optional>true

これをGradleでやるわけです。ちなみにGradleでは以下のようにdependencyを定義します。pomではscopeでcompileレベルかtestレベルか等を設定できましたが、Gradleではdependecy configurationというグループで定義できます。

dependencies {
    compile(
        [group: &#39;ch.qos.logback&#39;, name: &#39;logback-classic&#39;, version: &#39;1.0.13&#39;]
    )
    testCompile(
        [group: &#39;junit&#39;, name: &#39;junit&#39;, version: &#39;4.11&#39;]
    )
}

しかしこれ、logback-classicにoptional: trueとか設定しても効きません。実はGradleにはoptionalなんて属性が無いんですね。

そこでどうするか。だったら、optionalという独自のconfigurationを定義してやって、そこにlogback-classicを定義します。 optionalは独自属性なので、それを定義するだけではクラスパスには追加されません。そのため、別途sourceSets内のcompileClasspathにoptional内のdependencyを追加しています。

// 新たにoptionalというconfigurationを定義
configurations {
    optional
}

dependencies {
    // optionalに定義
    optional(
        [group: &#39;ch.qos.logback&#39;, name: &#39;logback-classic&#39;, version: &#39;1.0.13&#39;]
    )
    testCompile(
        [group: &#39;junit&#39;, name: &#39;junit&#39;, version: &#39;4.11&#39;]
    )
}

sourceSets {
    // compileClasspathにoptionalのdependencyを追加
    main {
        java { srcDirs = [&#39;src/main/java&#39;]}
        compileClasspath += configurations.optional
    }

    test {
        java { srcDirs = [&#39;src/test/java&#39;]}
        compileClasspath += configurations.optional
    }
}

こうすることでAというライブラリはlogback-classicに依存しながら、Bがlogback-classicに依存しないという状況を実現できます。

このGradleプロジェクトをMavenリポジトリにディプロイした場合pom.xmlが生成されますが、そのpom.xmlにはlogback-classicの依存そのものが無くなります(optionalで追加されるわけではない)。厳密な意味でのpomのoptionalには対応されてませんが、Gradleとしてはこれで十分ですね。Gradleはプログラマブルに書けるので、多少困ったときでもゴリッ書けてしまうのが良いですね。

ではでは