ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Gradle のマルチモジュールプロジェクトで maven-publish プラグインを使う場合の依存関係

Gradle でビルド成果物 (build artifact) を Maven リポジトリに公開するためのプラグインとして、maven-publish プラグインがある。

maven-publish プラグインとマルチプロジェクトの依存関係

簡単な例

Java ライブラリのプロジェクトがあったとして、JAR ファイルを Maven リポジトリに公開するための build.gradle の記述は以下のようになる。

// Java ライブラリのビルド用の設定などは省略

apply plugin: 'maven-publish'

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

これで publishToMavenLocal タスクなどが使えるようになるので、例えばローカルホスト上の Maven リポジトリに公開するには ./gradlew publishToMavenLocal コマンドを実行すればよい。

依存関係

上の例では、ソフトウェアコンポーネントとして java コンポーネントを指定している。 このとき、依存関係としては runtime コンフィギュレーションのものが使われる。

Name Provided By Artifacts Dependencies
java The Java Plugin Generated jar file Dependencies from 'runtime' configuration
web The War Plugin Generated war file No dependencies
Maven Publishing (new) - Gradle User Manual

マルチモジュールプロジェクトでの依存関係

例えば :foo プロジェクトと :bar プロジェクトからなるマルチモジュールプロジェクトで、:bar プロジェクトから :foo プロジェクトに依存している場合に、出力される pom.xml に記載される依存関係はどうなるのか?? 具体的には bar/build.gradle に以下のように書かれている状況である。

dependencies {
    compile project(':foo')
}

これはドキュメントには書かれていないが、maven-publish プラグインソースコードを確認したところ、依存先プロジェクトの設定に応じて自動的に依存先ライブラリの指定がなされるようになっていた。

例えば、依存先プロジェクトで maven-publish プラグインが使われていない場合は、プロジェクトのグループやプロジェクト名、バージョンが使われるようである。 依存先プロジェクトで maven-publish プラグインが使われており、特定の条件を満たす publication が存在する場合は、その publication で指定されているグループ・artifactId・バージョンが使われる。

publishing {
    publications {
        maven(MavenPublication) {
            groupId 'org.example'
            artifactId 'foo-sample'
            version '1.1'

            from components.java
        }
    }
}

foo/build.gradle に上のように書かれていたら、./gradlew :bar:publishToMavenLocal タスクで公開される成果物の pom ファイルには以下の内容が含まれることになる。

    <dependency>
      <groupId>org.example</groupId>
      <artifactId>foo-sample</artifactId>
      <version>1.1</version>
      <scope>compile</scope>
    </dependency>

気を付ける必要があること

依存先プロジェクトの中で maven-publish プラグインが使用されて、publication が定義されている必要がある。

下記のように、親プロジェクトで子プロジェクトの publication をまとめて定義することもできるのだが、そうすると依存関係の解決時に 「依存先プロジェクトでは publication がない」 という扱いになってしまって、デフォルト値が使用される。

publishing {
    publications {
        mavenFoo(MavenPublication) {
            groupId 'org.example'
            artifactId 'foo-sample'
            version '1.1'

            from findProject(':foo').components.java
        }

        mavenBar(MavenPublication) {
            groupId 'org.example'
            artifactId 'bar-sample'
            version '1.1'

            from findProject(':bar').components.java
        }
    }
}

私はこれでハマってしまった。 (Exposed の build.gradle を見て、親の build.gradle で子プロジェクトの publication を宣言していたので、それを参考にした、という。) 注意されたし。