読者です 読者をやめる 読者になる 読者になる

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>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.0.13</version>
    <optional>true</optional>
</dependency>

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

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

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

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

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

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

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

    test {
        java { srcDirs = ['src/test/java']}
        compileClasspath += configurations.optional
    }
}

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

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

ではでは